From: <th...@us...> - 2014-10-17 12:52:53
|
Revision: 764 http://sourceforge.net/p/py2exe/svn/764 Author: theller Date: 2014-10-17 12:52:49 +0000 (Fri, 17 Oct 2014) Log Message: ----------- py2exe/hooks.py: Add hook for the six compatibility library. py2exe does now understand the renaming of modules/packages the six.py does. Modified Paths: -------------- trunk/py2exe-3/ChangeLog trunk/py2exe-3/py2exe/hooks.py trunk/py2exe-3/py2exe/mf3.py trunk/py2exe-3/py2exe/runtime.py Modified: trunk/py2exe-3/ChangeLog =================================================================== --- trunk/py2exe-3/ChangeLog 2014-10-17 09:30:39 UTC (rev 763) +++ trunk/py2exe-3/ChangeLog 2014-10-17 12:52:49 UTC (rev 764) @@ -1,5 +1,11 @@ 2014-10-17 <th...@ct...> + * py2exe/hooks.py: Add hook for the six compatibility + library. py2exe does now understand the renaming of + modules/packages the six.py does. + +2014-10-17 <th...@ct...> + * py2exe/hooks.py: Add hooks for pycparser, OpenSSL, cffi. cffi needs some hacks so that it works from within zipfiles. Modified: trunk/py2exe-3/py2exe/hooks.py =================================================================== --- trunk/py2exe-3/py2exe/hooks.py 2014-10-17 09:30:39 UTC (rev 763) +++ trunk/py2exe-3/py2exe/hooks.py 2014-10-17 12:52:49 UTC (rev 764) @@ -262,11 +262,46 @@ finder.set_min_bundle("tkinter", 2) def hook_six(finder, module): - """six.py is a python2/python3 compatibility library. Exclude the - python2 modules. + """six.py has an object 'moves'. This allows to import + modules/packages via attribute access under new names. + + We install a fake module named 'six.moves' which simulates this + behaviour. """ - finder.ignore("StringIO") + class SixImporter(type(module)): + """Simulate six.moves. + + Import renamed modules when retrived as attributes. + """ + + __code__ = None + + def __init__(self, mf, *args, **kw): + import six + self.__moved_modules = {item.name: item.mod + for item in six._moved_attributes + if isinstance(item, six.MovedModule)} + super().__init__(*args, **kw) + self.__finder = mf + + def __getattr__(self, name): + if name in self.__moved_modules: + renamed = self.__moved_modules[name] + self.__finder.safe_import_hook(renamed, caller=self) + mod = self.__finder.modules[renamed] + # add the module again with the renamed name: + self.__finder._add_module("six.moves." + name, mod) + return mod + else: + raise AttributeError(name) + + m = SixImporter(finder, + None, "six.moves", finder._optimize) + finder._add_module("six.moves", m) + + + def hook_matplotlib(finder, module): """matplotlib requires data files in a 'mpl-data' subdirectory in the same directory as the executable. Modified: trunk/py2exe-3/py2exe/mf3.py =================================================================== --- trunk/py2exe-3/py2exe/mf3.py 2014-10-17 09:30:39 UTC (rev 763) +++ trunk/py2exe-3/py2exe/mf3.py 2014-10-17 12:52:49 UTC (rev 764) @@ -291,13 +291,26 @@ return self.modules[name] # Backwards-compatibility; be nicer to skip the dict lookup. parent_module = self.modules[parent] + try: + # try lazy imports via attribute access (six.moves + # does this)... + getattr(parent_module, name.rpartition('.')[2]) + module = self.modules[name] + except (AttributeError, KeyError): + pass + else: + if hasattr(module, "__code__"): + self._scan_code(module.__code__, module) + return module + + try: path = parent_module.__path__ except AttributeError: - # this fixes 'import os.path'. Does it create other problems? - child = name.rpartition('.')[2] - if child in parent_module.__globalnames__: - return parent_module + ## # this fixes 'import os.path'. Does it create other problems? + ## child = name.rpartition('.')[2] + ## if child in parent_module.__globalnames__: + ## return parent_module msg = ('No module named {!r}; {} is not a package').format(name, parent) self._add_badmodule(name) raise ImportError(msg, name=name) @@ -588,7 +601,7 @@ self.__file__ = fnm if loader.is_package(name): self.__path__ = [os.path.dirname(fnm)] - else: + elif hasattr(loader, "is_package"): # frozen or builtin modules if loader.is_package(name): self.__path__ = [name] @@ -697,6 +710,11 @@ --summary Print a single line listing how many modules were found and how many modules are missing + + -m + --missing + Print detailed report about missing modules + """ text = textwrap.dedent(helptext.format(os.path.basename(script))) @@ -706,7 +724,7 @@ import getopt try: opts, args = getopt.gnu_getopt(sys.argv[1:], - "x:f:hi:Op:rsv", + "x:f:hi:Op:rsvm", ["exclude=", "from=", "help", @@ -716,6 +734,7 @@ "report", "summary", "verbose", + "missing", ]) except getopt.GetoptError as err: print("Error: %s." % err) @@ -729,6 +748,7 @@ optimize = 0 summary = 0 packages = [] + missing = 0 for o, a in opts: if o in ("-h", "--help"): usage(sys.argv[0]) @@ -749,6 +769,8 @@ summary = 1 elif o in ("-p", "--package"): packages.append(a) + elif o in ("-m", "--missing"): + missing = 1 mf = ModuleFinder( excludes=excludes, @@ -767,6 +789,8 @@ mf.run_script(path) if report: mf.report() + if missing: + mf.report_missing() if summary: mf.report_summary() for modname in show_from: Modified: trunk/py2exe-3/py2exe/runtime.py =================================================================== --- trunk/py2exe-3/py2exe/runtime.py 2014-10-17 09:30:39 UTC (rev 763) +++ trunk/py2exe-3/py2exe/runtime.py 2014-10-17 12:52:49 UTC (rev 764) @@ -407,7 +407,9 @@ arc = zipfile.ZipFile(libpath, "a", compression=compression) - for mod in self.mf.modules.values(): + # The same modules may be in self.ms.modules under different + # keys; we only need one of them in the archive. + for mod in set(self.mf.modules.values()): if mod.__code__: if hasattr(mod, "__path__"): path = mod.__name__.replace(".", "\\") + "\\__init__" + bytecode_suffix This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |