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, 2022 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)
    – srhslvmn
    Jul 25, 2022 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, 2022 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`?
    – srhslvmn
    Jul 25, 2022 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)?
    – srhslvmn
    Jul 25, 2022 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
    – srhslvmn
    Jul 25, 2022 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.
    – srhslvmn
    Jul 24, 2022 at 22:50
  • Also, (^.*) looks like a winking smiley. xD
    – srhslvmn
    Jul 24, 2022 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
    – srhslvmn
    Jul 24, 2022 at 22:59
  • Ah, using this as the search string works: (^.*)def (with space at the end)
    – srhslvmn
    Jul 24, 2022 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, 2022 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
  • 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, 2022 at 14:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .