pyarmor 9.2.6__4-py3-none-any.whl

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.
Files changed (123) hide show
  1. pyarmor/README.rst +53 -0
  2. pyarmor/__init__.py +4 -0
  3. pyarmor/benchmark.py +382 -0
  4. pyarmor/build_meta.py +126 -0
  5. pyarmor/cli/__init__.py +46 -0
  6. pyarmor/cli/__main__.py +812 -0
  7. pyarmor/cli/batch.py +62 -0
  8. pyarmor/cli/bootstrap.py +207 -0
  9. pyarmor/cli/bug.py +137 -0
  10. pyarmor/cli/command.py +563 -0
  11. pyarmor/cli/config.py +306 -0
  12. pyarmor/cli/context.py +790 -0
  13. pyarmor/cli/core.data.1 +0 -0
  14. pyarmor/cli/core.data.2 +0 -0
  15. pyarmor/cli/core.data.3 +0 -0
  16. pyarmor/cli/default.cfg +564 -0
  17. pyarmor/cli/docker.py +192 -0
  18. pyarmor/cli/generate.py +256 -0
  19. pyarmor/cli/hdinfo.py +81 -0
  20. pyarmor/cli/merge.py +232 -0
  21. pyarmor/cli/mixer.py +109 -0
  22. pyarmor/cli/model.py +460 -0
  23. pyarmor/cli/plugin.py +292 -0
  24. pyarmor/cli/project.py +1281 -0
  25. pyarmor/cli/public_capsule.zip +0 -0
  26. pyarmor/cli/register.py +1093 -0
  27. pyarmor/cli/repack.py +793 -0
  28. pyarmor/cli/resource.py +265 -0
  29. pyarmor/cli/shell.py +481 -0
  30. pyarmor/cobuilder.py +154 -0
  31. pyarmor/config.py +58 -0
  32. pyarmor/examples/README-ZH.md +188 -0
  33. pyarmor/examples/README.md +201 -0
  34. pyarmor/examples/build-for-exe.bat +166 -0
  35. pyarmor/examples/build-for-freeze.bat +166 -0
  36. pyarmor/examples/build-with-project.bat +152 -0
  37. pyarmor/examples/build-with-project.sh +110 -0
  38. pyarmor/examples/cx_Freeze/hello.py +5 -0
  39. pyarmor/examples/cx_Freeze/queens.py +87 -0
  40. pyarmor/examples/cx_Freeze/setup.py +23 -0
  41. pyarmor/examples/helloworld/foo.py +68 -0
  42. pyarmor/examples/obfuscate-app.bat +65 -0
  43. pyarmor/examples/obfuscate-app.sh +45 -0
  44. pyarmor/examples/obfuscate-pkg.bat +82 -0
  45. pyarmor/examples/obfuscate-pkg.sh +60 -0
  46. pyarmor/examples/pack-obfuscated-scripts.bat +38 -0
  47. pyarmor/examples/pack-obfuscated-scripts.sh +31 -0
  48. pyarmor/examples/py2exe/hello.py +5 -0
  49. pyarmor/examples/py2exe/queens.py +87 -0
  50. pyarmor/examples/py2exe/setup.py +36 -0
  51. pyarmor/examples/pybench/Arithmetic.py +777 -0
  52. pyarmor/examples/pybench/Calls.py +560 -0
  53. pyarmor/examples/pybench/CommandLine.py +642 -0
  54. pyarmor/examples/pybench/Constructs.py +564 -0
  55. pyarmor/examples/pybench/Dict.py +504 -0
  56. pyarmor/examples/pybench/Exceptions.py +699 -0
  57. pyarmor/examples/pybench/Imports.py +138 -0
  58. pyarmor/examples/pybench/Instances.py +66 -0
  59. pyarmor/examples/pybench/Lists.py +350 -0
  60. pyarmor/examples/pybench/Lookups.py +945 -0
  61. pyarmor/examples/pybench/NewInstances.py +75 -0
  62. pyarmor/examples/pybench/Numbers.py +784 -0
  63. pyarmor/examples/pybench/Setup.py +43 -0
  64. pyarmor/examples/pybench/Strings.py +568 -0
  65. pyarmor/examples/pybench/Tuples.py +360 -0
  66. pyarmor/examples/pybench/With.py +190 -0
  67. pyarmor/examples/pybench/clockres.py +42 -0
  68. pyarmor/examples/pybench/package/__init__.py +0 -0
  69. pyarmor/examples/pybench/package/submodule.py +0 -0
  70. pyarmor/examples/pybench/pybench.py +954 -0
  71. pyarmor/examples/pybench/systimes.py +214 -0
  72. pyarmor/examples/simple/queens.py +87 -0
  73. pyarmor/examples/testmod/hello.py +66 -0
  74. pyarmor/examples/testmod/queens.py +159 -0
  75. pyarmor/examples/testpkg/main.py +4 -0
  76. pyarmor/examples/testpkg/mypkg/__init__.py +13 -0
  77. pyarmor/examples/testpkg/mypkg/foo.py +2 -0
  78. pyarmor/helper/__init__.py +1 -0
  79. pyarmor/helper/build_data_module.py +130 -0
  80. pyarmor/helper/buildext.py +446 -0
  81. pyarmor/helper/get_bind_key.py +29 -0
  82. pyarmor/helper/get_license_info.py +25 -0
  83. pyarmor/helper/get_platform_name.py +82 -0
  84. pyarmor/helper/merge.py +298 -0
  85. pyarmor/helper/repack.py +395 -0
  86. pyarmor/helper/superuntime.py +58 -0
  87. pyarmor/license.tri +0 -0
  88. pyarmor/packer.py +720 -0
  89. pyarmor/platforms/darwin/x86_64/_pytransform.dylib +0 -0
  90. pyarmor/platforms/linux/x86/_pytransform.so +0 -0
  91. pyarmor/platforms/linux/x86_64/_pytransform.so +0 -0
  92. pyarmor/platforms/windows/x86/_pytransform.dll +0 -0
  93. pyarmor/platforms/windows/x86_64/_pytransform.dll +0 -0
  94. pyarmor/plugins/README.md +176 -0
  95. pyarmor/plugins/check_ntp_time.py +482 -0
  96. pyarmor/polyfills/__init__.py +62 -0
  97. pyarmor/polyfills/argparse.py +2360 -0
  98. pyarmor/product.key +1 -0
  99. pyarmor/project.py +249 -0
  100. pyarmor/protect_code.pt +68 -0
  101. pyarmor/protect_code2.pt +47 -0
  102. pyarmor/public.key +0 -0
  103. pyarmor/public_capsule.zip +0 -0
  104. pyarmor/pyarmor-deprecated.py +843 -0
  105. pyarmor/pyarmor-webui.py +2 -0
  106. pyarmor/pyarmor.py +1647 -0
  107. pyarmor/pyimcore.py +65 -0
  108. pyarmor/pyshield.key +0 -0
  109. pyarmor/pyshield.lic +0 -0
  110. pyarmor/pytransform.py +483 -0
  111. pyarmor/reform.py +81 -0
  112. pyarmor/register.py +220 -0
  113. pyarmor/sppmode.py +105 -0
  114. pyarmor/utils.py +1871 -0
  115. pyarmor-9.2.6.dist-info/LICENSE +287 -0
  116. pyarmor-9.2.6.dist-info/LICENSE-ZH +297 -0
  117. pyarmor-9.2.6.dist-info/LICENSE-ZH.7 +102 -0
  118. pyarmor-9.2.6.dist-info/LICENSE.7 +145 -0
  119. pyarmor-9.2.6.dist-info/METADATA +79 -0
  120. pyarmor-9.2.6.dist-info/RECORD +123 -0
  121. pyarmor-9.2.6.dist-info/WHEEL +6 -0
  122. pyarmor-9.2.6.dist-info/entry_points.txt +6 -0
  123. pyarmor-9.2.6.dist-info/top_level.txt +1 -0
pyarmor/README.rst ADDED
@@ -0,0 +1,53 @@
1
+ Protect Python Scripts By Pyarmor
2
+ =================================
3
+
4
+ Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
5
+
6
+ Key Features
7
+ ------------
8
+
9
+ * The obfuscated script is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
10
+ * Provide many ways to obfuscate the scripts to balance security and performance
11
+ * Rename functions/methods/classes/variables/arguments, irreversible obfuscation
12
+ * Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
13
+ * Bind obfuscated scripts to fixed machine or expire obfuscted scripts
14
+ * Protect obfuscated scripts by Themida (Only for Windows)
15
+
16
+ Support Platforms
17
+ -----------------
18
+
19
+ * Python 3.7~3.15
20
+ * Windows
21
+ * Many linuxs, include embedded systems
22
+ * Apple Intel and Apple Silicon
23
+
24
+ Quick Start
25
+ -----------
26
+
27
+ Install::
28
+
29
+ pip install pyarmor
30
+
31
+ Obfuscate the script `foo.py`::
32
+
33
+ pyarmor gen foo.py
34
+
35
+ This command generates an obfuscated script `dist/foo.py` like this:
36
+
37
+ .. code:: python
38
+
39
+ from pyarmor_runtime import __pyarmor__
40
+ __pyarmor__(__name__, __file__, b'\x28\x83\x20\x58....')
41
+
42
+ Run it::
43
+
44
+ python dist/foo.py
45
+
46
+ More Resources
47
+ --------------
48
+
49
+ - `Home <https://github.com/dashingsoft/pyarmor>`_
50
+ - `Website <http://pyarmor.dashingsoft.com>`_
51
+ - `中文网站 <http://pyarmor.dashingsoft.com/index-zh.html>`_
52
+ - `Issues <https://github.com/dashingsoft/pyarmor/issues>`_
53
+ - `Documentation <https://pyarmor.readthedocs.io/>`_
pyarmor/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ # Package pyarmor
2
+ import sys
3
+ from os.path import abspath, dirname
4
+ sys.path.insert(0, abspath(dirname(__file__)))
pyarmor/benchmark.py ADDED
@@ -0,0 +1,382 @@
1
+ #! /usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ #############################################################
5
+ # #
6
+ # Copyright @ 2013 - 2017 Dashingsoft corp. #
7
+ # All rights reserved. #
8
+ # #
9
+ # pyarmor #
10
+ # #
11
+ # Version: 1.7.0 - #
12
+ # #
13
+ #############################################################
14
+ #
15
+ #
16
+ # @File: benchmark.py
17
+ #
18
+ # @Author: Jondy Zhao(jondy.zhao@gmail.com)
19
+ #
20
+ # @Create Date: 2017/11/21
21
+ #
22
+ # @Description:
23
+ #
24
+ # Check performance of pyarmor.
25
+ #
26
+ import logging
27
+ import os
28
+ import shutil
29
+ import sys
30
+ import subprocess
31
+ import time
32
+
33
+ from ctypes import c_int, c_void_p, py_object, pythonapi, PYFUNCTYPE
34
+
35
+ import pytransform
36
+
37
+ OBF_MODULE_MODE = 'none', 'des', 'aes'
38
+ OBF_CODE_MODE = 'none', 'fast', 'aes', 'wrap'
39
+
40
+ PYARMOR_PATH = os.path.dirname(__file__)
41
+ PYARMOR = 'pyarmor.py'
42
+
43
+
44
+ def make_test_script(filename):
45
+ lines = [
46
+ 'def empty():',
47
+ ' return 0',
48
+ '',
49
+ 'def call_1k_function(n):',
50
+ ' for i in range(n):',
51
+ ' one_thousand()',
52
+ '',
53
+ 'def call_10k_function(n):',
54
+ ' for i in range(n):',
55
+ ' ten_thousand()',
56
+ '',
57
+ 'def one_thousand():',
58
+ ' if True:',
59
+ ' i = 0',
60
+ ]
61
+ lines.extend([' i += 1'] * 100)
62
+ lines.append('\n return 1000\n')
63
+ lines.extend(['def ten_thousand():',
64
+ ' if True:',
65
+ ' i = 0'])
66
+ lines.extend([' i += 1'] * 1000)
67
+ lines.append('\n return 10000\n')
68
+
69
+ with open(filename, 'wb') as f:
70
+ f.write('\n'.join(lines).encode())
71
+
72
+
73
+ def call_pyarmor(args):
74
+ p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
75
+ p.wait()
76
+
77
+
78
+ def obffuscate_scripts(output, filename,
79
+ mod_mode, code_mode, wrap_mode, adv_mode):
80
+ project = os.path.join(output, 'project')
81
+ if os.path.exists(project):
82
+ shutil.rmtree(project)
83
+
84
+ args = [sys.executable, PYARMOR, 'init', '--src', output,
85
+ '--entry', filename, project]
86
+ call_pyarmor(args)
87
+
88
+ args = [sys.executable, PYARMOR, 'config',
89
+ '--manifest', 'include %s' % filename,
90
+ '--obf-mod', mod_mode,
91
+ '--obf-code', code_mode,
92
+ '--wrap-mode', wrap_mode,
93
+ '--advanced', adv_mode,
94
+ '--restrict-mode', '0',
95
+ '--package-runtime', '0',
96
+ project]
97
+ call_pyarmor(args)
98
+
99
+ args = [sys.executable, PYARMOR, 'build', '-B', project]
100
+ call_pyarmor(args)
101
+
102
+ for s in os.listdir(os.path.join(project, 'dist')):
103
+ shutil.copy(os.path.join(project, 'dist', s), output)
104
+
105
+
106
+ def metricmethod(func):
107
+ if not hasattr(time, 'process_time'):
108
+ time.process_time = time.clock
109
+
110
+ def wrap(*args, **kwargs):
111
+ t1 = time.process_time()
112
+ result = func(*args, **kwargs)
113
+ t2 = time.process_time()
114
+ logging.info('%-50s: %10.6f ms', func.__name__, (t2 - t1) * 1000)
115
+ return result
116
+ return wrap
117
+
118
+
119
+ @metricmethod
120
+ def verify_license(m):
121
+ try:
122
+ prototype = PYFUNCTYPE(py_object)
123
+ dlfunc = prototype(('get_registration_code', m))
124
+ code = dlfunc()
125
+ except Exception:
126
+ logging.warning('Verify license failed')
127
+ code = ''
128
+ return code
129
+
130
+
131
+ @metricmethod
132
+ def init_pytransform(m):
133
+ major, minor = sys.version_info[0:2]
134
+ # Python2.5 no sys.maxsize but sys.maxint
135
+ # bitness = 64 if sys.maxsize > 2**32 else 32
136
+ prototype = PYFUNCTYPE(c_int, c_int, c_int, c_void_p)
137
+ init_module = prototype(('init_module', m))
138
+ init_module(major, minor, pythonapi._handle)
139
+
140
+ prototype = PYFUNCTYPE(c_int, c_int, c_int, c_int)
141
+ init_runtime = prototype(('init_runtime', m))
142
+ init_runtime(0, 0, 0, 0)
143
+
144
+
145
+ @metricmethod
146
+ def load_pytransform():
147
+ return pytransform._load_library(PYARMOR_PATH, is_runtime=1)
148
+
149
+
150
+ @metricmethod
151
+ def total_extra_init_time():
152
+ m = load_pytransform()
153
+ init_pytransform(m)
154
+ verify_license(m)
155
+
156
+
157
+ @metricmethod
158
+ def import_first_no_obfuscated_module(name):
159
+ return __import__(name)
160
+
161
+
162
+ @metricmethod
163
+ def import_first_obfuscated_module(name):
164
+ return __import__(name)
165
+
166
+
167
+ @metricmethod
168
+ def re_import_no_obfuscated_module(name):
169
+ return __import__(name)
170
+
171
+
172
+ @metricmethod
173
+ def re_import_obfuscated_module(name):
174
+ return __import__(name)
175
+
176
+
177
+ @metricmethod
178
+ def run_empty_obfuscated_code_object(foo):
179
+ return foo.empty()
180
+
181
+
182
+ @metricmethod
183
+ def run_obfuscated_1k_bytecode(foo):
184
+ return foo.one_thousand()
185
+
186
+
187
+ @metricmethod
188
+ def run_obfuscated_10k_bytecode(foo):
189
+ return foo.ten_thousand()
190
+
191
+
192
+ @metricmethod
193
+ def run_empty_no_obfuscated_code_object(foo):
194
+ return foo.empty()
195
+
196
+
197
+ @metricmethod
198
+ def run_no_obfuscated_1k_bytecode(foo):
199
+ return foo.one_thousand()
200
+
201
+
202
+ @metricmethod
203
+ def run_no_obfuscated_10k_bytecode(foo):
204
+ return foo.ten_thousand()
205
+
206
+
207
+ @metricmethod
208
+ def import_many_obfuscated_modules(name, n=100):
209
+ for i in range(n):
210
+ __import__(name % i)
211
+
212
+
213
+ @metricmethod
214
+ def import_many_no_obfuscated_modules(name, n=100):
215
+ for i in range(n):
216
+ __import__(name % i)
217
+
218
+
219
+ @metricmethod
220
+ def call_1000_no_obfuscated_1k_bytecode(foo):
221
+ return foo.call_1k_function(1000)
222
+
223
+
224
+ @metricmethod
225
+ def call_1000_obfuscated_1k_bytecode(foo):
226
+ return foo.call_1k_function(1000)
227
+
228
+
229
+ @metricmethod
230
+ def call_1000_no_obfuscated_10k_bytecode(foo):
231
+ return foo.call_10k_function(1000)
232
+
233
+
234
+ @metricmethod
235
+ def call_1000_obfuscated_10k_bytecode(foo):
236
+ return foo.call_10k_function(1000)
237
+
238
+
239
+ @metricmethod
240
+ def call_10000_no_obfuscated_1k_bytecode(foo):
241
+ return foo.call_1k_function(10000)
242
+
243
+
244
+ @metricmethod
245
+ def call_10000_obfuscated_1k_bytecode(foo):
246
+ return foo.call_1k_function(10000)
247
+
248
+
249
+ @metricmethod
250
+ def call_10000_no_obfuscated_10k_bytecode(foo):
251
+ return foo.call_10k_function(10000)
252
+
253
+
254
+ @metricmethod
255
+ def call_10000_obfuscated_10k_bytecode(foo):
256
+ return foo.call_10k_function(10000)
257
+
258
+
259
+ def main():
260
+ if not os.path.exists('benchmark.py'):
261
+ logging.warning('Please change current path to %s', PYARMOR_PATH)
262
+ return
263
+
264
+ output = '.benchtest'
265
+ name = 'bfoo'
266
+ filename = os.path.join(output, name + '.py')
267
+
268
+ obname = 'obfoo'
269
+ obfilename = os.path.join(output, obname + '.py')
270
+
271
+ if len(sys.argv) > 1 and 'bootstrap'.startswith(sys.argv[1]):
272
+ if len(sys.argv) < 6:
273
+ sys.argv.extend(['1', '1', '1', '0'])
274
+ obf_mod, obf_code, wrap_mode, adv_mode = sys.argv[2:6]
275
+
276
+ if os.path.exists(output) and output.endswith('.benchtest'):
277
+ logging.info('Clean output path: %s', output)
278
+ shutil.rmtree(output)
279
+ logging.info('Create output path: %s', output)
280
+ os.makedirs(output)
281
+
282
+ logging.info('Generate test script %s ...', filename)
283
+ make_test_script(filename)
284
+
285
+ logging.info('Obffuscate test script ...')
286
+ shutil.copy(filename, obfilename)
287
+ obffuscate_scripts(output, os.path.basename(obfilename),
288
+ obf_mod, obf_code, wrap_mode, adv_mode)
289
+ if not os.path.exists(obfilename):
290
+ logging.info('Something is wrong to obsfucate the script')
291
+ return
292
+ logging.info('Generate obffuscated script %s', obfilename)
293
+
294
+ logging.info('Copy benchmark.py to %s', output)
295
+ shutil.copy('benchmark.py', output)
296
+
297
+ logging.info('')
298
+ logging.info('Now change to "%s"', output)
299
+ logging.info('Run "%s benchmark.py".', sys.executable)
300
+ return
301
+
302
+ filename = os.path.basename(filename)
303
+ if os.path.exists(filename):
304
+ logging.info('Test script: %s', filename)
305
+ else:
306
+ logging.warning('Test script: %s not found', filename)
307
+ logging.info('Run "%s benchmark.py bootstrap" first.', sys.executable)
308
+ return
309
+
310
+ obfilename = os.path.basename(obfilename)
311
+ if os.path.exists(obfilename):
312
+ logging.info('Obfuscated script: %s', obfilename)
313
+ else:
314
+ logging.warning('Obfuscated script: %s not found', obfilename)
315
+ logging.info('Run "%s benchmark.py bootstrap" first.', sys.executable)
316
+ return
317
+
318
+ logging.info('--------------------------------------')
319
+
320
+ # It doens't work for super mode
321
+ # logging.info('')
322
+ # total_extra_init_time()
323
+
324
+ logging.info('')
325
+ foo = import_first_no_obfuscated_module(name)
326
+ obfoo = import_first_obfuscated_module(obname)
327
+
328
+ logging.info('')
329
+ foo = re_import_no_obfuscated_module(name)
330
+ obfoo = re_import_obfuscated_module(obname)
331
+
332
+ logging.info('')
333
+ n = 10
334
+ logging.info('--- Import %d modules ---', n)
335
+ for i in range(n):
336
+ shutil.copy(filename, filename.replace('.py', '_%s.py' % i))
337
+ with open(obfilename) as f:
338
+ lines = f.readlines()
339
+ with open(obfilename.replace('.py', '_%s.py' % i), 'w') as f:
340
+ f.write(lines[2] if lines[0].find('pyarmor_runtime') > 0 \
341
+ else ''.join(lines))
342
+ import_many_no_obfuscated_modules('bfoo_%s', n)
343
+ import_many_obfuscated_modules('obfoo_%s', n)
344
+
345
+ logging.info('')
346
+ run_empty_no_obfuscated_code_object(foo)
347
+ run_empty_obfuscated_code_object(obfoo)
348
+
349
+ logging.info('')
350
+ run_no_obfuscated_1k_bytecode(foo)
351
+ run_obfuscated_1k_bytecode(obfoo)
352
+
353
+ logging.info('')
354
+ run_no_obfuscated_10k_bytecode(foo)
355
+ run_obfuscated_10k_bytecode(obfoo)
356
+
357
+ logging.info('')
358
+ call_1000_no_obfuscated_1k_bytecode(foo)
359
+ call_1000_obfuscated_1k_bytecode(obfoo)
360
+
361
+ logging.info('')
362
+ call_1000_no_obfuscated_10k_bytecode(foo)
363
+ call_1000_obfuscated_10k_bytecode(obfoo)
364
+
365
+ logging.info('')
366
+ call_10000_no_obfuscated_1k_bytecode(foo)
367
+ call_10000_obfuscated_1k_bytecode(obfoo)
368
+
369
+ logging.info('')
370
+ call_10000_no_obfuscated_10k_bytecode(foo)
371
+ call_10000_obfuscated_10k_bytecode(obfoo)
372
+
373
+ logging.info('')
374
+ logging.info('--------------------------------------')
375
+
376
+
377
+ if __name__ == '__main__':
378
+ logging.basicConfig(
379
+ level=logging.INFO,
380
+ format='%(message)s',
381
+ )
382
+ main()
pyarmor/build_meta.py ADDED
@@ -0,0 +1,126 @@
1
+ """A PEP 517 interface to building pyarmored wheel based on setuptools
2
+
3
+ Here is an example package
4
+
5
+ mypkg/
6
+ pyproject.toml
7
+ setup.py
8
+ src/
9
+ __init__.py
10
+ ...
11
+
12
+ The content of minimum build file "pyproject.toml"
13
+
14
+ [build-system]
15
+ requires = ["setuptools", "wheel", "pyarmor>=7.2.0"]
16
+ build-backend = "pyarmor.build_meta"
17
+
18
+ Now build a pyarmored wheel by pip
19
+
20
+ cd mypkg/
21
+ pip wheel .
22
+
23
+
24
+ Again, this is not a formal definition! Just a "taste" of the module.
25
+ """
26
+
27
+ import os
28
+ import shutil
29
+ import sys
30
+
31
+ from wheel.wheelfile import WheelFile
32
+ from wheel.cli.pack import pack as wheel_pack
33
+ from pyarmor.pyarmor import main as pyarmor_main
34
+
35
+ from setuptools.build_meta import build_wheel as setuptools_build_wheel
36
+
37
+ try:
38
+ from distutils.util import get_platform
39
+ except ModuleNotFoundError:
40
+ from polyfills import get_platform
41
+
42
+
43
+ def _wheel_unpack(path, dest='.'):
44
+ with WheelFile(path) as wf:
45
+ namever = wf.parsed_filename.group('namever')
46
+ destination = os.path.join(dest, namever)
47
+ sys.stdout.flush()
48
+ wf.extractall(destination)
49
+ return namever
50
+
51
+
52
+ def _wheel_append_runtime_files(build_path, namever, pkgname):
53
+ namelist = []
54
+ for name in os.listdir(os.path.join(build_path, pkgname)):
55
+ if name.startswith('pytransform'):
56
+ path = os.path.join(build_path, pkgname, name)
57
+ n = len(path) + 1
58
+ if os.path.isdir(path):
59
+ for root, dirs, files in os.walk(path):
60
+ prefix = root[n:].replace('\\', '/')
61
+ for x in files:
62
+ namelist.append(prefix + '/' + x)
63
+ else:
64
+ namelist.append(name)
65
+
66
+ wheel_record = os.path.join(build_path, namever + '.dist-info', 'RECORD')
67
+ with open(wheel_record, 'a') as f:
68
+ for name in namelist:
69
+ f.write(pkgname + '/' + name + ',,\n')
70
+
71
+
72
+ def _fix_config(config_settings, obf_options):
73
+ from pip._internal.configuration import Configuration, ConfigurationError
74
+ config = Configuration(False)
75
+ config.load()
76
+ for k, v in reversed(config.items()):
77
+ if k in ('pyarmor.advanced', ':env:.pyarmor-advanced'):
78
+ if v not in ('2', '3', '4', '5'):
79
+ raise ConfigurationError('Invalid pyarmor.advanced')
80
+ obf_options.extend(['--advanced', v])
81
+ break
82
+
83
+ config_settings = config_settings or {}
84
+ global_options = config_settings.get('--global-option', [])
85
+
86
+ plat_name = get_platform().replace('-', '_').replace('.', '_')
87
+ global_options.append('--plat-name=%s' % plat_name)
88
+
89
+ global_options.append('--python-tag=cp%s%s' % sys.version_info[:2])
90
+ # global_options.append('--py-limited-api=cp%s%s' % sys.version_info[:2])
91
+
92
+ config_settings['--global-option'] = global_options
93
+ return config_settings
94
+
95
+
96
+ def build_wheel(wheel_directory, config_settings=None,
97
+ metadata_directory=None):
98
+ obf_options = ['obfuscate', '--enable-suffix', '--in-place',
99
+ '-r', '--bootstrap', '3']
100
+ config_settings = _fix_config(config_settings, obf_options)
101
+
102
+ # Build wheel by setuptools
103
+ result_basename = setuptools_build_wheel(
104
+ wheel_directory,
105
+ config_settings=config_settings,
106
+ metadata_directory=metadata_directory
107
+ )
108
+
109
+ # Unpack wheel and replace the original .py with obfuscated ones
110
+ result_wheel = os.path.join(wheel_directory, result_basename)
111
+ namever = _wheel_unpack(result_wheel, wheel_directory)
112
+
113
+ pkgname = namever.split('-')[0]
114
+ build_path = os.path.join(wheel_directory, namever)
115
+
116
+ obf_options.append(os.path.join(build_path, pkgname, '__init__.py'))
117
+ pyarmor_main(obf_options)
118
+
119
+ # Append runtime files of obfuscated scripts to wheel
120
+ _wheel_append_runtime_files(build_path, namever, pkgname)
121
+
122
+ # Pack the patched wheel again
123
+ wheel_pack(build_path, wheel_directory, None)
124
+
125
+ shutil.rmtree(build_path)
126
+ return result_basename
@@ -0,0 +1,46 @@
1
+ import logging
2
+
3
+ __VERSION__ = '9.2.6'
4
+
5
+ logger = logging.getLogger('cli')
6
+
7
+
8
+ class CliError(Exception):
9
+ pass
10
+
11
+
12
+ def resoptions(meth):
13
+
14
+ def process(self, res, *args, **kwargs):
15
+ self._options = self.ctx.get_res_options(res.fullname, self._Catalog)
16
+ return meth(self, res, *args, **kwargs)
17
+
18
+ return process
19
+
20
+
21
+ class Component(object):
22
+
23
+ def __init__(self, ctx):
24
+ self.ctx = ctx
25
+ self._options = {}
26
+
27
+ self.logger = logging.getLogger(self.LOGNAME)
28
+
29
+ def __getattr__(self, opt):
30
+ if opt.startswith('o_'):
31
+ return self._options.get(opt[2:], '')
32
+ elif opt.startswith('oi_'):
33
+ return int(self._options.get(opt[3:]))
34
+ elif opt.startswith('ob_'):
35
+ v = self._options.get(opt[3:], '')
36
+ if isinstance(v, str):
37
+ if v.isdigit():
38
+ return bool(int(v))
39
+ return v.lower() in ('1', 'true', 'on', 'yes')
40
+
41
+ return v
42
+ return AttributeError(opt)
43
+
44
+ def trace(self, res, node, value):
45
+ lineno = getattr(node, 'lineno', -1)
46
+ self.logger.info('%s:%s:%s', res.fullname, lineno, value)