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