A command-line tool for obfuscating Python scripts, binding obfuscated scripts to specific machines, and setting expiration dates
—
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.
Modern configuration management with hierarchical settings and validation.
class Configer:
"""
Configuration file management and validation.
"""
def __init__(self, ctx, encoding: str = None):
"""
Initialize configuration manager.
Args:
ctx (Context): PyArmor context instance
encoding (str, optional): Configuration file encoding
"""
def list_sections(self, local: bool = True, name: str = None) -> list:
"""
List available configuration sections.
Args:
local (bool): Include local settings (default: True)
name (str, optional): Filter by section name pattern
Returns:
list: Available configuration sections
Example sections:
['pyarmor', 'builder', 'runtime', 'finder', 'mix', 'assert']
"""
def list_options(self, sect: str, local: bool = True, name: str = None) -> list:
"""
List options in a configuration section.
Args:
sect (str): Section name
local (bool): Include local settings
name (str, optional): Filter by option name pattern
Returns:
list: Available options in section
"""
def run(self, options: list, local: bool, name: str) -> None:
"""
Execute configuration commands.
Args:
options (list): Configuration options to set/query
local (bool): Apply to local settings
name (str): Private settings name for module/package
Options format:
['option'] - Query option value
['option=value'] - Set option value
['section.option=value'] - Set section-specific option
"""
def reset(self, options: list, local: bool, name: str) -> None:
"""
Reset configuration options to defaults.
Args:
options (list): Options to reset
local (bool): Reset local settings
name (str): Private settings name
"""Central context and environment management for PyArmor operations.
class Context:
"""
PyArmor execution context and environment management.
"""
def __init__(self, *paths):
"""
Initialize context with optional home path configuration.
Args:
*paths: Home directory paths (home, data, temp, config)
"""
def push(self, options: dict) -> None:
"""
Push configuration options to context stack.
Args:
options (dict): Configuration options to apply
"""
def pop(self) -> dict:
"""
Pop configuration options from context stack.
Returns:
dict: Popped configuration options
"""
def get_res_options(self, fullname: str, catalog: str) -> dict:
"""
Get resource-specific configuration options.
Args:
fullname (str): Full resource name (module.submodule)
catalog (str): Resource catalog type
Returns:
dict: Resource-specific configuration
"""
def version_info(self) -> str:
"""
Get PyArmor version information.
Returns:
str: Formatted version string
"""
# Context Properties
@property
def pyarmor_platform(self) -> str:
"""Current PyArmor platform specification."""
@property
def native_platform(self) -> str:
"""Native system platform specification."""
@property
def home_path(self) -> str:
"""PyArmor home directory path."""
@property
def runtime_platforms(self) -> list:
"""List of configured runtime platforms."""
@property
def runtime_outer(self) -> bool:
"""Whether outer runtime key is enabled."""
@property
def runtime_key(self) -> bytes:
"""Current runtime key data."""
@property
def runtime_keyfile(self) -> str:
"""Runtime key file name."""class PyarmorShell:
"""
Interactive command-line shell for configuration management.
"""
def __init__(self, ctx):
"""
Initialize interactive shell.
Args:
ctx (Context): PyArmor context instance
"""
def cmdloop(self, intro: str = None) -> None:
"""
Start interactive command loop.
Args:
intro (str, optional): Introduction message
"""
def do_cfg(self, line: str) -> None:
"""
Configuration command handler.
Args:
line (str): Command line arguments
"""
def do_show(self, line: str) -> None:
"""
Show configuration values.
Args:
line (str): Configuration keys to display
"""
def do_set(self, line: str) -> None:
"""
Set configuration values.
Args:
line (str): Configuration assignments
"""
def do_reset(self, line: str) -> None:
"""
Reset configuration to defaults.
Args:
line (str): Configuration keys to reset
"""# Configuration precedence (highest to lowest):
CONFIG_DOMAINS = {
'command_line': 'Command line arguments',
'project': 'Project-specific settings',
'local': 'Local directory settings (.pyarmor_config)',
'global': 'Global user settings (~/.pyarmor/config.ini)',
'default': 'Built-in default values'
}
# Configuration file locations
CONFIG_PATHS = {
'global': '~/.pyarmor/config.ini',
'local': './.pyarmor_config',
'project': './pyarmor.json'
}class PyarmorConfig:
"""Core PyArmor configuration options."""
# Version and licensing
version: str # PyArmor version
cli_runtime: str # CLI runtime version
buyurl: str # Purchase URL
class BuilderConfig:
"""Obfuscation builder configuration."""
# Obfuscation settings
obf_module: int # Module obfuscation (0/1)
obf_code: int # Code obfuscation (0/1/2)
wrap_mode: int # Wrap mode (0/1)
mix_str: int # String mixing (0/1)
# Advanced settings
enable_bcc: int # BCC mode (0/1)
enable_jit: int # JIT mode (0/1)
enable_rft: int # RFT mode (0/1)
enable_themida: int # Themida protection (0/1)
# Restriction settings
restrict_module: int # Module restriction (0-3)
assert_call: int # Function call assertion (0/1)
assert_import: int # Import assertion (0/1)
# Platform settings
runtime_platforms: str # Target platforms
enable_trace: int # Trace mode (0/1)
class RuntimeConfig:
"""Runtime package configuration."""
# Runtime settings
outer: int # Outer runtime key (0/1)
period: int # Validation period (days)
expired: str # Expiration date
devices: str # Bound devices
# Package settings
import_prefix: str # Import prefix
package_runtime: int # Package with scripts (0/1)
class FinderConfig:
"""Resource finder configuration."""
# Discovery settings
recursive: int # Recursive search (0/1)
findall: int # Find all files (0/1)
# Filter settings
includes: str # Include patterns
excludes: str # Exclude patterns[pyarmor]
version = 9.1.8
cli.runtime = 7.6.7
buyurl = https://jondy.github.io/paypal/index.html
[builder]
obf_module = 1
obf_code = 1
wrap_mode = 1
mix_str = 0
enable_bcc = 0
enable_jit = 0
enable_rft = 0
enable_themida = 0
restrict_module = 0
assert_call = 0
assert_import = 0
enable_trace = 0
[runtime]
outer = 0
import_prefix =
package_runtime = 0
[finder]
recursive = 1
findall = 0
includes =
excludes = __pycache__, *.pyc, test_*, *test.py{
"name": "MyProject",
"version": "1.0.0",
"src": "src",
"output": "dist",
"entry": "main.py",
"obf_code": 2,
"obf_mod": 1,
"wrap_mode": 1,
"advanced_mode": 2,
"restrict_mode": 2,
"mix_str": 1,
"platforms": ["linux.x86_64", "windows.x86_64"],
"runtime_path": "runtime",
"package_runtime": 1,
"license_file": "app.lic"
}from pyarmor.cli.config import Configer
from pyarmor.cli.context import Context
# Initialize configuration
ctx = Context()
cfg = Configer(ctx)
# List all sections
sections = cfg.list_sections()
print("Available sections:", sections)
# List options in builder section
options = cfg.list_options('builder')
print("Builder options:", options)
# Show current configuration
cfg.run(['builder.obf_code'], local=True, name=None)
# Set configuration values
cfg.run(['builder.obf_code=2'], local=True, name=None)
cfg.run(['builder.mix_str=1'], local=True, name=None)
# Reset to defaults
cfg.reset(['builder.obf_code'], local=True, name=None)from pyarmor.cli.context import Context
# Initialize context
ctx = Context()
# Check platform information
print(f"PyArmor platform: {ctx.pyarmor_platform}")
print(f"Native platform: {ctx.native_platform}")
print(f"Home path: {ctx.home_path}")
# Push configuration options
options = {
'obf_code': 2,
'mix_str': True,
'restrict_module': 2,
'platforms': ['linux.x86_64', 'windows.x86_64']
}
ctx.push(options)
# Get resource-specific options
res_options = ctx.get_res_options('mypackage.module', 'Python')
print("Resource options:", res_options)
# Pop configuration
old_options = ctx.pop()from pyarmor.cli.shell import PyarmorShell
from pyarmor.cli.context import Context
# Start interactive shell
ctx = Context()
shell = PyarmorShell(ctx)
# Example shell session:
# (pyarmor) cfg builder.obf_code
# builder.obf_code = 1
#
# (pyarmor) set builder.obf_code=2
# Set builder.obf_code = 2
#
# (pyarmor) show builder
# [builder]
# obf_code = 2
# obf_module = 1
# wrap_mode = 1
#
# (pyarmor) reset builder.obf_code
# Reset builder.obf_code to default value
shell.cmdloop("PyArmor Configuration Shell")# Global configuration (affects all projects)
cfg.run(['builder.obf_code=1'], local=False, name=None)
# Local configuration (current directory)
cfg.run(['builder.obf_code=2'], local=True, name=None)
# Private configuration (specific module)
cfg.run(['builder.mix_str=1'], local=True, name='sensitive_module')
# Project-specific configuration
# (handled by project management system)from pyarmor.cli.context import Context
import os
# Configure PyArmor home directory
os.environ['PYARMOR_HOME'] = '/custom/pyarmor/home'
# Initialize with custom paths
ctx = Context('/custom/home', '/custom/data', '/custom/temp', '/custom/config')
# Check environment
print(f"Version: {ctx.version_info()}")
print(f"Platform: {ctx.pyarmor_platform}")
print(f"Runtime platforms: {ctx.runtime_platforms}")
# Validate environment setup
if ctx.runtime_platforms:
print("Runtime platforms configured")
else:
print("No runtime platforms configured")# Configure cross-platform obfuscation
cfg.run([
'builder.runtime_platforms=linux.x86_64 windows.x86_64 darwin.x86_64'
], local=True, name=None)
# Configure maximum protection
cfg.run([
'builder.obf_code=2',
'builder.mix_str=1',
'builder.enable_bcc=1',
'builder.restrict_module=3',
'builder.assert_call=1',
'builder.assert_import=1'
], local=True, name=None)
# Configure development settings
cfg.run([
'builder.obf_code=1',
'builder.enable_trace=1',
'finder.excludes=test_*, __pycache__, *.pyc'
], local=True, name=None)
# Module-specific configuration
cfg.run([
'builder.obf_code=2',
'builder.mix_str=1'
], local=True, name='critical_module')
cfg.run([
'builder.obf_code=0' # No obfuscation for debug module
], local=True, name='debug_module')# Validate configuration consistency
def validate_config(cfg):
"""Validate PyArmor configuration for common issues."""
issues = []
# Check BCC mode compatibility
bcc_enabled = cfg.list_options('builder').get('enable_bcc', 0)
platforms = cfg.list_options('builder').get('runtime_platforms', '')
if bcc_enabled and len(platforms.split()) > 1:
issues.append("BCC mode does not support cross-platform obfuscation")
# Check Themida compatibility
themida_enabled = cfg.list_options('builder').get('enable_themida', 0)
if themida_enabled and not any(p.startswith('windows') for p in platforms.split()):
issues.append("Themida protection requires Windows platform")
# Check restriction mode compatibility
restrict_mode = cfg.list_options('builder').get('restrict_module', 0)
outer_key = cfg.list_options('runtime').get('outer', 0)
if restrict_mode >= 2 and not outer_key:
issues.append("Private/Restrict mode recommended with outer runtime key")
return issues
# Validate current configuration
issues = validate_config(cfg)
if issues:
print("Configuration issues found:")
for issue in issues:
print(f" - {issue}")from pyarmor.cli import CliError
from configparser import ConfigParser
try:
# Configuration operations
cfg.run(['invalid.option=value'], local=True, name=None)
except CliError as e:
print(f"Configuration error: {e}")
except FileNotFoundError:
print("Configuration file not found")
except PermissionError:
print("Permission denied accessing configuration")
# Safe configuration access
def get_config_option(cfg, section, option, default=None):
"""Safely get configuration option with default fallback."""
try:
options = cfg.list_options(section)
return options.get(option, default)
except Exception:
return default
# Example usage
obf_code = get_config_option(cfg, 'builder', 'obf_code', 1)
mix_str = get_config_option(cfg, 'builder', 'mix_str', 0)Install with Tessl CLI
npx tessl i tessl/pypi-pyarmor