pyarmor.cli 9.1.2__tar.gz → 9.2.0__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_cli-9.2.0/PKG-INFO +74 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/__init__.py +1 -1
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/__main__.py +2 -2
- pyarmor_cli-9.2.0/pyarmor/cli/core.data.1 +0 -0
- pyarmor_cli-9.2.0/pyarmor/cli/core.data.2 +0 -0
- pyarmor_cli-9.2.0/pyarmor/cli/core.data.3 +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/default.cfg +33 -6
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/project.py +41 -12
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/register.py +271 -39
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/repack.py +1 -1
- pyarmor_cli-9.2.0/pyarmor.cli.egg-info/PKG-INFO +74 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor.cli.egg-info/entry_points.txt +0 -1
- pyarmor_cli-9.2.0/pyarmor.cli.egg-info/requires.txt +1 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/setup.py +2 -2
- pyarmor.cli-9.1.2/PKG-INFO +0 -74
- pyarmor.cli-9.1.2/pyarmor/cli/core.data.1 +0 -0
- pyarmor.cli-9.1.2/pyarmor/cli/core.data.2 +0 -0
- pyarmor.cli-9.1.2/pyarmor/cli/core.data.3 +0 -0
- pyarmor.cli-9.1.2/pyarmor.cli.egg-info/PKG-INFO +0 -74
- pyarmor.cli-9.1.2/pyarmor.cli.egg-info/requires.txt +0 -1
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/README.rst +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/bootstrap.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/bug.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/command.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/config.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/context.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/docker.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/generate.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/hdinfo.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/merge.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/mixer.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/model.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/plugin.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/public_capsule.zip +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/resource.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor/cli/shell.py +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor.cli.egg-info/SOURCES.txt +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor.cli.egg-info/dependency_links.txt +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/pyarmor.cli.egg-info/top_level.txt +0 -0
- {pyarmor.cli-9.1.2 → pyarmor_cli-9.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyarmor.cli
|
|
3
|
+
Version: 9.2.0
|
|
4
|
+
Summary: A comand line tool to obfuscate python scripts
|
|
5
|
+
Home-page: https://github.com/dashingsoft/pyarmor
|
|
6
|
+
Author: Jondy Zhao
|
|
7
|
+
Author-email: pyarmor@163.com
|
|
8
|
+
License: Free To Use But Restricted
|
|
9
|
+
Keywords: protect obfuscate encrypt obfuscation distribute
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: License :: Free To Use But Restricted
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Classifier: Topic :: System :: Software Distribution
|
|
20
|
+
Requires-Dist: pyarmor.cli.core~=8.1.0
|
|
21
|
+
|
|
22
|
+
Protect Python Scripts By Pyarmor
|
|
23
|
+
=================================
|
|
24
|
+
|
|
25
|
+
Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
26
|
+
|
|
27
|
+
Key Features
|
|
28
|
+
------------
|
|
29
|
+
|
|
30
|
+
* The obfuscated scritpt is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
|
|
31
|
+
* Provide many ways to obfuscate the scripts to balance security and performance
|
|
32
|
+
* Rename functions/methods/classes/variables/arguments, irreversible obfuscation
|
|
33
|
+
* Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
|
|
34
|
+
* Bind obfuscated scripts to fixed machine or expire obfuscted scripts
|
|
35
|
+
* Protect obfuscated scripts by Themida (Only for Windows)
|
|
36
|
+
|
|
37
|
+
Support Platforms
|
|
38
|
+
-----------------
|
|
39
|
+
|
|
40
|
+
* Python 3.7~3.13
|
|
41
|
+
* Windows
|
|
42
|
+
* Many linuxs, include embedded systems
|
|
43
|
+
* Apple Intel and Apple Silicon
|
|
44
|
+
|
|
45
|
+
Quick Start
|
|
46
|
+
-----------
|
|
47
|
+
|
|
48
|
+
Install::
|
|
49
|
+
|
|
50
|
+
pip install pyarmor
|
|
51
|
+
|
|
52
|
+
Obfuscate the script `foo.py`::
|
|
53
|
+
|
|
54
|
+
pyarmor gen foo.py
|
|
55
|
+
|
|
56
|
+
This command generates an obfuscated script `dist/foo.py` like this:
|
|
57
|
+
|
|
58
|
+
.. code:: python
|
|
59
|
+
|
|
60
|
+
from pyarmor_runtime import __pyarmor__
|
|
61
|
+
__pyarmor__(__name__, __file__, b'\x28\x83\x20\x58....')
|
|
62
|
+
|
|
63
|
+
Run it::
|
|
64
|
+
|
|
65
|
+
python dist/foo.py
|
|
66
|
+
|
|
67
|
+
More Resources
|
|
68
|
+
--------------
|
|
69
|
+
|
|
70
|
+
- `Home <https://github.com/dashingsoft/pyarmor>`_
|
|
71
|
+
- `Website <http://pyarmor.dashingsoft.com>`_
|
|
72
|
+
- `中文网站 <http://pyarmor.dashingsoft.com/index-zh.html>`_
|
|
73
|
+
- `Issues <https://github.com/dashingsoft/pyarmor/issues>`_
|
|
74
|
+
- `Documentation <https://pyarmor.readthedocs.io/>`_
|
|
@@ -309,7 +309,7 @@ def cmd_reg(ctx, args):
|
|
|
309
309
|
raise CliError('please use ".zip" file to register group device')
|
|
310
310
|
regsvr = WebRegister(ctx)
|
|
311
311
|
regsvr.check_request_interval()
|
|
312
|
-
regsvr.
|
|
312
|
+
regsvr.request_device_regfile(regfile, args.device)
|
|
313
313
|
logger.info('The device regfile has been generated successfully')
|
|
314
314
|
|
|
315
315
|
elif args.ci:
|
|
@@ -764,7 +764,7 @@ def main_entry(argv):
|
|
|
764
764
|
log_settings(ctx, args)
|
|
765
765
|
|
|
766
766
|
x, y = sys.version_info[:2]
|
|
767
|
-
if not (x == 3 and y > 6 and y <
|
|
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
770
|
if args.version:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
;; Pyarmor version
|
|
4
4
|
major = 9
|
|
5
|
-
minor =
|
|
6
|
-
patch =
|
|
5
|
+
minor = 2
|
|
6
|
+
patch = 0
|
|
7
7
|
|
|
8
8
|
;; Compatible core version
|
|
9
|
-
cli.core =
|
|
10
|
-
mini.core =
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
cli.core = 8.1.0
|
|
10
|
+
mini.core = 2.0
|
|
11
|
+
|
|
12
|
+
;; ecc.core = 1.0
|
|
13
|
+
;; vmc.core = 1.0
|
|
13
14
|
|
|
14
15
|
;; Deprecated since Pyarmor 8.2.5
|
|
15
16
|
; cli.runtime = 3.2.5
|
|
@@ -147,6 +148,16 @@ enable_jit = 0
|
|
|
147
148
|
enable_bcc = 0
|
|
148
149
|
enable_rft = 0
|
|
149
150
|
|
|
151
|
+
;; Not implemented
|
|
152
|
+
;; Enable opcode virtual protection
|
|
153
|
+
;; This feature is meaningless in BCC mode
|
|
154
|
+
enable_vmc = 0
|
|
155
|
+
|
|
156
|
+
;; New in v9.2.0
|
|
157
|
+
;; Enable to obfuscate attribute name
|
|
158
|
+
;; When obf_code == 2, it's enabled implicitly
|
|
159
|
+
mix_attr = 0
|
|
160
|
+
|
|
150
161
|
;; assert: call import
|
|
151
162
|
assert_call = 0
|
|
152
163
|
assert_import = 0
|
|
@@ -165,7 +176,16 @@ mix_localnames = 1
|
|
|
165
176
|
;; mix argument names, it also clears annotations
|
|
166
177
|
mix_argnames = 0
|
|
167
178
|
|
|
179
|
+
;; Obfuscate the whole module
|
|
168
180
|
obf_module = 1
|
|
181
|
+
|
|
182
|
+
;; Obfuscate each code object
|
|
183
|
+
;;
|
|
184
|
+
;; 0: no obfuscation for each co
|
|
185
|
+
;; 1: obfuscate each co
|
|
186
|
+
;; 2: obfuscate each co plus mix attribute name
|
|
187
|
+
;; this is deprecated since 9.2.0, use
|
|
188
|
+
;; obf_code == 1 and mix_attr = 1
|
|
169
189
|
obf_code = 1
|
|
170
190
|
|
|
171
191
|
;; 0: no wrap mode
|
|
@@ -174,8 +194,15 @@ obf_code = 1
|
|
|
174
194
|
;; Since Python 3.12, "2" is same as "1", both of them use full wrap mode
|
|
175
195
|
wrap_mode = 1
|
|
176
196
|
|
|
197
|
+
;; 1: the obfuscated scripts can't be modified
|
|
198
|
+
;; 2: private module, can't be imported by plain scripts
|
|
199
|
+
;; 3: restrict module, module attribute is hidden for outer scripts
|
|
200
|
+
;;
|
|
177
201
|
restrict_module = 1
|
|
178
202
|
|
|
203
|
+
;; if set to 1, module attribute can't be written by plain scripts
|
|
204
|
+
readonly_module = 0
|
|
205
|
+
|
|
179
206
|
;;
|
|
180
207
|
;; Advanced features
|
|
181
208
|
;;
|
|
@@ -187,7 +187,7 @@ class Module:
|
|
|
187
187
|
|
|
188
188
|
@property
|
|
189
189
|
def destpath(self):
|
|
190
|
-
s = self.qualname + ('' if self.
|
|
190
|
+
s = self.qualname + ('' if self.name else '.__init__')
|
|
191
191
|
return joinpath(*s.split('.')) + splitext(self.path)[-1]
|
|
192
192
|
|
|
193
193
|
def compile_file(self, force=False):
|
|
@@ -241,17 +241,34 @@ class Script(Module):
|
|
|
241
241
|
class Package(Module):
|
|
242
242
|
"""Package concept"""
|
|
243
243
|
|
|
244
|
-
def __init__(self, path, name=None, parent=None):
|
|
244
|
+
def __init__(self, path, name=None, parent=None, excludes=[]):
|
|
245
245
|
super().__init__(path, name=name, parent=parent)
|
|
246
246
|
|
|
247
247
|
self._modules = None
|
|
248
248
|
self._packages = None
|
|
249
|
+
self._excludes = excludes if excludes else GLOBAL_EXCLS
|
|
250
|
+
self._filters = None
|
|
251
|
+
|
|
252
|
+
@property
|
|
253
|
+
def filters(self):
|
|
254
|
+
if self._filters is None:
|
|
255
|
+
self._filters = []
|
|
256
|
+
for x in self._excludes:
|
|
257
|
+
i = x.find(':')
|
|
258
|
+
if i == -1:
|
|
259
|
+
self._filters.append(x)
|
|
260
|
+
elif fnmatch(self.qualname, x[:i]):
|
|
261
|
+
self._filters.append(x[i+1:])
|
|
262
|
+
return self._filters
|
|
249
263
|
|
|
250
264
|
def load(self):
|
|
251
|
-
|
|
252
|
-
files, dirs = scan_path(self.abspath, excludes=
|
|
265
|
+
excls = self.filters
|
|
266
|
+
files, dirs = scan_path(self.abspath, excludes=excls)
|
|
253
267
|
self._modules = [Module(x, parent=self) for x in files]
|
|
254
|
-
self._packages = [
|
|
268
|
+
self._packages = [
|
|
269
|
+
Package(x, parent=self, excludes=self._excludes)
|
|
270
|
+
for x in dirs
|
|
271
|
+
]
|
|
255
272
|
|
|
256
273
|
@property
|
|
257
274
|
def modules(self):
|
|
@@ -858,17 +875,19 @@ class Project:
|
|
|
858
875
|
src = self.src = data['src']
|
|
859
876
|
name = data.get('name')
|
|
860
877
|
excludes = vlist('excludes') + list(GLOBAL_EXCLS)
|
|
878
|
+
proexcls = [x.strip(':') for x in excludes
|
|
879
|
+
if x.find(':') < 1]
|
|
861
880
|
|
|
862
881
|
scripts = []
|
|
863
882
|
for pat in vlist('scripts'):
|
|
864
|
-
scripts.extend(search_item(src, pat,
|
|
883
|
+
scripts.extend(search_item(src, pat, proexcls))
|
|
865
884
|
self._scripts.extend([
|
|
866
885
|
Script(self.relsrc(x), parent=self) for x in scripts
|
|
867
886
|
])
|
|
868
887
|
|
|
869
888
|
modules = []
|
|
870
889
|
for pat in vlist('modules'):
|
|
871
|
-
modules.extend(search_item(src, pat,
|
|
890
|
+
modules.extend(search_item(src, pat, proexcls))
|
|
872
891
|
|
|
873
892
|
packages = vlist('packages')
|
|
874
893
|
if packages:
|
|
@@ -883,7 +902,10 @@ class Project:
|
|
|
883
902
|
path, pkgname = item.split('@')
|
|
884
903
|
if not isabs(path):
|
|
885
904
|
path = joinpath(src, path)
|
|
886
|
-
obj = Package(path,
|
|
905
|
+
obj = Package(path,
|
|
906
|
+
name=pkgname,
|
|
907
|
+
parent=self,
|
|
908
|
+
excludes=excludes)
|
|
887
909
|
self._packages.append(obj)
|
|
888
910
|
|
|
889
911
|
recursive = data.get('recursive', '0')
|
|
@@ -891,10 +913,13 @@ class Project:
|
|
|
891
913
|
pkginit = joinpath(src, '__init__.py')
|
|
892
914
|
if exists(pkginit):
|
|
893
915
|
pkgname = name if name else basename(src)
|
|
894
|
-
obj = Package(src,
|
|
916
|
+
obj = Package(src,
|
|
917
|
+
name=pkgname,
|
|
918
|
+
parent=self,
|
|
919
|
+
excludes=excludes)
|
|
895
920
|
self._packages.append(obj)
|
|
896
921
|
else:
|
|
897
|
-
files, dirs = scan_path(src, excludes=
|
|
922
|
+
files, dirs = scan_path(src, excludes=proexcls)
|
|
898
923
|
modules.extend([joinpath(src, x) for x in files])
|
|
899
924
|
self._packages.extend([
|
|
900
925
|
Package(x, parent=self) for x in dirs
|
|
@@ -939,7 +964,7 @@ class Project:
|
|
|
939
964
|
|
|
940
965
|
def _get_external_types(self, modname, pypaths=None):
|
|
941
966
|
from sys import executable
|
|
942
|
-
from subprocess import check_output, CalledProcessError
|
|
967
|
+
from subprocess import check_output, CalledProcessError, DEVNULL
|
|
943
968
|
source = Template(dedent("""\
|
|
944
969
|
import json
|
|
945
970
|
import sys
|
|
@@ -960,12 +985,16 @@ class Project:
|
|
|
960
985
|
""")).substitute(name=modname, pypaths=repr(pypaths))
|
|
961
986
|
|
|
962
987
|
try:
|
|
963
|
-
output = check_output([executable, '-c', source])
|
|
988
|
+
output = check_output([executable, '-c', source], stderr=DEVNULL)
|
|
964
989
|
return jsonloads(output)
|
|
965
990
|
except CalledProcessError:
|
|
966
991
|
pass
|
|
967
992
|
|
|
968
993
|
def get_external_type(self, modname, clsname=None):
|
|
994
|
+
if not all([x.isidentifier() for x in modname.split('.')]):
|
|
995
|
+
logger.debug('invalid external module: %s', modname)
|
|
996
|
+
return []
|
|
997
|
+
|
|
969
998
|
extypes = self.used_external_types
|
|
970
999
|
if modname not in extypes:
|
|
971
1000
|
result = self._get_external_types(modname)
|
|
@@ -89,7 +89,7 @@ def parse_token(data):
|
|
|
89
89
|
|
|
90
90
|
def show_help_page(prompt, url):
|
|
91
91
|
choice = input('\n'.join(prompt)).lower()[:1]
|
|
92
|
-
if choice
|
|
92
|
+
if choice in ('h', 'y'):
|
|
93
93
|
import webbrowser
|
|
94
94
|
webbrowser.open(url)
|
|
95
95
|
return choice
|
|
@@ -208,7 +208,7 @@ class Register(object):
|
|
|
208
208
|
if len(line) == 192 and line.find(' ') == -1:
|
|
209
209
|
return regname, line
|
|
210
210
|
|
|
211
|
-
raise CliError('
|
|
211
|
+
raise CliError('invalid activation file "%s"' % filename)
|
|
212
212
|
|
|
213
213
|
def _register_offline_license(self, fzip, namelist):
|
|
214
214
|
logger.info('machine id in group license: %s', ', '.join(
|
|
@@ -279,13 +279,15 @@ class Register(object):
|
|
|
279
279
|
regname = regname.encode('utf-8')
|
|
280
280
|
product = product.encode('utf-8')
|
|
281
281
|
notes = notes.encode('utf-8')
|
|
282
|
-
|
|
282
|
+
sizes = len(regname), len(product), len(notes)
|
|
283
|
+
data = pack('<II8x20s28xBB{0}sB{1}sB{2}s'.format(*sizes),
|
|
284
|
+
token,
|
|
283
285
|
rev | features << 8,
|
|
284
286
|
licno.encode('utf-8'),
|
|
285
287
|
0,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
288
|
+
sizes[0], regname,
|
|
289
|
+
sizes[1], product,
|
|
290
|
+
sizes[2], notes)
|
|
289
291
|
return b64encode(data) + b' *=='
|
|
290
292
|
|
|
291
293
|
def register_regfile(self, regfile, clean=True):
|
|
@@ -443,7 +445,7 @@ class Register(object):
|
|
|
443
445
|
]
|
|
444
446
|
if lictype == 'trial':
|
|
445
447
|
self.notes.append('* Can\'t obfuscate big script and mix str')
|
|
446
|
-
elif lictype in ('
|
|
448
|
+
elif lictype in ('basic', 'pro'):
|
|
447
449
|
self.notes.append('* Need verify license online '
|
|
448
450
|
'when obfuscating scripts')
|
|
449
451
|
elif lictype == 'group':
|
|
@@ -478,6 +480,16 @@ The upgraded license information will be''')
|
|
|
478
480
|
|
|
479
481
|
class WebRegister(Register):
|
|
480
482
|
|
|
483
|
+
# Before v9.0: 1
|
|
484
|
+
# Pyarmor v9.0: 2
|
|
485
|
+
# Pyarmor v9.2: 3
|
|
486
|
+
LICENSE_REVSION = 3
|
|
487
|
+
|
|
488
|
+
# Before v9.0: no CI License
|
|
489
|
+
# Pyarmor v9.0: 1
|
|
490
|
+
# Pyarmor v9.2: 2
|
|
491
|
+
CI_LICENSE_REVSION = 2
|
|
492
|
+
|
|
481
493
|
def _request(self, url):
|
|
482
494
|
from http.client import HTTPSConnection
|
|
483
495
|
n = len('https://')
|
|
@@ -497,8 +509,9 @@ class WebRegister(Register):
|
|
|
497
509
|
from time import sleep, time
|
|
498
510
|
d = delta - (time() - st.st_mtime)
|
|
499
511
|
if d > 0:
|
|
500
|
-
logger.
|
|
501
|
-
|
|
512
|
+
logger.warning('caution: this activation file can only '
|
|
513
|
+
'be used no more than 10 times')
|
|
514
|
+
logger.info('waiting for %d seconds', d)
|
|
502
515
|
while time() - st.st_mtime < delta:
|
|
503
516
|
logger.info('waiting ...')
|
|
504
517
|
sleep(3.0)
|
|
@@ -566,6 +579,8 @@ class WebRegister(Register):
|
|
|
566
579
|
else:
|
|
567
580
|
lines.append(upgrade_to_basic_info.substitute())
|
|
568
581
|
else:
|
|
582
|
+
if info['lictype'] == 'OLD':
|
|
583
|
+
raise CliError('old license only works for Pyarmor <= 7.7.4')
|
|
569
584
|
if info['lictype'] not in ('BASIC', 'PRO', 'GROUP', 'CI'):
|
|
570
585
|
raise CliError('unknown license type %s' % info['lictype'])
|
|
571
586
|
lines.append('This license registration information will be')
|
|
@@ -611,7 +626,7 @@ class WebRegister(Register):
|
|
|
611
626
|
|
|
612
627
|
logger.info('send upgrade request to server')
|
|
613
628
|
res = self._send_request(url)
|
|
614
|
-
regfile = self._handle_response(res)
|
|
629
|
+
regfile, lictype = self._handle_response(res)
|
|
615
630
|
|
|
616
631
|
logger.info('update license token')
|
|
617
632
|
self.update_token()
|
|
@@ -631,15 +646,14 @@ class WebRegister(Register):
|
|
|
631
646
|
reginfo = self.parse_keyfile(keyfile)
|
|
632
647
|
|
|
633
648
|
url = self.regurl(reginfo[1], product=product)
|
|
634
|
-
|
|
635
|
-
url += '&rev=2'
|
|
649
|
+
url += '&rev=' + str(self.LICENSE_REVSION)
|
|
636
650
|
if upgrade:
|
|
637
651
|
url += '&upgrade_to_basic=1'
|
|
638
652
|
logger.debug('url: %s', url)
|
|
639
653
|
|
|
640
654
|
logger.info('send request to server')
|
|
641
655
|
res = self._send_request(url)
|
|
642
|
-
regfile = self._handle_response(res)
|
|
656
|
+
regfile, lictype = self._handle_response(res)
|
|
643
657
|
|
|
644
658
|
logger.info('')
|
|
645
659
|
logger.info('the registration file "%s" has been generated', regfile)
|
|
@@ -651,35 +665,22 @@ class WebRegister(Register):
|
|
|
651
665
|
'* Please backup regfile "%s", and '
|
|
652
666
|
'use this file for next any registration' % regfile,
|
|
653
667
|
'* Do not use this file in docker and CI/CD pipeline',
|
|
668
|
+
'',
|
|
654
669
|
]
|
|
655
|
-
|
|
656
|
-
if group:
|
|
657
|
-
notes.append('* Please check `pyarmor reg` in Man page for '
|
|
658
|
-
'how to register Pyarmor on offline device')
|
|
659
|
-
logger.info('\n\nImport Notes:\n%s\n', '\n'.join(notes))
|
|
660
|
-
return
|
|
661
|
-
|
|
662
|
-
notes.append('')
|
|
663
|
-
notes.append('Next register Pyarmor in build device by this command:')
|
|
664
|
-
|
|
665
|
-
notes.append('\tpyarmor reg %s' % regfile)
|
|
666
|
-
notes.append('')
|
|
667
670
|
logger.info('\n\nImport Notes:\n%s\n', '\n'.join(notes))
|
|
668
671
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
if choice == 'y':
|
|
672
|
-
logger.info('register "%s"', regfile)
|
|
673
|
-
self.register_regfile(regfile)
|
|
674
|
-
logger.info('This license registration information:\n\n%s', self)
|
|
672
|
+
input('Type Enter to continue ...')
|
|
673
|
+
LicenseHelper(self).run(lictype, regfile)
|
|
675
674
|
|
|
676
675
|
def _handle_response(self, res):
|
|
677
676
|
if res and res.code == 200:
|
|
677
|
+
lictype = None
|
|
678
678
|
dis = res.headers.get('Content-Disposition')
|
|
679
679
|
filename = dis.split('"')[1] if dis else 'pyarmor-regfile.zip'
|
|
680
680
|
logger.info('write registration file "%s"', filename)
|
|
681
681
|
data = res.read()
|
|
682
682
|
if data.startswith(b'{"group":'):
|
|
683
|
+
lictype = 'G'
|
|
683
684
|
n = data.find(b'}') + 1
|
|
684
685
|
with open(filename, 'wb') as f:
|
|
685
686
|
f.write(data[n:])
|
|
@@ -691,13 +692,15 @@ class WebRegister(Register):
|
|
|
691
692
|
n += i
|
|
692
693
|
with open(filename, 'wb') as f:
|
|
693
694
|
f.write(data[n:])
|
|
694
|
-
|
|
695
|
+
reginfo = data[i:n]
|
|
696
|
+
lictype = json_loads(reginfo).get('type', None)
|
|
697
|
+
self._write_reg_info(filename, reginfo)
|
|
695
698
|
else:
|
|
696
699
|
# Only for request group token
|
|
697
700
|
logger.debug('no REGINFO found')
|
|
698
701
|
with open(filename, 'wb') as f:
|
|
699
702
|
f.write(data)
|
|
700
|
-
return filename
|
|
703
|
+
return filename, lictype
|
|
701
704
|
|
|
702
705
|
elif res:
|
|
703
706
|
data = res.read()
|
|
@@ -723,10 +726,11 @@ class WebRegister(Register):
|
|
|
723
726
|
with ZipFile(filename, 'a') as f:
|
|
724
727
|
f.writestr('group.info', data)
|
|
725
728
|
|
|
726
|
-
def
|
|
729
|
+
def request_device_regfile(self, regfile, devid):
|
|
727
730
|
from zipfile import ZipFile
|
|
728
731
|
devfile = self.ctx.group_device_file(devid)
|
|
729
|
-
|
|
732
|
+
rev = self.LICENSE_REVSION
|
|
733
|
+
logger.info('request device regfile "%s" (v%d)', devfile, rev)
|
|
730
734
|
logger.info('use group license "%s"', regfile)
|
|
731
735
|
if not os.path.exists(devfile):
|
|
732
736
|
logger.error('please generate device file in offline device by')
|
|
@@ -770,7 +774,7 @@ class WebRegister(Register):
|
|
|
770
774
|
logger.debug('url: %s', url)
|
|
771
775
|
|
|
772
776
|
res = self._send_request(url)
|
|
773
|
-
filename = self._handle_response(res)
|
|
777
|
+
filename, lictype = self._handle_response(res)
|
|
774
778
|
with open(filename, 'rb') as f:
|
|
775
779
|
data = f.read()
|
|
776
780
|
os.makedirs(os.path.dirname(tokencache), exist_ok=True)
|
|
@@ -786,14 +790,18 @@ class WebRegister(Register):
|
|
|
786
790
|
logger.info('please copy deivce regfile to offline device and run')
|
|
787
791
|
logger.info(' pyarmor reg %s', filename)
|
|
788
792
|
|
|
793
|
+
register_group_device = request_device_regfile
|
|
794
|
+
|
|
789
795
|
def _write_ci_info(self, filename, data):
|
|
790
796
|
from zipfile import ZipFile
|
|
791
797
|
logger.info('write ci information')
|
|
792
798
|
with ZipFile(filename, 'a') as f:
|
|
793
799
|
f.writestr('ci.token', data)
|
|
794
800
|
|
|
795
|
-
def request_ci_regfile(self, regfile
|
|
796
|
-
|
|
801
|
+
def request_ci_regfile(self, regfile):
|
|
802
|
+
rev = self.LICENSE_REVSION
|
|
803
|
+
cirev = self.CI_LICENSE_REVSION
|
|
804
|
+
logger.info('request ci regfile (v%d) by "%s"', cirev, regfile)
|
|
797
805
|
from zipfile import ZipFile
|
|
798
806
|
|
|
799
807
|
with ZipFile(regfile, 'r') as f:
|
|
@@ -810,7 +818,7 @@ class WebRegister(Register):
|
|
|
810
818
|
raise CliError('invalid registration file "%s"', regfile)
|
|
811
819
|
|
|
812
820
|
url = self.regurl('ci/%s' % ucode)
|
|
813
|
-
paras = (
|
|
821
|
+
paras = ('rev', str(rev)), ('cirev', str(cirev))
|
|
814
822
|
url += '&'.join(['='.join(x) for x in paras])
|
|
815
823
|
logger.debug('url: %s', url)
|
|
816
824
|
|
|
@@ -850,3 +858,227 @@ class WebRegister(Register):
|
|
|
850
858
|
'\n\tpip install pyarmor==%s\n'
|
|
851
859
|
'\tpyarmor reg %s\n',
|
|
852
860
|
cifile, ver, cifile)
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
BASIC_LICENSE_HELP_INFO = Template('''
|
|
864
|
+
Using Basic license in CI/CD pipeline or docker container need extra steps, please check this page
|
|
865
|
+
|
|
866
|
+
$docurl/how-to/ci.html
|
|
867
|
+
|
|
868
|
+
More usage about Basic License, check this page
|
|
869
|
+
|
|
870
|
+
$docurl/how-to/register.html
|
|
871
|
+
|
|
872
|
+
If need register Pyarmor in build device, run this command:
|
|
873
|
+
|
|
874
|
+
pyarmor reg $regfile
|
|
875
|
+
|
|
876
|
+
''')
|
|
877
|
+
|
|
878
|
+
PRO_LICENSE_HELP_INFO = Template('''
|
|
879
|
+
Pro license can't be used in CI/CD pipeline or docker container direclty.
|
|
880
|
+
|
|
881
|
+
A few times for debug purpose, about 60 runs per month, may work.
|
|
882
|
+
|
|
883
|
+
But there is one workaroud for Pro licnese in CI/CD pipeline, please check this page
|
|
884
|
+
|
|
885
|
+
$docurl/how-to/ci.html
|
|
886
|
+
|
|
887
|
+
More usage about Pro License, check this page
|
|
888
|
+
|
|
889
|
+
$docurl/how-to/register.html
|
|
890
|
+
|
|
891
|
+
If need register Pyarmor in build device, run this command:
|
|
892
|
+
|
|
893
|
+
pyarmor reg $regfile
|
|
894
|
+
|
|
895
|
+
''')
|
|
896
|
+
|
|
897
|
+
GROUP_LICENSE_HELP_INFO = Template('''
|
|
898
|
+
Group License file `$regfile` is only used to request device regfile
|
|
899
|
+
|
|
900
|
+
In order to register Pyarmor in offline device:
|
|
901
|
+
|
|
902
|
+
1. In the build device (may be offline), generate device info by this command
|
|
903
|
+
|
|
904
|
+
pyarmor reg -g 1
|
|
905
|
+
|
|
906
|
+
2. In any online device, copy device file generated by first step, then request device regfile for this device
|
|
907
|
+
|
|
908
|
+
cp pyarmor-group-device.1 .pyarmor/group/
|
|
909
|
+
pyarmor reg -g 1 $regfile
|
|
910
|
+
|
|
911
|
+
3. In the build device, register Pyarmor by device regfile
|
|
912
|
+
|
|
913
|
+
pyarmor reg pyarmor-device-regfile-xxxx.1.zip
|
|
914
|
+
|
|
915
|
+
More usage about CI License, check section `Using group licnese`
|
|
916
|
+
|
|
917
|
+
$docurl/how-to/register.html
|
|
918
|
+
''')
|
|
919
|
+
|
|
920
|
+
CI_LICENSE_HELP_INFO = Template('''
|
|
921
|
+
CI license file `$regfile` is only used to request CI regfile
|
|
922
|
+
|
|
923
|
+
CI regfile is used to register Pyarmor in the CI/CD pipeline
|
|
924
|
+
|
|
925
|
+
If need request CI regfile, run this command:
|
|
926
|
+
|
|
927
|
+
pyarmor reg -C $regfile
|
|
928
|
+
|
|
929
|
+
Note that CI regfile can NOT be used in physical machine, and there is rate limits to register CI regfile in CI/CD pipeline and docker container.
|
|
930
|
+
|
|
931
|
+
It may need request new CI regfile after Pyarmor is upgraded, please check section `When need to request new CI regfile` in this page
|
|
932
|
+
|
|
933
|
+
$docurl/how-to/ci.html
|
|
934
|
+
|
|
935
|
+
More usage about CI License, check these pages
|
|
936
|
+
|
|
937
|
+
$docurl/how-to/register.html
|
|
938
|
+
$docurl/how-to/ci.html
|
|
939
|
+
''')
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
class LicenseHelper(object):
|
|
943
|
+
"""Only used for first activate license.
|
|
944
|
+
|
|
945
|
+
Help the beginner to understand how to use different licenses.
|
|
946
|
+
|
|
947
|
+
"""
|
|
948
|
+
|
|
949
|
+
def __init__(self, parent):
|
|
950
|
+
self.parent = parent
|
|
951
|
+
self.docurl = parent.ctx.cfg.get(
|
|
952
|
+
'pyarmor', 'docurl').rstrip('/').replace('{lang}', 'en')
|
|
953
|
+
self.print = print
|
|
954
|
+
|
|
955
|
+
def run(self, lictype, regfile):
|
|
956
|
+
if lictype == 'G':
|
|
957
|
+
self._group_license_helper(regfile)
|
|
958
|
+
|
|
959
|
+
elif lictype == 'C':
|
|
960
|
+
self._ci_license_helper(regfile)
|
|
961
|
+
|
|
962
|
+
elif lictype == 'Z':
|
|
963
|
+
self._pro_license_helper(regfile)
|
|
964
|
+
|
|
965
|
+
elif lictype in ('J', 'B', 'P'):
|
|
966
|
+
self._basic_license_helper(regfile)
|
|
967
|
+
|
|
968
|
+
else:
|
|
969
|
+
raise CliError('unknown license type "%s"' % lictype)
|
|
970
|
+
|
|
971
|
+
def _basic_license_helper(self, regfile):
|
|
972
|
+
self.print(BASIC_LICENSE_HELP_INFO.substitute(
|
|
973
|
+
docurl=self.docurl, regfile=regfile))
|
|
974
|
+
|
|
975
|
+
prompt = 'Yes (y), No (n), Quit (q): '
|
|
976
|
+
self.print('Show basic license usage in webbrowser? (n)')
|
|
977
|
+
choice = show_help_page([prompt], self.docurl + '/how-to/register.html')
|
|
978
|
+
if choice == 'q':
|
|
979
|
+
return
|
|
980
|
+
|
|
981
|
+
self.print('Show basic license for CI/CD pipeline or docker? (n)')
|
|
982
|
+
choice = show_help_page([prompt], self.docurl + '/how-to/ci.html')
|
|
983
|
+
if choice == 'q':
|
|
984
|
+
return
|
|
985
|
+
|
|
986
|
+
self.print('Do you want register Pyarmor in this machine? (y)')
|
|
987
|
+
choice = input(prompt).lower()[:1]
|
|
988
|
+
if choice == 'q':
|
|
989
|
+
return
|
|
990
|
+
|
|
991
|
+
if choice in ('y', ''):
|
|
992
|
+
self.print('register "%s"' % regfile)
|
|
993
|
+
self.parent.register_regfile(regfile)
|
|
994
|
+
self.print('This license registration information:\n\n'
|
|
995
|
+
'%s' % self.parent)
|
|
996
|
+
|
|
997
|
+
def _pro_license_helper(self, regfile):
|
|
998
|
+
self.print(PRO_LICENSE_HELP_INFO.substitute(
|
|
999
|
+
docurl=self.docurl, regfile=regfile))
|
|
1000
|
+
|
|
1001
|
+
prompt = 'Yes (y), No (n), Quit (q): '
|
|
1002
|
+
self.print('Show pro license usage in webbrowser? (n)')
|
|
1003
|
+
choice = show_help_page([prompt], self.docurl + '/how-to/register.html')
|
|
1004
|
+
if choice == 'q':
|
|
1005
|
+
return
|
|
1006
|
+
|
|
1007
|
+
self.print('Show pro license for CI/CD pipeline or docker? (n)')
|
|
1008
|
+
choice = show_help_page([prompt], self.docurl + '/how-to/ci.html')
|
|
1009
|
+
if choice == 'q':
|
|
1010
|
+
return
|
|
1011
|
+
|
|
1012
|
+
self.print('Do you want register Pyarmor in this machine? (y)')
|
|
1013
|
+
choice = input(prompt).lower()[:1]
|
|
1014
|
+
if choice == 'q':
|
|
1015
|
+
return
|
|
1016
|
+
|
|
1017
|
+
if choice in ('y', ''):
|
|
1018
|
+
self.print('register "%s"' % regfile)
|
|
1019
|
+
self.parent.register_regfile(regfile)
|
|
1020
|
+
self.print('This license registration information:\n\n'
|
|
1021
|
+
'%s' % self.parent)
|
|
1022
|
+
|
|
1023
|
+
def _group_license_helper(self, regfile):
|
|
1024
|
+
self.print(GROUP_LICENSE_HELP_INFO.substitute(
|
|
1025
|
+
docurl=self.docurl, regfile=regfile))
|
|
1026
|
+
|
|
1027
|
+
prompt = 'Yes (y), No (n), Quit (q): '
|
|
1028
|
+
self.print('Show group license usage in webbrowser? (n)')
|
|
1029
|
+
choice = show_help_page([prompt], self.docurl + '/how-to/register.html')
|
|
1030
|
+
if choice == 'q':
|
|
1031
|
+
return
|
|
1032
|
+
|
|
1033
|
+
self.print('Do you want register Pyarmor in this machine? (n)')
|
|
1034
|
+
choice = input(prompt).lower()[:1]
|
|
1035
|
+
if choice == 'q':
|
|
1036
|
+
return
|
|
1037
|
+
|
|
1038
|
+
if choice != 'y':
|
|
1039
|
+
return
|
|
1040
|
+
|
|
1041
|
+
self.print('Please assign one unused device no. to this device, '
|
|
1042
|
+
'starts from 1')
|
|
1043
|
+
devid = None
|
|
1044
|
+
while devid is None:
|
|
1045
|
+
a = input('Type device no. (default is 1): ')
|
|
1046
|
+
if a == '':
|
|
1047
|
+
devid = 1
|
|
1048
|
+
elif (not a.isdigit()) or int(a) < 1 or int(a) > 100:
|
|
1049
|
+
self.print('invalid input')
|
|
1050
|
+
else:
|
|
1051
|
+
devid = int(a)
|
|
1052
|
+
|
|
1053
|
+
if devid:
|
|
1054
|
+
sep = '-' * 16
|
|
1055
|
+
devinfo = self.parent.ctx.group_device_file(devid)
|
|
1056
|
+
self.print('%s 1. generate device info' % sep)
|
|
1057
|
+
if os.path.exists(devinfo):
|
|
1058
|
+
logger.warning('old device file has been exists')
|
|
1059
|
+
else:
|
|
1060
|
+
self.parent.generate_group_device(devid)
|
|
1061
|
+
self.print('%s 2. request device regfile' % sep)
|
|
1062
|
+
self.parent.request_device_regfile(regfile, devid)
|
|
1063
|
+
self.print('%s 3. register Pyarmor with device regfile' % sep)
|
|
1064
|
+
self.parent.register(regfile.
|
|
1065
|
+
replace('.zip', '.%d.zip' % devid).
|
|
1066
|
+
replace('-regfile', '-device-regfile'))
|
|
1067
|
+
|
|
1068
|
+
def _ci_license_helper(self, regfile):
|
|
1069
|
+
self.print(CI_LICENSE_HELP_INFO.substitute(
|
|
1070
|
+
docurl=self.docurl, regfile=regfile))
|
|
1071
|
+
|
|
1072
|
+
prompt = 'Yes (y), No (n), Quit (q): '
|
|
1073
|
+
self.print('Show ci license usage in webbrowser? (n)')
|
|
1074
|
+
choice = show_help_page([prompt], self.docurl + '/how-to/ci.html')
|
|
1075
|
+
if choice == 'q':
|
|
1076
|
+
return
|
|
1077
|
+
|
|
1078
|
+
self.print('Do you want request one CI Regfile now? (y)')
|
|
1079
|
+
choice = input(prompt).lower()[:1]
|
|
1080
|
+
if choice == 'q':
|
|
1081
|
+
return
|
|
1082
|
+
|
|
1083
|
+
if choice in ('y', ''):
|
|
1084
|
+
self.parent.request_ci_regfile(regfile)
|
|
@@ -96,7 +96,7 @@ for name, path, kind in a.binaries:
|
|
|
96
96
|
|
|
97
97
|
with open(resfile, 'wb') as f:
|
|
98
98
|
marshal.dump(mlist + list(plist), f)
|
|
99
|
-
with open(hookscript, 'w') as f:
|
|
99
|
+
with open(hookscript, 'w', encoding='utf-8') as f:
|
|
100
100
|
f.write("hiddenimports=[%s]" % ", ".join([repr(x) for x in hiddenimports]))
|
|
101
101
|
'''
|
|
102
102
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyarmor.cli
|
|
3
|
+
Version: 9.2.0
|
|
4
|
+
Summary: A comand line tool to obfuscate python scripts
|
|
5
|
+
Home-page: https://github.com/dashingsoft/pyarmor
|
|
6
|
+
Author: Jondy Zhao
|
|
7
|
+
Author-email: pyarmor@163.com
|
|
8
|
+
License: Free To Use But Restricted
|
|
9
|
+
Keywords: protect obfuscate encrypt obfuscation distribute
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: License :: Free To Use But Restricted
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Classifier: Topic :: System :: Software Distribution
|
|
20
|
+
Requires-Dist: pyarmor.cli.core~=8.1.0
|
|
21
|
+
|
|
22
|
+
Protect Python Scripts By Pyarmor
|
|
23
|
+
=================================
|
|
24
|
+
|
|
25
|
+
Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
26
|
+
|
|
27
|
+
Key Features
|
|
28
|
+
------------
|
|
29
|
+
|
|
30
|
+
* The obfuscated scritpt is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
|
|
31
|
+
* Provide many ways to obfuscate the scripts to balance security and performance
|
|
32
|
+
* Rename functions/methods/classes/variables/arguments, irreversible obfuscation
|
|
33
|
+
* Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
|
|
34
|
+
* Bind obfuscated scripts to fixed machine or expire obfuscted scripts
|
|
35
|
+
* Protect obfuscated scripts by Themida (Only for Windows)
|
|
36
|
+
|
|
37
|
+
Support Platforms
|
|
38
|
+
-----------------
|
|
39
|
+
|
|
40
|
+
* Python 3.7~3.13
|
|
41
|
+
* Windows
|
|
42
|
+
* Many linuxs, include embedded systems
|
|
43
|
+
* Apple Intel and Apple Silicon
|
|
44
|
+
|
|
45
|
+
Quick Start
|
|
46
|
+
-----------
|
|
47
|
+
|
|
48
|
+
Install::
|
|
49
|
+
|
|
50
|
+
pip install pyarmor
|
|
51
|
+
|
|
52
|
+
Obfuscate the script `foo.py`::
|
|
53
|
+
|
|
54
|
+
pyarmor gen foo.py
|
|
55
|
+
|
|
56
|
+
This command generates an obfuscated script `dist/foo.py` like this:
|
|
57
|
+
|
|
58
|
+
.. code:: python
|
|
59
|
+
|
|
60
|
+
from pyarmor_runtime import __pyarmor__
|
|
61
|
+
__pyarmor__(__name__, __file__, b'\x28\x83\x20\x58....')
|
|
62
|
+
|
|
63
|
+
Run it::
|
|
64
|
+
|
|
65
|
+
python dist/foo.py
|
|
66
|
+
|
|
67
|
+
More Resources
|
|
68
|
+
--------------
|
|
69
|
+
|
|
70
|
+
- `Home <https://github.com/dashingsoft/pyarmor>`_
|
|
71
|
+
- `Website <http://pyarmor.dashingsoft.com>`_
|
|
72
|
+
- `中文网站 <http://pyarmor.dashingsoft.com/index-zh.html>`_
|
|
73
|
+
- `Issues <https://github.com/dashingsoft/pyarmor/issues>`_
|
|
74
|
+
- `Documentation <https://pyarmor.readthedocs.io/>`_
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyarmor.cli.core~=8.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from setuptools import setup
|
|
2
2
|
|
|
3
|
-
__VERSION__ = '9.
|
|
3
|
+
__VERSION__ = ' 9.2.0'
|
|
4
4
|
|
|
5
5
|
with open('README.rst') as f:
|
|
6
6
|
long_description = f.read()
|
|
@@ -51,7 +51,7 @@ setup(
|
|
|
51
51
|
package_data={"pyarmor.cli": ["default.cfg", "public_capsule.zip", "core.data.*"]},
|
|
52
52
|
|
|
53
53
|
install_requires=[
|
|
54
|
-
'pyarmor.cli.core~=
|
|
54
|
+
'pyarmor.cli.core~=8.1.0'
|
|
55
55
|
],
|
|
56
56
|
|
|
57
57
|
entry_points={
|
pyarmor.cli-9.1.2/PKG-INFO
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 1.1
|
|
2
|
-
Name: pyarmor.cli
|
|
3
|
-
Version: 9.1.2
|
|
4
|
-
Summary: A comand line tool to obfuscate python scripts
|
|
5
|
-
Home-page: https://github.com/dashingsoft/pyarmor
|
|
6
|
-
Author: Jondy Zhao
|
|
7
|
-
Author-email: pyarmor@163.com
|
|
8
|
-
License: Free To Use But Restricted
|
|
9
|
-
Description: Protect Python Scripts By Pyarmor
|
|
10
|
-
=================================
|
|
11
|
-
|
|
12
|
-
Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
13
|
-
|
|
14
|
-
Key Features
|
|
15
|
-
------------
|
|
16
|
-
|
|
17
|
-
* The obfuscated scritpt is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
|
|
18
|
-
* Provide many ways to obfuscate the scripts to balance security and performance
|
|
19
|
-
* Rename functions/methods/classes/variables/arguments, irreversible obfuscation
|
|
20
|
-
* Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
|
|
21
|
-
* Bind obfuscated scripts to fixed machine or expire obfuscted scripts
|
|
22
|
-
* Protect obfuscated scripts by Themida (Only for Windows)
|
|
23
|
-
|
|
24
|
-
Support Platforms
|
|
25
|
-
-----------------
|
|
26
|
-
|
|
27
|
-
* Python 3.7~3.13
|
|
28
|
-
* Windows
|
|
29
|
-
* Many linuxs, include embedded systems
|
|
30
|
-
* Apple Intel and Apple Silicon
|
|
31
|
-
|
|
32
|
-
Quick Start
|
|
33
|
-
-----------
|
|
34
|
-
|
|
35
|
-
Install::
|
|
36
|
-
|
|
37
|
-
pip install pyarmor
|
|
38
|
-
|
|
39
|
-
Obfuscate the script `foo.py`::
|
|
40
|
-
|
|
41
|
-
pyarmor gen foo.py
|
|
42
|
-
|
|
43
|
-
This command generates an obfuscated script `dist/foo.py` like this:
|
|
44
|
-
|
|
45
|
-
.. code:: python
|
|
46
|
-
|
|
47
|
-
from pyarmor_runtime import __pyarmor__
|
|
48
|
-
__pyarmor__(__name__, __file__, b'\x28\x83\x20\x58....')
|
|
49
|
-
|
|
50
|
-
Run it::
|
|
51
|
-
|
|
52
|
-
python dist/foo.py
|
|
53
|
-
|
|
54
|
-
More Resources
|
|
55
|
-
--------------
|
|
56
|
-
|
|
57
|
-
- `Home <https://github.com/dashingsoft/pyarmor>`_
|
|
58
|
-
- `Website <http://pyarmor.dashingsoft.com>`_
|
|
59
|
-
- `中文网站 <http://pyarmor.dashingsoft.com/index-zh.html>`_
|
|
60
|
-
- `Issues <https://github.com/dashingsoft/pyarmor/issues>`_
|
|
61
|
-
- `Documentation <https://pyarmor.readthedocs.io/>`_
|
|
62
|
-
|
|
63
|
-
Keywords: protect obfuscate encrypt obfuscation distribute
|
|
64
|
-
Platform: UNKNOWN
|
|
65
|
-
Classifier: Programming Language :: Python :: 3
|
|
66
|
-
Classifier: License :: Free To Use But Restricted
|
|
67
|
-
Classifier: Operating System :: MacOS
|
|
68
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
69
|
-
Classifier: Operating System :: POSIX
|
|
70
|
-
Classifier: Intended Audience :: Developers
|
|
71
|
-
Classifier: Topic :: Software Development :: Build Tools
|
|
72
|
-
Classifier: Topic :: Utilities
|
|
73
|
-
Classifier: Topic :: Security
|
|
74
|
-
Classifier: Topic :: System :: Software Distribution
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 1.1
|
|
2
|
-
Name: pyarmor.cli
|
|
3
|
-
Version: 9.1.2
|
|
4
|
-
Summary: A comand line tool to obfuscate python scripts
|
|
5
|
-
Home-page: https://github.com/dashingsoft/pyarmor
|
|
6
|
-
Author: Jondy Zhao
|
|
7
|
-
Author-email: pyarmor@163.com
|
|
8
|
-
License: Free To Use But Restricted
|
|
9
|
-
Description: Protect Python Scripts By Pyarmor
|
|
10
|
-
=================================
|
|
11
|
-
|
|
12
|
-
Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
13
|
-
|
|
14
|
-
Key Features
|
|
15
|
-
------------
|
|
16
|
-
|
|
17
|
-
* The obfuscated scritpt is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
|
|
18
|
-
* Provide many ways to obfuscate the scripts to balance security and performance
|
|
19
|
-
* Rename functions/methods/classes/variables/arguments, irreversible obfuscation
|
|
20
|
-
* Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
|
|
21
|
-
* Bind obfuscated scripts to fixed machine or expire obfuscted scripts
|
|
22
|
-
* Protect obfuscated scripts by Themida (Only for Windows)
|
|
23
|
-
|
|
24
|
-
Support Platforms
|
|
25
|
-
-----------------
|
|
26
|
-
|
|
27
|
-
* Python 3.7~3.13
|
|
28
|
-
* Windows
|
|
29
|
-
* Many linuxs, include embedded systems
|
|
30
|
-
* Apple Intel and Apple Silicon
|
|
31
|
-
|
|
32
|
-
Quick Start
|
|
33
|
-
-----------
|
|
34
|
-
|
|
35
|
-
Install::
|
|
36
|
-
|
|
37
|
-
pip install pyarmor
|
|
38
|
-
|
|
39
|
-
Obfuscate the script `foo.py`::
|
|
40
|
-
|
|
41
|
-
pyarmor gen foo.py
|
|
42
|
-
|
|
43
|
-
This command generates an obfuscated script `dist/foo.py` like this:
|
|
44
|
-
|
|
45
|
-
.. code:: python
|
|
46
|
-
|
|
47
|
-
from pyarmor_runtime import __pyarmor__
|
|
48
|
-
__pyarmor__(__name__, __file__, b'\x28\x83\x20\x58....')
|
|
49
|
-
|
|
50
|
-
Run it::
|
|
51
|
-
|
|
52
|
-
python dist/foo.py
|
|
53
|
-
|
|
54
|
-
More Resources
|
|
55
|
-
--------------
|
|
56
|
-
|
|
57
|
-
- `Home <https://github.com/dashingsoft/pyarmor>`_
|
|
58
|
-
- `Website <http://pyarmor.dashingsoft.com>`_
|
|
59
|
-
- `中文网站 <http://pyarmor.dashingsoft.com/index-zh.html>`_
|
|
60
|
-
- `Issues <https://github.com/dashingsoft/pyarmor/issues>`_
|
|
61
|
-
- `Documentation <https://pyarmor.readthedocs.io/>`_
|
|
62
|
-
|
|
63
|
-
Keywords: protect obfuscate encrypt obfuscation distribute
|
|
64
|
-
Platform: UNKNOWN
|
|
65
|
-
Classifier: Programming Language :: Python :: 3
|
|
66
|
-
Classifier: License :: Free To Use But Restricted
|
|
67
|
-
Classifier: Operating System :: MacOS
|
|
68
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
69
|
-
Classifier: Operating System :: POSIX
|
|
70
|
-
Classifier: Intended Audience :: Developers
|
|
71
|
-
Classifier: Topic :: Software Development :: Build Tools
|
|
72
|
-
Classifier: Topic :: Utilities
|
|
73
|
-
Classifier: Topic :: Security
|
|
74
|
-
Classifier: Topic :: System :: Software Distribution
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pyarmor.cli.core~=7.6.4
|
|
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
|