On 7/6/14, 6:16 AM, Kim Gräsman wrote:
Hi all,

I've done most of the mechanical changes for Python 3 compatiblity in pymake.

But now I've come to the module structure. There are some challenges.

In Python 3, imports first check the standard library and then fall
back to searching the current directory [0]. Pymake's parser module
happens to conflict with the standard library parser module [1]. There
are essentially two solutions to this problem:

1) Rename parser.py -> mkparser.py and pray that we don't conflict again
2) Qualify imports always, e.g. ``import pymake.parser`` or ``from
pymake import parser``

(2) seems superior to me, as it paves the way for packaging. Once
pymake is installed in site-packages, using qualified imports is the
most natural way to reference modules, and development is easier
because we can just set PYTHONPATH to the checkout path, and imports
work transparently as if pymake was installed.

So I started moving toward this model, but immediately got stuck
because qualified imports do not allow circular module dependencies. I
generated a dependency graph for Pymake, and it came out like this:
http://tinypic.com/r/if3c40/8

To focus on the problem I trimmed everything that wasn't involved in a
cycle, so I could see more clearly which modules had circular deps:
http://tinypic.com/r/fa8uix/8

I have some ideas for dependency breaking, but some deps are so deeply
ingrained that I need some hand-holding...

I anticipated this would be a difficult problem to solve.

I would suggest two phases.

First, get the naming sorted out. Ensure all modules are using relative imports (from . import data) or are using fully qualified imports (from pymake import data).

Second, break the import cycles. If modules only have 1 or 2 references to another module that's in a cycle, move the module-level import into a def. As a follow-up, you can move things around to break the cycle. If you really want to be hacky, you can have the "parent" module set attributes on the "child" module for the symbols needed by the child. e.g.

# parent.py

from . import child

def parent_fn():
    pass

child.parent_fn = parent_fn

# child.py

def foo():
    parent_fn()

This breaks "import pymake.child" unless "parent" has been imported. But it breaks the cycle.

Long term, we should refactor to avoid this hackery. But as someone who has attempted that once, it's not going to be fun. I encourage you to try. But don't dismiss a "good enough" hacky solution.
_______________________________________________
dev-builds mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-builds

Reply via email to