FreezeTool.py 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. """ This module contains code to freeze a number of Python modules
  2. into a single (mostly) standalone DLL or EXE. """
  3. import modulefinder
  4. import sys
  5. import os
  6. import marshal
  7. import imp
  8. import platform
  9. from distutils.sysconfig import PREFIX, get_python_inc, get_python_version
  10. # Temporary (?) try..except to protect against unbuilt extend_frozen.
  11. try:
  12. import extend_frozen
  13. except ImportError:
  14. extend_frozen = None
  15. import direct
  16. from pandac.PandaModules import *
  17. from pandac.extension_native_helpers import dll_suffix, dll_ext
  18. # Check to see if we are running python_d, which implies we have a
  19. # debug build, and we have to build the module with debug options.
  20. # This is only relevant on Windows.
  21. # I wonder if there's a better way to determine this?
  22. python = os.path.splitext(os.path.split(sys.executable)[1])[0]
  23. isDebugBuild = (python.lower().endswith('_d'))
  24. # These are modules that Python always tries to import up-front. They
  25. # must be frozen in any main.exe.
  26. startupModules = [
  27. 'site', 'sitecustomize', 'os', 'encodings.cp1252',
  28. 'org',
  29. ]
  30. # These are missing modules that we've reported already this session.
  31. reportedMissing = {}
  32. # Our own Python source trees to watch out for.
  33. sourceTrees = ['direct']
  34. # The command to compile a c to an object file. Replace %(basename)s
  35. # with the basename of the source file, and an implicit .c extension.
  36. compileObj = 'error'
  37. # The command to link a single object file into an executable. As
  38. # above, replace $(basename)s with the basename of the original source
  39. # file, and of the target executable.
  40. linkExe = 'error'
  41. # The command to link a single object file into a shared library.
  42. linkDll = 'error'
  43. # Paths to Python stuff.
  44. Python = None
  45. PythonIPath = get_python_inc()
  46. PythonVersion = get_python_version()
  47. # The VC directory of Microsoft Visual Studio (if relevant)
  48. MSVC = None
  49. # Directory to Windows Platform SDK (if relevant)
  50. PSDK = None
  51. # The setting to control release vs. debug builds. Only relevant on
  52. # Windows.
  53. MD = None
  54. # The _d extension to add to dll filenames on Windows in debug builds.
  55. dllext = ''
  56. if sys.platform == 'win32':
  57. Python = PREFIX
  58. if ('VCINSTALLDIR' in os.environ):
  59. MSVC = os.environ['VCINSTALLDIR']
  60. elif (Filename('/c/Program Files/Microsoft Visual Studio 9.0/VC').exists()):
  61. MSVC = Filename('/c/Program Files/Microsoft Visual Studio 9.0/VC').toOsSpecific()
  62. elif (Filename('/c/Program Files/Microsoft Visual Studio .NET 2003/Vc7').exists()):
  63. MSVC = Filename('/c/Program Files/Microsoft Visual Studio .NET 2003/Vc7').toOsSpecific()
  64. else:
  65. print 'Could not locate Microsoft Visual C++ Compiler! Try running from the Visual Studio Command Prompt.'
  66. sys.exit(1)
  67. if ('WindowsSdkDir' in os.environ):
  68. PSDK = os.environ['WindowsSdkDir']
  69. elif (platform.architecture()[0] == '32bit' and Filename('/c/Program Files/Microsoft Platform SDK for Windows Server 2003 R2').exists()):
  70. PSDK = Filename('/c/Program Files/Microsoft Platform SDK for Windows Server 2003 R2').toOsSpecific()
  71. elif (os.path.exists(os.path.join(MSVC, 'PlatformSDK'))):
  72. PSDK = os.path.join(MSVC, 'PlatformSDK')
  73. else:
  74. print 'Could not locate the Microsoft Windows Platform SDK! Try running from the Visual Studio Command Prompt.'
  75. sys.exit(1)
  76. # We need to use the correct compiler setting for debug vs. release builds.
  77. MD = '/MD'
  78. if isDebugBuild:
  79. MD = '/MDd'
  80. dllext = '_d'
  81. # If it is run by makepanda, it handles the MSVC and PlatformSDK paths itself.
  82. if ('MAKEPANDA' in os.environ):
  83. compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" %(filename)s'
  84. linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(python)s\libs" /out:%(basename)s.exe %(basename)s.obj'
  85. linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(python)s\libs" /out:%(basename)s%(dllext)s.pyd %(basename)s.obj'
  86. else:
  87. os.environ['PATH'] += ';' + MSVC + '\\bin;' + MSVC + '\\Common7\\IDE;' + PSDK + '\\bin'
  88. compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" /I"%(PSDK)s\include" /I"%(MSVC)s\include" %(filename)s'
  89. linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\lib" /LIBPATH:"%(python)s\libs" /out:%(basename)s.exe %(basename)s.obj'
  90. linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\lib" /LIBPATH:"%(python)s\libs" /out:%(basename)s%(dllext)s.pyd %(basename)s.obj'
  91. elif sys.platform == 'darwin':
  92. # OSX
  93. compileObj = "gcc -fPIC -c -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s"
  94. linkExe = "gcc -o %(basename)s %(basename)s.o -framework Python"
  95. linkDll = "gcc -undefined dynamic_lookup -bundle -o %(basename)s.so %(basename)s.o"
  96. else:
  97. # Unix
  98. compileObj = "gcc -fPIC -c -o %(basename)s.o -O2 %(filename)s -I %(pythonIPath)s"
  99. linkExe = "gcc -o %(basename)s %(basename)s.o -lpython%(pythonVersion)s"
  100. linkDll = "gcc -shared -o %(basename)s.so %(basename)s.o -lpython%(pythonVersion)s"
  101. if (platform.uname()[1]=="pcbsd"):
  102. linkExe += " -L/usr/PCBSD/local/lib"
  103. linkDll += " -L/usr/PCBSD/local/lib"
  104. # The code from frozenmain.c in the Python source repository.
  105. frozenMainCode = """
  106. /* Python interpreter main program for frozen scripts */
  107. #include "Python.h"
  108. #ifdef MS_WINDOWS
  109. extern void PyWinFreeze_ExeInit(void);
  110. extern void PyWinFreeze_ExeTerm(void);
  111. extern int PyInitFrozenExtensions(void);
  112. #endif
  113. /* Main program */
  114. int
  115. Py_FrozenMain(int argc, char **argv)
  116. {
  117. char *p;
  118. int n, sts;
  119. int inspect = 0;
  120. int unbuffered = 0;
  121. Py_FrozenFlag = 1; /* Suppress errors from getpath.c */
  122. if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\\0')
  123. inspect = 1;
  124. if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\\0')
  125. unbuffered = 1;
  126. if (unbuffered) {
  127. setbuf(stdin, (char *)NULL);
  128. setbuf(stdout, (char *)NULL);
  129. setbuf(stderr, (char *)NULL);
  130. }
  131. #ifdef MS_WINDOWS
  132. PyInitFrozenExtensions();
  133. #endif /* MS_WINDOWS */
  134. Py_SetProgramName(argv[0]);
  135. Py_Initialize();
  136. #ifdef MS_WINDOWS
  137. PyWinFreeze_ExeInit();
  138. #endif
  139. if (Py_VerboseFlag)
  140. fprintf(stderr, "Python %s\\n%s\\n",
  141. Py_GetVersion(), Py_GetCopyright());
  142. PySys_SetArgv(argc, argv);
  143. n = PyImport_ImportFrozenModule("__main__");
  144. if (n == 0)
  145. Py_FatalError("__main__ not frozen");
  146. if (n < 0) {
  147. PyErr_Print();
  148. sts = 1;
  149. }
  150. else
  151. sts = 0;
  152. if (inspect && isatty((int)fileno(stdin)))
  153. sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
  154. #ifdef MS_WINDOWS
  155. PyWinFreeze_ExeTerm();
  156. #endif
  157. Py_Finalize();
  158. return sts;
  159. }
  160. """
  161. # The code from frozen_dllmain.c in the Python source repository.
  162. # Windows only.
  163. frozenDllMainCode = """
  164. #include "windows.h"
  165. static char *possibleModules[] = {
  166. "pywintypes",
  167. "pythoncom",
  168. "win32ui",
  169. NULL,
  170. };
  171. BOOL CallModuleDllMain(char *modName, DWORD dwReason);
  172. /*
  173. Called by a frozen .EXE only, so that built-in extension
  174. modules are initialized correctly
  175. */
  176. void PyWinFreeze_ExeInit(void)
  177. {
  178. char **modName;
  179. for (modName = possibleModules;*modName;*modName++) {
  180. /* printf("Initialising '%s'\\n", *modName); */
  181. CallModuleDllMain(*modName, DLL_PROCESS_ATTACH);
  182. }
  183. }
  184. /*
  185. Called by a frozen .EXE only, so that built-in extension
  186. modules are cleaned up
  187. */
  188. void PyWinFreeze_ExeTerm(void)
  189. {
  190. // Must go backwards
  191. char **modName;
  192. for (modName = possibleModules+(sizeof(possibleModules) / sizeof(char *))-2;
  193. modName >= possibleModules;
  194. *modName--) {
  195. /* printf("Terminating '%s'\\n", *modName);*/
  196. CallModuleDllMain(*modName, DLL_PROCESS_DETACH);
  197. }
  198. }
  199. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  200. {
  201. BOOL ret = TRUE;
  202. switch (dwReason) {
  203. case DLL_PROCESS_ATTACH:
  204. {
  205. char **modName;
  206. for (modName = possibleModules;*modName;*modName++) {
  207. BOOL ok = CallModuleDllMain(*modName, dwReason);
  208. if (!ok)
  209. ret = FALSE;
  210. }
  211. break;
  212. }
  213. case DLL_PROCESS_DETACH:
  214. {
  215. // Must go backwards
  216. char **modName;
  217. for (modName = possibleModules+(sizeof(possibleModules) / sizeof(char *))-2;
  218. modName >= possibleModules;
  219. *modName--)
  220. CallModuleDllMain(*modName, DLL_PROCESS_DETACH);
  221. break;
  222. }
  223. }
  224. return ret;
  225. }
  226. BOOL CallModuleDllMain(char *modName, DWORD dwReason)
  227. {
  228. BOOL (WINAPI * pfndllmain)(HINSTANCE, DWORD, LPVOID);
  229. char funcName[255];
  230. HMODULE hmod = GetModuleHandle(NULL);
  231. strcpy(funcName, "_DllMain");
  232. strcat(funcName, modName);
  233. strcat(funcName, "@12"); // stdcall convention.
  234. pfndllmain = (BOOL (WINAPI *)(HINSTANCE, DWORD, LPVOID))GetProcAddress(hmod, funcName);
  235. if (pfndllmain==NULL) {
  236. /* No function by that name exported - then that module does
  237. not appear in our frozen program - return OK
  238. */
  239. return TRUE;
  240. }
  241. return (*pfndllmain)(hmod, dwReason, NULL);
  242. }
  243. """
  244. # Our own glue code to start up a Python executable.
  245. mainInitCode = """
  246. %(frozenMainCode)s
  247. int
  248. main(int argc, char *argv[]) {
  249. PyImport_FrozenModules = _PyImport_FrozenModules;
  250. return Py_FrozenMain(argc, argv);
  251. }
  252. """
  253. # Our own glue code to start up a Python shared library.
  254. dllInitCode = """
  255. static PyMethodDef nullMethods[] = {
  256. {NULL, NULL}
  257. };
  258. /*
  259. * Call this function to extend the frozen modules array with a new
  260. * array of frozen modules, provided in a C-style array, at runtime.
  261. * Returns the total number of frozen modules.
  262. */
  263. static int
  264. extend_frozen_modules(const struct _frozen *new_modules, int new_count) {
  265. int orig_count;
  266. struct _frozen *realloc_FrozenModules;
  267. /* First, count the number of frozen modules we had originally. */
  268. orig_count = 0;
  269. while (PyImport_FrozenModules[orig_count].name != NULL) {
  270. ++orig_count;
  271. }
  272. if (new_count == 0) {
  273. /* Trivial no-op. */
  274. return orig_count;
  275. }
  276. /* Reallocate the PyImport_FrozenModules array bigger to make room
  277. for the additional frozen modules. We just leak the original
  278. array; it's too risky to try to free it. */
  279. realloc_FrozenModules = (struct _frozen *)malloc((orig_count + new_count + 1) * sizeof(struct _frozen));
  280. /* The new frozen modules go at the front of the list. */
  281. memcpy(realloc_FrozenModules, new_modules, new_count * sizeof(struct _frozen));
  282. /* Then the original set of frozen modules. */
  283. memcpy(realloc_FrozenModules + new_count, PyImport_FrozenModules, orig_count * sizeof(struct _frozen));
  284. /* Finally, a single 0-valued entry marks the end of the array. */
  285. memset(realloc_FrozenModules + orig_count + new_count, 0, sizeof(struct _frozen));
  286. /* Assign the new pointer. */
  287. PyImport_FrozenModules = realloc_FrozenModules;
  288. return orig_count + new_count;
  289. }
  290. %(dllexport)svoid init%(moduleName)s() {
  291. extend_frozen_modules(_PyImport_FrozenModules, %(newcount)s);
  292. Py_InitModule("%(moduleName)s", nullMethods);
  293. }
  294. """
  295. programFile = """
  296. #include "Python.h"
  297. %(moduleDefs)s
  298. static struct _frozen _PyImport_FrozenModules[] = {
  299. %(moduleList)s
  300. {NULL, NULL, 0}
  301. };
  302. %(initCode)s
  303. """
  304. # Windows needs this bit.
  305. frozenExtensions = """
  306. static struct _inittab extensions[] = {
  307. /* Sentinel */
  308. {0, 0}
  309. };
  310. extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);
  311. int PyInitFrozenExtensions()
  312. {
  313. return PyImport_ExtendInittab(extensions);
  314. }
  315. """
  316. okMissing = [
  317. 'Carbon.Folder', 'Carbon.Folders', 'HouseGlobals', 'Carbon.File',
  318. 'MacOS', '_emx_link', 'ce', 'mac', 'org.python.core', 'os.path',
  319. 'os2', 'posix', 'pwd', 'readline', 'riscos', 'riscosenviron',
  320. 'riscospath', 'dbm', 'fcntl', 'win32api',
  321. '_winreg', 'ctypes', 'ctypes.wintypes', 'nt','msvcrt',
  322. 'EasyDialogs', 'SOCKS', 'ic', 'rourl2path', 'termios',
  323. 'OverrideFrom23._Res', 'email', 'email.Utils', 'email.Generator',
  324. 'email.Iterators', '_subprocess', 'gestalt',
  325. 'direct.extensions_native.extensions_darwin',
  326. ]
  327. class Freezer:
  328. class ModuleDef:
  329. def __init__(self, moduleName, filename = None,
  330. implicit = False, guess = False,
  331. exclude = False, forbid = False,
  332. allowChildren = False, fromSource = None):
  333. # The Python module name.
  334. self.moduleName = moduleName
  335. # The file on disk it was loaded from, if any.
  336. self.filename = filename
  337. # True if the module was found via the modulefinder.
  338. self.implicit = implicit
  339. # True if the moduleName might refer to some Python object
  340. # other than a module, in which case the module should be
  341. # ignored.
  342. self.guess = guess
  343. # True if the module should *not* be included in the
  344. # generated output.
  345. self.exclude = exclude
  346. # True if the module should never be allowed, even if it
  347. # exists at runtime.
  348. self.forbid = forbid
  349. # True if excluding the module still allows its children
  350. # to be included. This only makes sense if the module
  351. # will exist at runtime through some other means
  352. # (e.g. from another package).
  353. self.allowChildren = allowChildren
  354. # Additional black-box information about where this module
  355. # record came from, supplied by the caller.
  356. self.fromSource = fromSource
  357. # Some sanity checks.
  358. if not self.exclude:
  359. self.allowChildren = True
  360. if self.forbid:
  361. self.exclude = True
  362. self.allowChildren = False
  363. def __repr__(self):
  364. args = [repr(self.moduleName), repr(self.filename)]
  365. if self.implicit:
  366. args.append('implicit = True')
  367. if self.guess:
  368. args.append('guess = True')
  369. if self.exclude:
  370. args.append('exclude = True')
  371. if self.forbid:
  372. args.append('forbid = True')
  373. if self.allowChildren:
  374. args.append('allowChildren = True')
  375. return 'ModuleDef(%s)' % (', '.join(args))
  376. def __init__(self, previous = None, debugLevel = 0):
  377. # Normally, we are freezing for our own platform. Change this
  378. # if untrue.
  379. self.platform = sys.platform
  380. # You will also need to change these for a cross-compiler
  381. # situation.
  382. self.compileObj = compileObj
  383. self.linkExe = linkExe
  384. self.linkDll = linkDll
  385. # The filename extension to append to the source file before
  386. # compiling.
  387. self.sourceExtension = '.c'
  388. # The filename extension to append to the object file.
  389. self.objectExtension = '.o'
  390. if self.platform == 'win32':
  391. self.objectExtension = '.obj'
  392. # Change any of these to change the generated startup and glue
  393. # code.
  394. self.frozenMainCode = frozenMainCode
  395. self.frozenDllMainCode = frozenDllMainCode
  396. self.mainInitCode = mainInitCode
  397. self.frozenExtensions = frozenExtensions
  398. # Set this true to encode Python files in a Multifile as their
  399. # original source if possible, or false to encode them as
  400. # compiled pyc or pyo files. This has no effect on frozen exe
  401. # or dll's; those are always stored with compiled code.
  402. self.storePythonSource = False
  403. # This list will be filled in by generateCode() or
  404. # addToMultifile(). It contains a list of all the extension
  405. # modules that were discovered, which have not been added to
  406. # the output. The list is a list of tuples of the form
  407. # (moduleName, filename).
  408. self.extras = []
  409. # End of public interface. These remaining members should not
  410. # be directly manipulated by callers.
  411. self.previousModules = {}
  412. self.modules = {}
  413. if previous:
  414. self.previousModules = dict(previous.modules)
  415. self.modules = dict(previous.modules)
  416. self.mf = None
  417. # Make sure we know how to find "direct".
  418. for sourceTree in sourceTrees:
  419. try:
  420. module = __import__(sourceTree)
  421. except:
  422. module = None
  423. if module and hasattr(module, '__path__'):
  424. path = getattr(module, '__path__')
  425. modulefinder.AddPackagePath(sourceTree, path[0])
  426. def excludeFrom(self, freezer):
  427. """ Excludes all modules that have already been processed by
  428. the indicated FreezeTool. This is equivalent to passing the
  429. indicated FreezeTool object as previous to this object's
  430. constructor, but it may be called at any point during
  431. processing. """
  432. for key, value in freezer.modules.items():
  433. self.previousModules[key] = value
  434. self.modules[key] = value
  435. def excludeModule(self, moduleName, forbid = False, allowChildren = False,
  436. fromSource = None):
  437. """ Adds a module to the list of modules not to be exported by
  438. this tool. If forbid is true, the module is furthermore
  439. forbidden to be imported, even if it exists on disk. If
  440. allowChildren is true, the children of the indicated module
  441. may still be included."""
  442. assert self.mf == None
  443. self.modules[moduleName] = self.ModuleDef(
  444. moduleName, exclude = True,
  445. forbid = forbid, allowChildren = allowChildren,
  446. fromSource = fromSource)
  447. def handleCustomPath(self, moduleName):
  448. """ Indicates a module that may perform runtime manipulation
  449. of its __path__ variable, and which must therefore be actually
  450. imported at runtime in order to determine the true value of
  451. __path__. """
  452. str = 'import %s' % (moduleName)
  453. exec str
  454. module = sys.modules[moduleName]
  455. for path in module.__path__:
  456. modulefinder.AddPackagePath(moduleName, path)
  457. def getModulePath(self, moduleName):
  458. """ Looks for the indicated directory module and returns the
  459. __path__ member: the list of directories in which its python
  460. files can be found. If the module is a .py file and not a
  461. directory, returns None. """
  462. # First, try to import the module directly. That's the most
  463. # reliable answer, if it works.
  464. try:
  465. module = __import__(moduleName)
  466. except:
  467. print "couldn't import %s" % (moduleName)
  468. module = None
  469. if module != None:
  470. for symbol in moduleName.split('.')[1:]:
  471. module = getattr(module, symbol)
  472. return module.__path__
  473. # If it didn't work--maybe the module is unimportable because
  474. # it makes certain assumptions about the builtins, or
  475. # whatever--then just look for file on disk. That's usually
  476. # good enough.
  477. path = None
  478. baseName = moduleName
  479. if '.' in baseName:
  480. parentName, baseName = moduleName.rsplit('.', 1)
  481. path = self.getModulePath(parentName)
  482. if path == None:
  483. return None
  484. file, pathname, description = imp.find_module(baseName, path)
  485. if not os.path.isdir(pathname):
  486. return None
  487. return [pathname]
  488. def getModuleStar(self, moduleName):
  489. """ Looks for the indicated directory module and returns the
  490. __all__ member: the list of symbols within the module. """
  491. # First, try to import the module directly. That's the most
  492. # reliable answer, if it works.
  493. try:
  494. module = __import__(moduleName)
  495. except:
  496. print "couldn't import %s" % (moduleName)
  497. module = None
  498. if module != None:
  499. for symbol in moduleName.split('.')[1:]:
  500. module = getattr(module, symbol)
  501. if hasattr(module, '__all__'):
  502. return module.__all__
  503. # If it didn't work, just open the directory and scan for *.py
  504. # files.
  505. path = None
  506. baseName = moduleName
  507. if '.' in baseName:
  508. parentName, baseName = moduleName.rsplit('.', 1)
  509. path = self.getModulePath(parentName)
  510. if path == None:
  511. return None
  512. try:
  513. file, pathname, description = imp.find_module(baseName, path)
  514. except ImportError:
  515. return None
  516. if not os.path.isdir(pathname):
  517. return None
  518. # Scan the directory, looking for .py files.
  519. modules = []
  520. for basename in os.listdir(pathname):
  521. if basename.endswith('.py') and basename != '__init__.py':
  522. modules.append(basename[:-3])
  523. return modules
  524. def addModule(self, moduleName, implicit = False, newName = None,
  525. filename = None, guess = False, fromSource = None):
  526. """ Adds a module to the list of modules to be exported by
  527. this tool. If implicit is true, it is OK if the module does
  528. not actually exist.
  529. newName is the name to call the module when it appears in the
  530. output. The default is the same name it had in the original.
  531. Use caution when renaming a module; if another module imports
  532. this module by its original name, you will also need to
  533. explicitly add the module under its original name, duplicating
  534. the module twice in the output.
  535. The module name may end in ".*", which means to add all of the
  536. .py files (other than __init__.py) in a particular directory.
  537. It may also end in ".*.*", which means to cycle through all
  538. directories within a particular directory.
  539. """
  540. assert self.mf == None
  541. if not newName:
  542. newName = moduleName
  543. if moduleName.endswith('.*'):
  544. assert(newName.endswith('.*'))
  545. # Find the parent module, so we can get its directory.
  546. parentName = moduleName[:-2]
  547. newParentName = newName[:-2]
  548. parentNames = [(parentName, newParentName)]
  549. if parentName.endswith('.*'):
  550. assert(newParentName.endswith('.*'))
  551. # Another special case. The parent name "*" means to
  552. # return all possible directories within a particular
  553. # directory.
  554. topName = parentName[:-2]
  555. newTopName = newParentName[:-2]
  556. parentNames = []
  557. for dirname in self.getModulePath(topName):
  558. for basename in os.listdir(dirname):
  559. if os.path.exists(os.path.join(dirname, basename, '__init__.py')):
  560. parentName = '%s.%s' % (topName, basename)
  561. newParentName = '%s.%s' % (newTopName, basename)
  562. if self.getModulePath(parentName):
  563. parentNames.append((parentName, newParentName))
  564. for parentName, newParentName in parentNames:
  565. modules = self.getModuleStar(parentName)
  566. if modules == None:
  567. # It's actually a regular module.
  568. self.modules[newParentName] = self.ModuleDef(
  569. parentName, implicit = implicit, guess = guess,
  570. fromSource = fromSource)
  571. else:
  572. # Now get all the py files in the parent directory.
  573. for basename in modules:
  574. moduleName = '%s.%s' % (parentName, basename)
  575. newName = '%s.%s' % (newParentName, basename)
  576. mdef = self.ModuleDef(
  577. moduleName, implicit = implicit, guess = True,
  578. fromSource = fromSource)
  579. self.modules[newName] = mdef
  580. else:
  581. # A normal, explicit module name.
  582. self.modules[newName] = self.ModuleDef(
  583. moduleName, filename = filename, implicit = implicit,
  584. guess = guess, fromSource = fromSource)
  585. def done(self, compileToExe = False):
  586. """ Call this method after you have added all modules with
  587. addModule(). You may then call generateCode() or
  588. writeMultifile() to dump the resulting output. After a call
  589. to done(), you may not add any more modules until you call
  590. reset(). """
  591. assert self.mf == None
  592. # If we are building an exe, we also need to implicitly
  593. # bring in Python's startup modules.
  594. if compileToExe:
  595. for moduleName in startupModules:
  596. if moduleName not in self.modules:
  597. self.modules[moduleName] = self.ModuleDef(moduleName, implicit = True)
  598. # Excluding a parent module also excludes all its
  599. # (non-explicit) children, unless the parent has allowChildren
  600. # set.
  601. # Walk through the list in sorted order, so we reach parents
  602. # before children.
  603. names = self.modules.items()
  604. names.sort()
  605. excludeDict = {}
  606. implicitParentDict = {}
  607. includes = []
  608. autoIncludes = []
  609. origToNewName = {}
  610. for newName, mdef in names:
  611. moduleName = mdef.moduleName
  612. origToNewName[moduleName] = newName
  613. if mdef.implicit and '.' in newName:
  614. # For implicit modules, check if the parent is excluded.
  615. parentName, baseName = newName.rsplit('.', 1)
  616. if parentName in excludeDict :
  617. mdef = excludeDict[parentName]
  618. if mdef.exclude:
  619. if not mdef.allowChildren:
  620. excludeDict[moduleName] = mdef
  621. elif mdef.implicit or mdef.guess:
  622. autoIncludes.append(mdef)
  623. else:
  624. includes.append(mdef)
  625. self.mf = PandaModuleFinder(excludes = excludeDict.keys())
  626. # Attempt to import the explicit modules into the modulefinder.
  627. for mdef in includes:
  628. try:
  629. self.__loadModule(mdef)
  630. except ImportError:
  631. print "Unknown module: %s" % (mdef.moduleName)
  632. import pdb; pdb.set_trace()
  633. # Also attempt to import any implicit modules. If any of
  634. # these fail to import, we don't really care.
  635. for mdef in autoIncludes:
  636. try:
  637. self.__loadModule(mdef)
  638. # Since it successfully loaded, it's no longer a guess.
  639. mdef.guess = False
  640. except:
  641. # Something went wrong, guess it's not an importable
  642. # module.
  643. pass
  644. # Now, any new modules we found get added to the export list.
  645. for origName in self.mf.modules.keys():
  646. if origName not in origToNewName:
  647. self.modules[origName] = self.ModuleDef(origName, implicit = True)
  648. missing = []
  649. for origName in self.mf.any_missing_maybe()[0]:
  650. if origName in startupModules:
  651. continue
  652. if origName in self.previousModules:
  653. continue
  654. # This module is missing. Let it be missing in the
  655. # runtime also.
  656. self.modules[origName] = self.ModuleDef(origName, exclude = True,
  657. implicit = True)
  658. if origName in okMissing:
  659. # If it's listed in okMissing, don't even report it.
  660. continue
  661. prefix = origName.split('.')[0]
  662. if origName not in reportedMissing:
  663. missing.append(origName)
  664. reportedMissing[origName] = True
  665. if missing:
  666. missing.sort()
  667. print "There are some missing modules: %r" % missing
  668. def __loadModule(self, mdef):
  669. """ Adds the indicated module to the modulefinder. """
  670. if mdef.filename:
  671. # If it has a filename, then we found it as a file on
  672. # disk. In this case, the moduleName may not be accurate
  673. # and useful, so load it as a file instead.
  674. tempPath = None
  675. if '.' not in mdef.moduleName:
  676. # If we loaded a python file from the root, we need to
  677. # temporarily add its directory to the module search
  678. # path, so the modulefinder can find any sibling
  679. # python files it imports as well.
  680. tempPath = Filename(mdef.filename.getDirname()).toOsSpecific()
  681. self.mf.path.append(tempPath)
  682. pathname = mdef.filename.toOsSpecific()
  683. ext = mdef.filename.getExtension()
  684. if ext == 'pyc' or ext == 'pyo':
  685. fp = open(pathname, 'rb')
  686. stuff = ("", "rb", imp.PY_COMPILED)
  687. self.mf.load_module(mdef.moduleName, fp, pathname, stuff)
  688. else:
  689. fp = open(pathname, modulefinder.READ_MODE)
  690. stuff = ("", "r", imp.PY_SOURCE)
  691. self.mf.load_module(mdef.moduleName, fp, pathname, stuff)
  692. if tempPath:
  693. del self.mf.path[-1]
  694. else:
  695. # Otherwise, we can just import it normally.
  696. self.mf.import_hook(mdef.moduleName)
  697. def reset(self):
  698. """ After a previous call to done(), this resets the
  699. FreezeTool object for a new pass. More modules may be added
  700. and dumped to a new target. Previously-added modules are
  701. remembered and will not be dumped again. """
  702. self.mf = None
  703. self.previousModules = dict(self.modules)
  704. def mangleName(self, moduleName):
  705. return 'M_' + moduleName.replace('.', '__').replace('-', '_')
  706. def getAllModuleNames(self):
  707. """ Return a list of all module names that have been included
  708. or forbidden, either in this current pass or in a previous
  709. pass. Module names that have been excluded are not included
  710. in this list. """
  711. moduleNames = []
  712. for newName, mdef in self.modules.items():
  713. if mdef.guess:
  714. # Not really a module.
  715. pass
  716. elif mdef.exclude and not mdef.forbid:
  717. # An excluded (but not forbidden) file.
  718. pass
  719. else:
  720. moduleNames.append(newName)
  721. moduleNames.sort()
  722. return moduleNames
  723. def getModuleDefs(self):
  724. """ Return a list of all of the modules we will be explicitly
  725. or implicitly including. The return value is actually a list
  726. of tuples: (moduleName, moduleDef)."""
  727. moduleDefs = []
  728. for newName, mdef in self.modules.items():
  729. prev = self.previousModules.get(newName, None)
  730. if not mdef.exclude:
  731. # Include this module (even if a previous pass
  732. # excluded it). But don't bother if we exported it
  733. # previously.
  734. if prev and not prev.exclude:
  735. # Previously exported.
  736. pass
  737. else:
  738. if mdef.moduleName in self.mf.modules or \
  739. mdef.moduleName in startupModules or \
  740. mdef.filename:
  741. moduleDefs.append((newName, mdef))
  742. elif not mdef.guess:
  743. print "Unknown module %s" % (mdef.moduleName)
  744. elif mdef.forbid:
  745. if not prev or not prev.forbid:
  746. moduleDefs.append((newName, mdef))
  747. moduleDefs.sort()
  748. return moduleDefs
  749. def __replacePaths(self):
  750. # Build up the replacement pathname table, so we can eliminate
  751. # the personal information in the frozen pathnames. The
  752. # actual filename we put in there is meaningful only for stack
  753. # traces, so we'll just use the module name.
  754. replace_paths = []
  755. for moduleName, module in self.mf.modules.items():
  756. if module.__code__:
  757. origPathname = module.__code__.co_filename
  758. replace_paths.append((origPathname, moduleName))
  759. self.mf.replace_paths = replace_paths
  760. # Now that we have built up the replacement mapping, go back
  761. # through and actually replace the paths.
  762. for moduleName, module in self.mf.modules.items():
  763. if module.__code__:
  764. co = self.mf.replace_paths_in_code(module.__code__)
  765. module.__code__ = co;
  766. def __addPyc(self, multifile, filename, code, compressionLevel):
  767. if code:
  768. data = imp.get_magic() + '\0\0\0\0' + \
  769. marshal.dumps(code)
  770. stream = StringStream(data)
  771. multifile.addSubfile(filename, stream, compressionLevel)
  772. multifile.flush()
  773. def __addPythonDirs(self, multifile, moduleDirs, dirnames, compressionLevel):
  774. """ Adds all of the names on dirnames as a module directory. """
  775. if not dirnames:
  776. return
  777. str = '.'.join(dirnames)
  778. if str not in moduleDirs:
  779. # Add an implicit __init__.py file.
  780. moduleName = '.'.join(dirnames)
  781. filename = '/'.join(dirnames) + '/__init__'
  782. if self.storePythonSource:
  783. filename += '.py'
  784. stream = StringStream('')
  785. multifile.addSubfile(filename, stream, 0)
  786. multifile.flush()
  787. else:
  788. if __debug__:
  789. filename += '.pyc'
  790. else:
  791. filename += '.pyo'
  792. code = compile('', moduleName, 'exec')
  793. self.__addPyc(multifile, filename, code, compressionLevel)
  794. moduleDirs[str] = True
  795. self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1], compressionLevel)
  796. def __addPythonFile(self, multifile, moduleDirs, moduleName, mdef,
  797. compressionLevel):
  798. """ Adds the named module to the multifile as a .pyc file. """
  799. # First, split the module into its subdirectory names.
  800. dirnames = moduleName.split('.')
  801. self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1], compressionLevel)
  802. filename = '/'.join(dirnames)
  803. module = self.mf.modules.get(mdef.moduleName, None)
  804. if getattr(module, '__path__', None) is not None:
  805. # It's actually a package. In this case, we really write
  806. # the file moduleName/__init__.py.
  807. filename += '/__init__'
  808. # Ensure we don't have an implicit filename from above.
  809. multifile.removeSubfile(filename + '.py')
  810. if __debug__:
  811. multifile.removeSubfile(filename + '.pyc')
  812. else:
  813. multifile.removeSubfile(filename + '.pyo')
  814. # Attempt to add the original source file if we can.
  815. sourceFilename = None
  816. if mdef.filename and mdef.filename.getExtension() == "py":
  817. sourceFilename = mdef.filename
  818. elif getattr(module, '__file__', None):
  819. sourceFilename = Filename.fromOsSpecific(module.__file__)
  820. sourceFilename.setExtension("py")
  821. if self.storePythonSource:
  822. if sourceFilename and sourceFilename.exists():
  823. filename += '.py'
  824. multifile.addSubfile(filename, sourceFilename, compressionLevel)
  825. return
  826. # If we can't find the source file, add the compiled pyc instead.
  827. if __debug__:
  828. filename += '.pyc'
  829. else:
  830. filename += '.pyo'
  831. code = None
  832. if module:
  833. # Get the compiled code directly from the module object.
  834. code = getattr(module, "__code__", None)
  835. if not code:
  836. # This is a module with no associated Python
  837. # code. It must be an extension module. Get the
  838. # filename.
  839. extensionFilename = getattr(module, '__file__', None)
  840. if extensionFilename:
  841. self.extras.append((moduleName, extensionFilename))
  842. else:
  843. # It doesn't even have a filename; it must
  844. # be a built-in module. No worries about
  845. # this one, then.
  846. pass
  847. else:
  848. # Read the code from the source file and compile it on-the-fly.
  849. if sourceFilename and sourceFilename.exists():
  850. source = open(sourceFilename.toOsSpecific(), 'r').read()
  851. if source and source[-1] != '\n':
  852. source = source + '\n'
  853. code = compile(source, sourceFilename.cStr(), 'exec')
  854. self.__addPyc(multifile, filename, code, compressionLevel)
  855. def addToMultifile(self, multifile, compressionLevel = 0):
  856. """ After a call to done(), this stores all of the accumulated
  857. python code into the indicated Multifile. Additional
  858. extension modules are listed in self.extras. """
  859. moduleDirs = {}
  860. for moduleName, mdef in self.getModuleDefs():
  861. if not mdef.exclude:
  862. self.__addPythonFile(multifile, moduleDirs, moduleName, mdef,
  863. compressionLevel)
  864. def writeMultifile(self, mfname):
  865. """ After a call to done(), this stores all of the accumulated
  866. python code into a Multifile with the indicated filename,
  867. including the extension. Additional extension modules are
  868. listed in self.extras."""
  869. self.__replacePaths()
  870. Filename(mfname).unlink()
  871. multifile = Multifile()
  872. if not multifile.openReadWrite(mfname):
  873. raise StandardError
  874. self.addToMultifile(multifile)
  875. multifile.flush()
  876. multifile.repack()
  877. def generateCode(self, basename, compileToExe = False):
  878. """ After a call to done(), this freezes all of the
  879. accumulated python code into either an executable program (if
  880. compileToExe is true) or a dynamic library (if compileToExe is
  881. false). The basename is the name of the file to write,
  882. without the extension.
  883. The return value is the newly-generated filename, including
  884. the filename extension. Additional extension modules are
  885. listed in self.extras. """
  886. if compileToExe:
  887. # We must have a __main__ module to make an exe file.
  888. if not self.__writingModule('__main__'):
  889. message = "Can't generate an executable without a __main__ module."
  890. raise StandardError, message
  891. self.__replacePaths()
  892. # Now generate the actual export table.
  893. moduleDefs = []
  894. moduleList = []
  895. for moduleName, mdef in self.getModuleDefs():
  896. origName = mdef.moduleName
  897. if mdef.forbid:
  898. # Explicitly disallow importing this module.
  899. moduleList.append(self.makeForbiddenModuleListEntry(moduleName))
  900. else:
  901. assert not mdef.exclude
  902. # Allow importing this module.
  903. module = self.mf.modules.get(origName, None)
  904. code = getattr(module, "__code__", None)
  905. if not code and moduleName in startupModules:
  906. # Forbid the loading of this startup module.
  907. moduleList.append(self.makeForbiddenModuleListEntry(moduleName))
  908. else:
  909. if origName in sourceTrees:
  910. # This is one of our Python source trees.
  911. # These are a special case: we don't compile
  912. # the __init__.py files within them, since
  913. # their only purpose is to munge the __path__
  914. # variable anyway. Instead, we pretend the
  915. # __init__.py files are empty.
  916. code = compile('', moduleName, 'exec')
  917. if code:
  918. code = marshal.dumps(code)
  919. mangledName = self.mangleName(moduleName)
  920. moduleDefs.append(self.makeModuleDef(mangledName, code))
  921. moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, module))
  922. else:
  923. # This is a module with no associated Python
  924. # code. It must be an extension module. Get the
  925. # filename.
  926. extensionFilename = getattr(module, '__file__', None)
  927. if extensionFilename:
  928. self.extras.append((moduleName, extensionFilename))
  929. else:
  930. # It doesn't even have a filename; it must
  931. # be a built-in module. No worries about
  932. # this one, then.
  933. pass
  934. filename = basename + self.sourceExtension
  935. dllexport = ''
  936. dllimport = ''
  937. if self.platform == 'win32':
  938. dllexport = '__declspec(dllexport) '
  939. dllimport = '__declspec(dllimport) '
  940. if compileToExe:
  941. code = self.frozenMainCode
  942. if self.platform == 'win32':
  943. code += self.frozenDllMainCode
  944. initCode = self.mainInitCode % {
  945. 'frozenMainCode' : code,
  946. 'programName' : os.path.basename(basename),
  947. 'dllexport' : dllexport,
  948. 'dllimport' : dllimport,
  949. }
  950. if self.platform == 'win32':
  951. initCode += self.frozenExtensions
  952. target = basename + '.exe'
  953. else:
  954. target = basename
  955. compileFunc = self.compileExe
  956. else:
  957. if self.platform == 'win32':
  958. target = basename + dllext + '.pyd'
  959. else:
  960. target = basename + '.so'
  961. initCode = dllInitCode % {
  962. 'moduleName' : os.path.basename(basename),
  963. 'newcount' : len(moduleList),
  964. 'dllexport' : dllexport,
  965. 'dllimport' : dllimport,
  966. }
  967. compileFunc = self.compileDll
  968. text = programFile % {
  969. 'moduleDefs' : '\n'.join(moduleDefs),
  970. 'moduleList' : '\n'.join(moduleList),
  971. 'initCode' : initCode,
  972. }
  973. file = open(filename, 'w')
  974. file.write(text)
  975. file.close()
  976. try:
  977. compileFunc(filename, basename)
  978. finally:
  979. if (os.path.exists(filename)):
  980. os.unlink(filename)
  981. if (os.path.exists(basename + self.objectExtension)):
  982. os.unlink(basename + self.objectExtension)
  983. return target
  984. def compileExe(self, filename, basename):
  985. compile = self.compileObj % {
  986. 'python' : Python,
  987. 'MSVC' : MSVC,
  988. 'PSDK' : PSDK,
  989. 'MD' : MD,
  990. 'pythonIPath' : PythonIPath,
  991. 'pythonVersion' : PythonVersion,
  992. 'filename' : filename,
  993. 'basename' : basename,
  994. }
  995. print >> sys.stderr, compile
  996. if os.system(compile) != 0:
  997. raise StandardError
  998. link = self.linkExe % {
  999. 'python' : Python,
  1000. 'MSVC' : MSVC,
  1001. 'PSDK' : PSDK,
  1002. 'pythonIPath' : PythonIPath,
  1003. 'pythonVersion' : PythonVersion,
  1004. 'filename' : filename,
  1005. 'basename' : basename,
  1006. }
  1007. print >> sys.stderr, link
  1008. if os.system(link) != 0:
  1009. raise StandardError
  1010. def compileDll(self, filename, basename):
  1011. compile = self.compileObj % {
  1012. 'python' : Python,
  1013. 'MSVC' : MSVC,
  1014. 'PSDK' : PSDK,
  1015. 'MD' : MD,
  1016. 'pythonIPath' : PythonIPath,
  1017. 'pythonVersion' : PythonVersion,
  1018. 'filename' : filename,
  1019. 'basename' : basename,
  1020. }
  1021. print >> sys.stderr, compile
  1022. if os.system(compile) != 0:
  1023. raise StandardError
  1024. link = self.linkDll % {
  1025. 'python' : Python,
  1026. 'MSVC' : MSVC,
  1027. 'PSDK' : PSDK,
  1028. 'pythonIPath' : PythonIPath,
  1029. 'pythonVersion' : PythonVersion,
  1030. 'filename' : filename,
  1031. 'basename' : basename,
  1032. 'dllext' : dllext,
  1033. }
  1034. print >> sys.stderr, link
  1035. if os.system(link) != 0:
  1036. raise StandardError
  1037. def makeModuleDef(self, mangledName, code):
  1038. result = ''
  1039. result += 'static unsigned char %s[] = {' % (mangledName)
  1040. for i in range(0, len(code), 16):
  1041. result += '\n '
  1042. for c in code[i:i+16]:
  1043. result += ('%d,' % ord(c))
  1044. result += '\n};\n'
  1045. return result
  1046. def makeModuleListEntry(self, mangledName, code, moduleName, module):
  1047. size = len(code)
  1048. if getattr(module, "__path__", None):
  1049. # Indicate package by negative size
  1050. size = -size
  1051. return ' {"%s", %s, %s},' % (moduleName, mangledName, size)
  1052. def makeForbiddenModuleListEntry(self, moduleName):
  1053. return ' {"%s", NULL, 0},' % (moduleName)
  1054. def __writingModule(self, moduleName):
  1055. """ Returns true if we are outputting the named module in this
  1056. pass, false if we have already output in a previous pass, or
  1057. if it is not yet on the output table. """
  1058. mdef = self.modules.get(moduleName, (None, None))
  1059. if mdef.exclude:
  1060. return False
  1061. if moduleName in self.previousModules:
  1062. return False
  1063. return True
  1064. class PandaModuleFinder(modulefinder.ModuleFinder):
  1065. """ We subclass ModuleFinder here, to add functionality for
  1066. finding the libpandaexpress etc. modules that interrogate
  1067. produces. """
  1068. def find_module(self, name, path, parent=None):
  1069. try:
  1070. return modulefinder.ModuleFinder.find_module(self, name, path, parent = parent)
  1071. except ImportError:
  1072. # It wasn't found through the normal channels. Maybe it's
  1073. # one of ours, or maybe it's frozen?
  1074. if path:
  1075. # Only if we're not looking on a particular path,
  1076. # though.
  1077. raise
  1078. if extend_frozen and extend_frozen.is_frozen_module(name):
  1079. # It's a frozen module.
  1080. return (None, name, ('', '', imp.PY_FROZEN))
  1081. # Look for a dtool extension. This loop is roughly lifted
  1082. # from extension_native_helpers.Dtool_PreloadDLL().
  1083. filename = name + dll_suffix + dll_ext
  1084. for dir in sys.path + [sys.prefix]:
  1085. lib = os.path.join(dir, filename)
  1086. if os.path.exists(lib):
  1087. file = open(lib, 'rb')
  1088. return (file, lib, (dll_ext, 'rb', imp.C_EXTENSION))
  1089. message = "DLL loader cannot find %s." % (name)
  1090. raise ImportError, message
  1091. def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
  1092. if type == imp.PY_FROZEN:
  1093. # It's a frozen module.
  1094. co, isPackage = extend_frozen.get_frozen_module_code(pathname)
  1095. m = self.add_module(fqname)
  1096. m.__file__ = '<frozen>'
  1097. if isPackage:
  1098. m.__path__ = pathname
  1099. co = marshal.loads(co)
  1100. if self.replace_paths:
  1101. co = self.replace_paths_in_code(co)
  1102. m.__code__ = co
  1103. self.scan_code(co, m)
  1104. self.msgout(2, "load_module ->", m)
  1105. return m
  1106. return modulefinder.ModuleFinder.load_module(self, fqname, fp, pathname, (suffix, mode, type))