[Python-porting] A few questions about the psycopg2 porting to Python 3

Daniele Varrazzo daniele.varrazzo at gmail.com
Wed Jan 12 18:34:12 CET 2011


On Tue, Jan 11, 2011 at 6:41 PM, Daniele Varrazzo
<daniele.varrazzo at gmail.com> wrote:

> As emerged from the discussion in this ML back in 2008, there is
> somewhere the need for a python function b('literal') that would
> evaluate to 'literal' in Py2 and to b'literal' in py3 (we want to keep
> compatibility with Python 2.4). Currently there is an encode()
> involved in Py3, so it would be great to have the transformation
> b('literal') -> b'literal' performed by 2to3 instead. Looking at the
> other fixers it seems easy, but I haven't found how to register a
> custom fixer for the use of build_py_2to3 in setup.py. Is there any
> reference?

I got in PM the suggestion to use distribute. My answer is that I
would prefer to avoid an extra dependency to solve this problem.


I've tested with some nasting monkeypatching to have the fix_b
injected. This seems working for instance:

    diff --git a/setup.py b/setup.py
    index 926169c..836d3e6 100644
    --- a/setup.py
    +++ b/setup.py
    @@ -58,6 +58,16 @@ try:
         from distutils.command.build_py import build_py_2to3 as build_py
     except ImportError:
         from distutils.command.build_py import build_py
    +else:
    +    # Monkeypatch lib2to3 to make it found our custom fixers
    +    import lib2to3.refactor
    +    from lib2to3.refactor import get_fixers_from_package
    +    def get_fixers_from_package_hacked(pkg_name):
    +        rv = get_fixers_from_package(pkg_name)
    +        return rv + ['fix_b']
    +
    +    lib2to3.refactor.get_fixers_from_package =
get_fixers_from_package_hacked
    +    sys.path.insert(0, 'scripts')

     try:
         import configparser

Is there a more proper way to use a custom fixer?


As b() fixer I've written the following:

    """Fixer to change b('string') into b'string'."""
    # Author: Daniele Varrazzo

    import token
    from lib2to3 import fixer_base
    from lib2to3.pytree import Leaf

    class FixB(fixer_base.BaseFix):

        PATTERN = """
                  power< wrapper='b' trailer< '(' arg=[any] ')' > rest=any* >
                  """

        def transform(self, node, results):
            arg = results['arg']
            wrapper = results["wrapper"]
            if len(arg) == 1 and arg[0].type == token.STRING:
                b = Leaf(token.STRING, 'b' + arg[0].value,
prefix=wrapper.prefix)
                node.children = [ b ] + results['rest']

It has been obtained by reverse-engineering the other fixers: is it
written as is meant to be?

Thanks


-- Daniele


More information about the Python-porting mailing list