pyarmor 8.5.3__zip → 8.5.5__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.3 → pyarmor-8.5.5}/PKG-INFO +1 -1
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/__init__.py +1 -1
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/__main__.py +15 -7
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/context.py +31 -4
- pyarmor-8.5.5/pyarmor/cli/core.data.1 +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/default.cfg +28 -1
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/generate.py +14 -2
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/repack.py +179 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/config.py +1 -1
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor.egg-info/PKG-INFO +1 -1
- pyarmor-8.5.3/pyarmor/cli/core.data.1 +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/MANIFEST.in +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/README.md +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/README.rst +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/__init__.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/benchmark.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/build_meta.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/bootstrap.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/bug.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/config.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/core.data.2 +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/core.data.3 +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/docker.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/hdinfo.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/merge.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/mixer.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/plugin.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/public_capsule.zip +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/register.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/resource.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cli/shell.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/cobuilder.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/README-ZH.md +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/README.md +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/build-for-exe.bat +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/build-for-freeze.bat +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/build-with-project.bat +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/build-with-project.sh +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/cx_Freeze/hello.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/cx_Freeze/queens.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/cx_Freeze/setup.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/helloworld/foo.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/obfuscate-app.bat +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/obfuscate-app.sh +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/obfuscate-pkg.bat +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/obfuscate-pkg.sh +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pack-obfuscated-scripts.bat +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pack-obfuscated-scripts.sh +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/py2exe/hello.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/py2exe/queens.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/py2exe/setup.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Arithmetic.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Calls.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/CommandLine.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Constructs.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Dict.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Exceptions.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Imports.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Instances.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Lists.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Lookups.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/NewInstances.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Numbers.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Setup.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Strings.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/Tuples.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/With.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/clockres.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/package/__init__.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/package/submodule.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/pybench.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/pybench/systimes.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/simple/queens.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/testmod/hello.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/testmod/queens.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/testpkg/main.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/testpkg/mypkg/__init__.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/examples/testpkg/mypkg/foo.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/__init__.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/build_data_module.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/buildext.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/get_bind_key.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/get_license_info.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/get_platform_name.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/merge.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/repack.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/helper/superuntime.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/license.tri +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/packer.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/platforms/darwin/x86_64/_pytransform.dylib +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/platforms/linux/x86/_pytransform.so +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/platforms/linux/x86_64/_pytransform.so +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/platforms/windows/x86/_pytransform.dll +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/platforms/windows/x86_64/_pytransform.dll +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/plugins/README.md +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/plugins/check_ntp_time.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/polyfills/__init__.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/polyfills/argparse.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/product.key +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/project.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/protect_code.pt +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/protect_code2.pt +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/public.key +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/public_capsule.zip +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/pyarmor-deprecated.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/pyarmor-webui.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/pyarmor.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/pyimcore.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/pyshield.key +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/pyshield.lic +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/pytransform.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/reform.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/register.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/sppmode.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor/utils.py +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor.egg-info/SOURCES.txt +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor.egg-info/dependency_links.txt +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor.egg-info/entry_points.txt +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor.egg-info/requires.txt +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/pyarmor.egg-info/top_level.txt +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/setup.cfg +0 -0
- {pyarmor-8.5.3 → pyarmor-8.5.5}/setup.py +0 -0
|
@@ -135,8 +135,8 @@ def format_gen_args(ctx, args):
|
|
|
135
135
|
options['user_data'] = args.bind_data
|
|
136
136
|
|
|
137
137
|
if args.pack:
|
|
138
|
-
dist_path =
|
|
139
|
-
logger.info('implicitly
|
|
138
|
+
dist_path = ctx.pack_obfpath
|
|
139
|
+
logger.info('implicitly save obfuscated scripts to "%s"', dist_path)
|
|
140
140
|
options['output'] = dist_path
|
|
141
141
|
|
|
142
142
|
return options
|
|
@@ -209,8 +209,10 @@ def check_gen_context(ctx, args):
|
|
|
209
209
|
raise CliError('--outer conflicts with any -e, --period, -b')
|
|
210
210
|
|
|
211
211
|
if args.pack:
|
|
212
|
-
|
|
213
|
-
|
|
212
|
+
choices = 'auto', 'onefile', 'onedir', 'F', 'D', 'FC', 'DC'
|
|
213
|
+
if args.pack not in choices and not os.path.isfile(args.pack):
|
|
214
|
+
raise CliError('--pack must be an executable file, '
|
|
215
|
+
'"auto", "onefile" or "onedir"')
|
|
214
216
|
if args.no_runtime:
|
|
215
217
|
raise CliError('--pack conficts with --no-runtime, --use-runtime')
|
|
216
218
|
if ctx.import_prefix:
|
|
@@ -230,10 +232,16 @@ def cmd_gen(ctx, args):
|
|
|
230
232
|
return _cmd_gen_key(builder, options)
|
|
231
233
|
elif args.inputs[0].lower() in ('runtime', 'run', 'r'):
|
|
232
234
|
_cmd_gen_runtime(builder, options)
|
|
235
|
+
elif args.pack in ('auto', 'onefile', 'onedir', 'F', 'D', 'FC', 'DC'):
|
|
236
|
+
from .repack import Repacker6
|
|
237
|
+
packer = Repacker6(ctx, args.pack, options['inputs'], args.output)
|
|
238
|
+
packer.check()
|
|
239
|
+
builder.process(options, packer)
|
|
240
|
+
Plugin.post_build(ctx, pack=args.pack)
|
|
233
241
|
elif args.pack:
|
|
234
242
|
from .repack import Repacker
|
|
235
243
|
codesign = ctx.cfg['pack'].get('codesign_identify', None)
|
|
236
|
-
packer = Repacker(args.pack, ctx.
|
|
244
|
+
packer = Repacker(args.pack, ctx.pack_basepath, codesign=codesign)
|
|
237
245
|
packer.check()
|
|
238
246
|
builder.process(options, packer=packer)
|
|
239
247
|
Plugin.post_build(ctx, pack=args.pack)
|
|
@@ -412,8 +420,8 @@ https://pyarmor.readthedocs.io/en/stable/reference/man.html#pyarmor-gen
|
|
|
412
420
|
'action arguments'
|
|
413
421
|
).add_mutually_exclusive_group()
|
|
414
422
|
group.add_argument(
|
|
415
|
-
'--pack', metavar='
|
|
416
|
-
help='
|
|
423
|
+
'--pack', metavar='MODE',
|
|
424
|
+
help='specify pack mode, onefile or onedir'
|
|
417
425
|
)
|
|
418
426
|
group.add_argument(
|
|
419
427
|
'--no-runtime', action='store_true', help=argparse.SUPPRESS
|
|
@@ -366,10 +366,6 @@ class Context(object):
|
|
|
366
366
|
return self._check_logpath(
|
|
367
367
|
self.cfg['logging'].get('trace_logfile', 'pyarmor.trace.log'))
|
|
368
368
|
|
|
369
|
-
@property
|
|
370
|
-
def repack_path(self):
|
|
371
|
-
return os.path.join(self.local_path, 'pack')
|
|
372
|
-
|
|
373
369
|
def _optb(self, section, name):
|
|
374
370
|
return self.cfg.getboolean(section, name, vars=self.cmd_options)
|
|
375
371
|
|
|
@@ -608,6 +604,10 @@ class Context(object):
|
|
|
608
604
|
def runtime_obf_key_mode(self):
|
|
609
605
|
return self._opti('runtime', 'obf_key_mode')
|
|
610
606
|
|
|
607
|
+
@property
|
|
608
|
+
def runtime_patch_extension(self):
|
|
609
|
+
return self._opti('runtime', 'patch_extension')
|
|
610
|
+
|
|
611
611
|
#
|
|
612
612
|
# RFT settings
|
|
613
613
|
#
|
|
@@ -717,3 +717,30 @@ class Context(object):
|
|
|
717
717
|
|
|
718
718
|
with get_response('pyarmor.dashingsoft.com') as res:
|
|
719
719
|
return res.read()
|
|
720
|
+
|
|
721
|
+
#
|
|
722
|
+
# Pack options for auto/onefile/onefolder mode
|
|
723
|
+
#
|
|
724
|
+
@property
|
|
725
|
+
def pyi_options(self):
|
|
726
|
+
from json import loads as json_loads
|
|
727
|
+
from shlex import split as split_opt
|
|
728
|
+
pyi_opts = []
|
|
729
|
+
jsmarker = 'json::'
|
|
730
|
+
for line in self.cfg['pack'].get('pyi_options', '').splitlines():
|
|
731
|
+
line = line.strip()
|
|
732
|
+
if line.startswith(jsmarker):
|
|
733
|
+
pyi_opts.extend(json_loads(line[len(jsmarker):]))
|
|
734
|
+
elif line.startswith('-'):
|
|
735
|
+
pyi_opts.extend(split_opt(line))
|
|
736
|
+
elif line:
|
|
737
|
+
pyi_opts.append(line)
|
|
738
|
+
return pyi_opts
|
|
739
|
+
|
|
740
|
+
@property
|
|
741
|
+
def pack_basepath(self):
|
|
742
|
+
return os.path.join(self.local_path, 'pack')
|
|
743
|
+
|
|
744
|
+
@property
|
|
745
|
+
def pack_obfpath(self):
|
|
746
|
+
return os.path.join(self.pack_basepath, 'dist')
|
|
Binary file
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
;; Pyarmor version
|
|
4
4
|
major = 8
|
|
5
5
|
minor = 5
|
|
6
|
-
patch =
|
|
6
|
+
patch = 5
|
|
7
7
|
|
|
8
8
|
;; Compatible core version
|
|
9
9
|
cli.core = 6.5.1
|
|
@@ -223,6 +223,19 @@ package_name_format = pyarmor_runtime_{suffix}
|
|
|
223
223
|
;; pyarmor_runtime.so
|
|
224
224
|
simple_extension_name = 1
|
|
225
225
|
|
|
226
|
+
;; Whether patching extension to embedded runtime key
|
|
227
|
+
;;
|
|
228
|
+
;; 0: do not patch extension, but store runtime key to one file
|
|
229
|
+
;; 1: runtime key is embedded into extension
|
|
230
|
+
;;
|
|
231
|
+
;; The purpose is to solve code sign issue for Darwin platform
|
|
232
|
+
;; Do not patch extension will keep code sign, so need not re-sign
|
|
233
|
+
;; But it need an extra file.
|
|
234
|
+
;;
|
|
235
|
+
;; Note: it's different from outer runtime key.
|
|
236
|
+
;;
|
|
237
|
+
patch_extension = 1
|
|
238
|
+
|
|
226
239
|
;; Obfuscate runtime key
|
|
227
240
|
;; 0: no obfuscation
|
|
228
241
|
;; 1: simple obfuscation
|
|
@@ -342,6 +355,20 @@ strip = 0
|
|
|
342
355
|
;; append, append it to archive
|
|
343
356
|
no_matched_pyc = error
|
|
344
357
|
|
|
358
|
+
;; Extra options to call PyInstaller when packing the obfuscated scripts
|
|
359
|
+
;; One option one line, name and value separted by one whitespace
|
|
360
|
+
;; For example
|
|
361
|
+
;;
|
|
362
|
+
;; pyi_options = -w
|
|
363
|
+
;; --add-data default.cfg:.
|
|
364
|
+
;; --icon myapp.ico
|
|
365
|
+
;;
|
|
366
|
+
;; The following options could not be used here:
|
|
367
|
+
;;
|
|
368
|
+
;; --distpath, --workpath, --specpath
|
|
369
|
+
;;
|
|
370
|
+
; pyi_options =
|
|
371
|
+
|
|
345
372
|
[bcc]
|
|
346
373
|
unsupported_functions = exec eval super locals __assert_armored__
|
|
347
374
|
unsupported_nodes = AsyncFunctionDef AsyncFor AsyncWith Await Yield YieldFrom GeneratorExp NamedExpr MatchValue MatchSingleton MatchSequence MatchMapping MatchClass MatchStar MatchAs MatchOr
|
|
@@ -62,6 +62,13 @@ class Finder(object):
|
|
|
62
62
|
self.ctx.obfuscated_modules.add(res.pkgname)
|
|
63
63
|
self.ctx.extra_resources.append(res)
|
|
64
64
|
|
|
65
|
+
def append(self, resources):
|
|
66
|
+
resnames = [x.pkgname for x in self.ctx.resources]
|
|
67
|
+
for res in self._build_resource(resources):
|
|
68
|
+
if res.pkgname not in resnames:
|
|
69
|
+
self.ctx.obfuscated_modules.add(res.pkgname)
|
|
70
|
+
self.ctx.extra_resources.append(res)
|
|
71
|
+
|
|
65
72
|
def process(self):
|
|
66
73
|
logger.info('search inputs ...')
|
|
67
74
|
self.prepare(self.ctx.input_paths)
|
|
@@ -149,8 +156,13 @@ class Builder(object):
|
|
|
149
156
|
finder = Finder(self.ctx)
|
|
150
157
|
finder.process()
|
|
151
158
|
|
|
152
|
-
if packer
|
|
153
|
-
|
|
159
|
+
if packer:
|
|
160
|
+
if options.get('self_contained'):
|
|
161
|
+
finder.process_extra(packer.contents)
|
|
162
|
+
if hasattr(packer, 'analysis'):
|
|
163
|
+
auto_resources = packer.analysis()
|
|
164
|
+
logger.info('find extra resources: %s', auto_resources)
|
|
165
|
+
finder.append(auto_resources)
|
|
154
166
|
|
|
155
167
|
Pytransform3.pre_build(self.ctx)
|
|
156
168
|
|
|
@@ -3,6 +3,7 @@ import marshal
|
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
5
|
import struct
|
|
6
|
+
import sys
|
|
6
7
|
import tempfile
|
|
7
8
|
|
|
8
9
|
from importlib._bootstrap_external import _code_to_timestamp_pyc
|
|
@@ -435,3 +436,181 @@ class Repacker:
|
|
|
435
436
|
check_call(cmdlist, stdout=DEVNULL, stderr=DEVNULL)
|
|
436
437
|
except Exception as e:
|
|
437
438
|
logger.warning('%s', e)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
# This patch is used to modify the specfile generate by PyInstaller
|
|
442
|
+
#
|
|
443
|
+
# It has 2 goals:
|
|
444
|
+
#
|
|
445
|
+
# 1. Find all the imported modules and packages
|
|
446
|
+
#
|
|
447
|
+
# Save them to hook script
|
|
448
|
+
#
|
|
449
|
+
# 2. Search scripts and packages in the path of entry script
|
|
450
|
+
#
|
|
451
|
+
# All of them will be obfuscated automatically
|
|
452
|
+
#
|
|
453
|
+
spec_patch_code = '''
|
|
454
|
+
from PyInstaller.compat import base_prefix
|
|
455
|
+
import marshal
|
|
456
|
+
import os
|
|
457
|
+
|
|
458
|
+
hiddenimports = set([])
|
|
459
|
+
plist = set([])
|
|
460
|
+
mlist = []
|
|
461
|
+
src = {src}
|
|
462
|
+
sn = len(src) + 1
|
|
463
|
+
prefix = os.path.relpath(src)
|
|
464
|
+
prefix = '' if prefix == '.' else prefix
|
|
465
|
+
|
|
466
|
+
for name, path, kind in a.pure:
|
|
467
|
+
if name.startswith('pyi_rth'):
|
|
468
|
+
continue
|
|
469
|
+
if path.startswith(src) and not path.startswith(base_prefix):
|
|
470
|
+
hiddenimports.add(name)
|
|
471
|
+
if name.find('.') == -1 and os.path.basename(path) != '__init__.py':
|
|
472
|
+
mlist.append(os.path.join(prefix, path[sn:]))
|
|
473
|
+
else:
|
|
474
|
+
pkgname = os.path.dirname(path[sn:]).split(os.sep)[0]
|
|
475
|
+
plist.add(os.path.join(prefix, pkgname))
|
|
476
|
+
else:
|
|
477
|
+
hiddenimports.add(name.split('.')[0])
|
|
478
|
+
|
|
479
|
+
with open({resfile}, 'wb') as f:
|
|
480
|
+
marshal.dump(mlist + list(plist), f)
|
|
481
|
+
with open({hookscript}, 'w') as f:
|
|
482
|
+
f.write("hiddenimports=[%s]" % ", ".join([repr(x) for x in hiddenimports]))
|
|
483
|
+
'''
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class Repacker6:
|
|
487
|
+
"""New repacker to support PyInstaller 6.0+
|
|
488
|
+
|
|
489
|
+
Args:
|
|
490
|
+
ctx: build context
|
|
491
|
+
mode: onefile or onefolder
|
|
492
|
+
inputs: main script to pack
|
|
493
|
+
"""
|
|
494
|
+
|
|
495
|
+
def __init__(self, ctx, mode, inputs, output):
|
|
496
|
+
self.ctx = ctx
|
|
497
|
+
self.inputs = inputs
|
|
498
|
+
self.output = 'dist' if output is None else os.path.normpath(output)
|
|
499
|
+
|
|
500
|
+
self.script = self.inputs[0]
|
|
501
|
+
self.obfpath = os.path.normpath(self.ctx.pack_obfpath)
|
|
502
|
+
self.packpath = os.path.normpath(self.ctx.pack_basepath)
|
|
503
|
+
self.workpath = os.path.join(self.packpath, 'build')
|
|
504
|
+
self.pyicmd = [sys.executable, '-m', 'PyInstaller']
|
|
505
|
+
self.pyiopts = self.init_opts(mode)
|
|
506
|
+
self.autoclean = mode in ('FC', 'DC')
|
|
507
|
+
|
|
508
|
+
def init_opts(self, mode):
|
|
509
|
+
opts = []
|
|
510
|
+
exopts = '--noconfirm', '-y'
|
|
511
|
+
if mode == 'auto':
|
|
512
|
+
exopts += ('--onefile', '-F', '--onefolder', '-D')
|
|
513
|
+
else:
|
|
514
|
+
opts.append('-F' if mode in ('onefile', 'F', 'FC') else '-D')
|
|
515
|
+
opts.extend(self.ctx.pyi_options)
|
|
516
|
+
|
|
517
|
+
exvalues = '--distpath', '--specpath', '--workpath'
|
|
518
|
+
return self.filter_opts(opts, exvalues, exopts)
|
|
519
|
+
|
|
520
|
+
def filter_opts(self, opts, exvalues, exopts=None):
|
|
521
|
+
result = []
|
|
522
|
+
isvalue = False
|
|
523
|
+
for x in opts:
|
|
524
|
+
if isvalue:
|
|
525
|
+
isvalue = False
|
|
526
|
+
elif x in exvalues:
|
|
527
|
+
isvalue = True
|
|
528
|
+
elif exopts is None or x not in exopts:
|
|
529
|
+
result.append(x)
|
|
530
|
+
return result
|
|
531
|
+
|
|
532
|
+
def analysis(self):
|
|
533
|
+
"""Got imported modules and packages by PyInstaller
|
|
534
|
+
|
|
535
|
+
Generate hook script
|
|
536
|
+
Return file/dir list need to be obfuscated
|
|
537
|
+
"""
|
|
538
|
+
cmdspec = [
|
|
539
|
+
sys.executable, '-m', 'PyInstaller.utils.cliutils.makespec',
|
|
540
|
+
'--specpath', self.packpath
|
|
541
|
+
]
|
|
542
|
+
cmdspec.extend(self.filter_opts(self.pyiopts, ('--name', '-N')))
|
|
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
|
+
name = os.path.splitext(os.path.basename(self.script))[0]
|
|
549
|
+
rtname = self.ctx.runtime_package_name
|
|
550
|
+
specfile = os.path.join(self.packpath, name + '.spec')
|
|
551
|
+
resfile = os.path.join(self.packpath, 'resources.list')
|
|
552
|
+
hookscript = os.path.join(self.packpath, 'hook-%s.py' % rtname)
|
|
553
|
+
self.patch_specfile(specfile, hookscript, resfile)
|
|
554
|
+
|
|
555
|
+
cmdlist = self.pyicmd + ['--clean', '--workpath', self.workpath]
|
|
556
|
+
cmdlist.extend(self.pyiopts)
|
|
557
|
+
cmdlist.append(specfile)
|
|
558
|
+
logger.debug('%s', ' '.join(cmdlist))
|
|
559
|
+
logger.info('call PyInstaller to analysis, '
|
|
560
|
+
'it may take several minutes ...')
|
|
561
|
+
check_call(cmdlist, stdout=DEVNULL, stderr=DEVNULL)
|
|
562
|
+
|
|
563
|
+
with open(resfile, 'rb') as f:
|
|
564
|
+
return marshal.load(f)
|
|
565
|
+
|
|
566
|
+
def build(self):
|
|
567
|
+
"""Generate final bundle to output"""
|
|
568
|
+
script = os.path.join(self.obfpath, os.path.basename(self.inputs[0]))
|
|
569
|
+
cmdlist = self.pyicmd + [
|
|
570
|
+
'--clean',
|
|
571
|
+
'--distpath', self.output,
|
|
572
|
+
'--workpath', self.workpath,
|
|
573
|
+
'--specpath', self.packpath,
|
|
574
|
+
'--additional-hooks-dir', self.packpath,
|
|
575
|
+
]
|
|
576
|
+
cmdlist.extend(self.pyiopts)
|
|
577
|
+
cmdlist.append(script)
|
|
578
|
+
|
|
579
|
+
logger.debug('%s', ' '.join(cmdlist))
|
|
580
|
+
logger.info('call PyInstaller to generate final bundle ...\n')
|
|
581
|
+
check_call(cmdlist)
|
|
582
|
+
logger.info('')
|
|
583
|
+
logger.info('the final bundle "%s" has been generate successfully',
|
|
584
|
+
self.output)
|
|
585
|
+
|
|
586
|
+
def repack(self, *unused):
|
|
587
|
+
"""Only for compatible with Repacker"""
|
|
588
|
+
self.build()
|
|
589
|
+
|
|
590
|
+
def patch_specfile(self, specfile, hookscript, resfile):
|
|
591
|
+
# TODO: non-ascii need specify encoding to open file
|
|
592
|
+
lines = []
|
|
593
|
+
with open(specfile, 'r') as f:
|
|
594
|
+
for line in f:
|
|
595
|
+
if line.startswith('pyz = PYZ'):
|
|
596
|
+
break
|
|
597
|
+
lines.append(line)
|
|
598
|
+
|
|
599
|
+
lines.append(spec_patch_code.format(
|
|
600
|
+
src=repr(os.path.abspath(os.path.dirname(self.script))),
|
|
601
|
+
hookscript=repr(os.path.abspath(hookscript)),
|
|
602
|
+
resfile=repr(os.path.abspath(resfile))))
|
|
603
|
+
|
|
604
|
+
with open(specfile, 'w') as f:
|
|
605
|
+
f.write(''.join(lines))
|
|
606
|
+
|
|
607
|
+
def check(self):
|
|
608
|
+
if os.path.exists(self.output) and self.autoclean:
|
|
609
|
+
n = len(os.path.abspath(self.output).split(os.sep))
|
|
610
|
+
if n < 3:
|
|
611
|
+
prompt = 'Are you sure to remove path "%s" (y/n)? '
|
|
612
|
+
choice = input(prompt % self.output).lower()[:1]
|
|
613
|
+
if not choice == 'y':
|
|
614
|
+
return
|
|
615
|
+
logger.info('clean output path "%s"', self.output)
|
|
616
|
+
shutil.rmtree(self.output)
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|