pyarmor 8.5.7__zip → 8.5.9__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyarmor-8.5.7 → pyarmor-8.5.9}/PKG-INFO +1 -1
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/__init__.py +1 -1
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/__main__.py +7 -12
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/bug.py +2 -2
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/context.py +5 -1
- pyarmor-8.5.9/pyarmor/cli/core.data.1 +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/core.data.2 +0 -0
- pyarmor-8.5.9/pyarmor/cli/core.data.3 +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/default.cfg +6 -9
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/docker.py +4 -2
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/generate.py +24 -12
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/plugin.py +5 -4
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/repack.py +371 -199
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/resource.py +1 -1
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/config.py +1 -1
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/packer.py +4 -2
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor.egg-info/PKG-INFO +1 -1
- pyarmor-8.5.9/pyarmor.egg-info/requires.txt +1 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/setup.py +1 -1
- pyarmor-8.5.7/pyarmor/cli/core.data.1 +0 -0
- pyarmor-8.5.7/pyarmor/cli/core.data.3 +0 -0
- pyarmor-8.5.7/pyarmor.egg-info/requires.txt +0 -1
- {pyarmor-8.5.7 → pyarmor-8.5.9}/MANIFEST.in +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/README.md +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/README.rst +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/__init__.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/benchmark.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/build_meta.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/bootstrap.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/config.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/hdinfo.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/merge.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/mixer.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/public_capsule.zip +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/register.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cli/shell.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/cobuilder.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/README-ZH.md +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/README.md +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/build-for-exe.bat +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/build-for-freeze.bat +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/build-with-project.bat +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/build-with-project.sh +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/cx_Freeze/hello.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/cx_Freeze/queens.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/cx_Freeze/setup.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/helloworld/foo.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/obfuscate-app.bat +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/obfuscate-app.sh +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/obfuscate-pkg.bat +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/obfuscate-pkg.sh +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pack-obfuscated-scripts.bat +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pack-obfuscated-scripts.sh +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/py2exe/hello.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/py2exe/queens.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/py2exe/setup.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Arithmetic.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Calls.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/CommandLine.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Constructs.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Dict.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Exceptions.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Imports.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Instances.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Lists.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Lookups.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/NewInstances.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Numbers.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Setup.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Strings.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/Tuples.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/With.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/clockres.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/package/__init__.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/package/submodule.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/pybench.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/pybench/systimes.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/simple/queens.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/testmod/hello.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/testmod/queens.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/testpkg/main.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/testpkg/mypkg/__init__.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/examples/testpkg/mypkg/foo.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/__init__.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/build_data_module.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/buildext.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/get_bind_key.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/get_license_info.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/get_platform_name.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/merge.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/repack.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/helper/superuntime.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/license.tri +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/platforms/darwin/x86_64/_pytransform.dylib +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/platforms/linux/x86/_pytransform.so +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/platforms/linux/x86_64/_pytransform.so +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/platforms/windows/x86/_pytransform.dll +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/platforms/windows/x86_64/_pytransform.dll +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/plugins/README.md +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/plugins/check_ntp_time.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/polyfills/__init__.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/polyfills/argparse.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/product.key +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/project.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/protect_code.pt +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/protect_code2.pt +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/public.key +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/public_capsule.zip +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/pyarmor-deprecated.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/pyarmor-webui.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/pyarmor.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/pyimcore.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/pyshield.key +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/pyshield.lic +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/pytransform.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/reform.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/register.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/sppmode.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor/utils.py +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor.egg-info/SOURCES.txt +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor.egg-info/dependency_links.txt +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor.egg-info/entry_points.txt +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/pyarmor.egg-info/top_level.txt +0 -0
- {pyarmor-8.5.7 → pyarmor-8.5.9}/setup.cfg +0 -0
|
@@ -2,24 +2,367 @@ import logging
|
|
|
2
2
|
import marshal
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
|
-
import struct
|
|
6
5
|
import sys
|
|
7
|
-
import tempfile
|
|
8
6
|
|
|
9
7
|
from fnmatch import fnmatch
|
|
10
|
-
from
|
|
11
|
-
from subprocess import check_call, check_output, DEVNULL
|
|
8
|
+
from subprocess import check_call, DEVNULL
|
|
12
9
|
|
|
10
|
+
# Only used by BundleRepacker, they could be removed with deprecated routines
|
|
11
|
+
import struct
|
|
12
|
+
import tempfile
|
|
13
|
+
from importlib._bootstrap_external import _code_to_timestamp_pyc
|
|
13
14
|
from PyInstaller.archive.writers import ZlibArchiveWriter, CArchiveWriter
|
|
14
15
|
from PyInstaller.archive.readers import CArchiveReader
|
|
15
|
-
try:
|
|
16
|
-
from PyInstaller.loader.pyimod02_archive import ZlibArchiveReader
|
|
17
|
-
except ModuleNotFoundError:
|
|
18
|
-
# Since 5.3
|
|
19
|
-
from PyInstaller.loader.pyimod01_archive import ZlibArchiveReader
|
|
20
16
|
from PyInstaller.compat import is_darwin, is_linux, is_win
|
|
21
17
|
|
|
22
18
|
|
|
19
|
+
logger = logging.getLogger('repack')
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def find_packer(mode):
|
|
23
|
+
if mode in ('onefile', 'onedir', 'F', 'D', 'FC', 'DC'):
|
|
24
|
+
return AutoRepacker
|
|
25
|
+
|
|
26
|
+
if isinstance(mode, str) and mode.endswith('.spec'):
|
|
27
|
+
return SpecRepacker
|
|
28
|
+
|
|
29
|
+
return BundleRepacker
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def autoclean_output(output, autoclean=True):
|
|
33
|
+
if os.path.exists(output) and autoclean:
|
|
34
|
+
n = len(os.path.abspath(output).split(os.sep))
|
|
35
|
+
if n < 3:
|
|
36
|
+
prompt = 'Are you sure to remove path "%s" (y/n)? '
|
|
37
|
+
choice = input(prompt % output).lower()[:1]
|
|
38
|
+
if not choice == 'y':
|
|
39
|
+
return
|
|
40
|
+
logger.info('clean output path "%s"', output)
|
|
41
|
+
shutil.rmtree(output)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# This patch is used to modify the specfile generated by PyInstaller
|
|
45
|
+
#
|
|
46
|
+
# It mainly does:
|
|
47
|
+
#
|
|
48
|
+
# 1. Find all the imported modules and packages, save to hook script
|
|
49
|
+
#
|
|
50
|
+
# 2. Find imported modules and packages in the same path of main
|
|
51
|
+
# script, and save their names to one list (all of them will be
|
|
52
|
+
# obfuscated automatically)
|
|
53
|
+
#
|
|
54
|
+
spec_patch_code = '''
|
|
55
|
+
import marshal
|
|
56
|
+
import os
|
|
57
|
+
|
|
58
|
+
from PyInstaller.compat import base_prefix, EXTENSION_SUFFIXES
|
|
59
|
+
from sys import prefix, exec_prefix
|
|
60
|
+
from fnmatch import fnmatch
|
|
61
|
+
|
|
62
|
+
exlist = set([base_prefix, prefix, exec_prefix])
|
|
63
|
+
expats = [os.path.join(os.path.normpath(x), '*') for x in exlist]
|
|
64
|
+
|
|
65
|
+
src = {src!r}
|
|
66
|
+
resfile = {resfile!r}
|
|
67
|
+
hookscript = {hookscript!r}
|
|
68
|
+
|
|
69
|
+
nsrc = len(src) + 1
|
|
70
|
+
rsrc = os.path.relpath(src)
|
|
71
|
+
rsrc = '' if rsrc == '.' else rsrc
|
|
72
|
+
psrc = os.path.join(src, '*')
|
|
73
|
+
|
|
74
|
+
hiddenimports = set([])
|
|
75
|
+
plist = set([])
|
|
76
|
+
mlist = []
|
|
77
|
+
|
|
78
|
+
for name, path, kind in a.pure:
|
|
79
|
+
if name.startswith('pyi_rth'):
|
|
80
|
+
continue
|
|
81
|
+
hiddenimports.add(name)
|
|
82
|
+
if fnmatch(path, psrc) and not any([fnmatch(path, x) for x in expats]):
|
|
83
|
+
if name.find('.') == -1 and os.path.basename(path) != '__init__.py':
|
|
84
|
+
mlist.append(os.path.join(rsrc, path[nsrc:]))
|
|
85
|
+
else:
|
|
86
|
+
pkgname = os.path.dirname(path[nsrc:]).split(os.sep)[0]
|
|
87
|
+
plist.add(os.path.join(rsrc, pkgname))
|
|
88
|
+
|
|
89
|
+
for name, path, kind in a.binaries:
|
|
90
|
+
if kind == 'EXTENSION':
|
|
91
|
+
for x in EXTENSION_SUFFIXES:
|
|
92
|
+
if fnmatch(name, '*' + x):
|
|
93
|
+
name = name[:-len(x)]
|
|
94
|
+
break
|
|
95
|
+
hiddenimports.add(name.replace(os.sep, '.'))
|
|
96
|
+
|
|
97
|
+
with open(resfile, 'wb') as f:
|
|
98
|
+
marshal.dump(mlist + list(plist), f)
|
|
99
|
+
with open(hookscript, 'w') as f:
|
|
100
|
+
f.write("hiddenimports=[%s]" % ", ".join([repr(x) for x in hiddenimports]))
|
|
101
|
+
'''
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class AutoRepacker:
|
|
105
|
+
"""New repacker to support PyInstaller 6.0+
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
ctx: build context
|
|
109
|
+
mode: onefile or onedir
|
|
110
|
+
inputs: main script to pack
|
|
111
|
+
output: path to store final bundle, default is `dist`
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
def __init__(self, ctx, mode, inputs, output):
|
|
115
|
+
self.ctx = ctx
|
|
116
|
+
self.script = inputs[0]
|
|
117
|
+
self.output = os.path.normpath(output) if output else 'dist'
|
|
118
|
+
|
|
119
|
+
self.name = os.path.splitext(os.path.basename(self.script))[0]
|
|
120
|
+
self.obfpath = os.path.normpath(self.ctx.pack_obfpath)
|
|
121
|
+
self.packpath = os.path.normpath(self.ctx.pack_basepath)
|
|
122
|
+
self.workpath = os.path.join(self.packpath, 'build')
|
|
123
|
+
self.pyicmd = [sys.executable, '-m', 'PyInstaller']
|
|
124
|
+
self.autoclean = mode in ('FC', 'DC')
|
|
125
|
+
self.modeopt = '-F' if mode in ('onefile', 'F', 'FC') else '-D'
|
|
126
|
+
self.init_opts()
|
|
127
|
+
|
|
128
|
+
def init_opts(self):
|
|
129
|
+
self.pyiopts = []
|
|
130
|
+
|
|
131
|
+
opts = self.ctx.pyi_options
|
|
132
|
+
exopts = '--noconfirm', '-y', '--onefile', '-F', '--onedir', '-D'
|
|
133
|
+
exvalues = '--distpath', '--specpath', '--workpath'
|
|
134
|
+
|
|
135
|
+
n = 0
|
|
136
|
+
while n < len(opts):
|
|
137
|
+
x = opts[n]
|
|
138
|
+
if x in ('--name', '-n'):
|
|
139
|
+
self.name = opts[n+1]
|
|
140
|
+
|
|
141
|
+
if x in ('--noconfirm', '-y'):
|
|
142
|
+
self.autoclean = True
|
|
143
|
+
|
|
144
|
+
if x in exvalues:
|
|
145
|
+
n += 1
|
|
146
|
+
elif x not in exopts:
|
|
147
|
+
self.pyiopts.append(x)
|
|
148
|
+
n += 1
|
|
149
|
+
|
|
150
|
+
def analysis(self):
|
|
151
|
+
"""Got imported modules and packages by PyInstaller
|
|
152
|
+
|
|
153
|
+
Generate hook script
|
|
154
|
+
Return file/dir list need to be obfuscated
|
|
155
|
+
"""
|
|
156
|
+
cmdspec = [sys.executable, '-m', 'PyInstaller.utils.cliutils.makespec']
|
|
157
|
+
cmdspec.extend(self.pyiopts)
|
|
158
|
+
cmdspec.append(self.script)
|
|
159
|
+
logger.debug('%s', ' '.join(cmdspec))
|
|
160
|
+
logger.info('call PyInstaller to generate specfile')
|
|
161
|
+
check_call(cmdspec, stdout=DEVNULL, stderr=DEVNULL)
|
|
162
|
+
|
|
163
|
+
specfile = self.name + '.spec'
|
|
164
|
+
rtname = self.ctx.runtime_package_name
|
|
165
|
+
resfile = os.path.join(self.packpath, 'resources.list')
|
|
166
|
+
hookscript = os.path.join(self.packpath, 'hook-%s.py' % rtname)
|
|
167
|
+
self.patch_specfile(specfile, hookscript, resfile)
|
|
168
|
+
|
|
169
|
+
cmdlist = self.pyicmd + ['--clean', '--workpath', self.workpath]
|
|
170
|
+
cmdlist.append(specfile)
|
|
171
|
+
logger.debug('%s', ' '.join(cmdlist))
|
|
172
|
+
logger.info('call PyInstaller to analysis, '
|
|
173
|
+
'it may take several minutes ...')
|
|
174
|
+
check_call(cmdlist, stdout=DEVNULL, stderr=DEVNULL)
|
|
175
|
+
|
|
176
|
+
with open(resfile, 'rb') as f:
|
|
177
|
+
reslist = marshal.load(f)
|
|
178
|
+
|
|
179
|
+
resoptions = self.ctx.get_res_options('')
|
|
180
|
+
excludes = resoptions.get('excludes', '').split()
|
|
181
|
+
if excludes:
|
|
182
|
+
reslist = [x for x in reslist
|
|
183
|
+
if not any([fnmatch(x, pat) for pat in excludes])]
|
|
184
|
+
return reslist
|
|
185
|
+
|
|
186
|
+
def build(self):
|
|
187
|
+
"""Generate final bundle to output"""
|
|
188
|
+
obfscript = os.path.join(self.obfpath, os.path.basename(self.script))
|
|
189
|
+
cmdlist = self.pyicmd + [
|
|
190
|
+
'--clean',
|
|
191
|
+
'--distpath', self.output,
|
|
192
|
+
'--workpath', self.workpath,
|
|
193
|
+
'--additional-hooks-dir', self.packpath,
|
|
194
|
+
self.modeopt
|
|
195
|
+
]
|
|
196
|
+
cmdlist.extend(self.pyiopts)
|
|
197
|
+
cmdlist.append(obfscript)
|
|
198
|
+
|
|
199
|
+
logger.debug('%s', ' '.join(cmdlist))
|
|
200
|
+
logger.info('call PyInstaller to generate final bundle ...\n')
|
|
201
|
+
check_call(cmdlist)
|
|
202
|
+
logger.info('')
|
|
203
|
+
logger.info('the final bundle has been generated to "%s" successfully',
|
|
204
|
+
self.output)
|
|
205
|
+
|
|
206
|
+
def patch_specfile(self, specfile, hookscript, resfile):
|
|
207
|
+
lines = []
|
|
208
|
+
with open(specfile, 'r', encoding='utf-8') as f:
|
|
209
|
+
for line in f:
|
|
210
|
+
if line.startswith('pyz = PYZ'):
|
|
211
|
+
break
|
|
212
|
+
lines.append(line)
|
|
213
|
+
else:
|
|
214
|
+
logger.error('no found line starts with "pyz = PYZ"')
|
|
215
|
+
raise RuntimeError('unsupported specfile "%s"' % specfile)
|
|
216
|
+
|
|
217
|
+
lines.append(spec_patch_code.format(
|
|
218
|
+
src=os.path.abspath(os.path.dirname(self.script)),
|
|
219
|
+
hookscript=os.path.abspath(hookscript),
|
|
220
|
+
resfile=os.path.abspath(resfile)))
|
|
221
|
+
|
|
222
|
+
with open(specfile, 'w', encoding='utf-8') as f:
|
|
223
|
+
f.write(''.join(lines))
|
|
224
|
+
|
|
225
|
+
def check(self):
|
|
226
|
+
autoclean_output(self.output, self.autoclean)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
manual_spec_patch = '''
|
|
230
|
+
# Pyarmor patch start:
|
|
231
|
+
|
|
232
|
+
def apply_pyarmor_patch():
|
|
233
|
+
|
|
234
|
+
srcpath = {srcpath!r}
|
|
235
|
+
obfpath = {obfpath!r}
|
|
236
|
+
pkgname = {rtname!r}
|
|
237
|
+
pkgpath = os.path.join(obfpath, pkgname)
|
|
238
|
+
extpath = os.path.join(pkgname, {extname!r})
|
|
239
|
+
|
|
240
|
+
if hasattr(a.pure, '_code_cache'):
|
|
241
|
+
code_cache = a.pure._code_cache
|
|
242
|
+
else:
|
|
243
|
+
from PyInstaller.config import CONF
|
|
244
|
+
code_cache = CONF['code_cache'].get(id(a.pure))
|
|
245
|
+
|
|
246
|
+
srclist = [os.path.normcase(x) for x in srcpath]
|
|
247
|
+
def match_obfuscated_script(orgpath):
|
|
248
|
+
for x in srclist:
|
|
249
|
+
if os.path.normcase(orgpath).startswith(x):
|
|
250
|
+
return os.path.join(obfpath, orgpath[len(x)+1:])
|
|
251
|
+
|
|
252
|
+
count = 0
|
|
253
|
+
for i in range(len(a.scripts)):
|
|
254
|
+
x = match_obfuscated_script(a.scripts[i][1])
|
|
255
|
+
if x and os.path.exists(x):
|
|
256
|
+
a.scripts[i] = a.scripts[i][0], x, a.scripts[i][2]
|
|
257
|
+
count += 1
|
|
258
|
+
if count == 0:
|
|
259
|
+
raise RuntimeError('No obfuscated script found')
|
|
260
|
+
|
|
261
|
+
for i in range(len(a.pure)):
|
|
262
|
+
x = match_obfuscated_script(a.pure[i][1])
|
|
263
|
+
if x and os.path.exists(x):
|
|
264
|
+
code_cache.pop(a.pure[i][0], None)
|
|
265
|
+
a.pure[i] = a.pure[i][0], x, a.pure[i][2]
|
|
266
|
+
|
|
267
|
+
a.pure.append((pkgname, os.path.join(pkgpath, '__init__.py'), 'PYMODULE'))
|
|
268
|
+
a.binaries.append((extpath, os.path.join(obfpath, extpath), 'EXTENSION'))
|
|
269
|
+
|
|
270
|
+
apply_pyarmor_patch()
|
|
271
|
+
|
|
272
|
+
# Pyarmor patch end.
|
|
273
|
+
'''
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class SpecRepacker:
|
|
277
|
+
"""Patch specfile and use it to pack obfuscated scripts
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
ctx: build context
|
|
281
|
+
specfile: specfile need to be patched
|
|
282
|
+
inputs: main script to pack
|
|
283
|
+
output: path to store final bundle, default is `dist`
|
|
284
|
+
"""
|
|
285
|
+
|
|
286
|
+
def __init__(self, ctx, specfile, inputs, output):
|
|
287
|
+
self.ctx = ctx
|
|
288
|
+
self.specfile = specfile
|
|
289
|
+
self.script = inputs[0]
|
|
290
|
+
self.output = os.path.normpath(output) if output else 'dist'
|
|
291
|
+
|
|
292
|
+
self.pyicmd = [sys.executable, '-m', 'PyInstaller']
|
|
293
|
+
self.obfpath = os.path.normpath(self.ctx.pack_obfpath)
|
|
294
|
+
|
|
295
|
+
def build(self):
|
|
296
|
+
"""Generate patched specfile and pack obfuscated scripts"""
|
|
297
|
+
specfile = self.specfile[:-5] + '.patched.spec'
|
|
298
|
+
logger.info('generate patched specfile "%s"', specfile)
|
|
299
|
+
|
|
300
|
+
rtpkg = self.ctx.runtime_package_name
|
|
301
|
+
for x in os.listdir(os.path.join(self.obfpath, rtpkg)):
|
|
302
|
+
if x.startswith('pyarmor_runtime'):
|
|
303
|
+
extname = x
|
|
304
|
+
break
|
|
305
|
+
else:
|
|
306
|
+
raise RuntimeError('no found extension `pyarmor_runtime`')
|
|
307
|
+
|
|
308
|
+
patch = manual_spec_patch.format(
|
|
309
|
+
srcpath=[os.path.abspath(os.path.dirname(self.script))],
|
|
310
|
+
obfpath=os.path.abspath(self.obfpath),
|
|
311
|
+
rtname=self.ctx.runtime_package_name,
|
|
312
|
+
extname=extname)
|
|
313
|
+
|
|
314
|
+
with open(self.specfile, 'r', encoding='utf-8') as f:
|
|
315
|
+
lines = f.readlines()
|
|
316
|
+
|
|
317
|
+
n = 0
|
|
318
|
+
for line in lines:
|
|
319
|
+
if line.startswith('pyz = PYZ'):
|
|
320
|
+
lines[n:n] = [patch]
|
|
321
|
+
break
|
|
322
|
+
n += 1
|
|
323
|
+
else:
|
|
324
|
+
logger.error('no found line starts with "pyz = PYZ"')
|
|
325
|
+
raise RuntimeError('unsupported specfile "%s"' % self.specfile)
|
|
326
|
+
|
|
327
|
+
with open(specfile, 'w', encoding='utf-8') as f:
|
|
328
|
+
f.write(''.join(lines))
|
|
329
|
+
|
|
330
|
+
cmdlist = self.pyicmd + [
|
|
331
|
+
'--clean',
|
|
332
|
+
'--distpath', self.output,
|
|
333
|
+
'--workpath', os.path.join(self.ctx.pack_basepath, 'build'),
|
|
334
|
+
specfile
|
|
335
|
+
]
|
|
336
|
+
logger.info('call PyInstaller to generate final bundle ...'
|
|
337
|
+
'\n\n%s\n', ' '.join(cmdlist))
|
|
338
|
+
check_call(cmdlist)
|
|
339
|
+
logger.info('')
|
|
340
|
+
logger.info('the final bundle has been generated to "%s" successfully',
|
|
341
|
+
self.output)
|
|
342
|
+
|
|
343
|
+
def check(self):
|
|
344
|
+
options = self.ctx.pyi_options
|
|
345
|
+
autoclean = '-y' in options or '--noconfirm' in options
|
|
346
|
+
autoclean_output(self.output, autoclean)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
##############################################################
|
|
350
|
+
#
|
|
351
|
+
# Deprecated routines
|
|
352
|
+
#
|
|
353
|
+
# This is the old method to repack executable generated by PyInstaller
|
|
354
|
+
#
|
|
355
|
+
# Why is it deprecated?
|
|
356
|
+
#
|
|
357
|
+
# 1. It need hack PyInstaller bundle structure which may be changed in
|
|
358
|
+
# different PyInstaller version.
|
|
359
|
+
#
|
|
360
|
+
# Actually, it doesn't work for PyInstaller 5.13+ because of this
|
|
361
|
+
#
|
|
362
|
+
# 2. Not friend to junior users
|
|
363
|
+
#
|
|
364
|
+
##
|
|
365
|
+
|
|
23
366
|
# Type codes for PYZ PYZ entries
|
|
24
367
|
PYZ_ITEM_MODULE = 0
|
|
25
368
|
PYZ_ITEM_PKG = 1
|
|
@@ -42,9 +385,6 @@ PKG_ITEM_SPLASH = 'l' # splash resources
|
|
|
42
385
|
EXTRACT_SUFFIX = '_extracted'
|
|
43
386
|
|
|
44
387
|
|
|
45
|
-
logger = logging.getLogger('repack')
|
|
46
|
-
|
|
47
|
-
|
|
48
388
|
class CArchiveReader2(CArchiveReader):
|
|
49
389
|
|
|
50
390
|
def find_magic_pattern(self, fp, magic_pattern):
|
|
@@ -94,6 +434,12 @@ class CArchiveReader2(CArchiveReader):
|
|
|
94
434
|
if hasattr(self, 'open_embedded_archive'):
|
|
95
435
|
return self.open_embedded_archive(name)
|
|
96
436
|
|
|
437
|
+
try:
|
|
438
|
+
from PyInstaller.loader.pyimod02_archive import ZlibArchiveReader
|
|
439
|
+
except ModuleNotFoundError:
|
|
440
|
+
# Since 5.3
|
|
441
|
+
from PyInstaller.loader.pyimod01_archive import ZlibArchiveReader
|
|
442
|
+
|
|
97
443
|
ndx = self.toc.find(name)
|
|
98
444
|
(dpos, dlen, ulen, flag, typcd, nm) = self.toc.get(ndx)
|
|
99
445
|
return ZlibArchiveReader(self.path, self.pkg_start + dpos)
|
|
@@ -307,13 +653,16 @@ def repack_executable(executable, buildpath, obfpath, rtentry, codesign=None):
|
|
|
307
653
|
logger.info('generate patched bundle "%s" successfully', executable)
|
|
308
654
|
|
|
309
655
|
|
|
310
|
-
class
|
|
656
|
+
class BundleRepacker:
|
|
657
|
+
"""Deprecated method since v8.5.8"""
|
|
311
658
|
|
|
312
|
-
def __init__(self, executable,
|
|
659
|
+
def __init__(self, ctx, executable, inputs, output):
|
|
660
|
+
self.ctx = ctx
|
|
313
661
|
self.executable = executable
|
|
314
|
-
self.
|
|
315
|
-
self.
|
|
316
|
-
self.
|
|
662
|
+
self.output = os.path.normpath(output) if output else 'dist'
|
|
663
|
+
self.buildpath = ctx.pack_basepath
|
|
664
|
+
self.codesign = ctx.cfg['pack'].get('codesign_identify', None)
|
|
665
|
+
self.extract_carchive(executable, self.buildpath)
|
|
317
666
|
|
|
318
667
|
def check(self):
|
|
319
668
|
try:
|
|
@@ -361,6 +710,10 @@ class Repacker:
|
|
|
361
710
|
for x in os.scandir(os.path.dirname(executable))])
|
|
362
711
|
logger.debug('one file mode is %s', bool(self.one_file_mode))
|
|
363
712
|
|
|
713
|
+
def build(self):
|
|
714
|
+
obfpath = os.path.normpath(self.ctx.pack_obfpath)
|
|
715
|
+
self.repack(obfpath, self.ctx.runtime_package_name)
|
|
716
|
+
|
|
364
717
|
def repack(self, obfpath, rtname, entry=None):
|
|
365
718
|
buildpath = self.buildpath
|
|
366
719
|
executable = self.executable
|
|
@@ -415,6 +768,7 @@ class Repacker:
|
|
|
415
768
|
def _fixup_darwin_rtbinary(self, rtbinary, pylib_name):
|
|
416
769
|
'''Unused since Pyarmor 8.3.0'''
|
|
417
770
|
from sys import version_info as pyver
|
|
771
|
+
from subprocess import check_output
|
|
418
772
|
pylib = os.path.normpath(os.path.join('@rpath', pylib_name))
|
|
419
773
|
output = check_output(['otool', '-L', rtbinary])
|
|
420
774
|
for line in output.splitlines():
|
|
@@ -437,185 +791,3 @@ class Repacker:
|
|
|
437
791
|
check_call(cmdlist, stdout=DEVNULL, stderr=DEVNULL)
|
|
438
792
|
except Exception as e:
|
|
439
793
|
logger.warning('%s', e)
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
# This patch is used to modify the specfile generate by PyInstaller
|
|
443
|
-
#
|
|
444
|
-
# It has 2 goals:
|
|
445
|
-
#
|
|
446
|
-
# 1. Find all the imported modules and packages
|
|
447
|
-
#
|
|
448
|
-
# Save them to hook script
|
|
449
|
-
#
|
|
450
|
-
# 2. Search scripts and packages in the path of entry script
|
|
451
|
-
#
|
|
452
|
-
# All of them will be obfuscated automatically
|
|
453
|
-
#
|
|
454
|
-
spec_patch_code = '''
|
|
455
|
-
import marshal
|
|
456
|
-
import os
|
|
457
|
-
|
|
458
|
-
from PyInstaller.compat import base_prefix
|
|
459
|
-
from sys import prefix, exec_prefix
|
|
460
|
-
|
|
461
|
-
exlist = set([base_prefix, prefix, exec_prefix])
|
|
462
|
-
exlist = [os.path.normpath(x) for x in exlist]
|
|
463
|
-
|
|
464
|
-
src = {src}
|
|
465
|
-
sn = len(src) + 1
|
|
466
|
-
sdir = os.path.relpath(src)
|
|
467
|
-
sdir = '' if sdir == '.' else sdir
|
|
468
|
-
|
|
469
|
-
hiddenimports = set([])
|
|
470
|
-
plist = set([])
|
|
471
|
-
mlist = []
|
|
472
|
-
|
|
473
|
-
for name, path, kind in a.pure:
|
|
474
|
-
if name.startswith('pyi_rth'):
|
|
475
|
-
continue
|
|
476
|
-
hiddenimports.add(name)
|
|
477
|
-
if path.startswith(src) and not any([path.startswith(x) for x in exlist]):
|
|
478
|
-
if name.find('.') == -1 and os.path.basename(path) != '__init__.py':
|
|
479
|
-
mlist.append(os.path.join(sdir, path[sn:]))
|
|
480
|
-
else:
|
|
481
|
-
pkgname = os.path.dirname(path[sn:]).split(os.sep)[0]
|
|
482
|
-
plist.add(os.path.join(sdir, pkgname))
|
|
483
|
-
|
|
484
|
-
with open({resfile}, 'wb') as f:
|
|
485
|
-
marshal.dump(mlist + list(plist), f)
|
|
486
|
-
with open({hookscript}, 'w') as f:
|
|
487
|
-
f.write("hiddenimports=[%s]" % ", ".join([repr(x) for x in hiddenimports]))
|
|
488
|
-
'''
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
class Repacker6:
|
|
492
|
-
"""New repacker to support PyInstaller 6.0+
|
|
493
|
-
|
|
494
|
-
Args:
|
|
495
|
-
ctx: build context
|
|
496
|
-
mode: onefile or onedir
|
|
497
|
-
inputs: main script to pack
|
|
498
|
-
output: path to store final bundle, default is `dist`
|
|
499
|
-
"""
|
|
500
|
-
|
|
501
|
-
def __init__(self, ctx, mode, inputs, output):
|
|
502
|
-
self.ctx = ctx
|
|
503
|
-
self.inputs = inputs
|
|
504
|
-
self.output = os.path.normpath(output) if output else 'dist'
|
|
505
|
-
|
|
506
|
-
self.script = self.inputs[0]
|
|
507
|
-
self.name = os.path.splitext(os.path.basename(self.script))[0]
|
|
508
|
-
self.obfpath = os.path.normpath(self.ctx.pack_obfpath)
|
|
509
|
-
self.packpath = os.path.normpath(self.ctx.pack_basepath)
|
|
510
|
-
self.workpath = os.path.join(self.packpath, 'build')
|
|
511
|
-
self.pyicmd = [sys.executable, '-m', 'PyInstaller']
|
|
512
|
-
self.autoclean = mode in ('FC', 'DC')
|
|
513
|
-
self.modeopt = '-F' if mode in ('onefile', 'F', 'FC') else '-D'
|
|
514
|
-
self.init_opts()
|
|
515
|
-
|
|
516
|
-
def init_opts(self):
|
|
517
|
-
opts = self.ctx.pyi_options
|
|
518
|
-
exopts = '--noconfirm', '-y', '--onefile', '-F', '--onedir', '-D'
|
|
519
|
-
exvalues = '--distpath', '--specpath', '--workpath'
|
|
520
|
-
|
|
521
|
-
self.pyiopts = []
|
|
522
|
-
|
|
523
|
-
n = 0
|
|
524
|
-
while n < len(opts):
|
|
525
|
-
x = opts[n]
|
|
526
|
-
if x in ('--name', '-n'):
|
|
527
|
-
self.name = opts[n+1]
|
|
528
|
-
|
|
529
|
-
if x in exvalues:
|
|
530
|
-
n += 1
|
|
531
|
-
elif x not in exopts:
|
|
532
|
-
self.pyiopts.append(x)
|
|
533
|
-
n += 1
|
|
534
|
-
|
|
535
|
-
def analysis(self):
|
|
536
|
-
"""Got imported modules and packages by PyInstaller
|
|
537
|
-
|
|
538
|
-
Generate hook script
|
|
539
|
-
Return file/dir list need to be obfuscated
|
|
540
|
-
"""
|
|
541
|
-
cmdspec = [sys.executable, '-m', 'PyInstaller.utils.cliutils.makespec']
|
|
542
|
-
cmdspec.extend(self.pyiopts)
|
|
543
|
-
cmdspec.append(self.script)
|
|
544
|
-
logger.debug('%s', ' '.join(cmdspec))
|
|
545
|
-
logger.info('call PyInstaller to generate specfile')
|
|
546
|
-
check_call(cmdspec, stdout=DEVNULL, stderr=DEVNULL)
|
|
547
|
-
|
|
548
|
-
specfile = self.name + '.spec'
|
|
549
|
-
rtname = self.ctx.runtime_package_name
|
|
550
|
-
resfile = os.path.join(self.packpath, 'resources.list')
|
|
551
|
-
hookscript = os.path.join(self.packpath, 'hook-%s.py' % rtname)
|
|
552
|
-
self.patch_specfile(specfile, hookscript, resfile)
|
|
553
|
-
|
|
554
|
-
cmdlist = self.pyicmd + ['--clean', '--workpath', self.workpath]
|
|
555
|
-
cmdlist.append(specfile)
|
|
556
|
-
logger.debug('%s', ' '.join(cmdlist))
|
|
557
|
-
logger.info('call PyInstaller to analysis, '
|
|
558
|
-
'it may take several minutes ...')
|
|
559
|
-
check_call(cmdlist, stdout=DEVNULL, stderr=DEVNULL)
|
|
560
|
-
|
|
561
|
-
with open(resfile, 'rb') as f:
|
|
562
|
-
reslist = marshal.load(f)
|
|
563
|
-
|
|
564
|
-
resoptions = self.ctx.get_res_options('')
|
|
565
|
-
excludes = resoptions.get('excludes', '').split()
|
|
566
|
-
if excludes:
|
|
567
|
-
reslist = [x for x in reslist
|
|
568
|
-
if not any([fnmatch(x, pat) for pat in excludes])]
|
|
569
|
-
return reslist
|
|
570
|
-
|
|
571
|
-
def build(self):
|
|
572
|
-
"""Generate final bundle to output"""
|
|
573
|
-
obfscript = os.path.join(self.obfpath, os.path.basename(self.script))
|
|
574
|
-
cmdlist = self.pyicmd + [
|
|
575
|
-
'--clean',
|
|
576
|
-
'--distpath', self.output,
|
|
577
|
-
'--workpath', self.workpath,
|
|
578
|
-
'--additional-hooks-dir', self.packpath,
|
|
579
|
-
self.modeopt
|
|
580
|
-
]
|
|
581
|
-
cmdlist.extend(self.pyiopts)
|
|
582
|
-
cmdlist.append(obfscript)
|
|
583
|
-
|
|
584
|
-
logger.debug('%s', ' '.join(cmdlist))
|
|
585
|
-
logger.info('call PyInstaller to generate final bundle ...\n')
|
|
586
|
-
check_call(cmdlist)
|
|
587
|
-
logger.info('')
|
|
588
|
-
logger.info('the final bundle has been generated to "%s" successfully',
|
|
589
|
-
self.output)
|
|
590
|
-
|
|
591
|
-
def repack(self, *unused):
|
|
592
|
-
"""Only for compatible with Repacker"""
|
|
593
|
-
self.build()
|
|
594
|
-
|
|
595
|
-
def patch_specfile(self, specfile, hookscript, resfile):
|
|
596
|
-
# TODO: non-ascii need specify encoding to open file
|
|
597
|
-
lines = []
|
|
598
|
-
with open(specfile, 'r') as f:
|
|
599
|
-
for line in f:
|
|
600
|
-
if line.startswith('pyz = PYZ'):
|
|
601
|
-
break
|
|
602
|
-
lines.append(line)
|
|
603
|
-
|
|
604
|
-
lines.append(spec_patch_code.format(
|
|
605
|
-
src=repr(os.path.abspath(os.path.dirname(self.script))),
|
|
606
|
-
hookscript=repr(os.path.abspath(hookscript)),
|
|
607
|
-
resfile=repr(os.path.abspath(resfile))))
|
|
608
|
-
|
|
609
|
-
with open(specfile, 'w') as f:
|
|
610
|
-
f.write(''.join(lines))
|
|
611
|
-
|
|
612
|
-
def check(self):
|
|
613
|
-
if os.path.exists(self.output) and self.autoclean:
|
|
614
|
-
n = len(os.path.abspath(self.output).split(os.sep))
|
|
615
|
-
if n < 3:
|
|
616
|
-
prompt = 'Are you sure to remove path "%s" (y/n)? '
|
|
617
|
-
choice = input(prompt % self.output).lower()[:1]
|
|
618
|
-
if not choice == 'y':
|
|
619
|
-
return
|
|
620
|
-
logger.info('clean output path "%s"', self.output)
|
|
621
|
-
shutil.rmtree(self.output)
|
|
@@ -200,7 +200,7 @@ class PycResource(FileResource):
|
|
|
200
200
|
class PathResource(Resource):
|
|
201
201
|
|
|
202
202
|
def __init__(self, path, name=None, parent=None):
|
|
203
|
-
super().__init__(path, name=
|
|
203
|
+
super().__init__(path, name=os.path.basename(path), parent=parent)
|
|
204
204
|
self.respaths = []
|
|
205
205
|
self.resfiles = []
|
|
206
206
|
|
|
@@ -294,6 +294,8 @@ def _patch_specfile(obfdist, src, specfile, hookpath=None, encoding=None,
|
|
|
294
294
|
end_lines = ("# Patch end.", "", "",)
|
|
295
295
|
|
|
296
296
|
main_lines = (
|
|
297
|
+
"from PyInstaller.config import CONF",
|
|
298
|
+
"_code_cache = getattr(a.pure, '_code_cache', CONF['code_cache'].get(id(a.pure)))",
|
|
297
299
|
"_src = %s" % repr(os.path.abspath(src)),
|
|
298
300
|
"_obf = 0",
|
|
299
301
|
"for i in range(len(a.scripts)):",
|
|
@@ -308,9 +310,9 @@ def _patch_specfile(obfdist, src, specfile, hookpath=None, encoding=None,
|
|
|
308
310
|
" if a.pure[i][1].startswith(_src):",
|
|
309
311
|
" x = a.pure[i][1].replace(_src, r'%s')" % p,
|
|
310
312
|
" if os.path.exists(x):",
|
|
311
|
-
" if
|
|
313
|
+
" if _code_cache:",
|
|
312
314
|
" with open(x) as f:",
|
|
313
|
-
"
|
|
315
|
+
" _code_cache[a.pure[i][0]] = compile(f.read(), a.pure[i][1], 'exec')",
|
|
314
316
|
" a.pure[i] = a.pure[i][0], x, a.pure[i][2]",
|
|
315
317
|
)
|
|
316
318
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyarmor.cli.core~=6.5.2
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pyarmor.cli.core~=6.5.1
|
|
File without changes
|
|
File without changes
|