pyarmor 9.2.0__tar.gz → 9.2.2__tar.gz
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-9.2.0 → pyarmor-9.2.2}/PKG-INFO +1 -1
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/__init__.py +1 -1
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/__main__.py +4 -1
- pyarmor-9.2.2/pyarmor/cli/batch.py +62 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/command.py +58 -12
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/config.py +3 -3
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/context.py +8 -2
- pyarmor-9.2.2/pyarmor/cli/core.data.1 +0 -0
- pyarmor-9.2.2/pyarmor/cli/core.data.2 +0 -0
- pyarmor-9.2.2/pyarmor/cli/core.data.3 +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/default.cfg +5 -5
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/model.py +9 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/plugin.py +5 -5
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/project.py +94 -21
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/register.py +5 -3
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/resource.py +21 -9
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/shell.py +5 -2
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/config.py +1 -1
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor.egg-info/PKG-INFO +1 -1
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor.egg-info/SOURCES.txt +1 -0
- pyarmor-9.2.0/pyarmor/cli/core.data.1 +0 -0
- pyarmor-9.2.0/pyarmor/cli/core.data.2 +0 -0
- pyarmor-9.2.0/pyarmor/cli/core.data.3 +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/MANIFEST.in +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/README.md +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/README.rst +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/__init__.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/benchmark.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/build_meta.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/bootstrap.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/bug.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/docker.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/generate.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/hdinfo.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/merge.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/mixer.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/public_capsule.zip +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cli/repack.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/cobuilder.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/README-ZH.md +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/README.md +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/build-for-exe.bat +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/build-for-freeze.bat +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/build-with-project.bat +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/build-with-project.sh +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/cx_Freeze/hello.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/cx_Freeze/queens.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/cx_Freeze/setup.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/helloworld/foo.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/obfuscate-app.bat +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/obfuscate-app.sh +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/obfuscate-pkg.bat +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/obfuscate-pkg.sh +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pack-obfuscated-scripts.bat +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pack-obfuscated-scripts.sh +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/py2exe/hello.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/py2exe/queens.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/py2exe/setup.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Arithmetic.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Calls.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/CommandLine.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Constructs.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Dict.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Exceptions.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Imports.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Instances.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Lists.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Lookups.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/NewInstances.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Numbers.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Setup.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Strings.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/Tuples.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/With.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/clockres.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/package/__init__.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/package/submodule.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/pybench.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/pybench/systimes.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/simple/queens.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/testmod/hello.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/testmod/queens.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/testpkg/main.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/testpkg/mypkg/__init__.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/examples/testpkg/mypkg/foo.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/__init__.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/build_data_module.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/buildext.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/get_bind_key.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/get_license_info.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/get_platform_name.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/merge.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/repack.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/helper/superuntime.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/license.tri +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/packer.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/platforms/darwin/x86_64/_pytransform.dylib +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/platforms/linux/x86/_pytransform.so +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/platforms/linux/x86_64/_pytransform.so +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/platforms/windows/x86/_pytransform.dll +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/platforms/windows/x86_64/_pytransform.dll +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/plugins/README.md +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/plugins/check_ntp_time.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/polyfills/__init__.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/polyfills/argparse.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/product.key +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/project.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/protect_code.pt +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/protect_code2.pt +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/public.key +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/public_capsule.zip +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/pyarmor-deprecated.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/pyarmor-webui.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/pyarmor.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/pyimcore.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/pyshield.key +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/pyshield.lic +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/pytransform.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/reform.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/register.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/sppmode.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor/utils.py +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor.egg-info/dependency_links.txt +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor.egg-info/entry_points.txt +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor.egg-info/requires.txt +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/pyarmor.egg-info/top_level.txt +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/setup.cfg +0 -0
- {pyarmor-9.2.0 → pyarmor-9.2.2}/setup.py +0 -0
|
@@ -325,7 +325,7 @@ def cmd_reg(ctx, args):
|
|
|
325
325
|
|
|
326
326
|
else:
|
|
327
327
|
regsvr = WebRegister(ctx)
|
|
328
|
-
regsvr.check_request_interval()
|
|
328
|
+
regsvr.check_request_interval(activation=regfile)
|
|
329
329
|
info, msg = regsvr.prepare(regfile, args.product, upgrade=upgrade)
|
|
330
330
|
prompt = 'Are you sure to continue? (yes/no) '
|
|
331
331
|
if args.confirm:
|
|
@@ -767,6 +767,9 @@ def main_entry(argv):
|
|
|
767
767
|
if not (x == 3 and y > 6 and y < 16):
|
|
768
768
|
raise CliError('Python %s.%s is not supported' % (x, y))
|
|
769
769
|
|
|
770
|
+
if ctx.py_gil_disabled:
|
|
771
|
+
raise CliError('Pyarmor does not support free-threading Python')
|
|
772
|
+
|
|
770
773
|
if args.version:
|
|
771
774
|
print_version(ctx)
|
|
772
775
|
parser.exit()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
#############################################################
|
|
5
|
+
# #
|
|
6
|
+
# Copyright @ 2025 - Dashingsoft corp. #
|
|
7
|
+
# All rights reserved. #
|
|
8
|
+
# #
|
|
9
|
+
# Pyarmor #
|
|
10
|
+
# #
|
|
11
|
+
# Version: 9.2.1 - #
|
|
12
|
+
# #
|
|
13
|
+
#############################################################
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @File: cli/shell.py
|
|
17
|
+
#
|
|
18
|
+
# @Author: Jondy Zhao (pyarmor@163.com)
|
|
19
|
+
#
|
|
20
|
+
# @Create Date: Wed Nov 5 20:22:52 CST 2025
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
"""This script could run batch pyarmor commands.
|
|
24
|
+
|
|
25
|
+
For example:
|
|
26
|
+
|
|
27
|
+
python3 -m pyarmor.cli.batch build-script.sh
|
|
28
|
+
|
|
29
|
+
cd abc
|
|
30
|
+
pyarmor
|
|
31
|
+
|
|
32
|
+
The main purpose is to fix pyarmor CI License send too many request issues.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
import shlex
|
|
36
|
+
import os
|
|
37
|
+
|
|
38
|
+
from pyarmor.cli.__main__ import main_entry as pyarmor_run
|
|
39
|
+
|
|
40
|
+
# Do not run `pyarmor reg pyarmor-ci-xxxx.zip` here, run it before this script
|
|
41
|
+
|
|
42
|
+
build_commands = """
|
|
43
|
+
pyarmor gen main.py
|
|
44
|
+
cd ../package1
|
|
45
|
+
pyarmor gen -R --enable-bcc src/
|
|
46
|
+
cd ../package2
|
|
47
|
+
pyarmor gen -R --enable-jit --private src/
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
for cmd in build_commands.splitlines():
|
|
51
|
+
if cmd.startswith('#'):
|
|
52
|
+
continue
|
|
53
|
+
|
|
54
|
+
if cmd.startswith('cd '):
|
|
55
|
+
path = cmd[3:].strip()
|
|
56
|
+
print('Change current path:', path)
|
|
57
|
+
os.chdir(path)
|
|
58
|
+
|
|
59
|
+
elif cmd.startswith('pyarmor '):
|
|
60
|
+
print('Execute: ', cmd)
|
|
61
|
+
args = shlex.split(cmd[8:].strip())
|
|
62
|
+
pyarmor_run(args)
|
|
@@ -135,16 +135,6 @@ class Commander:
|
|
|
135
135
|
# action="store_const", const='std',
|
|
136
136
|
# help='genetate standard obfuscated scripts'
|
|
137
137
|
# )
|
|
138
|
-
# group.add_argument(
|
|
139
|
-
# '--ecc', dest='target', default='std',
|
|
140
|
-
# action="store_const", const='ecc',
|
|
141
|
-
# help='genetate scripts with embedded C code'
|
|
142
|
-
# )
|
|
143
|
-
# group.add_argument(
|
|
144
|
-
# '--vmc', dest='target', default='std',
|
|
145
|
-
# action="store_const", const='vmc',
|
|
146
|
-
# help='genetate scripts with vm C code'
|
|
147
|
-
# )
|
|
148
138
|
group.add_argument(
|
|
149
139
|
'--rft', dest='target', default='std',
|
|
150
140
|
action="store_const", const='rft',
|
|
@@ -158,7 +148,38 @@ class Commander:
|
|
|
158
148
|
group.add_argument(
|
|
159
149
|
'--mini-rft', dest='target', default='std',
|
|
160
150
|
action="store_const", const='mini-rft',
|
|
161
|
-
help='
|
|
151
|
+
help='generate scripts by combining --rft and --mini'
|
|
152
|
+
)
|
|
153
|
+
group.add_argument(
|
|
154
|
+
'--vmc', dest='target', default='std',
|
|
155
|
+
action="store_const", const='vmc',
|
|
156
|
+
help='genetate scripts with vmc code'
|
|
157
|
+
)
|
|
158
|
+
group.add_argument(
|
|
159
|
+
'--vmc-rft', dest='target', default='std',
|
|
160
|
+
action="store_const", const='vmc-rft',
|
|
161
|
+
help='generate scripts by combining --rft and --vmc'
|
|
162
|
+
)
|
|
163
|
+
group.add_argument(
|
|
164
|
+
'--ecc', dest='target', default='std',
|
|
165
|
+
action="store_const", const='ecc',
|
|
166
|
+
help='genetate scripts with embedded C code'
|
|
167
|
+
)
|
|
168
|
+
group.add_argument(
|
|
169
|
+
'--ecc-rft', dest='target', default='std',
|
|
170
|
+
action="store_const", const='ecc-rft',
|
|
171
|
+
help='generate scripts by combining --rft and --ecc'
|
|
172
|
+
)
|
|
173
|
+
group.add_argument(
|
|
174
|
+
'--ecc-nogil', dest='target', default='std',
|
|
175
|
+
action="store_const", const='ecc-nogil',
|
|
176
|
+
help='genetate ECC scripts for free-threading Python'
|
|
177
|
+
)
|
|
178
|
+
group.add_argument(
|
|
179
|
+
'--ecc-rft-nogil', dest='target', default='std',
|
|
180
|
+
action="store_const", const='ecc-rft-nogil',
|
|
181
|
+
help=('generate scripts by combining --rft and --ecc'
|
|
182
|
+
' for free-threading Python')
|
|
162
183
|
)
|
|
163
184
|
group.add_argument(
|
|
164
185
|
'--list', dest='target', default='std',
|
|
@@ -338,7 +359,7 @@ class Commander:
|
|
|
338
359
|
logger.info('%-20s: %s', key, value)
|
|
339
360
|
|
|
340
361
|
makedirs(ctx.local_path, exist_ok=True)
|
|
341
|
-
with open(ctx.local_config, 'w') as f:
|
|
362
|
+
with open(ctx.local_config, 'w', encoding=ctx.encoding) as f:
|
|
342
363
|
cfg.write(f)
|
|
343
364
|
logger.info('project saved')
|
|
344
365
|
|
|
@@ -366,6 +387,10 @@ class Commander:
|
|
|
366
387
|
)
|
|
367
388
|
cfg.read([ctx.local_config], encoding=ctx.encoding)
|
|
368
389
|
|
|
390
|
+
x, y = ctx.python_version
|
|
391
|
+
if not (x == 3 and y > 8 and y < 16):
|
|
392
|
+
raise CliError('`pyarmor build` only works for Python 3.9+')
|
|
393
|
+
|
|
369
394
|
sectname = 'project'
|
|
370
395
|
if not cfg.has_section(sectname):
|
|
371
396
|
raise CliError('no project information')
|
|
@@ -412,6 +437,8 @@ class Commander:
|
|
|
412
437
|
logger.info('build target %s ...', args.target)
|
|
413
438
|
output = args.output if args.output else 'dist'
|
|
414
439
|
self._build(project, args.target, output)
|
|
440
|
+
if args.target.startswith('std'):
|
|
441
|
+
self._cmd_gen(args)
|
|
415
442
|
logger.info('build target %s end', args.target)
|
|
416
443
|
|
|
417
444
|
def _build(self, project, target, output, value=None):
|
|
@@ -420,6 +447,25 @@ class Commander:
|
|
|
420
447
|
m = Pytransform3.init(self.ctx)
|
|
421
448
|
m.pre_build(args)
|
|
422
449
|
|
|
450
|
+
def _cmd_gen(self, args):
|
|
451
|
+
"""If build target is std, then call `pyarmor gen`
|
|
452
|
+
|
|
453
|
+
It will obfuscate the scripts with `pyarmor_runtime.so`
|
|
454
|
+
|
|
455
|
+
Most of obfuscated options are got from config file, not from
|
|
456
|
+
command line
|
|
457
|
+
|
|
458
|
+
Option `--pack` may be still got from command line
|
|
459
|
+
"""
|
|
460
|
+
from .generate import Builder
|
|
461
|
+
from .plugin import Plugin
|
|
462
|
+
|
|
463
|
+
ctx = self.ctx
|
|
464
|
+
builder = Builder(ctx)
|
|
465
|
+
Plugin.install(ctx)
|
|
466
|
+
builder.process(args)
|
|
467
|
+
Plugin.post_build(ctx)
|
|
468
|
+
|
|
423
469
|
def cmd_env(self, ctx, args):
|
|
424
470
|
"""Check and change pyarmor settings
|
|
425
471
|
|
|
@@ -43,7 +43,7 @@ class Configer(object):
|
|
|
43
43
|
|
|
44
44
|
def __init__(self, ctx, encoding=None):
|
|
45
45
|
self.ctx = ctx
|
|
46
|
-
self._encoding = encoding
|
|
46
|
+
self._encoding = encoding or ctx.encoding
|
|
47
47
|
|
|
48
48
|
def _read_config(self, filename):
|
|
49
49
|
cfg = configparser.ConfigParser(empty_lines_in_values=False)
|
|
@@ -166,7 +166,7 @@ class Configer(object):
|
|
|
166
166
|
cfg.set(sect, optname, optvalue)
|
|
167
167
|
|
|
168
168
|
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
169
|
-
with open(filename, 'w') as f:
|
|
169
|
+
with open(filename, 'w', encoding=self._encoding) as f:
|
|
170
170
|
cfg.write(f)
|
|
171
171
|
|
|
172
172
|
self._list_value(sect, optname, local=local, name=name)
|
|
@@ -196,7 +196,7 @@ class Configer(object):
|
|
|
196
196
|
logger.info('remove empty section "%s"', section)
|
|
197
197
|
cfg.remove_section(section)
|
|
198
198
|
|
|
199
|
-
with open(filename, 'w') as f:
|
|
199
|
+
with open(filename, 'w', encoding=self._encoding) as f:
|
|
200
200
|
cfg.write(f)
|
|
201
201
|
|
|
202
202
|
def _clear(self, section=None, options=None, local=True, name=None):
|
|
@@ -164,9 +164,9 @@ class Context(object):
|
|
|
164
164
|
os.path.join(self.home_path, rpath)
|
|
165
165
|
|
|
166
166
|
# self.encoding is just for reading config file
|
|
167
|
-
self.encoding = encoding
|
|
167
|
+
self.encoding = encoding if encoding else 'utf-8'
|
|
168
168
|
cfglist = self.default_config, self.global_config, self.local_config
|
|
169
|
-
self.cfg = self._read_config(cfglist, encoding=encoding)
|
|
169
|
+
self.cfg = self._read_config(cfglist, encoding=self.encoding)
|
|
170
170
|
|
|
171
171
|
# self.runtime_package = 'pyarmor_runtime'
|
|
172
172
|
# self.runtime_suffix = '_000000'
|
|
@@ -205,6 +205,7 @@ class Context(object):
|
|
|
205
205
|
empty_lines_in_values=False,
|
|
206
206
|
interpolation=configparser.ExtendedInterpolation(),
|
|
207
207
|
)
|
|
208
|
+
encoding = encoding or self.encoding
|
|
208
209
|
cfg.read(filelist, encoding=encoding)
|
|
209
210
|
return cfg
|
|
210
211
|
|
|
@@ -330,6 +331,11 @@ class Context(object):
|
|
|
330
331
|
def python_version(self):
|
|
331
332
|
return sys.version_info[:2]
|
|
332
333
|
|
|
334
|
+
@property
|
|
335
|
+
def py_gil_disabled(self):
|
|
336
|
+
from sysconfig import get_config_var
|
|
337
|
+
return 1 if get_config_var("Py_GIL_DISABLED") else 0
|
|
338
|
+
|
|
333
339
|
@property
|
|
334
340
|
def default_config(self):
|
|
335
341
|
return os.path.join(os.path.dirname(__file__), 'default.cfg')
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
;; Pyarmor version
|
|
4
4
|
major = 9
|
|
5
5
|
minor = 2
|
|
6
|
-
patch =
|
|
6
|
+
patch = 2
|
|
7
7
|
|
|
8
|
-
;; Compatible core version
|
|
8
|
+
;; Compatible core version for package: pyarmor.cli.core
|
|
9
9
|
cli.core = 8.1.0
|
|
10
|
-
mini.core = 2.0
|
|
11
10
|
|
|
12
|
-
;;
|
|
13
|
-
;;
|
|
11
|
+
;; Compatible core version for package: pyarmor.mini
|
|
12
|
+
;; Which is required to run MINI, VMC, or ECC mode scripts
|
|
13
|
+
mini.core = 3.0
|
|
14
14
|
|
|
15
15
|
;; Deprecated since Pyarmor 8.2.5
|
|
16
16
|
; cli.runtime = 3.2.5
|
|
@@ -186,7 +186,7 @@ class MultiPythonPlugin:
|
|
|
186
186
|
os.makedirs(verpath)
|
|
187
187
|
|
|
188
188
|
pkgscript = os.path.join(pkgpath, '__init__.py')
|
|
189
|
-
with open(pkgscript) as f:
|
|
189
|
+
with open(pkgscript, encoding=ctx.encoding) as f:
|
|
190
190
|
lines = f.readlines()
|
|
191
191
|
start = 1 if lines[0].startswith('#') else 0
|
|
192
192
|
|
|
@@ -196,13 +196,13 @@ class MultiPythonPlugin:
|
|
|
196
196
|
'{0} = __import__("py%d%d.pyarmor_runtime" % py_version[:2],'
|
|
197
197
|
' globals(), locals(), ["{0}"], 1).{0}'.format('__pyarmor__')
|
|
198
198
|
])
|
|
199
|
-
with open(pkgscript, 'w') as f:
|
|
199
|
+
with open(pkgscript, 'w', encoding=ctx.encoding) as f:
|
|
200
200
|
f.write(''.join(lines))
|
|
201
201
|
for x in MultiPythonPlugin.RUNTIME_FILES:
|
|
202
202
|
move(x, verpath)
|
|
203
203
|
else:
|
|
204
204
|
lines[start:start] = 'from sys import version_info as py_version\n'
|
|
205
|
-
with open(pkgscript, 'w') as f:
|
|
205
|
+
with open(pkgscript, 'w', encoding=ctx.encoding) as f:
|
|
206
206
|
f.write(''.join(lines).replace(
|
|
207
207
|
"join(['_'", "join(['py%d%d' % py_version[:2], '_'"))
|
|
208
208
|
for x in MultiPythonPlugin.RUNTIME_FILES:
|
|
@@ -253,7 +253,7 @@ class DarwinUniversalPlugin:
|
|
|
253
253
|
return
|
|
254
254
|
|
|
255
255
|
def rebuild_init(oneplat, init_script):
|
|
256
|
-
with open(init_script, 'r') as f:
|
|
256
|
+
with open(init_script, 'r', encoding=ctx.encoding) as f:
|
|
257
257
|
lines = f.readlines()
|
|
258
258
|
if oneplat:
|
|
259
259
|
lines[1:] = ['from .pyarmor_runtime import __pyarmor__']
|
|
@@ -262,7 +262,7 @@ class DarwinUniversalPlugin:
|
|
|
262
262
|
if lines[i].strip().startswith("# mach = 'universal'"):
|
|
263
263
|
lines[i] = lines[i].replace('# ', '')
|
|
264
264
|
break
|
|
265
|
-
with open(init_script, 'w') as f:
|
|
265
|
+
with open(init_script, 'w', encoding=ctx.encoding) as f:
|
|
266
266
|
f.write(''.join(lines))
|
|
267
267
|
|
|
268
268
|
rtpath = find_runtime_package(ctx, outputs[0])
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
#
|
|
24
24
|
# - Define project object for Pyarmor 9.
|
|
25
25
|
# - Define project commands: init, build
|
|
26
|
-
# - Define targets: std,
|
|
26
|
+
# - Define targets: std, mini, vmc, ecc, rft
|
|
27
27
|
|
|
28
28
|
"""Manage projects
|
|
29
29
|
|
|
@@ -151,6 +151,8 @@ class Module:
|
|
|
151
151
|
self._tree = None
|
|
152
152
|
self._type = None
|
|
153
153
|
|
|
154
|
+
self._shebang = ''
|
|
155
|
+
|
|
154
156
|
@property
|
|
155
157
|
def name(self):
|
|
156
158
|
return '' if self._name == '__init__' else self._name
|
|
@@ -190,14 +192,21 @@ class Module:
|
|
|
190
192
|
s = self.qualname + ('' if self.name else '.__init__')
|
|
191
193
|
return joinpath(*s.split('.')) + splitext(self.path)[-1]
|
|
192
194
|
|
|
193
|
-
|
|
195
|
+
@property
|
|
196
|
+
def shebang(self):
|
|
197
|
+
return self._shebang
|
|
198
|
+
|
|
199
|
+
def compile_file(self, force=False, optimize=-1):
|
|
194
200
|
if self._co is not None and not force:
|
|
195
201
|
return
|
|
196
202
|
|
|
197
203
|
self.parse_file(force=force)
|
|
198
204
|
|
|
205
|
+
options = {
|
|
206
|
+
'optimize': optimize
|
|
207
|
+
}
|
|
199
208
|
logger.info('compile %s ...', self.qualname)
|
|
200
|
-
self._co = compile(self._tree, self.abspath, 'exec')
|
|
209
|
+
self._co = compile(self._tree, self.abspath, 'exec', **options)
|
|
201
210
|
logger.info('compile %s end', self.qualname)
|
|
202
211
|
|
|
203
212
|
def parse_file(self, force=False):
|
|
@@ -206,7 +215,9 @@ class Module:
|
|
|
206
215
|
|
|
207
216
|
filename = self.abspath
|
|
208
217
|
with open(filename, 'rb') as f:
|
|
209
|
-
encoding,
|
|
218
|
+
encoding, lines = tokenize.detect_encoding(f.readline)
|
|
219
|
+
if lines and lines[0].startswith(b'#!'):
|
|
220
|
+
self._shebang = lines[0].decode(encoding)
|
|
210
221
|
|
|
211
222
|
with open(filename, 'r', encoding=encoding) as f:
|
|
212
223
|
logger.info('parse %s ...', self.qualname)
|
|
@@ -385,6 +396,11 @@ class Project:
|
|
|
385
396
|
self._rft_include_attrs = None
|
|
386
397
|
self._used_external_types = None
|
|
387
398
|
|
|
399
|
+
self._std_options = None
|
|
400
|
+
self._mini_options = None
|
|
401
|
+
self._vmc_options = None
|
|
402
|
+
self._ecc_options = None
|
|
403
|
+
|
|
388
404
|
# Log variable name in chain attributes
|
|
389
405
|
#
|
|
390
406
|
# For example, in module "foo.py":
|
|
@@ -496,6 +512,20 @@ class Project:
|
|
|
496
512
|
for x in self._namespaces:
|
|
497
513
|
yield x
|
|
498
514
|
|
|
515
|
+
@property
|
|
516
|
+
def std_options(self):
|
|
517
|
+
"""Options got from ctx.builder, not in project"""
|
|
518
|
+
if self._std_options is None:
|
|
519
|
+
cfg = self.ctx.cfg
|
|
520
|
+
optimize = cfg['builder'].getint('optimize', -1)
|
|
521
|
+
self._std_options = {
|
|
522
|
+
'optimize': optimize
|
|
523
|
+
}
|
|
524
|
+
return self._std_options
|
|
525
|
+
|
|
526
|
+
def std_opt(self, name):
|
|
527
|
+
return self.std_options.get(name)
|
|
528
|
+
|
|
499
529
|
@property
|
|
500
530
|
def rft_options(self):
|
|
501
531
|
"""Refactor options:
|
|
@@ -764,6 +794,62 @@ class Project:
|
|
|
764
794
|
self._rft_type_rules = vartypes
|
|
765
795
|
return self._rft_type_rules
|
|
766
796
|
|
|
797
|
+
@property
|
|
798
|
+
def mini_options(self):
|
|
799
|
+
"""MINI mode options:
|
|
800
|
+
|
|
801
|
+
- import_from: str
|
|
802
|
+
|
|
803
|
+
Default value is "pyarmor.mini.pyarmor_mini", it means from
|
|
804
|
+
package `pyarmor.mini` import extension `pyarmor_mini`
|
|
805
|
+
|
|
806
|
+
Set it to "pyarmor_mini" if it's distributed with obfuscated
|
|
807
|
+
scripts
|
|
808
|
+
"""
|
|
809
|
+
if self._mini_options is None:
|
|
810
|
+
cfg = self.ctx.cfg
|
|
811
|
+
sect = 'mini'
|
|
812
|
+
if cfg.has_section(sect):
|
|
813
|
+
self._mini_options = dict(cfg.items(sect))
|
|
814
|
+
else:
|
|
815
|
+
self._mini_options = {}
|
|
816
|
+
self._mini_options.setdefault(
|
|
817
|
+
'import_from', 'pyarmor.mini.pyarmor_mini')
|
|
818
|
+
return self._mini_options
|
|
819
|
+
|
|
820
|
+
def mini_opt(self, name):
|
|
821
|
+
return self.mini_options.get(name)
|
|
822
|
+
|
|
823
|
+
@property
|
|
824
|
+
def vmc_options(self):
|
|
825
|
+
"""VMC mode options"""
|
|
826
|
+
if self._vmc_options is None:
|
|
827
|
+
cfg = self.ctx.cfg
|
|
828
|
+
sect = 'vmc'
|
|
829
|
+
if cfg.has_section(sect):
|
|
830
|
+
self._vmc_options = dict(cfg.items(sect))
|
|
831
|
+
else:
|
|
832
|
+
self._vmc_options = {}
|
|
833
|
+
return self._vmc_options
|
|
834
|
+
|
|
835
|
+
def vmc_opt(self, name):
|
|
836
|
+
return self.vmc_options.get(name)
|
|
837
|
+
|
|
838
|
+
@property
|
|
839
|
+
def ecc_options(self):
|
|
840
|
+
"""ECC mode options"""
|
|
841
|
+
if self._ecc_options is None:
|
|
842
|
+
cfg = self.ctx.cfg
|
|
843
|
+
sect = 'ecc'
|
|
844
|
+
if cfg.has_section(sect):
|
|
845
|
+
self._ecc_options = dict(cfg.items(sect))
|
|
846
|
+
else:
|
|
847
|
+
self._ecc_options = {}
|
|
848
|
+
return self._ecc_options
|
|
849
|
+
|
|
850
|
+
def ecc_opt(self, name):
|
|
851
|
+
return self.ecc_options.get(name)
|
|
852
|
+
|
|
767
853
|
@property
|
|
768
854
|
def builtins(self):
|
|
769
855
|
if self._builtins is None:
|
|
@@ -780,7 +866,7 @@ class Project:
|
|
|
780
866
|
for name in names.split():
|
|
781
867
|
if name.endswith('.json'):
|
|
782
868
|
if exists(name):
|
|
783
|
-
with open(name) as f:
|
|
869
|
+
with open(name, encoding='utf-8') as f:
|
|
784
870
|
used_types.update(jsonload(f))
|
|
785
871
|
else:
|
|
786
872
|
modname = name.split('::')[0]
|
|
@@ -819,19 +905,6 @@ class Project:
|
|
|
819
905
|
self._rft_include_attrs.update(value.split())
|
|
820
906
|
return self._rft_include_attrs
|
|
821
907
|
|
|
822
|
-
def std_options(self):
|
|
823
|
-
"""Obfuscation options only for std target
|
|
824
|
-
|
|
825
|
-
- std_assert_import
|
|
826
|
-
- std_assert_call
|
|
827
|
-
- std_restrict_module
|
|
828
|
-
- std_expired_date
|
|
829
|
-
- std_bind_devices
|
|
830
|
-
|
|
831
|
-
Got from command line, not in config file
|
|
832
|
-
"""
|
|
833
|
-
pass
|
|
834
|
-
|
|
835
908
|
def get_module(self, qualname):
|
|
836
909
|
"""Get module in the project by unique qualname
|
|
837
910
|
It equals one dict: map_qualname_to_module
|
|
@@ -1013,7 +1086,7 @@ class Project:
|
|
|
1013
1086
|
if not exists(rulefile):
|
|
1014
1087
|
logger.info('no found %s', rulefile)
|
|
1015
1088
|
return
|
|
1016
|
-
with open(rulefile) as f:
|
|
1089
|
+
with open(rulefile, encoding='utf-8') as f:
|
|
1017
1090
|
fixtable = jsonload(f)
|
|
1018
1091
|
|
|
1019
1092
|
if mode == 2:
|
|
@@ -1071,7 +1144,7 @@ class Project:
|
|
|
1071
1144
|
inattrs = fixtable.get('include_attrs', [])
|
|
1072
1145
|
rftattrs = header.substitute(attrs='\n'.join(
|
|
1073
1146
|
[f'[[*{x}][{x}]]' for x in inattrs]))
|
|
1074
|
-
with open(output, 'w') as fp:
|
|
1147
|
+
with open(output, 'w', encoding='utf-8') as fp:
|
|
1075
1148
|
fp.write(rftattrs)
|
|
1076
1149
|
for attr in inattrs:
|
|
1077
1150
|
infos = attrinfo.get(attr)
|
|
@@ -1164,7 +1237,7 @@ class Project:
|
|
|
1164
1237
|
"""))
|
|
1165
1238
|
|
|
1166
1239
|
attrs = sorted(rftattrs.keys())
|
|
1167
|
-
with open(output, 'w') as fp:
|
|
1240
|
+
with open(output, 'w', encoding='utf-8') as fp:
|
|
1168
1241
|
fp.write(header.substitute(
|
|
1169
1242
|
attrs='\n'.join([f'[[*{x}][{x}]]' for x in attrs])
|
|
1170
1243
|
))
|
|
@@ -498,7 +498,7 @@ class WebRegister(Register):
|
|
|
498
498
|
conn.request("GET", url[k:])
|
|
499
499
|
return conn.getresponse()
|
|
500
500
|
|
|
501
|
-
def check_request_interval(self, delta=30.0):
|
|
501
|
+
def check_request_interval(self, delta=30.0, activation=False):
|
|
502
502
|
"""Make sure no more than 2 requests in 1 minute"""
|
|
503
503
|
tspath = os.path.join(self.ctx.reg_path, 'last_register')
|
|
504
504
|
try:
|
|
@@ -509,8 +509,10 @@ class WebRegister(Register):
|
|
|
509
509
|
from time import sleep, time
|
|
510
510
|
d = delta - (time() - st.st_mtime)
|
|
511
511
|
if d > 0:
|
|
512
|
-
|
|
513
|
-
|
|
512
|
+
if activation:
|
|
513
|
+
logger.warning(
|
|
514
|
+
'caution: this activation file "%s" can only '
|
|
515
|
+
'be used no more than 10 times', activation)
|
|
514
516
|
logger.info('waiting for %d seconds', d)
|
|
515
517
|
while time() - st.st_mtime < delta:
|
|
516
518
|
logger.info('waiting ...')
|
|
@@ -109,22 +109,34 @@ class FileResource(Resource):
|
|
|
109
109
|
return self.pyext.lower() == '.pyc'
|
|
110
110
|
|
|
111
111
|
def _get_encoding(self, encoding):
|
|
112
|
+
# Maybe: from tokenize import detect_encoding
|
|
112
113
|
from codecs import BOM_UTF8
|
|
113
114
|
from re import search as research
|
|
115
|
+
|
|
116
|
+
def find_encoding(line):
|
|
117
|
+
try:
|
|
118
|
+
pat = r'coding[=:]\s*([-\w.]+)'
|
|
119
|
+
n = line.find(b'\n')
|
|
120
|
+
if n > -1:
|
|
121
|
+
m = research(pat, line[:n].decode())
|
|
122
|
+
if m:
|
|
123
|
+
return m.group(1)
|
|
124
|
+
if line[n+1] == 35:
|
|
125
|
+
k = n + 1
|
|
126
|
+
n = line.find(b'\n', k)
|
|
127
|
+
m = research(pat, line[k:n].decode())
|
|
128
|
+
if m:
|
|
129
|
+
return m.group(1)
|
|
130
|
+
except Exception:
|
|
131
|
+
# Ignore decoding error or index error
|
|
132
|
+
pass
|
|
133
|
+
|
|
114
134
|
with open(self.fullpath, 'rb') as f:
|
|
115
135
|
line = f.read(80)
|
|
116
136
|
if line and line[:3] == BOM_UTF8:
|
|
117
137
|
return 'utf-8'
|
|
118
138
|
if line and line[0] == 35:
|
|
119
|
-
|
|
120
|
-
m = research(r'coding[=:]\s*([-\w.]+)', line[:n].decode())
|
|
121
|
-
if m:
|
|
122
|
-
return m.group(1)
|
|
123
|
-
if n > -1 and len(line) > (n+1) and line[n+1] == 35:
|
|
124
|
-
k = n + 1
|
|
125
|
-
n = line.find(b'\n', k)
|
|
126
|
-
m = research(r'coding[=:]\s*([-\w.]+)', line[k:n].decode())
|
|
127
|
-
return m and m.group(1)
|
|
139
|
+
encoding = find_encoding(line) or encoding
|
|
128
140
|
return encoding
|
|
129
141
|
|
|
130
142
|
def readlines(self, encoding=None):
|
|
@@ -86,7 +86,7 @@ class CfgEntity:
|
|
|
86
86
|
self._reader = self._writer = None
|
|
87
87
|
|
|
88
88
|
def save(self):
|
|
89
|
-
with open(self.cfgfile, 'w') as f:
|
|
89
|
+
with open(self.cfgfile, 'w', encoding=self._encoding) as f:
|
|
90
90
|
self.writer.write(f)
|
|
91
91
|
|
|
92
92
|
|
|
@@ -260,7 +260,7 @@ class PyarmorShell(cmd.Cmd):
|
|
|
260
260
|
ctx.default_config,
|
|
261
261
|
ctx.global_config,
|
|
262
262
|
ctx.local_config
|
|
263
|
-
])
|
|
263
|
+
], encoding=ctx.encoding)
|
|
264
264
|
self._domains = self._init_domains()
|
|
265
265
|
self._domain = self._section = self._domains[domain]
|
|
266
266
|
|
|
@@ -281,6 +281,9 @@ class PyarmorShell(cmd.Cmd):
|
|
|
281
281
|
domain.add_group(name, GROUPS[name])
|
|
282
282
|
|
|
283
283
|
ps.add_section('rft')
|
|
284
|
+
ps.add_section('mini')
|
|
285
|
+
ps.add_section('vmc')
|
|
286
|
+
ps.add_section('ecc')
|
|
284
287
|
|
|
285
288
|
return {'global': gs, 'local': ls, 'project': ps}
|
|
286
289
|
|
|
Binary file
|
|
Binary file
|
|
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
|