-
Notifications
You must be signed in to change notification settings - Fork 0
/
hooks.py
483 lines (435 loc) · 16.9 KB
/
hooks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# -*- coding: utf-8 -*-
#
# Hooks module for py2exe.
# Inspired by cx_freeze's hooks.py, which is:
#
# Copyright © 2007-2013, Anthony Tuininga.
# Copyright © 2001-2006, Computronix (Canada) Ltd., Edmonton, Alberta, Canada.
# All rights reserved.
#
import os, sys
# Exclude modules that the standard library imports (conditionally),
# but which are not present on windows.
#
# _memimporter can be excluded because it is built into the run-stub.
windows_excludes = """
_curses
_dummy_threading
_emx_link
_gestalt
_posixsubprocess
ce
clr
console
fcntl
grp
java
org
os2
posix
pwd
site
termios
vms_lib
_memimporter
""".split()
def init_finder(finder):
# what about renamed functions, like urllib.pathname2url?
#
# We should use ignore() for Python 2 names so that my py2to3
# importhook works. For modules that are not present on Windows,
# we should probably use excludes.append()
finder.excludes.extend(windows_excludes)
# python2 modules are ignored (but not excluded)
finder.ignore("BaseHTTPServer")
finder.ignore("ConfigParser")
finder.ignore("IronPython")
finder.ignore("SimpleHTTPServer")
finder.ignore("StringIO")
finder.ignore("__builtin__")
finder.ignore("_winreg")
finder.ignore("cPickle")
finder.ignore("cStringIO")
finder.ignore("commands")
finder.ignore("compiler")
finder.ignore("copy_reg")
finder.ignore("dummy_thread")
finder.ignore("future_builtins")
finder.ignore("htmlentitydefs")
finder.ignore("httplib")
finder.ignore("md5")
finder.ignore("new")
finder.ignore("thread")
finder.ignore("unittest2")
finder.ignore("urllib2")
finder.ignore("urlparse")
def hook_pycparser(finder, module):
"""pycparser needs lextab.py and yacctab.py which are not picked
up automatically. Make sure the complete package is included;
otherwise the exe-files may create yacctab.py and lextab.py when
they are run.
"""
finder.import_package_later("pycparser")
def hook_pycparser__build_tables(finder, module):
finder.ignore("lextab")
finder.ignore("yacctab")
finder.ignore("_ast_gen")
finder.ignore("c_ast")
def hook_pycparser_ply(finder, module):
finder.ignore("lex")
finder.ignore("ply")
def hook_OpenSSL(finder, module):
"""OpenSSL needs the cryptography package."""
finder.import_package_later("cryptography")
def hook_cffi_cparser(finder, module):
finder.ignore("cffi._pycparser")
def hook_cffi(finder, module):
# We need to patch two methods in the
# cffi.vengine_cpy.VCPythonEngine class so that cffi libraries
# work from within zip-files.
finder.add_bootcode("""
def patch_cffi():
def find_module(self, module_name, path, so_suffixes):
import sys
name = "%s.%s" % (self.verifier.ext_package, module_name)
try:
__import__(name)
except ImportError:
return None
self.__module = mod = sys.modules[name]
return mod.__file__
def load_library(self):
from cffi import ffiplatform
import sys
# XXX review all usages of 'self' here!
# import it as a new extension module
module = self.__module
#
# call loading_cpy_struct() to get the struct layout inferred by
# the C compiler
self._load(module, 'loading')
#
# the C code will need the <ctype> objects. Collect them in
# order in a list.
revmapping = dict([(value, key)
for (key, value) in self._typesdict.items()])
lst = [revmapping[i] for i in range(len(revmapping))]
lst = list(map(self.ffi._get_cached_btype, lst))
#
# build the FFILibrary class and instance and call _cffi_setup().
# this will set up some fields like '_cffi_types', and only then
# it will invoke the chained list of functions that will really
# build (notably) the constant objects, as <cdata> if they are
# pointers, and store them as attributes on the 'library' object.
class FFILibrary(object):
_cffi_python_module = module
_cffi_ffi = self.ffi
_cffi_dir = []
def __dir__(self):
return FFILibrary._cffi_dir + list(self.__dict__)
library = FFILibrary()
if module._cffi_setup(lst, ffiplatform.VerificationError, library):
import warnings
warnings.warn("reimporting %r might overwrite older definitions"
% (self.verifier.get_module_name()))
#
# finally, call the loaded_cpy_xxx() functions. This will perform
# the final adjustments, like copying the Python->C wrapper
# functions from the module to the 'library' object, and setting
# up the FFILibrary class with properties for the global C variables.
self._load(module, 'loaded', library=library)
module._cffi_original_ffi = self.ffi
module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions
return library
from cffi.vengine_cpy import VCPythonEngine
VCPythonEngine.find_module = find_module
VCPythonEngine.load_library = load_library
patch_cffi()
del patch_cffi
""")
def hook_multiprocessing(finder, module):
module.__globalnames__.add("AuthenticationError")
module.__globalnames__.add("BufferTooShort")
module.__globalnames__.add("Manager")
module.__globalnames__.add("TimeoutError")
module.__globalnames__.add("cpu_count")
module.__globalnames__.add("current_process")
module.__globalnames__.add("get_context")
module.__globalnames__.add("get_start_method")
module.__globalnames__.add("set_start_method")
module.__globalnames__.add("JoinableQueue")
module.__globalnames__.add("Lock")
module.__globalnames__.add("Process")
module.__globalnames__.add("Queue")
module.__globalnames__.add("freeze_support")
def import_psutil(finder, module):
"""Exclude stuff for other operating systems."""
finder.excludes.append("_psutil_bsd")
finder.excludes.append("_psutil_linux")
finder.excludes.append("_psutil_osx")
finder.excludes.append("_psutil_posix")
finder.excludes.append("_psutil_sunos")
def hook_PIL(finder, module):
# c:\Python33-64\lib\site-packages\PIL
"""Pillow loads plugins"""
# Exclude python 2 imports
finder.excludes.append("Tkinter")
finder.import_package_later("PIL")
def hook__socket(finder, module):
"""
_socket.pyd uses the 'idna' encoding; and that requires
'unicodedata.pyd'.
"""
finder.import_hook("encodings.idna")
finder.import_hook("unicodedata")
def hook_pyreadline(finder, module):
"""
"""
finder.ignore("IronPythonConsole")
finder.excludes.append("StringIO") # in pyreadline.py3k_compat
finder.ignore("System")
finder.excludes.append("sets")
finder.ignore("startup")
def hook_xml_etree_ElementTree(finder, module):
"""ElementC14N is an optional extension. Ignore if it is not
found.
"""
finder.ignore("ElementC14N")
def hook_urllib_request(finder, module):
"""urllib.request imports _scproxy on darwin
"""
finder.excludes.append("_scproxy")
def hook_pythoncom(finder, module):
"""pythoncom is a Python extension module with .dll extension,
usually in the windows system directory as pythoncom3X.dll.
"""
import pythoncom
finder.add_dll(pythoncom.__file__)
def hook_pywintypes(finder, module):
"""pywintypes is a Python extension module with .dll extension,
usually in the windows system directory as pywintypes3X.dll.
"""
import pywintypes
finder.add_dll(pywintypes.__file__)
def hook_win32com(finder, module):
"""The win32com package extends it's __path__ at runtime.
"""
finder.import_hook("pywintypes")
finder.import_hook("pythoncom")
import win32com
module.__path__ = win32com.__path__
def hook_win32api(finder, module):
"""win32api.FindFiles(...) needs this."""
finder.import_hook("pywintypes")
finder.import_hook("win32timezone")
def hook_tkinter(finder, module):
"""Recusively copy tcl and tk directories.
"""
# It probably doesn't make sense to exclude tix from the tcl distribution,
# and only copy it when tkinter.tix is imported...
import tkinter._fix as fix
tcl_dir = os.path.normpath(os.path.join(fix.tcldir, ".."))
assert os.path.isdir(tcl_dir)
finder.add_datadirectory("tcl", tcl_dir, recursive=True)
finder.set_min_bundle("tkinter", 2)
def hook_six(finder, module):
"""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.
"""
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.
"""
# c:\Python33\lib\site-packages\matplotlib
mpl_data_path = os.path.join(os.path.dirname(module.__loader__.path),
"mpl-data")
finder.add_datadirectory("mpl-data", mpl_data_path, recursive=True)
finder.excludes.append("wx")
# XXX matplotlib requires tkinter which modulefinder does not
# detect because of the six bug.
def hook_numpy(finder, module):
"""numpy for Python 3 still tries to import some Python 2 modules;
exclude them."""
# I'm not sure if we can safely exclude these:
finder.ignore("Numeric")
finder.ignore("numarray")
finder.ignore("numpy_distutils")
finder.ignore("setuptools")
finder.ignore("Pyrex")
finder.ignore("nose")
finder.ignore("scipy")
def hook_nose(finder, module):
finder.ignore("IronPython")
finder.ignore("cStringIO")
finder.ignore("unittest2")
def hook_sysconfig(finder, module):
finder.ignore("_sysconfigdata")
def hook_numpy_random_mtrand(finder, module):
"""the numpy.random.mtrand module is an extension module and the
numpy.random module imports * from this module; define the list of
global names available to this module in order to avoid spurious
errors about missing modules.
"""
module.__globalnames__.add('RandomState')
module.__globalnames__.add('beta')
module.__globalnames__.add('binomial')
module.__globalnames__.add('bytes')
module.__globalnames__.add('chisquare')
module.__globalnames__.add('choice')
module.__globalnames__.add('dirichlet')
module.__globalnames__.add('exponential')
module.__globalnames__.add('f')
module.__globalnames__.add('gamma')
module.__globalnames__.add('geometric')
module.__globalnames__.add('get_state')
module.__globalnames__.add('gumbel')
module.__globalnames__.add('hypergeometric')
module.__globalnames__.add('laplace')
module.__globalnames__.add('logistic')
module.__globalnames__.add('lognormal')
module.__globalnames__.add('logseries')
module.__globalnames__.add('multinomial')
module.__globalnames__.add('multivariate_normal')
module.__globalnames__.add('negative_binomial')
module.__globalnames__.add('noncentral_chisquare')
module.__globalnames__.add('noncentral_f')
module.__globalnames__.add('normal')
module.__globalnames__.add('np')
module.__globalnames__.add('operator')
module.__globalnames__.add('pareto')
module.__globalnames__.add('permutation')
module.__globalnames__.add('poisson')
module.__globalnames__.add('power')
module.__globalnames__.add('rand')
module.__globalnames__.add('randint')
module.__globalnames__.add('randn')
module.__globalnames__.add('random_integers')
module.__globalnames__.add('random_sample')
module.__globalnames__.add('rayleigh')
module.__globalnames__.add('seed')
module.__globalnames__.add('set_state')
module.__globalnames__.add('shuffle')
module.__globalnames__.add('standard_cauchy')
module.__globalnames__.add('standard_exponential')
module.__globalnames__.add('standard_gamma')
module.__globalnames__.add('standard_normal')
module.__globalnames__.add('standard_t')
module.__globalnames__.add('triangular')
module.__globalnames__.add('uniform')
module.__globalnames__.add('vonmises')
module.__globalnames__.add('wald')
module.__globalnames__.add('weibull')
module.__globalnames__.add('zipf')
def hook_numpy_distutils(finder, module):
"""In a 'if sys.version_info[0] < 3:' block numpy.distutils does
an implicit relative import: 'import __config__'. This will not
work in Python3 so ignore it.
"""
finder.excludes.append("__config__")
def hook_numpy_f2py(finder, module):
""" numpy.f2py tries to import __svn_version__. Ignore when his fails.
"""
finder.excludes.append("__svn_version__")
def hook_numpy_core_umath(finder, module):
"""the numpy.core.umath module is an extension module and the numpy module
imports * from this module; define the list of global names available
to this module in order to avoid spurious errors about missing
modules"""
module.__globalnames__.add("add")
module.__globalnames__.add("absolute")
module.__globalnames__.add("arccos")
module.__globalnames__.add("arccosh")
module.__globalnames__.add("arcsin")
module.__globalnames__.add("arcsinh")
module.__globalnames__.add("arctan")
module.__globalnames__.add("arctanh")
module.__globalnames__.add("bitwise_and")
module.__globalnames__.add("bitwise_or")
module.__globalnames__.add("bitwise_xor")
module.__globalnames__.add("ceil")
module.__globalnames__.add("conjugate")
module.__globalnames__.add("cosh")
module.__globalnames__.add("divide")
module.__globalnames__.add("exp")
module.__globalnames__.add("e")
module.__globalnames__.add("fabs")
module.__globalnames__.add("floor")
module.__globalnames__.add("floor_divide")
module.__globalnames__.add("fmod")
module.__globalnames__.add("geterrobj")
module.__globalnames__.add("greater")
module.__globalnames__.add("hypot")
module.__globalnames__.add("invert")
module.__globalnames__.add("isfinite")
module.__globalnames__.add("isinf")
module.__globalnames__.add("isnan")
module.__globalnames__.add("less")
module.__globalnames__.add("left_shift")
module.__globalnames__.add("log")
module.__globalnames__.add("logical_and")
module.__globalnames__.add("logical_not")
module.__globalnames__.add("logical_or")
module.__globalnames__.add("logical_xor")
module.__globalnames__.add("maximum")
module.__globalnames__.add("minimum")
module.__globalnames__.add("multiply")
module.__globalnames__.add("negative")
module.__globalnames__.add("not_equal")
module.__globalnames__.add("power")
module.__globalnames__.add("remainder")
module.__globalnames__.add("right_shift")
module.__globalnames__.add("sign")
module.__globalnames__.add("signbit")
module.__globalnames__.add("sinh")
module.__globalnames__.add("sqrt")
module.__globalnames__.add("tan")
module.__globalnames__.add("tanh")
module.__globalnames__.add("true_divide")
def hook_numpy_core_numerictypes(finder, module):
"""the numpy.core.numerictypes module adds a number of items to itself
dynamically; define these to avoid spurious errors about missing
modules"""
module.__globalnames__.add("bool_")
module.__globalnames__.add("cdouble")
module.__globalnames__.add("complexfloating")
module.__globalnames__.add("csingle")
module.__globalnames__.add("double")
module.__globalnames__.add("longdouble")
module.__globalnames__.add("float32")
module.__globalnames__.add("float64")
module.__globalnames__.add("float_")
module.__globalnames__.add("inexact")
module.__globalnames__.add("integer")
module.__globalnames__.add("intc")
module.__globalnames__.add("int32")
module.__globalnames__.add("number")
module.__globalnames__.add("single")
def hook_numpy_core(finder, module):
finder.ignore("numpy.core._dotblas")