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/config.py
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
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/config.py
|
|
17
|
+
#
|
|
18
|
+
# @Author: Jondy Zhao (pyarmor@163.com)
|
|
19
|
+
#
|
|
20
|
+
# @Create Date: Thu Jan 12 10:27:05 CST 2023
|
|
21
|
+
#
|
|
22
|
+
import configparser
|
|
23
|
+
import fnmatch
|
|
24
|
+
import os
|
|
25
|
+
|
|
26
|
+
from . import logger, CliError
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def indent(lines, n=2):
|
|
30
|
+
fmt = ' ' * 2 + '%s'
|
|
31
|
+
return [fmt % x for x in lines]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def str_opt(k, v, n=30):
|
|
35
|
+
v = '\n\t'.join(v.splitlines())
|
|
36
|
+
return ' %s = %s%s' % (k, v[:n], '...' if len(v) > n else '')
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Configer(object):
|
|
40
|
+
|
|
41
|
+
SECTIONS = 'pyarmor', 'logging', 'finder', 'builder', 'runtime', \
|
|
42
|
+
'pack', 'bcc', 'mix.str', 'assert.call', 'assert.import'
|
|
43
|
+
|
|
44
|
+
def __init__(self, ctx, encoding=None):
|
|
45
|
+
self.ctx = ctx
|
|
46
|
+
self._encoding = encoding or ctx.encoding
|
|
47
|
+
|
|
48
|
+
def _read_config(self, filename):
|
|
49
|
+
cfg = configparser.ConfigParser(empty_lines_in_values=False)
|
|
50
|
+
cfg.read(filename, encoding=self._encoding)
|
|
51
|
+
return cfg
|
|
52
|
+
|
|
53
|
+
def list_sections(self, local=True, name=None):
|
|
54
|
+
lines = ['All available sections:']
|
|
55
|
+
cfg = self.ctx.cfg
|
|
56
|
+
lines.extend(indent(self.SECTIONS))
|
|
57
|
+
|
|
58
|
+
lines.extend(['', 'Global sections'])
|
|
59
|
+
cfg = self._read_config(self.ctx.global_config)
|
|
60
|
+
lines.extend(indent(cfg.sections()))
|
|
61
|
+
|
|
62
|
+
if local:
|
|
63
|
+
lines.extend(['', 'Local sections'])
|
|
64
|
+
cfg = self._read_config(self.ctx.local_config)
|
|
65
|
+
lines.extend(indent(cfg.sections()))
|
|
66
|
+
|
|
67
|
+
if name:
|
|
68
|
+
lines.extend(['', 'Private "%s" sections' % name])
|
|
69
|
+
cfg = self._read_config(self.ctx.get_filename(local, name))
|
|
70
|
+
lines.extend(indent(cfg.sections()))
|
|
71
|
+
|
|
72
|
+
return lines
|
|
73
|
+
|
|
74
|
+
def list_options(self, sect, local=True, name=None):
|
|
75
|
+
lines = ['Current options']
|
|
76
|
+
|
|
77
|
+
cfg = self.ctx.cfg
|
|
78
|
+
if cfg.has_section(sect):
|
|
79
|
+
lines.extend([str_opt(*x) for x in cfg.items(sect)])
|
|
80
|
+
|
|
81
|
+
lines.extend(['', 'Global options'])
|
|
82
|
+
cfg = self._read_config(self.ctx.global_config)
|
|
83
|
+
if cfg.has_section(sect):
|
|
84
|
+
lines.extend([str_opt(*x) for x in cfg.items(sect)])
|
|
85
|
+
|
|
86
|
+
if local:
|
|
87
|
+
lines.extend(['', 'Local options'])
|
|
88
|
+
cfg = self._read_config(self.ctx.local_config)
|
|
89
|
+
if cfg.has_section(sect):
|
|
90
|
+
lines.extend([str_opt(*x) for x in cfg.items(sect)])
|
|
91
|
+
|
|
92
|
+
if name:
|
|
93
|
+
lines.extend(['', 'Private "%s" options' % name])
|
|
94
|
+
|
|
95
|
+
cfg = self._read_config(self.ctx.get_filename(local, name))
|
|
96
|
+
if cfg.has_section(sect):
|
|
97
|
+
lines.extend([str_opt(*x) for x in cfg.items(sect)])
|
|
98
|
+
|
|
99
|
+
return lines
|
|
100
|
+
|
|
101
|
+
def _list_value(self, sect, opt, local=True, name=None):
|
|
102
|
+
clines, glines, lines, plines = self.infos
|
|
103
|
+
|
|
104
|
+
def format_value(opt):
|
|
105
|
+
v = cfg[sect].get(opt)
|
|
106
|
+
n = 1 << 30
|
|
107
|
+
return 'no option "%s"' % opt if v is None else str_opt(opt, v, n)
|
|
108
|
+
|
|
109
|
+
cfg = self.ctx.cfg
|
|
110
|
+
if cfg.has_section(sect):
|
|
111
|
+
clines.append(format_value(opt))
|
|
112
|
+
|
|
113
|
+
cfg = self._read_config(self.ctx.global_config)
|
|
114
|
+
if cfg.has_section(sect) and cfg.has_option(sect, opt):
|
|
115
|
+
glines.append(format_value(opt))
|
|
116
|
+
|
|
117
|
+
if local:
|
|
118
|
+
cfg = self._read_config(self.ctx.local_config)
|
|
119
|
+
if cfg.has_section(sect) and cfg.has_option(sect, opt):
|
|
120
|
+
lines.append(format_value(opt))
|
|
121
|
+
|
|
122
|
+
if name:
|
|
123
|
+
cfg = self._read_config(self.ctx.get_filename(local, name))
|
|
124
|
+
if cfg.has_section(sect) and cfg.has_option(sect, opt):
|
|
125
|
+
plines.append(format_value(opt))
|
|
126
|
+
|
|
127
|
+
return clines, glines, lines, plines
|
|
128
|
+
|
|
129
|
+
def _set_option(self, sect, opt, value, local=True, name=None):
|
|
130
|
+
ctx = self.ctx
|
|
131
|
+
filename = ctx.get_filename(local=local, name=name)
|
|
132
|
+
|
|
133
|
+
cfg = self._read_config(filename)
|
|
134
|
+
if not cfg.has_section(sect):
|
|
135
|
+
cfg.add_section(sect)
|
|
136
|
+
|
|
137
|
+
# TBD: input multiple lines
|
|
138
|
+
optname, optvalue = opt, value
|
|
139
|
+
if optvalue and optvalue[:1] in ('+', '-', '=', '^'):
|
|
140
|
+
op = optvalue[:1]
|
|
141
|
+
optvalue = optvalue.strip(op)
|
|
142
|
+
if op == '=':
|
|
143
|
+
op = None
|
|
144
|
+
else:
|
|
145
|
+
op = None
|
|
146
|
+
if optvalue and optvalue[:1] in ("'", '"'):
|
|
147
|
+
optvalue = optvalue.strip(optvalue[0])
|
|
148
|
+
|
|
149
|
+
if not optvalue:
|
|
150
|
+
if op is None:
|
|
151
|
+
self._remove(sect, [optname], local, name)
|
|
152
|
+
return
|
|
153
|
+
|
|
154
|
+
ctxcfg = ctx.cfg
|
|
155
|
+
old = ctxcfg[sect].get(optname, '') if ctxcfg.has_section(sect) else ''
|
|
156
|
+
|
|
157
|
+
if op == '+':
|
|
158
|
+
if (optvalue + ' ').find(old + ' ') == -1:
|
|
159
|
+
optvalue = ('%s %s' % (old, optvalue)).strip()
|
|
160
|
+
elif op == '-':
|
|
161
|
+
optvalue = (old + ' ').replace(optvalue + ' ', '').strip()
|
|
162
|
+
elif op == '^':
|
|
163
|
+
optvalue = '\n'.join((old.splitlines() + [optvalue]))
|
|
164
|
+
|
|
165
|
+
logger.info('change option "%s" to new value "%s"', optname, optvalue)
|
|
166
|
+
cfg.set(sect, optname, optvalue)
|
|
167
|
+
|
|
168
|
+
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
169
|
+
with open(filename, 'w', encoding=self._encoding) as f:
|
|
170
|
+
cfg.write(f)
|
|
171
|
+
|
|
172
|
+
self._list_value(sect, optname, local=local, name=name)
|
|
173
|
+
|
|
174
|
+
def _remove(self, section=None, options=None, local=True, name=None):
|
|
175
|
+
ctx = self.ctx
|
|
176
|
+
filename = ctx.get_filename(local=local, name=name)
|
|
177
|
+
|
|
178
|
+
if section is None:
|
|
179
|
+
logger.info('remove config file "%s"', filename)
|
|
180
|
+
if os.path.exists(filename):
|
|
181
|
+
os.remove(filename)
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
cfg = self._read_config(filename)
|
|
185
|
+
|
|
186
|
+
if cfg.has_section(section):
|
|
187
|
+
if not options:
|
|
188
|
+
logger.info('remove section "%s"', section)
|
|
189
|
+
cfg.remove_section(section)
|
|
190
|
+
else:
|
|
191
|
+
for opt in [x for x in options if cfg.has_option(section, x)]:
|
|
192
|
+
logger.info('remove option "%s:%s"', section, opt)
|
|
193
|
+
cfg.remove_option(section, opt)
|
|
194
|
+
|
|
195
|
+
if not cfg.options(section):
|
|
196
|
+
logger.info('remove empty section "%s"', section)
|
|
197
|
+
cfg.remove_section(section)
|
|
198
|
+
|
|
199
|
+
with open(filename, 'w', encoding=self._encoding) as f:
|
|
200
|
+
cfg.write(f)
|
|
201
|
+
|
|
202
|
+
def _clear(self, section=None, options=None, local=True, name=None):
|
|
203
|
+
ctx = self.ctx
|
|
204
|
+
scope = '%s%s config file' % (
|
|
205
|
+
'local' if local else 'global',
|
|
206
|
+
' "%s"' % name if name else ''
|
|
207
|
+
)
|
|
208
|
+
filename = ctx.get_filename(local=local, name=name)
|
|
209
|
+
|
|
210
|
+
if not filename:
|
|
211
|
+
logger.info('no %s', scope)
|
|
212
|
+
return
|
|
213
|
+
|
|
214
|
+
logger.info('remove %s "%s"', scope, filename)
|
|
215
|
+
if os.path.exists(filename):
|
|
216
|
+
os.remove(filename)
|
|
217
|
+
|
|
218
|
+
def _parse_opt(self, opt):
|
|
219
|
+
i = opt.find(':')
|
|
220
|
+
if i == -1:
|
|
221
|
+
j = opt.find('=')
|
|
222
|
+
pat, v = (opt, '') if j == -1 else (opt[:j], opt[j:])
|
|
223
|
+
cfg = self.ctx.cfg
|
|
224
|
+
rlist = []
|
|
225
|
+
for sect in self.SECTIONS:
|
|
226
|
+
if cfg.has_section(sect):
|
|
227
|
+
rlist.append((sect, [x+v for x in cfg.options(sect)
|
|
228
|
+
if fnmatch.fnmatch(x, pat)]))
|
|
229
|
+
return [x for x in rlist if x[1]]
|
|
230
|
+
else:
|
|
231
|
+
return [(opt[:i], [opt[i+1:]])]
|
|
232
|
+
|
|
233
|
+
def reset(self, options=None, local=True, name=None):
|
|
234
|
+
for pat in options:
|
|
235
|
+
for sect, opts in self._parse_opt(pat):
|
|
236
|
+
self._remove(sect, opts, local, name)
|
|
237
|
+
|
|
238
|
+
def run(self, options=None, local=True, name=None):
|
|
239
|
+
lines = []
|
|
240
|
+
|
|
241
|
+
if options and len(options) == 1 and options[0].find('=') == -1:
|
|
242
|
+
for sect, opts in self._parse_opt(options[0]):
|
|
243
|
+
title = 'Section: %s' % sect
|
|
244
|
+
lines.extend(['', '-' * 60, title])
|
|
245
|
+
self.infos = [], [], [], []
|
|
246
|
+
|
|
247
|
+
for opt in opts:
|
|
248
|
+
self._list_value(sect, opt, local, name)
|
|
249
|
+
|
|
250
|
+
lines.extend(['', 'Current settings'])
|
|
251
|
+
lines.extend(self.infos[0])
|
|
252
|
+
lines.extend(['', 'Global settings'])
|
|
253
|
+
lines.extend(self.infos[1])
|
|
254
|
+
lines.extend(['', 'Local settings'])
|
|
255
|
+
lines.extend(self.infos[2])
|
|
256
|
+
if name:
|
|
257
|
+
lines.extend(['', 'Private "%s" settings' % name])
|
|
258
|
+
lines.extend(self.infos[3])
|
|
259
|
+
|
|
260
|
+
elif options:
|
|
261
|
+
pairs = []
|
|
262
|
+
prev, op = None, ''
|
|
263
|
+
for opt in options:
|
|
264
|
+
i = opt.find('=')
|
|
265
|
+
if i > 0:
|
|
266
|
+
pairs.append([opt[:i], opt[i+1:]])
|
|
267
|
+
elif opt in ('+', '=', '-', '^'):
|
|
268
|
+
op = opt
|
|
269
|
+
elif prev:
|
|
270
|
+
pairs.append((prev, op + opt))
|
|
271
|
+
prev, op = None, ''
|
|
272
|
+
else:
|
|
273
|
+
prev = opt
|
|
274
|
+
if prev:
|
|
275
|
+
raise CliError('no value for option "%s"' % prev)
|
|
276
|
+
|
|
277
|
+
for pat, value in pairs:
|
|
278
|
+
sect_opts = self._parse_opt(pat)
|
|
279
|
+
if not sect_opts:
|
|
280
|
+
logger.debug('new builder option "%s"', pat)
|
|
281
|
+
sect_opts = [('builder', [pat])]
|
|
282
|
+
for sect, opts in sect_opts:
|
|
283
|
+
title = 'Section: %s' % sect
|
|
284
|
+
lines.extend(['', '-' * 60, title])
|
|
285
|
+
self.infos = [], [], [], []
|
|
286
|
+
|
|
287
|
+
for opt in opts:
|
|
288
|
+
self._set_option(sect, opt, value, local, name)
|
|
289
|
+
|
|
290
|
+
lines.extend(['', 'Current settings'])
|
|
291
|
+
lines.extend(self.infos[0])
|
|
292
|
+
lines.extend(['', 'Global settings'])
|
|
293
|
+
lines.extend(self.infos[1])
|
|
294
|
+
lines.extend(['', 'Local settings'])
|
|
295
|
+
lines.extend(self.infos[2])
|
|
296
|
+
if name:
|
|
297
|
+
lines.extend(['', 'Private "%s" settings' % name])
|
|
298
|
+
lines.extend(self.infos[3])
|
|
299
|
+
|
|
300
|
+
else:
|
|
301
|
+
for sect in self.SECTIONS:
|
|
302
|
+
title = 'Section: %s' % sect
|
|
303
|
+
lines.extend(['', '-' * 60, title, ''])
|
|
304
|
+
lines.extend(self.list_options(sect, local, name))
|
|
305
|
+
|
|
306
|
+
print('\n'.join(lines))
|