pyarmor.cli 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.
- 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/plugin.py
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
#############################################################
|
|
5
|
+
# #
|
|
6
|
+
# Copyright @ 2023 - Dashingsoft corp. #
|
|
7
|
+
# All rights reserved. #
|
|
8
|
+
# #
|
|
9
|
+
# Pyarmor #
|
|
10
|
+
# #
|
|
11
|
+
# Version: 8.0.1 - #
|
|
12
|
+
# #
|
|
13
|
+
#############################################################
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @File: cli/plugin.py
|
|
17
|
+
#
|
|
18
|
+
# @Author: Jondy Zhao (pyarmor@163.com)
|
|
19
|
+
#
|
|
20
|
+
# @Create Date: Fri Apr 21 18:42:14 CST 2023
|
|
21
|
+
#
|
|
22
|
+
import os
|
|
23
|
+
|
|
24
|
+
from importlib.util import spec_from_file_location, module_from_spec
|
|
25
|
+
|
|
26
|
+
from . import logger
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__all__ = ['CodesignPlugin', 'MultiPythonPlugin', 'PlatformTagPlugin',
|
|
30
|
+
'PycPlugin', 'DarwinUniversalPlugin']
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Plugin(object):
|
|
34
|
+
|
|
35
|
+
def __init__(self, ctx=None):
|
|
36
|
+
self.ctx = ctx
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def install(ctx, pkg='pyarmor.cli.plugin'):
|
|
40
|
+
ctx.Plugin = Plugin
|
|
41
|
+
|
|
42
|
+
for pname in ctx.cfg['builder'].get('plugins', '').split():
|
|
43
|
+
if pname in __all__:
|
|
44
|
+
logger.debug('install plugin: %s', pname)
|
|
45
|
+
ctx.plugins.append(globals().get(pname))
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
for x in '', ctx.local_path, ctx.global_path:
|
|
49
|
+
path = os.path.join(x, pname + '.py')
|
|
50
|
+
if os.path.exists(path):
|
|
51
|
+
logger.debug('plugin script "%s"', path)
|
|
52
|
+
break
|
|
53
|
+
else:
|
|
54
|
+
logger.warning('no plugin "%s" found', pname)
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
spec = spec_from_file_location(pkg + '.' + pname, path)
|
|
58
|
+
module = module_from_spec(spec)
|
|
59
|
+
spec.loader.exec_module(module)
|
|
60
|
+
|
|
61
|
+
names = getattr(module, '__all__', [])
|
|
62
|
+
logger.debug('install plugins: %s', ' '.join(names))
|
|
63
|
+
ctx.plugins.extend([getattr(module, x, None) for x in names])
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def post_build(ctx, pack=None):
|
|
67
|
+
inputs = ctx.input_paths
|
|
68
|
+
outputs = ctx.outputs
|
|
69
|
+
for plugin in [x for x in ctx.plugins if hasattr(x, 'post_build')]:
|
|
70
|
+
logger.debug('call post build plugin %s', plugin)
|
|
71
|
+
plugin.post_build(ctx, inputs, outputs, pack=pack)
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def post_key(ctx, keyfile):
|
|
75
|
+
kwargs = {
|
|
76
|
+
'expired': ctx.runtime_expired,
|
|
77
|
+
'devices': ctx.runtime_devices,
|
|
78
|
+
'period': ctx.runtime_period,
|
|
79
|
+
'data': ctx.cmd_options.get('user_data')
|
|
80
|
+
}
|
|
81
|
+
for plugin in [x for x in ctx.plugins if hasattr(x, 'post_key')]:
|
|
82
|
+
logger.debug('call post key plugin %s', plugin)
|
|
83
|
+
plugin.post_key(ctx, keyfile, **kwargs)
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
def post_runtime(ctx, source, dest, platform):
|
|
87
|
+
for plugin in [x for x in ctx.plugins if hasattr(x, 'post_runtime')]:
|
|
88
|
+
logger.debug('call post runtime plugin %s', plugin)
|
|
89
|
+
plugin.post_runtime(ctx, source, dest, platform)
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def post_bcc(ctx, res, csource):
|
|
93
|
+
for plugin in [x for x in ctx.plugins if hasattr(x, 'post_bcc')]:
|
|
94
|
+
patched_csource = plugin.post_bcc(ctx, res, csource)
|
|
95
|
+
if patched_csource:
|
|
96
|
+
csource = patched_csource
|
|
97
|
+
return csource
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class PycPlugin:
|
|
101
|
+
'''Change all obfuscated scripts name entension from ".pyc" to ".py"'''
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def post_build(ctx, inputs, outputs, pack):
|
|
105
|
+
for path, dirnames, filenames in os.walk(outputs[0]):
|
|
106
|
+
for x in filenames:
|
|
107
|
+
if x.endswith('.pyc'):
|
|
108
|
+
pycname = os.path.join(path, x)
|
|
109
|
+
os.replace(pycname, pycname[:-1])
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def osx_sign_binary(dest, identity=None):
|
|
113
|
+
from subprocess import check_call, CalledProcessError, DEVNULL
|
|
114
|
+
cmdlist = ['codesign', '-f', '-s', identity,
|
|
115
|
+
'--all-architectures', '--timestamp', dest]
|
|
116
|
+
logger.debug('%s', ' '.join(cmdlist))
|
|
117
|
+
try:
|
|
118
|
+
check_call(cmdlist, stdout=DEVNULL, stderr=DEVNULL)
|
|
119
|
+
except CalledProcessError as e:
|
|
120
|
+
logger.warning('codesign command failed with error code %d',
|
|
121
|
+
e.returncode)
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.warning('codesign command failed with:\n%s', e)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class CodesignPlugin:
|
|
127
|
+
'''codesign darwin runtime extension "pyarmor_runtime"'''
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def post_runtime(ctx, source, dest, platform):
|
|
131
|
+
if platform.startswith('darwin'):
|
|
132
|
+
identity = ctx.cfg['pack'].get('codesign_identify', '-')
|
|
133
|
+
osx_sign_binary(dest, identity)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class PlatformTagPlugin:
|
|
137
|
+
'''Rename runtime extension "pyarmor_runtime" with platform tag.'''
|
|
138
|
+
|
|
139
|
+
@staticmethod
|
|
140
|
+
def post_runtime(ctx, source, dest, platform):
|
|
141
|
+
pyver = '%s%s' % ctx.python_version[:2]
|
|
142
|
+
if platform.startswith('windows.'):
|
|
143
|
+
tag = 'cp%s' % pyver
|
|
144
|
+
tagname = '.'.join(['pyarmor_runtime', tag, 'pyd'])
|
|
145
|
+
logger.info('rename "%s" to "%s"', dest, tagname)
|
|
146
|
+
os.rename(dest, dest.replace('pyarmor_runtime.pyd', tagname))
|
|
147
|
+
elif platform.startswith('darwin.'):
|
|
148
|
+
tag = 'cpython-%s-darwin' % pyver
|
|
149
|
+
tagname = '.'.join(['pyarmor_runtime', tag, 'so'])
|
|
150
|
+
logger.info('rename "%s" to "%s"', dest, tagname)
|
|
151
|
+
os.rename(dest, dest.replace('pyarmor_runtime.so', tagname))
|
|
152
|
+
elif platform.startswith('linux.'):
|
|
153
|
+
arch = platform.split('.')[1]
|
|
154
|
+
tag = 'cpython-%s-%s-linux-gnu' % (pyver, arch)
|
|
155
|
+
tagname = '.'.join(['pyarmor_runtime', tag, 'so'])
|
|
156
|
+
logger.info('rename "%s" to "%s"', dest, tagname)
|
|
157
|
+
os.rename(dest, dest.replace('pyarmor_runtime.so', tagname))
|
|
158
|
+
else:
|
|
159
|
+
raise RuntimeError('PlatformTagPlugin unknown "%s"' % platform)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class MultiPythonPlugin:
|
|
163
|
+
'''Refine runtime package to support multiple python versions'''
|
|
164
|
+
|
|
165
|
+
RUNTIME_PATH = None
|
|
166
|
+
RUNTIME_FILES = []
|
|
167
|
+
|
|
168
|
+
@staticmethod
|
|
169
|
+
def post_runtime(ctx, source, dest, platform):
|
|
170
|
+
MultiPythonPlugin.RUNTIME_PATH = os.path.dirname(dest)
|
|
171
|
+
MultiPythonPlugin.RUNTIME_FILES.append(dest)
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
def post_build(ctx, inputs, outputs, pack):
|
|
175
|
+
'''Rewrite runtime package __init__.py'''
|
|
176
|
+
from shutil import move, rmtree
|
|
177
|
+
pyver = 'py%s%s' % ctx.python_version[:2]
|
|
178
|
+
platforms = ctx.target_platforms
|
|
179
|
+
|
|
180
|
+
oneplat = len(platforms) == 1
|
|
181
|
+
pkgpath = MultiPythonPlugin.RUNTIME_PATH if oneplat else \
|
|
182
|
+
os.path.dirname(MultiPythonPlugin.RUNTIME_PATH)
|
|
183
|
+
verpath = os.path.join(pkgpath, pyver)
|
|
184
|
+
if os.path.exists(verpath):
|
|
185
|
+
rmtree(verpath)
|
|
186
|
+
os.makedirs(verpath)
|
|
187
|
+
|
|
188
|
+
pkgscript = os.path.join(pkgpath, '__init__.py')
|
|
189
|
+
with open(pkgscript, encoding=ctx.encoding) as f:
|
|
190
|
+
lines = f.readlines()
|
|
191
|
+
start = 1 if lines[0].startswith('#') else 0
|
|
192
|
+
|
|
193
|
+
if oneplat:
|
|
194
|
+
lines[start:] = '\n'.join([
|
|
195
|
+
'from sys import version_info as py_version',
|
|
196
|
+
'{0} = __import__("py%d%d.pyarmor_runtime" % py_version[:2],'
|
|
197
|
+
' globals(), locals(), ["{0}"], 1).{0}'.format('__pyarmor__')
|
|
198
|
+
])
|
|
199
|
+
with open(pkgscript, 'w', encoding=ctx.encoding) as f:
|
|
200
|
+
f.write(''.join(lines))
|
|
201
|
+
for x in MultiPythonPlugin.RUNTIME_FILES:
|
|
202
|
+
move(x, verpath)
|
|
203
|
+
else:
|
|
204
|
+
lines[start:start] = 'from sys import version_info as py_version\n'
|
|
205
|
+
with open(pkgscript, 'w', encoding=ctx.encoding) as f:
|
|
206
|
+
f.write(''.join(lines).replace(
|
|
207
|
+
"join(['_'", "join(['py%d%d' % py_version[:2], '_'"))
|
|
208
|
+
for x in MultiPythonPlugin.RUNTIME_FILES:
|
|
209
|
+
move(os.path.dirname(x), verpath)
|
|
210
|
+
|
|
211
|
+
MultiPythonPlugin.RUNTIME_FILES.clear()
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def osx_merge_binary(target, rtpath, plats):
|
|
215
|
+
from subprocess import check_call, CalledProcessError, DEVNULL
|
|
216
|
+
cmdlist = ['lipo', '-create', '-output', target]
|
|
217
|
+
for plat in plats:
|
|
218
|
+
filename = os.path.join(rtpath, plat, 'pyarmor_runtime.so')
|
|
219
|
+
arch = 'x86_64' if plat == 'darwin_x86_64' else 'arm64'
|
|
220
|
+
cmdlist.extend(['-arch', arch, filename])
|
|
221
|
+
try:
|
|
222
|
+
check_call(cmdlist, stdout=DEVNULL, stderr=DEVNULL)
|
|
223
|
+
return True
|
|
224
|
+
except CalledProcessError as e:
|
|
225
|
+
logger.warning('lipo command "%s" failed with error code %d',
|
|
226
|
+
' '.join(cmdlist), e.returncode)
|
|
227
|
+
except Exception as e:
|
|
228
|
+
logger.warning('lipo command "%s" failed with:\n%s',
|
|
229
|
+
' '.join(cmdlist), e)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def find_runtime_package(ctx, output):
|
|
233
|
+
prefix = ctx.import_prefix
|
|
234
|
+
rtname = ctx.runtime_package_name
|
|
235
|
+
if not prefix:
|
|
236
|
+
return os.path.join(output, rtname)
|
|
237
|
+
if isinstance(prefix, str):
|
|
238
|
+
return os.path.join(output, prefix.replace('.', os.path.sep), rtname)
|
|
239
|
+
with os.scandir(output) as iterator:
|
|
240
|
+
for entry in iterator:
|
|
241
|
+
if entry.is_dir():
|
|
242
|
+
if rtname in os.listdir(entry.path):
|
|
243
|
+
return os.path.join(entry.path, rtname)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class DarwinUniversalPlugin:
|
|
247
|
+
|
|
248
|
+
@staticmethod
|
|
249
|
+
def post_build(ctx, inputs, outputs, pack):
|
|
250
|
+
from shutil import rmtree
|
|
251
|
+
|
|
252
|
+
if not ctx.native_platform.startswith('darwin.'):
|
|
253
|
+
return
|
|
254
|
+
|
|
255
|
+
def rebuild_init(oneplat, init_script):
|
|
256
|
+
with open(init_script, 'r', encoding=ctx.encoding) as f:
|
|
257
|
+
lines = f.readlines()
|
|
258
|
+
if oneplat:
|
|
259
|
+
lines[1:] = ['from .pyarmor_runtime import __pyarmor__']
|
|
260
|
+
else:
|
|
261
|
+
for i in range(1, len(lines)):
|
|
262
|
+
if lines[i].strip().startswith("# mach = 'universal'"):
|
|
263
|
+
lines[i] = lines[i].replace('# ', '')
|
|
264
|
+
break
|
|
265
|
+
with open(init_script, 'w', encoding=ctx.encoding) as f:
|
|
266
|
+
f.write(''.join(lines))
|
|
267
|
+
|
|
268
|
+
rtpath = find_runtime_package(ctx, outputs[0])
|
|
269
|
+
if rtpath is None or not os.path.exists(rtpath):
|
|
270
|
+
logger.debug('no found runtime package "%s"', rtpath)
|
|
271
|
+
return
|
|
272
|
+
dirs = [x.name for x in os.scandir(rtpath) if x.is_dir()]
|
|
273
|
+
plats = set(['darwin_x86_64', 'darwin_arm64', 'darwin_aarch64'])
|
|
274
|
+
plats = plats.intersection(set(dirs))
|
|
275
|
+
if len(plats) > 1:
|
|
276
|
+
oneplat = all([x.startswith('darwin_') for x in dirs])
|
|
277
|
+
if oneplat:
|
|
278
|
+
target = rtpath
|
|
279
|
+
else:
|
|
280
|
+
target = os.path.join(rtpath, 'darwin_universal')
|
|
281
|
+
os.makedirs(target, exist_ok=True)
|
|
282
|
+
target = os.path.join(target, 'pyarmor_runtime.so')
|
|
283
|
+
|
|
284
|
+
if not osx_merge_binary(target, rtpath, plats):
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
rebuild_init(oneplat, os.path.join(rtpath, '__init__.py'))
|
|
288
|
+
identity = ctx.cfg['pack'].get('codesign_identify', '-')
|
|
289
|
+
osx_sign_binary(target, identity)
|
|
290
|
+
|
|
291
|
+
# Clean old files
|
|
292
|
+
[rmtree(os.path.join(rtpath, x)) for x in plats]
|