0
# Configuration Management
1
2
PyArmor provides hierarchical configuration management with global, local, and project-specific settings. The configuration system supports interactive shell editing, programmatic access, and persistent storage of obfuscation parameters and environment settings.
3
4
## Capabilities
5
6
### Configuration Manager (v8+)
7
8
Modern configuration management with hierarchical settings and validation.
9
10
```python { .api }
11
class Configer:
12
"""
13
Configuration file management and validation.
14
"""
15
16
def __init__(self, ctx, encoding: str = None):
17
"""
18
Initialize configuration manager.
19
20
Args:
21
ctx (Context): PyArmor context instance
22
encoding (str, optional): Configuration file encoding
23
"""
24
25
def list_sections(self, local: bool = True, name: str = None) -> list:
26
"""
27
List available configuration sections.
28
29
Args:
30
local (bool): Include local settings (default: True)
31
name (str, optional): Filter by section name pattern
32
33
Returns:
34
list: Available configuration sections
35
36
Example sections:
37
['pyarmor', 'builder', 'runtime', 'finder', 'mix', 'assert']
38
"""
39
40
def list_options(self, sect: str, local: bool = True, name: str = None) -> list:
41
"""
42
List options in a configuration section.
43
44
Args:
45
sect (str): Section name
46
local (bool): Include local settings
47
name (str, optional): Filter by option name pattern
48
49
Returns:
50
list: Available options in section
51
"""
52
53
def run(self, options: list, local: bool, name: str) -> None:
54
"""
55
Execute configuration commands.
56
57
Args:
58
options (list): Configuration options to set/query
59
local (bool): Apply to local settings
60
name (str): Private settings name for module/package
61
62
Options format:
63
['option'] - Query option value
64
['option=value'] - Set option value
65
['section.option=value'] - Set section-specific option
66
"""
67
68
def reset(self, options: list, local: bool, name: str) -> None:
69
"""
70
Reset configuration options to defaults.
71
72
Args:
73
options (list): Options to reset
74
local (bool): Reset local settings
75
name (str): Private settings name
76
"""
77
```
78
79
### Context Management
80
81
Central context and environment management for PyArmor operations.
82
83
```python { .api }
84
class Context:
85
"""
86
PyArmor execution context and environment management.
87
"""
88
89
def __init__(self, *paths):
90
"""
91
Initialize context with optional home path configuration.
92
93
Args:
94
*paths: Home directory paths (home, data, temp, config)
95
"""
96
97
def push(self, options: dict) -> None:
98
"""
99
Push configuration options to context stack.
100
101
Args:
102
options (dict): Configuration options to apply
103
"""
104
105
def pop(self) -> dict:
106
"""
107
Pop configuration options from context stack.
108
109
Returns:
110
dict: Popped configuration options
111
"""
112
113
def get_res_options(self, fullname: str, catalog: str) -> dict:
114
"""
115
Get resource-specific configuration options.
116
117
Args:
118
fullname (str): Full resource name (module.submodule)
119
catalog (str): Resource catalog type
120
121
Returns:
122
dict: Resource-specific configuration
123
"""
124
125
def version_info(self) -> str:
126
"""
127
Get PyArmor version information.
128
129
Returns:
130
str: Formatted version string
131
"""
132
133
# Context Properties
134
@property
135
def pyarmor_platform(self) -> str:
136
"""Current PyArmor platform specification."""
137
138
@property
139
def native_platform(self) -> str:
140
"""Native system platform specification."""
141
142
@property
143
def home_path(self) -> str:
144
"""PyArmor home directory path."""
145
146
@property
147
def runtime_platforms(self) -> list:
148
"""List of configured runtime platforms."""
149
150
@property
151
def runtime_outer(self) -> bool:
152
"""Whether outer runtime key is enabled."""
153
154
@property
155
def runtime_key(self) -> bytes:
156
"""Current runtime key data."""
157
158
@property
159
def runtime_keyfile(self) -> str:
160
"""Runtime key file name."""
161
```
162
163
### Interactive Configuration Shell
164
165
```python { .api }
166
class PyarmorShell:
167
"""
168
Interactive command-line shell for configuration management.
169
"""
170
171
def __init__(self, ctx):
172
"""
173
Initialize interactive shell.
174
175
Args:
176
ctx (Context): PyArmor context instance
177
"""
178
179
def cmdloop(self, intro: str = None) -> None:
180
"""
181
Start interactive command loop.
182
183
Args:
184
intro (str, optional): Introduction message
185
"""
186
187
def do_cfg(self, line: str) -> None:
188
"""
189
Configuration command handler.
190
191
Args:
192
line (str): Command line arguments
193
"""
194
195
def do_show(self, line: str) -> None:
196
"""
197
Show configuration values.
198
199
Args:
200
line (str): Configuration keys to display
201
"""
202
203
def do_set(self, line: str) -> None:
204
"""
205
Set configuration values.
206
207
Args:
208
line (str): Configuration assignments
209
"""
210
211
def do_reset(self, line: str) -> None:
212
"""
213
Reset configuration to defaults.
214
215
Args:
216
line (str): Configuration keys to reset
217
"""
218
```
219
220
### Configuration Hierarchy
221
222
#### Configuration Domains
223
224
```python { .api }
225
# Configuration precedence (highest to lowest):
226
CONFIG_DOMAINS = {
227
'command_line': 'Command line arguments',
228
'project': 'Project-specific settings',
229
'local': 'Local directory settings (.pyarmor_config)',
230
'global': 'Global user settings (~/.pyarmor/config.ini)',
231
'default': 'Built-in default values'
232
}
233
234
# Configuration file locations
235
CONFIG_PATHS = {
236
'global': '~/.pyarmor/config.ini',
237
'local': './.pyarmor_config',
238
'project': './pyarmor.json'
239
}
240
```
241
242
#### Core Configuration Sections
243
244
```python { .api }
245
class PyarmorConfig:
246
"""Core PyArmor configuration options."""
247
248
# Version and licensing
249
version: str # PyArmor version
250
cli_runtime: str # CLI runtime version
251
buyurl: str # Purchase URL
252
253
class BuilderConfig:
254
"""Obfuscation builder configuration."""
255
256
# Obfuscation settings
257
obf_module: int # Module obfuscation (0/1)
258
obf_code: int # Code obfuscation (0/1/2)
259
wrap_mode: int # Wrap mode (0/1)
260
mix_str: int # String mixing (0/1)
261
262
# Advanced settings
263
enable_bcc: int # BCC mode (0/1)
264
enable_jit: int # JIT mode (0/1)
265
enable_rft: int # RFT mode (0/1)
266
enable_themida: int # Themida protection (0/1)
267
268
# Restriction settings
269
restrict_module: int # Module restriction (0-3)
270
assert_call: int # Function call assertion (0/1)
271
assert_import: int # Import assertion (0/1)
272
273
# Platform settings
274
runtime_platforms: str # Target platforms
275
enable_trace: int # Trace mode (0/1)
276
277
class RuntimeConfig:
278
"""Runtime package configuration."""
279
280
# Runtime settings
281
outer: int # Outer runtime key (0/1)
282
period: int # Validation period (days)
283
expired: str # Expiration date
284
devices: str # Bound devices
285
286
# Package settings
287
import_prefix: str # Import prefix
288
package_runtime: int # Package with scripts (0/1)
289
290
class FinderConfig:
291
"""Resource finder configuration."""
292
293
# Discovery settings
294
recursive: int # Recursive search (0/1)
295
findall: int # Find all files (0/1)
296
297
# Filter settings
298
includes: str # Include patterns
299
excludes: str # Exclude patterns
300
```
301
302
### Configuration File Formats
303
304
#### Global Configuration (INI format)
305
306
```ini
307
[pyarmor]
308
version = 9.1.8
309
cli.runtime = 7.6.7
310
buyurl = https://jondy.github.io/paypal/index.html
311
312
[builder]
313
obf_module = 1
314
obf_code = 1
315
wrap_mode = 1
316
mix_str = 0
317
enable_bcc = 0
318
enable_jit = 0
319
enable_rft = 0
320
enable_themida = 0
321
restrict_module = 0
322
assert_call = 0
323
assert_import = 0
324
enable_trace = 0
325
326
[runtime]
327
outer = 0
328
import_prefix =
329
package_runtime = 0
330
331
[finder]
332
recursive = 1
333
findall = 0
334
includes =
335
excludes = __pycache__, *.pyc, test_*, *test.py
336
```
337
338
#### Project Configuration (JSON format)
339
340
```json
341
{
342
"name": "MyProject",
343
"version": "1.0.0",
344
"src": "src",
345
"output": "dist",
346
"entry": "main.py",
347
"obf_code": 2,
348
"obf_mod": 1,
349
"wrap_mode": 1,
350
"advanced_mode": 2,
351
"restrict_mode": 2,
352
"mix_str": 1,
353
"platforms": ["linux.x86_64", "windows.x86_64"],
354
"runtime_path": "runtime",
355
"package_runtime": 1,
356
"license_file": "app.lic"
357
}
358
```
359
360
## Usage Examples
361
362
### Basic Configuration Management
363
364
```python
365
from pyarmor.cli.config import Configer
366
from pyarmor.cli.context import Context
367
368
# Initialize configuration
369
ctx = Context()
370
cfg = Configer(ctx)
371
372
# List all sections
373
sections = cfg.list_sections()
374
print("Available sections:", sections)
375
376
# List options in builder section
377
options = cfg.list_options('builder')
378
print("Builder options:", options)
379
380
# Show current configuration
381
cfg.run(['builder.obf_code'], local=True, name=None)
382
383
# Set configuration values
384
cfg.run(['builder.obf_code=2'], local=True, name=None)
385
cfg.run(['builder.mix_str=1'], local=True, name=None)
386
387
# Reset to defaults
388
cfg.reset(['builder.obf_code'], local=True, name=None)
389
```
390
391
### Context Management
392
393
```python
394
from pyarmor.cli.context import Context
395
396
# Initialize context
397
ctx = Context()
398
399
# Check platform information
400
print(f"PyArmor platform: {ctx.pyarmor_platform}")
401
print(f"Native platform: {ctx.native_platform}")
402
print(f"Home path: {ctx.home_path}")
403
404
# Push configuration options
405
options = {
406
'obf_code': 2,
407
'mix_str': True,
408
'restrict_module': 2,
409
'platforms': ['linux.x86_64', 'windows.x86_64']
410
}
411
ctx.push(options)
412
413
# Get resource-specific options
414
res_options = ctx.get_res_options('mypackage.module', 'Python')
415
print("Resource options:", res_options)
416
417
# Pop configuration
418
old_options = ctx.pop()
419
```
420
421
### Interactive Shell Usage
422
423
```python
424
from pyarmor.cli.shell import PyarmorShell
425
from pyarmor.cli.context import Context
426
427
# Start interactive shell
428
ctx = Context()
429
shell = PyarmorShell(ctx)
430
431
# Example shell session:
432
# (pyarmor) cfg builder.obf_code
433
# builder.obf_code = 1
434
#
435
# (pyarmor) set builder.obf_code=2
436
# Set builder.obf_code = 2
437
#
438
# (pyarmor) show builder
439
# [builder]
440
# obf_code = 2
441
# obf_module = 1
442
# wrap_mode = 1
443
#
444
# (pyarmor) reset builder.obf_code
445
# Reset builder.obf_code to default value
446
447
shell.cmdloop("PyArmor Configuration Shell")
448
```
449
450
### Hierarchical Configuration
451
452
```python
453
# Global configuration (affects all projects)
454
cfg.run(['builder.obf_code=1'], local=False, name=None)
455
456
# Local configuration (current directory)
457
cfg.run(['builder.obf_code=2'], local=True, name=None)
458
459
# Private configuration (specific module)
460
cfg.run(['builder.mix_str=1'], local=True, name='sensitive_module')
461
462
# Project-specific configuration
463
# (handled by project management system)
464
```
465
466
### Environment Setup
467
468
```python
469
from pyarmor.cli.context import Context
470
import os
471
472
# Configure PyArmor home directory
473
os.environ['PYARMOR_HOME'] = '/custom/pyarmor/home'
474
475
# Initialize with custom paths
476
ctx = Context('/custom/home', '/custom/data', '/custom/temp', '/custom/config')
477
478
# Check environment
479
print(f"Version: {ctx.version_info()}")
480
print(f"Platform: {ctx.pyarmor_platform}")
481
print(f"Runtime platforms: {ctx.runtime_platforms}")
482
483
# Validate environment setup
484
if ctx.runtime_platforms:
485
print("Runtime platforms configured")
486
else:
487
print("No runtime platforms configured")
488
```
489
490
### Advanced Configuration Patterns
491
492
```python
493
# Configure cross-platform obfuscation
494
cfg.run([
495
'builder.runtime_platforms=linux.x86_64 windows.x86_64 darwin.x86_64'
496
], local=True, name=None)
497
498
# Configure maximum protection
499
cfg.run([
500
'builder.obf_code=2',
501
'builder.mix_str=1',
502
'builder.enable_bcc=1',
503
'builder.restrict_module=3',
504
'builder.assert_call=1',
505
'builder.assert_import=1'
506
], local=True, name=None)
507
508
# Configure development settings
509
cfg.run([
510
'builder.obf_code=1',
511
'builder.enable_trace=1',
512
'finder.excludes=test_*, __pycache__, *.pyc'
513
], local=True, name=None)
514
515
# Module-specific configuration
516
cfg.run([
517
'builder.obf_code=2',
518
'builder.mix_str=1'
519
], local=True, name='critical_module')
520
521
cfg.run([
522
'builder.obf_code=0' # No obfuscation for debug module
523
], local=True, name='debug_module')
524
```
525
526
### Configuration Validation
527
528
```python
529
# Validate configuration consistency
530
def validate_config(cfg):
531
"""Validate PyArmor configuration for common issues."""
532
533
issues = []
534
535
# Check BCC mode compatibility
536
bcc_enabled = cfg.list_options('builder').get('enable_bcc', 0)
537
platforms = cfg.list_options('builder').get('runtime_platforms', '')
538
539
if bcc_enabled and len(platforms.split()) > 1:
540
issues.append("BCC mode does not support cross-platform obfuscation")
541
542
# Check Themida compatibility
543
themida_enabled = cfg.list_options('builder').get('enable_themida', 0)
544
if themida_enabled and not any(p.startswith('windows') for p in platforms.split()):
545
issues.append("Themida protection requires Windows platform")
546
547
# Check restriction mode compatibility
548
restrict_mode = cfg.list_options('builder').get('restrict_module', 0)
549
outer_key = cfg.list_options('runtime').get('outer', 0)
550
551
if restrict_mode >= 2 and not outer_key:
552
issues.append("Private/Restrict mode recommended with outer runtime key")
553
554
return issues
555
556
# Validate current configuration
557
issues = validate_config(cfg)
558
if issues:
559
print("Configuration issues found:")
560
for issue in issues:
561
print(f" - {issue}")
562
```
563
564
## Error Handling
565
566
```python
567
from pyarmor.cli import CliError
568
from configparser import ConfigParser
569
570
try:
571
# Configuration operations
572
cfg.run(['invalid.option=value'], local=True, name=None)
573
574
except CliError as e:
575
print(f"Configuration error: {e}")
576
577
except FileNotFoundError:
578
print("Configuration file not found")
579
580
except PermissionError:
581
print("Permission denied accessing configuration")
582
583
# Safe configuration access
584
def get_config_option(cfg, section, option, default=None):
585
"""Safely get configuration option with default fallback."""
586
try:
587
options = cfg.list_options(section)
588
return options.get(option, default)
589
except Exception:
590
return default
591
592
# Example usage
593
obf_code = get_config_option(cfg, 'builder', 'obf_code', 1)
594
mix_str = get_config_option(cfg, 'builder', 'mix_str', 0)
595
```