From: <th...@us...> - 2017-01-04 15:34:10
|
Revision: 766 http://sourceforge.net/p/py2exe/svn/766 Author: theller Date: 2017-01-04 15:34:08 +0000 (Wed, 04 Jan 2017) Log Message: ----------- Updates from upstream version. Modified Paths: -------------- trunk/py2exe-3/py2exe/__init__.py trunk/py2exe-3/py2exe/boot_ctypes_com_server.py trunk/py2exe-3/py2exe/distutils_buildexe.py trunk/py2exe-3/py2exe/dllfinder.py trunk/py2exe-3/py2exe/hooks.py trunk/py2exe-3/py2exe/mf3.py trunk/py2exe-3/py2exe/mf34.py trunk/py2exe-3/py2exe/py2exe_distutils.py trunk/py2exe-3/py2exe/runtime.py trunk/py2exe-3/setup.py trunk/py2exe-3/source/MyLoadLibrary.c trunk/py2exe-3/source/Python-dynload.h trunk/py2exe-3/source/_memimporter.c trunk/py2exe-3/source/python-dynload.c trunk/py2exe-3/source/run_ctypes_dll.c trunk/py2exe-3/zipextimporter.py Modified: trunk/py2exe-3/py2exe/__init__.py =================================================================== --- trunk/py2exe-3/py2exe/__init__.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/__init__.py 2017-01-04 15:34:08 UTC (rev 766) @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """py2exe package """ -__version__ = "0.9.2.2" +__version__ = "0.9.2.5" from .patch_distutils import patch_distutils Modified: trunk/py2exe-3/py2exe/boot_ctypes_com_server.py =================================================================== --- trunk/py2exe-3/py2exe/boot_ctypes_com_server.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/boot_ctypes_com_server.py 2017-01-04 15:34:08 UTC (rev 766) @@ -66,6 +66,7 @@ # dump each class for cls in get_classes(mod): classmap[cls._reg_clsid_] = cls + #print("build_class_map: ",classmap) import comtypes.server.inprocserver comtypes.server.inprocserver._clsid_to_class = classmap build_class_map() Modified: trunk/py2exe-3/py2exe/distutils_buildexe.py =================================================================== --- trunk/py2exe-3/py2exe/distutils_buildexe.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/distutils_buildexe.py 2017-01-04 15:34:08 UTC (rev 766) @@ -130,9 +130,12 @@ ('custom-boot-script=', None, "Python file that will be run when setting up the runtime environment"), + + ('use-assembly', None, + "use windows assembly to isolate python dll in ctypes-com-server."), ] - boolean_options = ["compressed", "xref", "ascii", "skip-archive"] + boolean_options = ["compressed", "xref", "ascii", "skip-archive","use-assembly"] def initialize_options (self): self.xref =0 @@ -150,6 +153,7 @@ self.skip_archive = 0 self.ascii = 0 self.custom_boot_script = None + self.use_assembly = False def finalize_options (self): self.optimize = int(self.optimize) @@ -258,11 +262,12 @@ data_files = self.distribution.data_files, compress = self.compressed, + use_assembly = self.use_assembly, ) ## level = logging.INFO if options.verbose else logging.WARNING ## logging.basicConfig(level=level) - + #import pdb;pdb.set_trace() builder = runtime.Runtime(options) builder.analyze() builder.build() Modified: trunk/py2exe-3/py2exe/dllfinder.py =================================================================== --- trunk/py2exe-3/py2exe/dllfinder.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/dllfinder.py 2017-01-04 15:34:08 UTC (rev 766) @@ -84,9 +84,18 @@ """Call BindImageEx and collect all dlls that are bound. """ # XXX Should cache results! + import platform + if platform.architecture()[0]=="32bit": + pth = ";".join([p for p in os.environ["PATH"].split(';') if not "intel64_win" in p]) + elif platform.architecture()[0]=="64bit": + pth = ";".join([p for p in os.environ["PATH"].split(';') if not "ia32_win" in p]) + else: + pth = os.environ["PATH"] + + #import pdb;pdb.set_trace() path = ";".join([os.path.dirname(imagename), os.path.dirname(sys.executable), - os.environ["PATH"]]) + pth]) result = set() @_wapi.PIMAGEHLP_STATUS_ROUTINE @@ -278,4 +287,4 @@ scanner = Scanner() scanner.import_package("numpy") - scanner.report_dlls() + print(scanner.all_dlls()) Modified: trunk/py2exe-3/py2exe/hooks.py =================================================================== --- trunk/py2exe-3/py2exe/hooks.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/hooks.py 2017-01-04 15:34:08 UTC (rev 766) @@ -326,6 +326,7 @@ finder.ignore("nose") finder.ignore("scipy") + def hook_nose(finder, module): finder.ignore("IronPython") finder.ignore("cStringIO") @@ -481,3 +482,45 @@ def hook_numpy_core(finder, module): finder.ignore("numpy.core._dotblas") + numpy_core_path = os.path.dirname(module.__loader__.path) + #add mkl dlls from numpy.core, if present + from os import listdir + dlls = [os.path.join(numpy_core_path,mkl) for mkl in listdir(numpy_core_path) if mkl.startswith('mkl_')] + for dll in dlls: + finder.add_dll(dll) + + +def hook_scipy_special(finder, module): + #import pdb;pdb.set_trace() + depth = getattr(finder,"recursion_depth_special",0) + if depth==0: + finder.recursion_depth_special = depth + 1 + finder.import_hook("scipy.special._ufuncs_cxx") + finder.import_hook("scipy.special.orthogonal") + finder.import_hook("scipy", fromlist=("linalg",)) + finder.recursion_depth_special = depth + +def hook_scipy_linalg(finder, module): + depth = getattr(finder,"recursion_depth_linalg",0) + if depth==0: + finder.recursion_depth_linalg = depth + 1 + finder.import_hook("scipy.linalg.cython_blas") + finder.import_hook("scipy.linalg.cython_lapack") + finder.import_hook("scipy.integrate") + finder.recursion_depth_linalg = depth + + +def hook_scipy_sparse_csgraph(finder, module): + depth = getattr(finder,"recursion_depth_sparse",0) + if depth==0: + finder.recursion_depth_sparse = depth + 1 + finder.import_hook("scipy.sparse.csgraph._validation") + finder.recursion_depth_sparse = depth + +def hook_scipy_optimize(finder, module): + #import pdb;pdb.set_trace() + depth = getattr(finder,"recursion_depth_optimize",0) + if depth==0: + finder.recursion_depth_optimize = depth + 1 + finder.import_hook("scipy.optimize.minpack2") + finder.recursion_depth_optimize = depth Modified: trunk/py2exe-3/py2exe/mf3.py =================================================================== --- trunk/py2exe-3/py2exe/mf3.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/mf3.py 2017-01-04 15:34:08 UTC (rev 766) @@ -17,12 +17,12 @@ import warnings # XXX Clean up once str8's cstor matches bytes. -LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')]) -IMPORT_NAME = bytes([dis.opname.index('IMPORT_NAME')]) -STORE_NAME = bytes([dis.opname.index('STORE_NAME')]) -STORE_GLOBAL = bytes([dis.opname.index('STORE_GLOBAL')]) +LOAD_CONST = dis.opname.index('LOAD_CONST') +IMPORT_NAME = dis.opname.index('IMPORT_NAME') +STORE_NAME = dis.opname.index('STORE_NAME') +STORE_GLOBAL = dis.opname.index('STORE_GLOBAL') STORE_OPS = [STORE_NAME, STORE_GLOBAL] -HAVE_ARGUMENT = bytes([dis.HAVE_ARGUMENT]) +HAVE_ARGUMENT = dis.HAVE_ARGUMENT # Monkeypatch some missing methods in Python 3.3's NamespaceLoader def __patch_py33(): @@ -317,11 +317,43 @@ try: loader = importlib.find_loader(name, path) except ValueError as details: + # XXX XXX XXX + # namespace modules only have these attributes (in Python 3.4, when + # a xxx.pth file is present in Lib/site-packages: + # + # __doc__: None + # __loader__: None + # __name__: <the module name> + # __package__: None + # __path__: [<the directory name>] + # __spec__: None + # + # + # When the xxx.pth file is NOT present: + # + # __doc__: None + # __loader__: <_frozen_importlib._NamespaceLoader object at ...> + # __name__: <the module name> + # __package__: <the module name> + # __path__: <_NamespacePath([<the directory name>]> + # __spec__: ModuleSpec(name=<module_name>, origin='namespace', + # submodule_search_locations=_NamespacePath([<dir name>])) + # Python 3.4 raises this error for namespace packages if str(details) == "{}.__loader__ is None".format(name): - msg = "Error: Namespace packages not yet supported: Skipping package {!r}" - print(msg.format(name)) - loader = None + ## msg = "Error: Namespace packages not yet supported: Skipping package {!r}" + from importlib._bootstrap import _NamespaceLoader + ## print(msg.format(name)) + ## loader = None + loader = _NamespaceLoader(name, path, None) + self._load_module(loader, name) + mod = self.modules[name] + real_mod = __import__(name) + print("PATH", path) + print("__path__", dir(real_mod)) + mod.__path__ = real_mod.__path__ + for n in dir(mod): + print(n, getattr(mod, n)) else: raise except AttributeError as details: @@ -406,26 +438,43 @@ Scan the code object, and yield 'interesting' opcode combinations """ - code = co.co_code - names = co.co_names - consts = co.co_consts - LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME - while code: - c = bytes([code[0]]) - if c in STORE_OPS: - oparg, = unpack('<H', code[1:3]) - yield "store", (names[oparg],) - code = code[3:] - continue - if code[:9:3] == LOAD_LOAD_AND_IMPORT: - oparg_1, oparg_2, oparg_3 = unpack('<xHxHxH', code[:9]) - yield "import", (consts[oparg_1], consts[oparg_2], names[oparg_3]) - code = code[9:] - continue - if c >= HAVE_ARGUMENT: - code = code[3:] - else: - code = code[1:] + if hasattr(dis, "get_instructions"): + # dis.get_instructions() is only available in python 3.4 + # and higher + instructions = [] + for inst in dis.get_instructions(co): + instructions.append(inst) + c = inst.opcode + if c == IMPORT_NAME: + assert instructions[-3].opcode == LOAD_CONST + level = instructions[-3].argval + assert instructions[-2].opcode == LOAD_CONST + fromlist = instructions[-2].argval + name = inst.argval + yield "import", (level, fromlist, name) + elif c in STORE_OPS: + yield "store", (inst.argval,) + else: + code = co.co_code + names = co.co_names + consts = co.co_consts + LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME + while code: + c = code[0] + if c in STORE_OPS: + oparg, = unpack('<H', code[1:3]) + yield "store", (names[oparg],) + code = code[3:] + continue + if code[:9:3] == LOAD_LOAD_AND_IMPORT: + oparg_1, oparg_2, oparg_3 = unpack('<xHxHxH', code[:9]) + yield "import", (consts[oparg_1], consts[oparg_2], names[oparg_3]) + code = code[9:] + continue + if c >= HAVE_ARGUMENT: + code = code[3:] + else: + code = code[1:] def ignore(self, name): """If the module or package with the given name is not found, @@ -621,7 +670,11 @@ if self.__optimize__ == sys.flags.optimize: self.__code_object__ = self.__loader__.get_code(self.__name__) else: - source = self.__source__ + try: + source = self.__source__ + except Exception: + import traceback; traceback.print_exc() + raise RuntimeError("loading %r" % self) from None if source is not None: # XXX??? for py3exe: __file__ = self.__file__ \ Modified: trunk/py2exe-3/py2exe/mf34.py =================================================================== --- trunk/py2exe-3/py2exe/mf34.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/mf34.py 2017-01-04 15:34:08 UTC (rev 766) @@ -1,4 +1,4 @@ -#!/usr/bin/python3.3 +#!/usr/bin/python3.4 # -*- coding: utf-8 -*- """ModuleFinder based on importlib """ @@ -14,6 +14,7 @@ import struct import sys import textwrap +import warnings # XXX Clean up once str8's cstor matches bytes. LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')]) @@ -23,31 +24,7 @@ STORE_OPS = [STORE_NAME, STORE_GLOBAL] HAVE_ARGUMENT = bytes([dis.HAVE_ARGUMENT]) -# Monkeypatch some missing methods in Python 3.3's NamespaceLoader -def __patch_py33(): - if sys.version_info < (3, 4): - def is_package(self, fullname): - return True - def get_source(self, fullname): - return '' - - def get_code(self, fullname): - return compile('', '<string>', 'exec', dont_inherit=True) - - def init_module_attrs(self, module): - module.__loader__ = self - module.__package__ = module.__name__ - from importlib._bootstrap import NamespaceLoader - NamespaceLoader.is_package = is_package - NamespaceLoader.get_source = get_source - NamespaceLoader.get_code = get_code - NamespaceLoader.init_module_attrs = init_module_attrs - -__patch_py33() -del __patch_py33 - - class ModuleFinder: def __init__(self, path=None, verbose=0, excludes=None, optimize=0, ignores=None): @@ -79,7 +56,11 @@ """ assert "__SCRIPT__" not in sys.modules ldr = importlib.machinery.SourceFileLoader("__SCRIPT__", path) - mod = Module(ldr, "__SCRIPT__", self._optimize) + if sys.version_info >= (3, 4): + spec = importlib.machinery.ModuleSpec("__SCRIPT__", ldr) + mod = Module(spec, "__SCRIPT__", self._optimize) + else: + mod = Module(ldr, "__SCRIPT__", self._optimize) # Do NOT add it... # self._add_module("__SCRIPT__", mod) self._scan_code(mod.__code__, mod) @@ -95,6 +76,8 @@ raise TypeError("{0} is not a package".format(name)) for finder, modname, ispkg in pkgutil.iter_modules(package.__path__): self.safe_import_hook("%s.%s" % (name, modname)) + if ispkg: + self.import_package("%s.%s" % (name, modname)) def import_hook(self, name, caller=None, fromlist=(), level=0): @@ -298,14 +281,27 @@ msg = ('No module named {!r}; {} is not a package').format(name, parent) self._add_badmodule(name) raise ImportError(msg, name=name) - loader = importlib.find_loader(name, path) - if loader is None: + try: + spec = importlib.util.find_spec(name, path) + except ValueError as details: + # workaround for the .pth file for namespace packages that + # setuptools installs. The pth file inserts a 'damaged' + # module into sys.modules: it has no __spec__. Reloading + # the module helps (at least in Python3.4). + if details.args[0] == '{}.__spec__ is None'.format(name): + import imp + _ = __import__(name, path) + imp.reload(_) + spec = importlib.util.find_spec(name, path) + else: + raise + if spec is None: self._add_badmodule(name) raise ImportError(name) elif name not in self.modules: # The parent import may have already imported this module. try: - self._load_module(loader, name) + self._load_module(spec, name) except ImportError: self._add_badmodule(name) raise @@ -335,8 +331,8 @@ self.modules[name] = mod - def _load_module(self, loader, name): - mod = Module(loader, name, self._optimize) + def _load_module(self, spec, name): + mod = Module(spec, name, self._optimize) self._add_module(name, mod) if name in self._package_paths: mod.__path__.extend(self._package_paths[name]) @@ -481,8 +477,10 @@ print("P", end=" ") else: print("m", end=" ") - print("%-35s" % name, getattr(m, "__file__", - "(built-in, frozen, or namespace)")) + if m.__spec__.has_location and hasattr(m, "__file__"): + print("%-35s" % name, getattr(m, "__file__")) + else: + print("%-35s" % name, "(%s)" % m.__spec__.origin) deps = sorted(self._depgraph[name]) text = "\n".join(textwrap.wrap(", ".join(deps))) print(" imported from:\n%s" % textwrap.indent(text, " ")) @@ -549,14 +547,16 @@ extension modules) """ - def __init__(self, loader, name, optimize): + def __init__(self, spec, name, optimize): self.__optimize__ = optimize self.__globalnames__ = set() self.__name__ = name - self.__loader__ = loader + self.__spec__ = spec self.__code_object__ = None + loader = self.__loader__ = spec.loader + if hasattr(loader, "get_filename"): # python modules fnm = loader.get_filename(name) @@ -569,6 +569,9 @@ self.__file__ = fnm if loader.is_package(name): self.__path__ = [os.path.dirname(fnm)] + elif spec.origin == "namespace": + # namespace modules have no loader + self.__path__ = spec.submodule_search_locations else: # frozen or builtin modules if loader.is_package(name): @@ -585,13 +588,12 @@ @property def __code__(self): - if self.__code_object__ is None: + if self.__code_object__ is None and self.__loader__ is not None: if self.__optimize__ == sys.flags.optimize: self.__code_object__ = self.__loader__.get_code(self.__name__) else: source = self.__source__ if source is not None: - # XXX??? for py3exe: __file__ = self.__file__ \ if hasattr(self, "__file__") else "<string>" try: Modified: trunk/py2exe-3/py2exe/py2exe_distutils.py =================================================================== --- trunk/py2exe-3/py2exe/py2exe_distutils.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/py2exe_distutils.py 2017-01-04 15:34:08 UTC (rev 766) @@ -6,10 +6,12 @@ from distutils.command import build_ext, build from distutils.sysconfig import customize_compiler from distutils.dep_util import newer_group -from distutils.errors import DistutilsError, DistutilsSetupError +from distutils.errors import DistutilsError, DistutilsSetupError, DistutilsPlatformError +from distutils.errors import CCompilerError, CompileError from distutils.util import get_platform +from distutils import log -# We don't need a manifest in the executable, so monkeypath the code away: +# We don't need a manifest in the executable, so monkeypatch the code away: from distutils.msvc9compiler import MSVCCompiler MSVCCompiler.manifest_setup_ldargs = lambda *args: None @@ -40,134 +42,30 @@ description = "build special python interpreter stubs" def finalize_options(self): - build_ext.build_ext.finalize_options(self) + super().finalize_options() self.interpreters = self.distribution.interpreters - def run (self): + def run(self): + # Copied from build_ext.run() except that we use + # self.interpreters instead of self.extensions and + # self.build_interpreters() instead of self.build_extensions() + from distutils.ccompiler import new_compiler + if not self.interpreters: return - self.setup_compiler() - - # Now actually compile and link everything. - for inter in self.interpreters: - sources = inter.sources - if sources is None or type(sources) not in (type([]), type(())): - raise DistutilsSetupError(("in 'interpreters' option ('%s'), " + - "'sources' must be present and must be " + - "a list of source filenames") % inter.name) - sources = list(sources) - - fullname = self.get_exe_fullname(inter.name) - if self.inplace: - # ignore build-lib -- put the compiled extension into - # the source tree along with pure Python modules - modpath = fullname.split('.') - package = '.'.join(modpath[0:-1]) - base = modpath[-1] - - build_py = self.get_finalized_command('build_py') - package_dir = build_py.get_package_dir(package) - exe_filename = os.path.join(package_dir, - self.get_exe_filename(base)) - else: - exe_filename = os.path.join(self.build_lib, - self.get_exe_filename(fullname)) - if inter.target_desc == "executable": - exe_filename += ".exe" - else: - exe_filename += ".dll" - - if not (self.force or \ - newer_group(sources + inter.depends, exe_filename, 'newer')): - self.announce("skipping '%s' interpreter (up-to-date)" % - inter.name) - continue # 'for' loop over all interpreters - else: - self.announce("building '%s' interpreter" % inter.name) - - extra_args = inter.extra_compile_args or [] - - macros = inter.define_macros[:] - for undef in inter.undef_macros: - macros.append((undef,)) - - objects = self.compiler.compile(sources, - output_dir=self.build_temp, - macros=macros, - include_dirs=inter.include_dirs, - debug=self.debug, - extra_postargs=extra_args, - depends=inter.depends) - - if inter.extra_objects: - objects.extend(inter.extra_objects) - extra_args = inter.extra_link_args or [] - - if inter.export_symbols: - # The mingw32 compiler writes a .def file containing - # the export_symbols. Since py2exe uses symbols in - # the extended form 'DllCanUnloadNow,PRIVATE' (to - # avoid MS linker warnings), we have to replace the - # comma(s) with blanks, so that the .def file can be - # properly parsed. - # XXX MingW32CCompiler, or CygwinCCompiler ? - from distutils.cygwinccompiler import Mingw32CCompiler - if isinstance(self.compiler, Mingw32CCompiler): - inter.export_symbols = [s.replace(",", " ") for s in inter.export_symbols] - inter.export_symbols = [s.replace("=", "\t") for s in inter.export_symbols] - - # XXX - is msvccompiler.link broken? From what I can see, the - # following should work, instead of us checking the param: - self.compiler.link(inter.target_desc, - objects, exe_filename, - libraries=self.get_libraries(inter), - library_dirs=inter.library_dirs, - runtime_library_dirs=inter.runtime_library_dirs, - export_symbols=inter.export_symbols, - extra_postargs=extra_args, - debug=self.debug) - # build_extensions () - - def get_exe_fullname (self, inter_name): - if self.package is None: - return inter_name - else: - return self.package + '.' + inter_name - - def get_exe_filename (self, inter_name): - ext_path = inter_name.split('.') - if self.debug: - fnm = os.path.join(*ext_path) + '_d' - else: - fnm = os.path.join(*ext_path) - if ext_path[-1] == "resources": - return fnm - return '%s-py%s.%s-%s' % (fnm, sys.version_info[0], sys.version_info[1], get_platform()) - - def setup_compiler(self): - # This method *should* be available separately in build_ext! - from distutils.ccompiler import new_compiler - - # If we were asked to build any C/C++ libraries, make sure that the - # directory where we put them is in the library search path for - # linking interpreters. - if self.distribution.has_c_libraries(): - build_clib = self.get_finalized_command('build_clib') - self.libraries.extend(build_clib.get_library_names() or []) - self.library_dirs.append(build_clib.build_clib) - # Setup the CCompiler object that we'll use to do all the # compiling and linking self.compiler = new_compiler(compiler=self.compiler, verbose=self.verbose, dry_run=self.dry_run, force=self.force) - try: - self.compiler.initialize() - except AttributeError: - pass # initialize doesn't exist before 2.5 customize_compiler(self.compiler) + # If we are cross-compiling, init the compiler now (if we are not + # cross-compiling, init would not hurt, but people may rely on + # late initialization of compiler even if they shouldn't...) + if os.name == 'nt' and self.plat_name != get_platform(): + self.compiler.initialize(self.plat_name) # And make sure that any compile/link-related options (which might # come from the command-line or from the setup script) are set in @@ -176,8 +74,8 @@ if self.include_dirs is not None: self.compiler.set_include_dirs(self.include_dirs) if self.define is not None: - # 'define' option is a list of (name, value) tuples - for (name,value) in self.define: + # 'define' option is a list of (name,value) tuples + for (name, value) in self.define: self.compiler.define_macro(name, value) if self.undef is not None: for macro in self.undef: @@ -191,10 +89,125 @@ if self.link_objects is not None: self.compiler.set_link_objects(self.link_objects) - # setup_compiler() + # Now actually compile and link everything. + self.build_interpreters() -# class BuildInterpreters + def build_interpreters(self): + for interp in self.interpreters: + self.build_interp(interp) + + def build_interp(self, ext): + sources = ext.sources + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'interpreters' option (extension '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % ext.name) + sources = list(sources) + + ext_path = self.get_ext_fullpath(ext.name) + + if ext.target_desc == "executable": + ext_path += ".exe" + else: + ext_path += ".dll" + + depends = sources + ext.depends + if not (self.force or newer_group(depends, ext_path, 'newer')): + log.debug("skipping '%s' extension (up-to-date)", ext.name) + return + else: + log.info("building '%s' extension", ext.name) + + # First, compile the source code to object files. + + # XXX not honouring 'define_macros' or 'undef_macros' -- the + # CCompiler API needs to change to accommodate this, and I + # want to do one thing at a time! + + # Two possible sources for extra compiler arguments: + # - 'extra_compile_args' in Extension object + # - CFLAGS environment variable (not particularly + # elegant, but people seem to expect it and I + # guess it's useful) + # The environment variable should take precedence, and + # any sensible compiler will give precedence to later + # command line args. Hence we combine them in order: + extra_args = ext.extra_compile_args or [] + + macros = ext.define_macros[:] + for undef in ext.undef_macros: + macros.append((undef,)) + + objects = self.compiler.compile(sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=ext.include_dirs, + debug=self.debug, + extra_postargs=extra_args, + depends=ext.depends) + + # XXX -- this is a Vile HACK! + # + # The setup.py script for Python on Unix needs to be able to + # get this list so it can perform all the clean up needed to + # avoid keeping object files around when cleaning out a failed + # build of an extension module. Since Distutils does not + # track dependencies, we have to get rid of intermediates to + # ensure all the intermediates will be properly re-built. + # + self._built_objects = objects[:] + + # Now link the object files together into a "shared object" -- + # of course, first we have to figure out all the other things + # that go into the mix. + if ext.extra_objects: + objects.extend(ext.extra_objects) + extra_args = ext.extra_link_args or [] + + # Detect target language, if not provided +## language = ext.language or self.compiler.detect_language(sources) + + ## self.compiler.link_shared_object( + ## objects, ext_path, + ## libraries=self.get_libraries(ext), + ## library_dirs=ext.library_dirs, + ## runtime_library_dirs=ext.runtime_library_dirs, + ## extra_postargs=extra_args, + ## export_symbols=self.get_export_symbols(ext), + ## debug=self.debug, + ## build_temp=self.build_temp, + ## target_lang=language) + + # Hm, for Python 3.5 to link a shared library (instead of exe + # or pyd) we need to add /DLL to the linker arguments. + # Currently this is done in the setup script; should we do it + # here? + + self.compiler.link(ext.target_desc, + objects, ext_path, + libraries=self.get_libraries(ext), + library_dirs=ext.library_dirs, + runtime_library_dirs=ext.runtime_library_dirs, + export_symbols=ext.export_symbols, + extra_postargs=extra_args, + debug=self.debug) + + + # -- Name generators ----------------------------------------------- + + def get_ext_filename (self, inter_name): + ext_path = inter_name.split('.') + if self.debug: + fnm = os.path.join(*ext_path) + '_d' + else: + fnm = os.path.join(*ext_path) + if ext_path[-1] == "resources": + return fnm + return '%s-py%s.%s-%s' % (fnm, sys.version_info[0], sys.version_info[1], get_platform()) + + def InstallSubCommands(): """Adds our own sub-commands to build and install""" has_interpreters = lambda self: self.distribution.has_interpreters() Modified: trunk/py2exe-3/py2exe/runtime.py =================================================================== --- trunk/py2exe-3/py2exe/runtime.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/py2exe/runtime.py 2017-01-04 15:34:08 UTC (rev 766) @@ -423,7 +423,7 @@ arc.writestr(path, stream.getvalue()) elif hasattr(mod, "__file__"): - assert mod.__file__.endswith(EXTENSION_SUFFIXES[0]) + assert mod.__file__.endswith(tuple(EXTENSION_SUFFIXES)) if self.options.bundle_files <= 2: # put .pyds into the archive arcfnm = mod.__name__.replace(".", "\\") + EXTENSION_SUFFIXES[0] @@ -495,7 +495,7 @@ # nothing to do for python modules. continue if hasattr(mod, "__file__"): - assert mod.__file__.endswith(EXTENSION_SUFFIXES[0]) + assert mod.__file__.endswith(tuple(EXTENSION_SUFFIXES)) pydfile = mod.__name__ + EXTENSION_SUFFIXES[0] dst = os.path.join(libdir, pydfile) Modified: trunk/py2exe-3/setup.py =================================================================== --- trunk/py2exe-3/setup.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/setup.py 2017-01-04 15:34:08 UTC (rev 766) @@ -40,11 +40,12 @@ extra_link_args = [] if 0: - # enable this to debug a release build + # XXX enable this to debug a release build, otherwise let disabled + # because the .PDB files are huge. extra_compile_args.append("/Od") extra_compile_args.append("/Z7") extra_link_args.append("/DEBUG") - macros.append(("VERBOSE", "1")) + #macros.append(("VERBOSE", "1")) run_ctypes_dll = Interpreter("py2exe.run_ctypes_dll", ["source/run_ctypes_dll.c", @@ -67,7 +68,7 @@ target_desc = "shared_library", define_macros=macros, extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args, + extra_link_args=extra_link_args + ["/DLL"], ) run = Interpreter("py2exe.run", @@ -119,7 +120,7 @@ ["source/dll.c", "source/icon.rc"], target_desc = "shared_library", - extra_link_args=["/NOENTRY"], + extra_link_args=["/DLL", "/NOENTRY"], ) interpreters = [run, run_w, resource_dll, @@ -132,12 +133,12 @@ else: class my_bdist_wheel(bdist_wheel.bdist_wheel): """We change the bdist_wheel command so that it creates a - wheel-file compatible with Python 3.3 and Python 3.4 only by - setting the impl_tag to py33.py34. + wheel-file compatible with CPython, 3.4, 3.5, and 3.6 only + by setting the impl_tag to 'cp33.cp34.cp35.cp36' """ def get_tag(self): impl_tag, abi_tag, plat_tag = super().get_tag() - return "py33.py34", abi_tag, plat_tag + return "cp33.cp34.cp35.cp36", abi_tag, plat_tag if __name__ == "__main__": Modified: trunk/py2exe-3/source/MyLoadLibrary.c =================================================================== --- trunk/py2exe-3/source/MyLoadLibrary.c 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/source/MyLoadLibrary.c 2017-01-04 15:34:08 UTC (rev 766) @@ -198,7 +198,8 @@ if (lib) return lib->module; SetLastError(0); - return GetModuleHandle(name); + return NULL; + //return GetModuleHandle(name); } HMODULE MyLoadLibrary(LPCSTR name, void *bytes, void *userdata) Modified: trunk/py2exe-3/source/Python-dynload.h =================================================================== --- trunk/py2exe-3/source/Python-dynload.h 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/source/Python-dynload.h 2017-01-04 15:34:08 UTC (rev 766) @@ -1,9 +1,11 @@ #define Py_OptimizeFlag *(_Py_OptimizeFlag_PTR()) #define Py_NoSiteFlag *(_Py_NoSiteFlag_PTR()) #define Py_VerboseFlag *(_Py_VerboseFlag_PTR()) +#define _Py_PackageContext *(__Py_PackageContext_PTR()) extern int *_Py_OptimizeFlag_PTR(); extern int *_Py_NoSiteFlag_PTR(); extern int *_Py_VerboseFlag_PTR(); +extern char **__Py_PackageContext_PTR(); extern int PythonLoaded(HMODULE hmod); Modified: trunk/py2exe-3/source/_memimporter.c =================================================================== --- trunk/py2exe-3/source/_memimporter.c 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/source/_memimporter.c 2017-01-04 15:34:08 UTC (rev 766) @@ -52,7 +52,7 @@ PyObject* (*p)(void); PyObject *m = NULL; struct PyModuleDef *def; -// char *oldcontext; + char *oldcontext; PyObject *name = PyUnicode_FromString(modname); if (name == NULL) @@ -75,16 +75,16 @@ Py_DECREF(name); return -1; } -/* + oldcontext = _Py_PackageContext; _Py_PackageContext = modname; -*/ + p = (PyObject*(*)(void))init_func; m = (*p)(); -/* + _Py_PackageContext = oldcontext; -*/ + if (PyErr_Occurred()) { Py_DECREF(name); return -1; Modified: trunk/py2exe-3/source/python-dynload.c =================================================================== --- trunk/py2exe-3/source/python-dynload.c 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/source/python-dynload.c 2017-01-04 15:34:08 UTC (rev 766) @@ -55,6 +55,11 @@ DATA(int *, Py_VerboseFlag); } +char **__Py_PackageContext_PTR() +{ + DATA(char **, _Py_PackageContext); +} + //////////////////////////////////////////////////////////////// int Py_IsInitialized(void) Modified: trunk/py2exe-3/source/run_ctypes_dll.c =================================================================== --- trunk/py2exe-3/source/run_ctypes_dll.c 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/source/run_ctypes_dll.c 2017-01-04 15:34:08 UTC (rev 766) @@ -81,6 +81,7 @@ extern int init_with_instance(HMODULE, char *); extern void fini(); extern int run_script(void); +extern wchar_t libfilename[_MAX_PATH + _MAX_FNAME + _MAX_EXT]; #include "MyLoadLibrary.h" @@ -90,7 +91,9 @@ int load_ctypes(void) { char dll_path[_MAX_PATH+_MAX_FNAME+1]; - + wchar_t ctypes_path[_MAX_PATH+_MAX_FNAME+1]; + wchar_t * temp=NULL; + int length=0; // shouldn't do this twice assert(g_ctypes == NULL); @@ -104,7 +107,14 @@ if (g_ctypes == NULL) { // not already loaded - try and load from the current dir // char *temp; - GetModuleFileNameA(gInstance, dll_path, sizeof(dll_path)); + //wrong, this is myself, makes an endless loop... + //GetModuleFileNameA(gInstance, dll_path, sizeof(dll_path)); + temp=wcsrchr(libfilename,L'\\'); + length=temp-(wchar_t*)libfilename+1; + wcscpy(ctypes_path,libfilename); + ctypes_path[length]=L'\0'; + wcscat(ctypes_path,L"_ctypes.pyd"); + /* ??? temp = dll_path + strlen(dll_path); while (temp>dll_path && *temp != '\\') @@ -113,13 +123,14 @@ // temp points to '\\filename.ext'! */ /* ??? + #ifdef _DEBUG g_ctypes = MyGetModuleHandle("_ctypes_d.pyd"); #else g_ctypes = MyGetModuleHandle("_ctypes.pyd"); #endif */ - g_ctypes = LoadLibraryEx(dll_path, // points to name of executable module + g_ctypes = LoadLibraryExW(ctypes_path, // points to name of executable module NULL, // HANDLE hFile, // reserved, must be NULL LOAD_WITH_ALTERED_SEARCH_PATH // DWORD dwFlags // entry-point execution flag ); @@ -202,7 +213,8 @@ // ***************************************************************** BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { - if ( dwReason == DLL_PROCESS_ATTACH) { + OutputDebugString("DllMain"); + if ( dwReason == DLL_PROCESS_ATTACH) { gInstance = hInstance; InitializeCriticalSection(&csInit); _MyLoadActCtxPointers(); @@ -224,7 +236,10 @@ HRESULT __stdcall DllCanUnloadNow(void) { HRESULT rc; + ULONG_PTR cookie = 0; + cookie = _My_ActivateActCtx(); // some windows manifest magic... check_init(); + _My_DeactivateActCtx(cookie); assert(Pyc_DllCanUnloadNow); if (!Pyc_DllCanUnloadNow) return E_UNEXPECTED; rc = Pyc_DllCanUnloadNow(); @@ -235,10 +250,22 @@ HRESULT __stdcall DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { HRESULT rc; + ULONG_PTR cookie = 0; + /* + OutputDebugString("DllGetClassObject"); + + MessageBox(NULL,"Debug\n", + "DllGetClassObject", + MB_OK | MB_ICONINFORMATION); + */ + cookie = _My_ActivateActCtx(); // some windows manifest magic... check_init(); + assert(Pyc_DllGetClassObject); if (!Pyc_DllGetClassObject) return E_UNEXPECTED; rc = Pyc_DllGetClassObject(rclsid, riid, ppv); + _My_DeactivateActCtx(cookie); + return rc; } @@ -247,8 +274,28 @@ { int rc=0; PyGILState_STATE state; + wchar_t buf[300]; + ULONG_PTR cookie = 0; + + OutputDebugString("DllRegisterServer"); + /* + MessageBox(NULL, + "Debug\n", + "DllregisterServer", + MB_OK | MB_ICONINFORMATION); + */ + cookie = _My_ActivateActCtx(); // some windows manifest magic... check_init(); + _My_DeactivateActCtx(cookie); + + OutputDebugString("check_init ok"); + state = PyGILState_Ensure(); + OutputDebugString("PyGILState_Ensure done"); + + swprintf(buf,300,L"DllRegisterServer: libfilename=%s\n",&libfilename); + OutputDebugStringW(buf); + rc = PyRun_SimpleString("DllRegisterServer()\n"); if (rc != 0) PyErr_Print(); @@ -260,7 +307,11 @@ { int rc=0; PyGILState_STATE state; + ULONG_PTR cookie = 0; + cookie = _My_ActivateActCtx(); // some windows manifest magic... check_init(); + _My_DeactivateActCtx(cookie); + state = PyGILState_Ensure(); rc = PyRun_SimpleString("DllUnregisterServer()\n"); if (rc != 0) Modified: trunk/py2exe-3/zipextimporter.py =================================================================== --- trunk/py2exe-3/zipextimporter.py 2014-10-21 15:22:50 UTC (rev 765) +++ trunk/py2exe-3/zipextimporter.py 2017-01-04 15:34:08 UTC (rev 766) @@ -75,6 +75,7 @@ def load_module(self, fullname): verbose = _memimporter.get_verbose_flag() + if fullname in sys.modules: mod = sys.modules[fullname] if verbose: @@ -84,37 +85,39 @@ return mod try: return zipimport.zipimporter.load_module(self, fullname) - except ImportError: - pass - if sys.version_info >= (3, 0): - # name of initfunction - initname = "PyInit_" + fullname.split(".")[-1] - else: - # name of initfunction - initname = "init" + fullname.split(".")[-1] - filename = fullname.replace(".", "\\") - if filename in ("pywintypes", "pythoncom"): - filename = filename + "%d%d" % sys.version_info[:2] - suffixes = ('.dll',) - else: - suffixes = self._suffixes - for s in suffixes: - path = filename + s - if path in self._files: - if verbose > 1: - sys.stderr.write("# found %s in zipfile %s\n" - % (path, self.archive)) - mod = _memimporter.import_module(fullname, path, - initname, - self.get_data) - mod.__file__ = "%s\\%s" % (self.archive, path) - mod.__loader__ = self - if verbose: - sys.stderr.write("import %s # loaded from zipfile %s\n" - % (fullname, mod.__file__)) - return mod - raise zipimport.ZipImportError("can't find module %s" % fullname) + except ImportError as err: + if verbose: + sys.stderr.write("error loading %s: %s\n"% (fullname, err)) + if sys.version_info >= (3, 0): + # name of initfunction + initname = "PyInit_" + fullname.split(".")[-1] + else: + # name of initfunction + initname = "init" + fullname.split(".")[-1] + filename = fullname.replace(".", "\\") + if filename in ("pywintypes", "pythoncom"): + filename = filename + "%d%d" % sys.version_info[:2] + suffixes = ('.dll',) + else: + suffixes = self._suffixes + for s in suffixes: + path = filename + s + if path in self._files: + if verbose > 1: + sys.stderr.write("# found %s in zipfile %s\n" + % (path, self.archive)) + mod = _memimporter.import_module(fullname, path, + initname, + self.get_data) + mod.__file__ = "%s\\%s" % (self.archive, path) + mod.__loader__ = self + if verbose: + sys.stderr.write("import %s # loaded from zipfile %s\n" + % (fullname, mod.__file__)) + return mod + raise zipimport.ZipImportError("can't find module %s" % fullname) from err + def __repr__(self): return "<%s object %r>" % (self.__class__.__name__, self.archive) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |