Skip to content Skip to sidebar Skip to footer

Bash Script To Select A Single Python Function From A File

For a git alias problem, I'd like to be able to select a single Python function from a file, by name. eg: ... def notyet(): wait for it def ok_start(x): stuff

Solution 1:

One way using awk. Code is well commented, so I hope it's easy to understand.

Content of infile:

  ...
  defnotyet():
      wait for it

  defok_start(x):
      stuff
      stuff
      defdontgettrickednow():
         keep going
  #stuff
      more stuff

  defok_stop_now():

Content of script.awk:

BEGIN {
        ## 'f' variable is the function to search, set a regexp with it.
        f_regex = "^" f "[^a-zA-Z0-9]"## When set, print line. Otherwise omit line.## It is set when found the function searched.## It is unset when found any character different from '#' with less## spaces before it.
        in_func = 0
}

## Found function.
$1 == "def" && $2 ~ f_regex {

        ## Get position of first 'd' in the line.
        i = index( $0, "d" )

        ## Sanity check. Never should success because the condition was## checked before.if ( i == 0 ) {
                next
        }

        ## Get characters until matched index before, check that all of## them are spaces, and get its length.
        indent = substr( $0, 0, i - 1 )
        if ( indent ~ /^[[:space:]]*$/ ) {
                num_spaces = length( indent )
        }

        ## Set variable, print line and read next one.
        in_func = 1printnext
}

## When we are inside the function, line doesn't begin with '#' and## it's not a blank line (only spaces).
in_func == 1 && $1 ~ /^[^#]/ && $0 ~ /[^[:space:]]/ {

        ## Get how many characters there are until first non-space. The result## is the position of first non-blank, so substract one to get the number## of spaces.
        spaces = match( $0, /[^[:space:]]/ )
        spaces -= 1## If current indent is less or equal that the indent of function definition, then## end of function found, so end processing.if ( spaces <= num_spaces ) {
                in_func = 0
        }
}

## Self-explanatory.
in_func == 1 { 
        print
}

Run it like:

awk -f script.awk -v f="ok_start" infile

With following output:

defok_start(x):
      stuff
      stuff
      defdontgettrickednow():
         keep going
  #stuff
      more stuff

Solution 2:

Why not just let python do it? I think the inspection module can print out the source of a function, so you could just import the module, select the function and inspect it. Hang on. Banging away at a solution for you...

OK. It turns out the inspect.getsource function doesn't work for stuff defined interactively:

>>> deftest(f):
... print'arg:', f
...
>>> test(1)
arg: 1>>> inspect.getsource(test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\inspect.py", line 699, in getsource
    lines, lnum = getsourcelines(object)
  File "C:\Python27\lib\inspect.py", line 688, in getsourcelines
    lines, lnum = findsource(object)
  File "C:\Python27\lib\inspect.py", line 529, in findsource
    raise IOError('source code not available')
IOError: source code not available
>>>

But for your use case, it will work: For modules that are saved to disk. Take for instance my test.py file:

deftest(f):
    print'arg:', f

defother(f):
    print'other:', f

And compare with this interactive session:

>>>import inspect>>>import test>>>inspect.getsource(test.test)
"def test(f):\n    print 'arg:', f\n"
>>>inspect.getsource(test.other)
"def other(f):\n    print 'other:', f\n"
>>>

So... You need to write a simple python script that accepts the name of a python source file and a function/object name as arguments. It should then import the module and inspect the function and print that to STDOUT.

Post a Comment for "Bash Script To Select A Single Python Function From A File"