8

I need to replace, in a large number of Python files with many function definitions, all occurrences of

def some_func(foo, bar):

with

@jit(parallel=True)
def some_func(foo, bar):

with whatever level of indentation def some_func(foo, bar) has.

Example: I want to replace

def some_func_1(foo, bar):

    def some_func_2(foo, bar):

        def some_func_3(foo, bar):

def some_func_4(foo, bar):

with

@jit(parallel=True)
def some_func_1(foo, bar):

    @jit(parallel=True)
    def some_func_2(foo, bar):

        @jit(parallel=True)
        def some_func_3(foo, bar):

@jit(parallel=True)
def some_func_4(foo, bar):

Motivation: I want to "brute-force accelerate/parallelize" a FDTD simulation package without having to rewrite the entire codebase by making use of numba's automatic parallelization with @jit.

PS.: Any comment/critique of this naive approach of (ab)using @jit is also welcome (e.g. if this wouldn't work at all)!

4 Answers 4

6

A better solution may be using jit_module to jit all your functions automatically

1
  • 1
    It may be a better solution to this particular problem, but long term learning a bit of Regex is a better solution.
    – jmoreno
    Jul 26 at 3:47
13

This will work for any kind of spaces (white spaces or tabulations) and for any kind of linebreak \n, \r\n, \r.


  • Ctrl+H
  • Find what: ^(\h*)(?=def\b.*(\R))
  • Replace with: $1@jit\(parallel=True\)$2$1
  • TICK Match case
  • TICK Wrap around
  • SELECT Regular expression
  • UNTICK . matches newline
  • Replace all

Explanation:

^           # beginning of line
    (           # group 1
        \h*         # 0 or more horizontal spaces
    )           # end group
    (?=         # positive lookahead, make sure we have after:
        def\b       # literally "def" and a word boundary, in order to not match "default"
        .*          # 0 or more any character but newline
        (\R)        # group 2, any kind of linebreak
    )           # end lookahead

Replacement:

$1                      # content of group 1, the spaces to insert
@jit\(parallel=True\)   # literally
$2                      # content of group 2, the linebreak used in the file
$1                      # content of group 1, the spaces to insert

Screenshot (before):

enter image description here

Screenshot (after):

enter image description here

10
  • Thanks for your solution, could you briefly check comments below and also my suggestion, which (as far as I can tell) works, but is much shorter? Also, you and @Yisroel Tech appear to be using a different group replacement syntax ($1 vs. \1)
    – sarahslvmn
    Jul 25 at 16:20
  • 1
    @joanna:Your regex (^.*)(def ) matches 0 or more any character preceding def, for example undef will match or blah blah def blah, not sure you want that. Notepad++ supports both \1 and $1, the former is a legacy notation that should be use in the regex only (it is called backreference), the latter should be used in the replacement part, it allows to capture more than 9 groups. It is used in PCRE and BOOST regex flavour.
    – Toto
    Jul 25 at 16:34
  • 1
    Okay, and what about the usage of \h? Why not \s or simply ` ` (space)? Wikipedia only mentions \h as a notation for "word head", not "horizontal space". Or is it that * cannot operate on ` , but only on \h`?
    – sarahslvmn
    Jul 25 at 17:24
  • Furthermore, could you explain the function of ?=? You call it a "positive lookahead", but it's not clear what it does. Also, is it necessary to have \b at the end of def\b? Again, wouldn't also a space work, i.e. def (as this is literally what comes after)?
    – sarahslvmn
    Jul 25 at 17:26
  • ...ah, I think that I can see from my second-last comment above how using ` ` isn't a good idea (SE comment interpreter mangles my input). It seems that whitespaces might not be recognized as characters, so one has to be more explicit and use \s or \h. But then the question remains, why \h and not \s
    – sarahslvmn
    Jul 25 at 17:30
4

You can do that using Regex capture groups and then reusing the first group (the indentation) on both lines in the replacement.

Search (with Regex):

(^.*)(def .*\([^\(]+\))

And replace with:

\1@jit\(parallel=True\)\r\n\1\2

See in action: enter image description here

13
  • 1
    Hi, thanks for your answer!! Could you please briefly explain what "capture groups" means? I can't really tell from your animation.
    – sarahslvmn
    Jul 24 at 22:50
  • Also, (^.*) looks like a winking smiley. xD
    – sarahslvmn
    Jul 24 at 22:50
  • Okay, this solution doesn't work, especially since I don't want (foo, bar) inserted everywhere. This part obviously needs to stay variable, the same as the function names
    – sarahslvmn
    Jul 24 at 22:59
  • Ah, using this as the search string works: (^.*)def (with space at the end)
    – sarahslvmn
    Jul 24 at 23:01
  • 1
    I'm a programmer and I've made a more generic RegEx that'll capture anything in the round brackets.
    – Nelson
    Jul 25 at 9:10
-1

In Notepad++, searching for (^.*)(def ) (with space at the end) and replacing with \1@jit\(parallel=True\)\r\n\1\2 works. The space at the end is important as otherwise strings such as default will also get replaced.

1
  • Since .* matches any character, this will also match any lines with words ending in "def" for example var mydef = 5 would be matched and replaced.
    – Falco
    Jul 26 at 14:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.