[Python-porting] Port of psycopg2

"Martin v. Löwis" martin at v.loewis.de
Mon Dec 15 22:17:47 CET 2008

> Can I register new ones somewhere ? (other than copying them into the
> fixes package dir or monkey patching them in there)

No need to register them. Just pass the module names.

> The API looks rather complicated, even for very simple search and
> replace tasks such as __nonzero__ -> __bool__ conversion, e.g. from
> fix_nonzero.py:
> class FixNonzero(fixer_base.BaseFix):
>     PATTERN = """
>     classdef< 'class' any+ ':'
>               suite< any*
>                      funcdef< 'def' name='__nonzero__'
>                               parameters< '(' NAME ')' > any+ >
>                      any* > >
>     """
>     def transform(self, node, results):
>         name = results["name"]
>         new = Name("__bool__", prefix=name.get_prefix())
>         name.replace(new)
> PATTERN looks like some kind of tree pattern recognition language.
> I would assume that node is the found node, but have no idea
> what results means. prefix also is a mystery - method names don't
> have prefixes, so this has got to be something else.

You shouldn't try to write the patterns yourself, but instead use
the find_pattern.py tool from the 2to3 sandbox. The node that
matches follows Grammar/Grammar, where classdef is defined as

classdef: 'class' NAME ['(' [testlist] ')'] ':' suite

and the embedded productions are

suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
funcdef: 'def' NAME parameters ':' suite
parameters: '(' [varargslist] ')'

prefix is the lexical prefix of the token, i.e. typically the
set of whitespace preceding the name. This is necessary
so that __bool__ gets into the same column that __nonzero__
was in, in case you wrote

   def           __nonzero__(self):pass


More information about the Python-porting mailing list