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/batch.py ADDED
@@ -0,0 +1,62 @@
1
+ #! /usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ #############################################################
5
+ # #
6
+ # Copyright @ 2025 - Dashingsoft corp. #
7
+ # All rights reserved. #
8
+ # #
9
+ # Pyarmor #
10
+ # #
11
+ # Version: 9.2.1 - #
12
+ # #
13
+ #############################################################
14
+ #
15
+ #
16
+ # @File: cli/shell.py
17
+ #
18
+ # @Author: Jondy Zhao (pyarmor@163.com)
19
+ #
20
+ # @Create Date: Wed Nov 5 20:22:52 CST 2025
21
+ #
22
+
23
+ """This script could run batch pyarmor commands.
24
+
25
+ For example:
26
+
27
+ python3 -m pyarmor.cli.batch build-script.sh
28
+
29
+ cd abc
30
+ pyarmor
31
+
32
+ The main purpose is to fix pyarmor CI License send too many request issues.
33
+
34
+ """
35
+ import shlex
36
+ import os
37
+
38
+ from pyarmor.cli.__main__ import main_entry as pyarmor_run
39
+
40
+ # Do not run `pyarmor reg pyarmor-ci-xxxx.zip` here, run it before this script
41
+
42
+ build_commands = """
43
+ pyarmor gen main.py
44
+ cd ../package1
45
+ pyarmor gen -R --enable-bcc src/
46
+ cd ../package2
47
+ pyarmor gen -R --enable-jit --private src/
48
+ """
49
+
50
+ for cmd in build_commands.splitlines():
51
+ if cmd.startswith('#'):
52
+ continue
53
+
54
+ if cmd.startswith('cd '):
55
+ path = cmd[3:].strip()
56
+ print('Change current path:', path)
57
+ os.chdir(path)
58
+
59
+ elif cmd.startswith('pyarmor '):
60
+ print('Execute: ', cmd)
61
+ args = shlex.split(cmd[8:].strip())
62
+ pyarmor_run(args)
@@ -0,0 +1,207 @@
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.2.1 - #
12
+ # #
13
+ #############################################################
14
+ #
15
+ #
16
+ # @File: pyarmor/cli/bootstrap.py
17
+ #
18
+ # @Author: Jondy Zhao (pyarmor@163.com)
19
+ #
20
+ # @Create Date: Fri Apr 14 17:43:59 CST 2023
21
+ #
22
+ import logging
23
+ import os
24
+ import shutil
25
+ import sys
26
+
27
+ from subprocess import check_output, check_call, Popen, PIPE
28
+
29
+
30
+ def check_prebuilt_runtime_library(platnames, extra=None, rtver=''):
31
+ pkgpath = os.path.normpath(os.path.dirname(__file__))
32
+ corepath = os.path.join(pkgpath, 'core')
33
+ if not os.path.exists(corepath):
34
+ raise RuntimeError('no found "{0}", please run "pip install {0}" to '
35
+ 'install it'.format('pyarmor.cli.core'))
36
+
37
+ instcmd = [sys.executable, '-m', 'pip', 'install',
38
+ '--disable-pip-version-check']
39
+
40
+ # Before Pyarmor 8.3, prefer to "pyarmor.cli.runtime"
41
+ # It could be disabled by
42
+ # pyarmor cfg pyarmor:cli.runtime = false
43
+ if rtver.find('.') > 0:
44
+ runtime_pkgpath = os.path.join(pkgpath, 'runtime')
45
+ if os.path.exists(runtime_pkgpath):
46
+ from pyarmor.cli.runtime import __VERSION__ as current_rtver
47
+ if current_rtver == rtver:
48
+ return
49
+
50
+ pkgver = 'pyarmor.cli.runtime~=%s' % rtver
51
+ logging.info('install "%s" for cross platforms', pkgver)
52
+ try:
53
+ return check_call(instcmd + [pkgver])
54
+ except Exception:
55
+ logging.warning('failed to install "%s"' % pkgver)
56
+
57
+ # From Pyarmor 8.3, prefer to "pyarmor.cli.core.PLATFORM"
58
+ from pyarmor.cli.core import __VERSION__ as corever
59
+
60
+ pkgnames = set(extra if isinstance(extra, list) else
61
+ [extra] if isinstance(extra, str) else
62
+ ['themida'] if extra else [])
63
+ if platnames:
64
+ for plat in platnames:
65
+ pkgnames.add(plat.split('.')[0])
66
+
67
+ for entry in os.scandir(corepath):
68
+ if entry.name in pkgnames:
69
+ m = __import__('pyarmor.cli.core.' + entry.name,
70
+ globals(), locals(),
71
+ ['__VERSION__'], 0)
72
+ if getattr(m, '__VERSION__', None) == corever:
73
+ pkgnames.remove(entry.name)
74
+
75
+ if pkgnames:
76
+ pkgvers = ['pyarmor.cli.core.%s~=%s' % (x, corever) for x in pkgnames]
77
+ logging.info('install packages %s for cross platforms', str(pkgvers))
78
+ try:
79
+ check_call(instcmd + pkgvers)
80
+ except Exception as e:
81
+ logging.error('%s', e)
82
+ raise RuntimeError('failed to install runtime packages')
83
+
84
+
85
+ def _shell_cmd(cmdlist):
86
+ logging.info('run: %s', ' '.join(cmdlist))
87
+ p = Popen(cmdlist, stdout=PIPE, stderr=PIPE, shell=True)
88
+ stdout, stderr = p.communicate()
89
+ return p.returncode, stderr
90
+
91
+
92
+ def _check_extension(fullpath):
93
+ if not os.path.exists(fullpath):
94
+ logging.error('please re-install pyarmor.cli.core to fix this problem')
95
+ raise RuntimeError('no found extension "%s"' % fullpath)
96
+
97
+
98
+ def _fixup_darwin_rpath(fullpath, pyver):
99
+ output = check_output(['otool', '-L', sys.executable])
100
+ for line in output.splitlines():
101
+ if line.find(b'Frameworks/Python.framework/Versions') > 0:
102
+ pydll = line.split()[0].decode()
103
+ logging.info('found CPython library "%s"', pydll)
104
+ break
105
+
106
+ if line.find(('libpython' + pyver).encode('utf-8')) > 0:
107
+ pydll = line.split()[0].decode()
108
+ logging.info('found CPython library "%s"', pydll)
109
+ break
110
+ else:
111
+ raise RuntimeError('no found CPython library')
112
+
113
+ # old = '@rpath/Frameworks/Python.framework/Versions/%s/Python' % pyver
114
+ old = '@rpath/lib/libpython%s.dylib' % pyver
115
+ cmdlist = ['install_name_tool', '-change', old, pydll, fullpath]
116
+ rc, err = _shell_cmd(cmdlist)
117
+ if rc:
118
+ raise RuntimeError('install_name_tool failed (%d): %s' % (rc, err))
119
+
120
+ identity = '-'
121
+ cmdlist = ['codesign', '-s', identity, '--force',
122
+ '--all-architectures', '--timestamp', fullpath]
123
+ rc, err = _shell_cmd(cmdlist)
124
+ if rc:
125
+ raise RuntimeError('codesign failed (%d): %s' % (rc, err))
126
+
127
+
128
+ def _fixup_darwin(path, filename, pyver):
129
+ fullpath = os.path.join(path, filename)
130
+ _check_extension(fullpath)
131
+
132
+ if not os.access(path, os.W_OK):
133
+ logging.error('please run Python with super user or anyone who has'
134
+ 'write permission on path "%s"', path)
135
+ raise RuntimeError('current user has no write permission')
136
+
137
+ backup = fullpath + '.bak'
138
+ if os.path.exists(backup):
139
+ logging.info('create backup file "%s"', backup)
140
+ shutil.copy2(fullpath, backup)
141
+
142
+ try:
143
+ logging.info('start to fixup extension "%s"', fullpath)
144
+ _fixup_darwin_rpath(fullpath, pyver)
145
+
146
+ logging.info('fixup extension "pytransform3" successfully')
147
+ logging.info('try command ``pyarmor gen foo.py`` to make sure '
148
+ 'it works')
149
+ logging.info('if something is wrong, please restore it from '
150
+ 'backup file')
151
+ except Exception:
152
+ logging.error('fixup extension "pytransform3" failed')
153
+ shutil.move(backup, fullpath)
154
+ raise
155
+
156
+
157
+ def _fixup_linux(path, filename, pyver):
158
+ fullpath = os.path.join(path, filename)
159
+ _check_extension(fullpath)
160
+
161
+ rc = _shell_cmd(['ldd', fullpath])
162
+ if rc:
163
+ logging.info('try to install package "libpython%s" to fix it' % pyver)
164
+ else:
165
+ logging.info('nothing to do in this platform')
166
+
167
+
168
+ def _fixup_windows(path, filename, pyver):
169
+ fullpath = os.path.join(path, filename)
170
+ _check_extension(fullpath)
171
+ logging.info('nothing to do in this platform')
172
+
173
+
174
+ def auto_fix(path):
175
+ '''Deprecated since Pyarmor 8.3.0'''
176
+ pyver = '%s.%s' % sys.version_info[:2]
177
+ plat = sys.platform.lower()
178
+
179
+ if plat.startswith('darwin'):
180
+ _fixup_darwin(path, 'pytransform3.so', pyver)
181
+
182
+ elif plat.startswith('win'):
183
+ _fixup_windows(path, 'pytransform3.pyd', pyver)
184
+
185
+ elif plat.startswith('linux'):
186
+ _fixup_windows(path, 'pytransform3.so', pyver)
187
+
188
+ else:
189
+ logging.info('nothing to fixup in this platform "%s"', plat)
190
+
191
+
192
+ def main():
193
+ logging.basicConfig(
194
+ level=logging.INFO,
195
+ format='%(levelname)-8s %(message)s',
196
+ )
197
+
198
+ logging.info('Python: %d.%d', *sys.version_info[:2])
199
+ corepath = os.path.join(os.path.dirname(__file__), 'core')
200
+ logging.info('pyarmor.cli.core: %s', corepath)
201
+ # auto_fix(corepath)
202
+ logging.warning('this feature has been deprecated since Pyarmor 8.3.0')
203
+ logging.info('nothing to do')
204
+
205
+
206
+ if __name__ == '__main__':
207
+ main()
pyarmor/cli/bug.py ADDED
@@ -0,0 +1,137 @@
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: 8.5.1 - #
12
+ # #
13
+ #############################################################
14
+ #
15
+ #
16
+ # @File: cli/bug.py
17
+ #
18
+ # @Author: Jondy Zhao (pyarmor@163.com)
19
+ #
20
+ # @Create Date: Tue Mar 12 15:19:41 CST 2024
21
+
22
+
23
+ #############################################################
24
+ # #
25
+ # Deprecated since Pyarmor 9, use `pyarmor man` instead #
26
+ # #
27
+ #############################################################
28
+
29
+ import logging
30
+
31
+ from string import Template
32
+
33
+ BUG_FILE, LOG_FILE = 'pyarmor.report.bug', '.pyarmor/pyarmor.debug.log'
34
+
35
+ BUG_TEMPLATE = Template('''[Bug] $title
36
+
37
+ ### Full command options and console output
38
+ $cmdline
39
+
40
+ $tracelog
41
+
42
+ ### Traceback
43
+ $tb
44
+ ''')
45
+
46
+ UNUSED_ENABLE_DEBUG_HINTS = '''something is wrong
47
+ *=============================================================*
48
+ * Please enable debug option `-d` to run it again *
49
+ * pyarmor -d gen options ... *
50
+ * *
51
+ * Then check console log to find more information *
52
+ * *
53
+ * Please also check *
54
+ * https://pyarmor.readthedocs.io/en/latest/questions.html *
55
+ *=============================================================*
56
+ '''
57
+
58
+ UNUSED_SOLUTION_HINTS = Template('''something is wrong
59
+ *=============================================================*
60
+ * Please check *
61
+ * https://pyarmor.readthedocs.io/en/latest/questions.html *
62
+ * or run `pyarmor man` to find solutions quickly *
63
+ * *
64
+ * It's recommand to report issue by `pyarmor man` in order *
65
+ * to provide necessary information, and avoid dupcliated *
66
+ * issues or unclear question. *
67
+ *=============================================================*
68
+ ''')
69
+
70
+ ENABLE_DEBUG_HINTS = 'please enable debug option `-d` to run it again'
71
+
72
+ SOLUTION_HINTS = Template('''
73
+ *=============================================================*
74
+ * Please check console log to find out what's wrong *
75
+ * *
76
+ * If still not solved, please find solutions by *
77
+ * https://pyarmor.readthedocs.io/en/latest/questions.html *
78
+ *=============================================================*
79
+ ''')
80
+
81
+
82
+ def generate_bug_report(e, logfile=LOG_FILE, output=BUG_FILE):
83
+ 'Generate file `pyarmor.report.bug` in current path'
84
+ from os.path import exists
85
+ from sys import argv
86
+ from traceback import format_exc
87
+
88
+ if exists(logfile):
89
+ with open(logfile, 'r') as f:
90
+ lines = f.readlines()
91
+ n = len(lines)
92
+ if n > 128:
93
+ tracelog = ''.join(lines[:100] + ['...\n'] + lines[n-20:n])
94
+ else:
95
+ tracelog = ''.join(lines[:n])
96
+ else:
97
+ tracelog = Template(
98
+ 'TODO: no found logfile "$logfile", please paste console log '
99
+ 'here manually').substitute(logfile=logfile)
100
+
101
+ title = '%s: %s' % (type(e).__name__, str(e))
102
+ with open(output, 'w') as f:
103
+ f.write(BUG_TEMPLATE.substitute(
104
+ title=title,
105
+ cmdline=' '.join(argv),
106
+ tracelog=tracelog,
107
+ tb=format_exc()
108
+ ))
109
+
110
+
111
+ def find_solutions(e):
112
+ '''Print quick solutions according to exception
113
+
114
+ If not enable debug, tell user try `pyarmor -d cmd...`
115
+
116
+ If it raises CliError, print possible solutions
117
+
118
+ For unknown error, print FAQ page link and `pyarmor man`
119
+
120
+ Pyarmor Man is designed to help Pyarmor users to learn
121
+ and use Pyarmor by web-ui, to find solution quickly when
122
+ something is wrong, to report bugs and ask questions in
123
+ standard form in order to save both Pyarmor team's and
124
+ Pyarmor users' time.
125
+ '''
126
+ logger = logging.getLogger()
127
+ if logger.getEffectiveLevel() > logging.DEBUG:
128
+ return
129
+
130
+ print('\nDebug Information:')
131
+ logger.info('generate bug file "%s"', BUG_FILE)
132
+ generate_bug_report(e)
133
+ logger.info(SOLUTION_HINTS.substitute(bugfile=BUG_FILE))
134
+
135
+
136
+ if __name__ == '__main__':
137
+ pass