Hi guys,

I just finished an import checker. It runs an "import sympy" and checks that all symbols are imported from the module that defines them, not from some other module that just re-exported it inside its __init__.

I had it run and did some spot checking, and the results looked alright to me.

It should probably become part of the unit test suite in the long run; any tips on how to best prepare the code for it appreciated.

Sources are attached; the file as it is goes into $sympy/bin.

Warning: Running the program gives 3955 errors (I think I'll be fixing them for a while).

--
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy.
For more options, visit https://groups.google.com/groups/opt_out.
#!/usr/bin/env python

"""
Checks that running "import sympy" does not trigger a package import from any
SymPy module (module imports are fine).

Importing sympy packages from inside a SymPy package's __init__ is fragile
because the imported package may itself assume that other packages are already
loaded an fully initialized, causing subtle ordering dependencies.
Reporting package imports as errors does not prevent these problems, but it
removes the indirection through the package import and makes them easier to
diagnose.

Usage:

$ bin/test_module_imports
"""

from __future__ import print_function

import __builtin__
builtin_import = __builtin__.__import__

symbol_definers = {} # Maps each function/variable name to name of module to 
define it

def tracking_import(module, globals = globals(), locals = [], fromlist = None, 
level = -1):
    importer_filename = globals['__file__']
    importer_module = globals['__name__']
    result = builtin_import(module, globals, locals, fromlist, level)
    importee_module = result.__name__
    # We're only interested if importer and importee are in SymPy
    if (
        # Importer is a SymPy module
        importer_module != None # Main module does not have a name
        and (importer_module == 'sympy' or importer_module.startswith('sympy.'))
        # Importee is a SymPy module
        and (importee_module == 'sympy' or importee_module.startswith('sympy.'))
        ):
        global symbol_definers
        for symbol in result.__dict__.iterkeys():
            # Note that in nested imports, the innermost one is filled in first.
            # When an __init__ re-exports a function, the initial import will
            # already have been recorded as definer and won't be overwritten.
            if not symbol_definers.has_key(symbol):
                symbol_definers[symbol] = importee_module
        if hasattr(result, 'path'):
            print("Error: %s contains package import %s" % (importer_filename, 
module))
        if fromlist != None:
            symbol_list = fromlist
            if '*' in symbol_list:
                symbol_list = result.__dict__.iterkeys()
            for symbol in symbol_list:
                symbol_definer = symbol_definers[symbol]
                if symbol_definer != importee_module:
                    print("Error: %s imports %s from %s, but should import it 
from its definer %s"
                          % (importer_filename, symbol, importee_module, 
symbol_definer))
    return result

__builtin__.__import__ = tracking_import

import sympy

Reply via email to