4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
1 |
#!/usr/bin/python
|
2 |
# -*- coding: utf-8 -*-
|
|
3 |
#
|
|
4 |
# Usage for setup.py:
|
|
5 |
#
|
|
6 |
# from distutils.core import setup
|
|
7 |
# import py2exe
|
|
8 |
# from setup_py2exe_custom import custom_py2exe
|
|
9 |
#
|
|
10 |
# setup(...,
|
|
11 |
# cmdclass={'py2exe': custom_py2exe},
|
|
12 |
# options={'py2exe': {
|
|
13 |
# skip_archive=1, # mandatory overwith will be opt-out
|
|
14 |
# compressed=0, # do not compress - mandatory when skip_archive=1
|
|
15 |
# bundle_files=3, # keep pythonXX.dll out of exe
|
|
16 |
# optimize=0, # do not compile .py files
|
|
17 |
# collected_libs_dir='libs', # move all collected libs into this director
|
|
18 |
# collected_libs_data_relocate='babel,pytz', # force moving collected libs data into collected libs dir
|
|
19 |
# }},
|
|
20 |
# data_files=fixup_data_pytz_zoneinfo() # to add pytz zoneinfo files
|
|
21 |
# )
|
|
22 |
#
|
|
23 |
#
|
|
24 |
||
25 |
import os |
|
26 |
import tempfile |
|
4831.1.1
by Jeff Allen
[IMP] US-2374 Make setup.py usable from Linux |
27 |
|
4836.1.1
by Jeff Allen
Fixed failure while making AIOs. |
28 |
if os.name == 'nt': |
5019
by jf
WIP py2exe |
29 |
from py2exe import build_exe |
30 |
from py2exe.distutils_buildexe import py2exe, fancy_split |
|
4831.1.1
by Jeff Allen
[IMP] US-2374 Make setup.py usable from Linux |
31 |
else: |
32 |
# fake it for non-Windows, so that setup.py can be run for
|
|
33 |
# installing dependencies.
|
|
34 |
class _be(dict): |
|
35 |
def __init__(self, arg1,arg2,arg3): |
|
36 |
pass
|
|
37 |
def __dir__(self): |
|
38 |
return tuple(self) |
|
39 |
def __getattribute__(self, name): |
|
40 |
if name == 'user_options': |
|
41 |
return [] |
|
42 |
else: |
|
43 |
raise AttributeError(name) |
|
44 |
build_exe = _be(1, 2, 3) |
|
45 |
fancy_split = None |
|
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
46 |
|
47 |
def fixup_data_pytz_zoneinfo(): |
|
48 |
r = {} |
|
49 |
import pytz |
|
4850.3.1
by Jeff Allen
[IMP] Fix character encoding of installer. Other cleanup as well. |
50 |
tzdir = os.path.relpath(os.path.dirname(pytz.__file__)) |
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
51 |
for root, _, filenames in os.walk(os.path.join(tzdir, "zoneinfo")): |
52 |
base = os.path.join('pytz', root[len(tzdir) + 1:]) |
|
53 |
r[base] = [os.path.join(root, f) for f in filenames] |
|
5010
by jf
2to3 |
54 |
return list(r.items()) |
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
55 |
|
56 |
def byte_compile_noop(py_files, optimize=0, force=0, |
|
4831.1.1
by Jeff Allen
[IMP] US-2374 Make setup.py usable from Linux |
57 |
target_dir=None, verbose=1, dry_run=0, |
58 |
direct=None): |
|
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
59 |
|
60 |
compiled_files = [] |
|
61 |
from distutils.dir_util import mkpath |
|
62 |
from distutils.dep_util import newer |
|
63 |
from distutils.file_util import copy_file |
|
64 |
||
65 |
for file in py_files: |
|
66 |
# Terminology from the py_compile module:
|
|
67 |
# cfile - byte-compiled file
|
|
68 |
# dfile - purported source filename (same as 'file' by default)
|
|
69 |
cfile = file.__name__.replace('.', '\\') |
|
70 |
||
71 |
if file.__path__: |
|
72 |
dfile = cfile + '\\__init__.py' |
|
73 |
else: |
|
74 |
dfile = cfile + '.py' |
|
75 |
if target_dir: |
|
76 |
cfile = os.path.join(target_dir, dfile) |
|
77 |
||
78 |
if force or newer(file.__file__, cfile): |
|
79 |
if verbose: |
|
5010
by jf
2to3 |
80 |
print("fake-byte-compiling %s to %s" % (file.__file__, dfile)) |
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
81 |
if not dry_run: |
82 |
mkpath(os.path.dirname(cfile)) |
|
83 |
copy_file(file.__file__, cfile, preserve_mode=0) |
|
84 |
else: |
|
85 |
if verbose: |
|
5010
by jf
2to3 |
86 |
print("skipping byte-compilation of %s to %s" % \ |
87 |
(file.__file__, dfile)) |
|
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
88 |
compiled_files.append(dfile) |
89 |
return compiled_files |
|
90 |
||
91 |
# byte_compile()
|
|
92 |
||
5019
by jf
WIP py2exe |
93 |
class custom_py2exe(py2exe): |
94 |
user_options = py2exe.user_options + [ |
|
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
95 |
("collected-libs-dir", None, |
96 |
"Place all collected libs under a specific sub-directory"), |
|
97 |
("collected-libs-data-relocate", None, |
|
98 |
"List of prefix to rellocate under collected-libs-dir directory"), |
|
99 |
("package-build-extra-dirs", None, |
|
100 |
"List extra packages dirs to check for - moving them to exe root dir"), |
|
101 |
]
|
|
102 |
||
103 |
def initialize_options(self): |
|
104 |
build_exe.initialize_options(self) |
|
105 |
self.collected_libs_dir = '.' |
|
106 |
self.collected_libs_data_relocate = [] |
|
107 |
self.package_build_extra_dirs = [] |
|
108 |
||
109 |
def finalize_options(self): |
|
110 |
build_exe.finalize_options(self) |
|
111 |
self.collected_libs_data_relocate = fancy_split(self.collected_libs_data_relocate) |
|
112 |
self.package_build_extra_dirs = fancy_split(self.package_build_extra_dirs) |
|
113 |
||
114 |
def create_directories(self): |
|
115 |
build_exe.create_directories(self) |
|
116 |
self.lib_dir = os.path.join(self.lib_dir, self.collected_libs_dir) |
|
117 |
self.mkpath(self.lib_dir) |
|
118 |
self.boot_tmp_dir = tempfile.mkdtemp() |
|
119 |
||
120 |
def get_boot_script(self, boot_type): |
|
121 |
py2exe_boot_file = build_exe.get_boot_script(self, boot_type) |
|
122 |
custom_boot_file = os.path.join(self.boot_tmp_dir, os.path.basename(py2exe_boot_file)) |
|
123 |
if not os.path.exists(custom_boot_file): |
|
124 |
cbootfile = open(custom_boot_file, 'wb') |
|
125 |
obootfile = open(py2exe_boot_file, 'rb') |
|
126 |
||
127 |
# copy original file
|
|
128 |
cbootfile.write(obootfile.read()) |
|
129 |
obootfile.close() |
|
130 |
||
131 |
# write special custom handlers
|
|
132 |
if boot_type in ['common', 'service']: |
|
133 |
cbootfile.write(""" |
|
134 |
import sys, os
|
|
135 |
||
136 |
if hasattr(sys, 'frozen'):
|
|
137 |
# executable is frozen, add executable directory to sys.path
|
|
138 |
sys.path.append(os.path.dirname(sys.executable))
|
|
139 |
||
140 |
""") |
|
141 |
elif boot_type == 'service': |
|
142 |
pass
|
|
143 |
||
144 |
cbootfile.close() |
|
145 |
return custom_boot_file |
|
146 |
||
147 |
def create_binaries(self, py_files, extensions, dlls): |
|
148 |
dist = self.distribution |
|
149 |
||
5019
by jf
WIP py2exe |
150 |
# Do not try compiling .py files for 'packages', we
|
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
151 |
# want them into the exe directory - and only collected
|
152 |
# dependencies with 'collected libbs dir'
|
|
153 |
src_build_cmd = dist.get_command_obj('build') |
|
154 |
src_build_cmd.ensure_finalized() |
|
155 |
build_lib = getattr(src_build_cmd, 'build_lib', None) |
|
156 |
if build_lib is None: |
|
157 |
raise Exception("Could not continue with no 'build_lib' set") |
|
158 |
||
159 |
dist_packages_py_files = [] |
|
160 |
def is_forced_packages_files(m): |
|
161 |
if m.__file__: |
|
162 |
for build_dir in [build_lib] + self.package_build_extra_dirs: |
|
163 |
if m.__file__.startswith(build_dir): |
|
164 |
dist_packages_py_files.append((m.__file__, m.__file__[len(build_dir)+1:])) |
|
165 |
return True |
|
166 |
return False |
|
167 |
py_files = [ m for m in py_files if not is_forced_packages_files(m) ] |
|
168 |
||
169 |
if dist_packages_py_files: |
|
170 |
print("*** copy package's python file to root directory ***") |
|
171 |
for (srcfile, relfile) in dist_packages_py_files: |
|
172 |
dstfile = os.path.join(self.exe_dir, *os.path.split(relfile)) |
|
173 |
dstfile_dir = os.path.dirname(dstfile) |
|
174 |
self.mkpath(dstfile_dir) |
|
175 |
self.copy_file(srcfile, dstfile, preserve_mode=0) |
|
176 |
||
177 |
# Run fake compilation - just copy raw .py file into their
|
|
178 |
# destination directory
|
|
179 |
self.no_compiled_files = byte_compile_noop(py_files, |
|
4831.1.1
by Jeff Allen
[IMP] US-2374 Make setup.py usable from Linux |
180 |
target_dir=self.collect_dir, |
181 |
optimize=self.optimize, |
|
182 |
force=0, |
|
183 |
verbose=self.verbose, |
|
184 |
dry_run=self.dry_run) |
|
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
185 |
|
186 |
# Force relocate of specific packages data within collected libs dir
|
|
187 |
def fixup_location(l): |
|
188 |
if isinstance(l, tuple) and any([ l[0].startswith(reloc_prefix) |
|
189 |
for reloc_prefix in self.collected_libs_data_relocate ]): |
|
190 |
return (os.path.join(self.collected_libs_dir, l[0]), l[1]) |
|
191 |
return l |
|
192 |
if dist.has_data_files(): |
|
193 |
dist.data_files = [ fixup_location(f) for f in dist.data_files ] |
|
194 |
||
5019
by jf
WIP py2exe |
195 |
# Call parent create_binaries() without any py_files, so that py2exe
|
4680.3.4
by Xavier ALT
[AIO-45] win32: modidify package to not compile .py files |
196 |
# do no force their compilations
|
197 |
return build_exe.create_binaries(self, [], extensions, dlls) |
|
198 |
||
199 |
def make_lib_archive(self, zip_filename, base_dir, files, |
|
200 |
verbose=0, dry_run=0): |
|
201 |
allfiles = files + self.no_compiled_files |
|
202 |
return build_exe.make_lib_archive(self, zip_filename, base_dir, allfiles, verbose=verbose, dry_run=dry_run) |
|
203 |