pyarmor.cli 9.2.6__3-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.
- pyarmor/cli/__init__.py +46 -0
- pyarmor/cli/__main__.py +812 -0
- pyarmor/cli/batch.py +62 -0
- pyarmor/cli/bootstrap.py +207 -0
- pyarmor/cli/bug.py +137 -0
- pyarmor/cli/command.py +563 -0
- pyarmor/cli/config.py +306 -0
- pyarmor/cli/context.py +790 -0
- pyarmor/cli/core.data.1 +0 -0
- pyarmor/cli/core.data.2 +0 -0
- pyarmor/cli/core.data.3 +0 -0
- pyarmor/cli/default.cfg +564 -0
- pyarmor/cli/docker.py +192 -0
- pyarmor/cli/generate.py +256 -0
- pyarmor/cli/hdinfo.py +81 -0
- pyarmor/cli/merge.py +232 -0
- pyarmor/cli/mixer.py +109 -0
- pyarmor/cli/model.py +460 -0
- pyarmor/cli/plugin.py +292 -0
- pyarmor/cli/project.py +1281 -0
- pyarmor/cli/public_capsule.zip +0 -0
- pyarmor/cli/register.py +1093 -0
- pyarmor/cli/repack.py +793 -0
- pyarmor/cli/resource.py +265 -0
- pyarmor/cli/shell.py +481 -0
- pyarmor_cli-9.2.6.dist-info/METADATA +74 -0
- pyarmor_cli-9.2.6.dist-info/RECORD +30 -0
- pyarmor_cli-9.2.6.dist-info/WHEEL +6 -0
- pyarmor_cli-9.2.6.dist-info/entry_points.txt +3 -0
- pyarmor_cli-9.2.6.dist-info/top_level.txt +1 -0
pyarmor/cli/shell.py
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
#############################################################
|
|
5
|
+
# #
|
|
6
|
+
# Copyright @ 2024 - Dashingsoft corp. #
|
|
7
|
+
# All rights reserved. #
|
|
8
|
+
# #
|
|
9
|
+
# Pyarmor #
|
|
10
|
+
# #
|
|
11
|
+
# Version: 9.1.0 - #
|
|
12
|
+
# #
|
|
13
|
+
#############################################################
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @File: cli/shell.py
|
|
17
|
+
#
|
|
18
|
+
# @Author: Jondy Zhao (pyarmor@163.com)
|
|
19
|
+
#
|
|
20
|
+
# @Create Date: Fri Nov 15 10:52:00 CST 2024
|
|
21
|
+
#
|
|
22
|
+
import configparser
|
|
23
|
+
import cmd
|
|
24
|
+
import shlex
|
|
25
|
+
|
|
26
|
+
from .model import SECTIONS, GROUPS
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class CfgEntity:
|
|
30
|
+
"""Store option to cfg file"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, cfgfiles, encoding=None):
|
|
33
|
+
self._cfgfiles = cfgfiles
|
|
34
|
+
self._reader = None
|
|
35
|
+
self._writer = None
|
|
36
|
+
self._index = -1
|
|
37
|
+
self._encoding = encoding
|
|
38
|
+
|
|
39
|
+
def _load_cfg(self, filenames):
|
|
40
|
+
cfg = configparser.ConfigParser(
|
|
41
|
+
empty_lines_in_values=False,
|
|
42
|
+
interpolation=configparser.ExtendedInterpolation(),
|
|
43
|
+
)
|
|
44
|
+
cfg.read(filenames, encoding=self._encoding)
|
|
45
|
+
return cfg
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def cfgfile(self):
|
|
49
|
+
return self._cfgfiles[self._index]
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def reader(self):
|
|
53
|
+
if self._reader is None:
|
|
54
|
+
self._reader = self._load_cfg(self._cfgfiles)
|
|
55
|
+
return self._reader
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def writer(self):
|
|
59
|
+
if self._writer is None:
|
|
60
|
+
self._writer = self._load_cfg(self.cfgfile)
|
|
61
|
+
return self._writer
|
|
62
|
+
|
|
63
|
+
def store(self, sect, opt, value):
|
|
64
|
+
for cfg in (self.writer, self.reader):
|
|
65
|
+
if not cfg.has_section(sect):
|
|
66
|
+
cfg.add_section(sect)
|
|
67
|
+
cfg.set(sect, opt, value)
|
|
68
|
+
|
|
69
|
+
def fetch(self, sect, opt):
|
|
70
|
+
cfg = self.reader
|
|
71
|
+
if cfg.has_section(sect):
|
|
72
|
+
return cfg[sect].get(opt, None)
|
|
73
|
+
|
|
74
|
+
def remove(self, sect, opt=None):
|
|
75
|
+
for cfg in (self.writer, self.reader):
|
|
76
|
+
if cfg.has_section(sect):
|
|
77
|
+
if opt is None:
|
|
78
|
+
cfg.remove_section(sect)
|
|
79
|
+
else:
|
|
80
|
+
cfg.remove_option(sect, opt)
|
|
81
|
+
|
|
82
|
+
def reset(self, index):
|
|
83
|
+
if self._index == index:
|
|
84
|
+
return
|
|
85
|
+
self._index = index
|
|
86
|
+
self._reader = self._writer = None
|
|
87
|
+
|
|
88
|
+
def save(self):
|
|
89
|
+
with open(self.cfgfile, 'w', encoding=self._encoding) as f:
|
|
90
|
+
self.writer.write(f)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Domain:
|
|
94
|
+
|
|
95
|
+
def __init__(self, name, default='pyarmor'):
|
|
96
|
+
self.name = name
|
|
97
|
+
self._dirty = False
|
|
98
|
+
|
|
99
|
+
self._sections = []
|
|
100
|
+
self._groups = []
|
|
101
|
+
|
|
102
|
+
self._default = Section(default, parent=self)
|
|
103
|
+
self._cfgentity = None
|
|
104
|
+
self._children = None
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def qualname(self):
|
|
108
|
+
return self.name
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def title(self):
|
|
112
|
+
return '(%s) ' % self.name
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def dirty(self):
|
|
116
|
+
return self._dirty
|
|
117
|
+
|
|
118
|
+
@dirty.setter
|
|
119
|
+
def dirty(self, value):
|
|
120
|
+
self._dirty = value
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def groups(self):
|
|
124
|
+
for x in self._groups:
|
|
125
|
+
yield x
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def sections(self):
|
|
129
|
+
for x in self._sections:
|
|
130
|
+
yield x
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def options(self):
|
|
134
|
+
if self._default:
|
|
135
|
+
for x in self._default.options:
|
|
136
|
+
yield x
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def children(self):
|
|
140
|
+
if self._children is None:
|
|
141
|
+
items = {x.name: x for x in self.groups}
|
|
142
|
+
items.update({x.name: x for x in self.sections})
|
|
143
|
+
self._children = items
|
|
144
|
+
return self._children
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def cfgentity(self):
|
|
148
|
+
return self._cfgentity
|
|
149
|
+
|
|
150
|
+
def link(self, cfgentity):
|
|
151
|
+
self._cfgentity = cfgentity
|
|
152
|
+
|
|
153
|
+
def save(self, force=False):
|
|
154
|
+
cfgentity = self._cfgentity
|
|
155
|
+
if (self.dirty or force) and cfgentity:
|
|
156
|
+
cfgentity.save()
|
|
157
|
+
self._dirty = False
|
|
158
|
+
|
|
159
|
+
def add_section(self, name):
|
|
160
|
+
if self._default and self._default.name == name:
|
|
161
|
+
return
|
|
162
|
+
self._sections.append(Section(name, parent=self))
|
|
163
|
+
|
|
164
|
+
def add_group(self, name, sections):
|
|
165
|
+
group = Group(name, parent=self)
|
|
166
|
+
group.add_sections(sections)
|
|
167
|
+
self._groups.append(group)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class Section:
|
|
171
|
+
|
|
172
|
+
def __init__(self, name, parent=None):
|
|
173
|
+
self.parent = parent
|
|
174
|
+
self.name = name
|
|
175
|
+
self.models = SECTIONS.get(name, [])
|
|
176
|
+
self._options = None
|
|
177
|
+
self._children = {}
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def qualname(self):
|
|
181
|
+
parent = self.parent
|
|
182
|
+
name = self.name
|
|
183
|
+
return ':'.join([parent.qualname, name])
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def title(self):
|
|
187
|
+
return '({0})[{1}] '.format(*self.qualname.split(':', 1))
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def options(self):
|
|
191
|
+
if self._options is None:
|
|
192
|
+
self._options = [x.factory(self) for x in self.models]
|
|
193
|
+
|
|
194
|
+
for x in self._options:
|
|
195
|
+
yield x
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def children(self):
|
|
199
|
+
return self._children
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def cfgentity(self):
|
|
203
|
+
return self.parent.cfgentity
|
|
204
|
+
|
|
205
|
+
def store(self, opt, value):
|
|
206
|
+
self.cfgentity.store(self.name, opt, value)
|
|
207
|
+
|
|
208
|
+
def fetch(self, opt):
|
|
209
|
+
return self.cfgentity.fetch(self.name, opt)
|
|
210
|
+
|
|
211
|
+
def remove(self, opt):
|
|
212
|
+
self.cfgentity.remove(self.name, opt)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class Group(Section):
|
|
216
|
+
|
|
217
|
+
def __init__(self, name, parent=None, sections=None):
|
|
218
|
+
super().__init__(name, parent=parent)
|
|
219
|
+
self._groups = []
|
|
220
|
+
self._sections = []
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def group(self):
|
|
224
|
+
for x in self._group:
|
|
225
|
+
yield x
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def sections(self):
|
|
229
|
+
for x in self._sections:
|
|
230
|
+
yield x
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def children(self):
|
|
234
|
+
if self._children is None:
|
|
235
|
+
items = {x.name: x for x in self.groups}
|
|
236
|
+
items.update({x.name: x for x in self.sections})
|
|
237
|
+
self._children = items
|
|
238
|
+
return self._children
|
|
239
|
+
|
|
240
|
+
def add_group(self, name, sections):
|
|
241
|
+
group = Group(name, parent=self)
|
|
242
|
+
group.add_sections(sections)
|
|
243
|
+
self._group.append(group)
|
|
244
|
+
|
|
245
|
+
def add_sections(self, sections):
|
|
246
|
+
self._sections.extend([
|
|
247
|
+
Section(x, parent=self) for x in sections
|
|
248
|
+
])
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class PyarmorShell(cmd.Cmd):
|
|
252
|
+
|
|
253
|
+
intro = 'Type help or ? to list commands.\n'
|
|
254
|
+
col = 60
|
|
255
|
+
|
|
256
|
+
def __init__(self, ctx, domain='local'):
|
|
257
|
+
super().__init__()
|
|
258
|
+
self.ctx = ctx
|
|
259
|
+
self._entity = CfgEntity([
|
|
260
|
+
ctx.default_config,
|
|
261
|
+
ctx.global_config,
|
|
262
|
+
ctx.local_config
|
|
263
|
+
], encoding=ctx.encoding)
|
|
264
|
+
self._domains = self._init_domains()
|
|
265
|
+
self._domain = self._section = self._domains[domain]
|
|
266
|
+
|
|
267
|
+
def _init_domains(self):
|
|
268
|
+
gs = Domain('global')
|
|
269
|
+
ls = Domain('local')
|
|
270
|
+
ps = Domain('project', default='project')
|
|
271
|
+
|
|
272
|
+
gs.link(self._entity)
|
|
273
|
+
ls.link(self._entity)
|
|
274
|
+
ps.link(self._entity)
|
|
275
|
+
|
|
276
|
+
sections = 'finder', 'builder', 'runtime', 'pack'
|
|
277
|
+
[(gs.add_section(x), ls.add_section(x)) for x in sections]
|
|
278
|
+
|
|
279
|
+
for domain in (gs, ls):
|
|
280
|
+
for name in ('filter', 'bcc'):
|
|
281
|
+
domain.add_group(name, GROUPS[name])
|
|
282
|
+
|
|
283
|
+
ps.add_section('rft')
|
|
284
|
+
ps.add_section('mini')
|
|
285
|
+
ps.add_section('vmc')
|
|
286
|
+
ps.add_section('ecc')
|
|
287
|
+
|
|
288
|
+
return {'global': gs, 'local': ls, 'project': ps}
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def section(self):
|
|
292
|
+
return self._section
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def prompt(self):
|
|
296
|
+
return self.section.title
|
|
297
|
+
|
|
298
|
+
def get_sections(self, name=''):
|
|
299
|
+
obj = self.section
|
|
300
|
+
sects = [x for x in getattr(obj, 'groups', [])]
|
|
301
|
+
sects.extend([x for x in getattr(obj, 'sections', [])])
|
|
302
|
+
return (sects if name in ('-a', '*', '') else
|
|
303
|
+
[x for x in sects if x.name.startswith(name)])
|
|
304
|
+
|
|
305
|
+
def get_options(self, name=''):
|
|
306
|
+
options = [x for x in self.section.options]
|
|
307
|
+
return (options if name in ('-a', '*', '') else
|
|
308
|
+
[x for x in options if x.name.startswith(name)])
|
|
309
|
+
|
|
310
|
+
def printf(self, *args):
|
|
311
|
+
print(*args)
|
|
312
|
+
|
|
313
|
+
def find(self, opt):
|
|
314
|
+
for item in self.section.options:
|
|
315
|
+
if item.name == opt:
|
|
316
|
+
return item
|
|
317
|
+
|
|
318
|
+
def save(self):
|
|
319
|
+
self._domain.save()
|
|
320
|
+
|
|
321
|
+
def do_exit(self, arg=None):
|
|
322
|
+
"""Finish config and exit"""
|
|
323
|
+
self.save()
|
|
324
|
+
self.printf('')
|
|
325
|
+
self.printf('Thank you for using Pyarmor')
|
|
326
|
+
return True
|
|
327
|
+
do_EOF = do_q = do_exit
|
|
328
|
+
|
|
329
|
+
def do_use(self, arg):
|
|
330
|
+
"""Switch domain: global, local, project"""
|
|
331
|
+
names = list(self._domains.keys())
|
|
332
|
+
if arg not in names:
|
|
333
|
+
self.printf('Invalid name: ', arg)
|
|
334
|
+
self.printf('Please type one of', str(names))
|
|
335
|
+
elif self._domain.name == arg:
|
|
336
|
+
pass
|
|
337
|
+
else:
|
|
338
|
+
self._domain.save()
|
|
339
|
+
if arg == 'global':
|
|
340
|
+
self._entity.reset(index=1)
|
|
341
|
+
elif self._domain.name == 'global':
|
|
342
|
+
self._entity.reset(index=-1)
|
|
343
|
+
self._domain = self._domains[arg]
|
|
344
|
+
self._section = self._domain
|
|
345
|
+
|
|
346
|
+
def do_ls(self, arg):
|
|
347
|
+
"""List all the available items in current domain"""
|
|
348
|
+
sections = self.get_sections(arg)
|
|
349
|
+
if sections:
|
|
350
|
+
self.printf('Sections:')
|
|
351
|
+
self.columnize([x.name for x in sections], self.col)
|
|
352
|
+
self.printf('')
|
|
353
|
+
|
|
354
|
+
options = self.get_options(arg)
|
|
355
|
+
if options:
|
|
356
|
+
self.printf('Options:')
|
|
357
|
+
self.columnize([x.name for x in options], self.col)
|
|
358
|
+
self.printf('')
|
|
359
|
+
|
|
360
|
+
def do_cd(self, arg):
|
|
361
|
+
"""Switch to section, .. to parent, blank to top"""
|
|
362
|
+
if arg == '..':
|
|
363
|
+
if self._section is not self._domain:
|
|
364
|
+
self._section = self._section.parent
|
|
365
|
+
elif arg:
|
|
366
|
+
item = self.section.children.get(arg)
|
|
367
|
+
if item:
|
|
368
|
+
self._section = item
|
|
369
|
+
else:
|
|
370
|
+
self.printf('No item', repr(arg))
|
|
371
|
+
else:
|
|
372
|
+
self._section = self._domain
|
|
373
|
+
|
|
374
|
+
def do_get(self, arg):
|
|
375
|
+
"""Show option value"""
|
|
376
|
+
options = self.get_options(arg)
|
|
377
|
+
if not options:
|
|
378
|
+
self.printf('No found any', repr(arg))
|
|
379
|
+
return
|
|
380
|
+
for opt in options:
|
|
381
|
+
value = opt.value
|
|
382
|
+
if value is not None:
|
|
383
|
+
self.printf('%-20s= %s' % (opt.name, value))
|
|
384
|
+
|
|
385
|
+
def do_info(self, arg):
|
|
386
|
+
"""List sections, options, and all the values"""
|
|
387
|
+
if arg == '':
|
|
388
|
+
self.do_ls('')
|
|
389
|
+
self.do_get('')
|
|
390
|
+
return
|
|
391
|
+
item = self.section.children.get(arg)
|
|
392
|
+
if item:
|
|
393
|
+
self.do_cd(arg)
|
|
394
|
+
self.do_ls('')
|
|
395
|
+
self.do_get('')
|
|
396
|
+
self.do_cd('..')
|
|
397
|
+
else:
|
|
398
|
+
item = self.find(arg)
|
|
399
|
+
if item:
|
|
400
|
+
self.printf(item.usage())
|
|
401
|
+
self.do_get(arg)
|
|
402
|
+
else:
|
|
403
|
+
self.printf('No found', arg)
|
|
404
|
+
|
|
405
|
+
def do_set(self, arg):
|
|
406
|
+
"""Set option value"""
|
|
407
|
+
if arg.find(' ') == -1:
|
|
408
|
+
self.printf('Missing value')
|
|
409
|
+
return
|
|
410
|
+
name, value = arg.split(None, 1)
|
|
411
|
+
item = self.find(name)
|
|
412
|
+
if item:
|
|
413
|
+
c = value[:1]
|
|
414
|
+
if c in ('"', "'"):
|
|
415
|
+
value = value.strip(c)
|
|
416
|
+
try:
|
|
417
|
+
item.value = value
|
|
418
|
+
self._domain.dirty = True
|
|
419
|
+
except ValueError as e:
|
|
420
|
+
self.printf(str(e))
|
|
421
|
+
else:
|
|
422
|
+
self.printf('No found', name)
|
|
423
|
+
|
|
424
|
+
def do_reset(self, arg):
|
|
425
|
+
"""Reset option in the domain"""
|
|
426
|
+
if arg in ('', '*'):
|
|
427
|
+
self.printf('Please specify one option')
|
|
428
|
+
return
|
|
429
|
+
item = self.find(arg)
|
|
430
|
+
if item:
|
|
431
|
+
item.reset()
|
|
432
|
+
self._domain.dirty = True
|
|
433
|
+
else:
|
|
434
|
+
self.printf('No found', arg)
|
|
435
|
+
|
|
436
|
+
def do_push(self, arg, silent=False):
|
|
437
|
+
"""Append new value to option"""
|
|
438
|
+
if arg.find(' ') == -1:
|
|
439
|
+
self.printf('Missing value')
|
|
440
|
+
return
|
|
441
|
+
name, value = arg.split(None, 1)
|
|
442
|
+
item = self.find(name)
|
|
443
|
+
if item:
|
|
444
|
+
for x in shlex.split(value):
|
|
445
|
+
try:
|
|
446
|
+
item.push(x)
|
|
447
|
+
except ValueError as e:
|
|
448
|
+
self.printf(str(e))
|
|
449
|
+
break
|
|
450
|
+
else:
|
|
451
|
+
self._domain.dirty = True
|
|
452
|
+
self.do_get(name)
|
|
453
|
+
else:
|
|
454
|
+
self.printf('No found', name)
|
|
455
|
+
|
|
456
|
+
def do_pop(self, arg):
|
|
457
|
+
"""Remove one choice from option"""
|
|
458
|
+
if arg.find(' ') == -1:
|
|
459
|
+
self.printf('Missing value')
|
|
460
|
+
return
|
|
461
|
+
name, value = arg.split(None, 1)
|
|
462
|
+
item = self.find(name)
|
|
463
|
+
if item:
|
|
464
|
+
for x in shlex.split(value):
|
|
465
|
+
item.pop(x)
|
|
466
|
+
self._domain.dirty = True
|
|
467
|
+
self.do_get(name)
|
|
468
|
+
else:
|
|
469
|
+
self.printf('No found', name)
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
if __name__ == '__main__':
|
|
473
|
+
from os.path import join as joinpath, abspath, expanduser
|
|
474
|
+
|
|
475
|
+
from .context import Context
|
|
476
|
+
|
|
477
|
+
home = joinpath('~', '.pyarmor')
|
|
478
|
+
home = abspath(expanduser(home))
|
|
479
|
+
|
|
480
|
+
ctx = Context(home)
|
|
481
|
+
PyarmorShell(ctx).cmdloop()
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyarmor.cli
|
|
3
|
+
Version: 9.2.6
|
|
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.1
|
|
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 script 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.15
|
|
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,30 @@
|
|
|
1
|
+
pyarmor/cli/__init__.py,sha256=hsPY2kypxxO4MlApFlgRoO1rRjzUr2r8jZxWZxibXrc,1153
|
|
2
|
+
pyarmor/cli/__main__.py,sha256=0IhOmOhs91SSYOALE-hz84LjAVxfe0XtokLSn3xxUvU,26604
|
|
3
|
+
pyarmor/cli/batch.py,sha256=51uBFWRdQk3Fa1l1EdLj-KwN7fwY9D6tfJXpR2WRSg8,1671
|
|
4
|
+
pyarmor/cli/bootstrap.py,sha256=C0RIl-PxJVEVISMGMgotZo8Q-jZQ8ztN7-IYxu4O-C0,7189
|
|
5
|
+
pyarmor/cli/bug.py,sha256=fwT_2oPi4rcLN5ziYEuZS2IKLljt05hKEbQM1fjkM88,4872
|
|
6
|
+
pyarmor/cli/command.py,sha256=n2j0Luwm5WXf5wt_NBmmbhzi7fmwnr9X_tgw7fhcSXg,18212
|
|
7
|
+
pyarmor/cli/config.py,sha256=Roti0bOPzUELm3zp_XLCUphZ_eFzhTGTZVcN_dJ1_lc,10795
|
|
8
|
+
pyarmor/cli/context.py,sha256=TogVCF9-jDyYJgLn9YQVlIYgtzB50OC5dOSKvOsHcww,24388
|
|
9
|
+
pyarmor/cli/core.data.1,sha256=TwImKy17vfR04b_Za6rN6DPDGtx8fdHz1ANAbDUllho,299632
|
|
10
|
+
pyarmor/cli/core.data.2,sha256=43qFFxPg_50oMcx1GETBMOZqKYKy1le8bsE1VeJz2wg,231091
|
|
11
|
+
pyarmor/cli/core.data.3,sha256=So9jEsfw2H3QEMkzR6IffB1fWPCAhxMtP1wuPl160G8,171453
|
|
12
|
+
pyarmor/cli/default.cfg,sha256=xG-o3LgzIrZpwWumaWsuizdqTP_xpEfBQ9tTKUtz4YE,14080
|
|
13
|
+
pyarmor/cli/docker.py,sha256=f82zF2LgLXtCLI0w_EtMGoKDuejJFDQbSb_zhoHDSss,6469
|
|
14
|
+
pyarmor/cli/generate.py,sha256=zLp5bqYffrRA_uEJzcXsydaWvVIadiZoEXzRzAvSmrM,9445
|
|
15
|
+
pyarmor/cli/hdinfo.py,sha256=JK9i-4UrU-4bljzi3Z_0pKKHqHlT9sZde8wx4SP8BG8,2537
|
|
16
|
+
pyarmor/cli/merge.py,sha256=0QqQ8idac5OVvzw6tOtdx5qWlSdD1NzvmWeCiLkvLns,7282
|
|
17
|
+
pyarmor/cli/mixer.py,sha256=i4IrXukoG5L3V3Wv5BgDSTkNU5NB03-Q4bgsWwug6LY,3956
|
|
18
|
+
pyarmor/cli/model.py,sha256=K6Fec0tgRYtoXZgsmoaEq-k0-ZOg1YQPQS6ahTUFsDE,10933
|
|
19
|
+
pyarmor/cli/plugin.py,sha256=Nxm249i9UbwUhLuirwIlKw9k_FnVzd0mlo4_ATPYjz4,11117
|
|
20
|
+
pyarmor/cli/project.py,sha256=FNNxKI4dHliW6ziPDrYILeOM9-gQW89rY72GE2ixI70,37463
|
|
21
|
+
pyarmor/cli/public_capsule.zip,sha256=1r4u42ixfocGPMQc0OklpoHF3nvVW6GA1f4SwcEJWVI,2487
|
|
22
|
+
pyarmor/cli/register.py,sha256=OuBjyD8uxGRJhs2ke29zqKW3ee3_JR5FqbkSufkbdkM,39973
|
|
23
|
+
pyarmor/cli/repack.py,sha256=J9okR-1NdgROcRvpsvDTir11eDAH0JXfbiOGl51gphE,28679
|
|
24
|
+
pyarmor/cli/resource.py,sha256=NVVkn2VNfv8K55pRPWaGfvchl3Nu9JLaoifm6qohcWw,8630
|
|
25
|
+
pyarmor/cli/shell.py,sha256=W5fcMbYXdTKB77loHsPeg2vEVoWJPHLfNYHG-4DT-Y4,13268
|
|
26
|
+
pyarmor_cli-9.2.6.dist-info/METADATA,sha256=gy2eI0LKdxZVRIcjHQ2sZKZ6sPwP0hGZ23EDoy1LsS8,2375
|
|
27
|
+
pyarmor_cli-9.2.6.dist-info/WHEEL,sha256=kaMOOuGDRs3OZA3I9YTs0dJFtrnzzh8BHRx5jSb3e54,100
|
|
28
|
+
pyarmor_cli-9.2.6.dist-info/entry_points.txt,sha256=QDU0TXJn8QG3tkLK4_hoSVW7bvbrMca8hDkIMyIDwow,93
|
|
29
|
+
pyarmor_cli-9.2.6.dist-info/top_level.txt,sha256=UE1ovZ_90YzwF_lZ3LV7o8HKLe-RgzUaUUvdH5UTUus,8
|
|
30
|
+
pyarmor_cli-9.2.6.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyarmor
|