taipanstack 0.1.0__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.
- taipanstack/__init__.py +53 -0
- taipanstack/config/__init__.py +25 -0
- taipanstack/config/generators.py +357 -0
- taipanstack/config/models.py +316 -0
- taipanstack/config/version_config.py +227 -0
- taipanstack/core/__init__.py +47 -0
- taipanstack/core/compat.py +329 -0
- taipanstack/core/optimizations.py +392 -0
- taipanstack/core/result.py +199 -0
- taipanstack/security/__init__.py +55 -0
- taipanstack/security/decorators.py +369 -0
- taipanstack/security/guards.py +362 -0
- taipanstack/security/sanitizers.py +321 -0
- taipanstack/security/validators.py +342 -0
- taipanstack/utils/__init__.py +24 -0
- taipanstack/utils/circuit_breaker.py +268 -0
- taipanstack/utils/filesystem.py +417 -0
- taipanstack/utils/logging.py +328 -0
- taipanstack/utils/metrics.py +272 -0
- taipanstack/utils/retry.py +300 -0
- taipanstack/utils/subprocess.py +344 -0
- taipanstack-0.1.0.dist-info/METADATA +350 -0
- taipanstack-0.1.0.dist-info/RECORD +25 -0
- taipanstack-0.1.0.dist-info/WHEEL +4 -0
- taipanstack-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python Version Compatibility and Feature Detection.
|
|
3
|
+
|
|
4
|
+
This module provides runtime detection of Python version and available
|
|
5
|
+
performance features, enabling version-specific optimizations while
|
|
6
|
+
maintaining compatibility with Python 3.11+.
|
|
7
|
+
|
|
8
|
+
Following Stack pillars: Security, Stability, Simplicity, Scalability, Compatibility.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import logging
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from enum import Enum
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from typing import Final
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"PY311",
|
|
25
|
+
"PY312",
|
|
26
|
+
"PY313",
|
|
27
|
+
"PY314",
|
|
28
|
+
"PY_VERSION",
|
|
29
|
+
"PythonFeatures",
|
|
30
|
+
"VersionTier",
|
|
31
|
+
"get_features",
|
|
32
|
+
"get_python_info",
|
|
33
|
+
"is_experimental_enabled",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
# =============================================================================
|
|
39
|
+
# Version Constants
|
|
40
|
+
# =============================================================================
|
|
41
|
+
|
|
42
|
+
PY_VERSION: Final = sys.version_info
|
|
43
|
+
"""Current Python version tuple."""
|
|
44
|
+
|
|
45
|
+
PY311: Final[bool] = PY_VERSION >= (3, 11)
|
|
46
|
+
"""True if running Python 3.11 or higher."""
|
|
47
|
+
|
|
48
|
+
PY312: Final[bool] = PY_VERSION >= (3, 12)
|
|
49
|
+
"""True if running Python 3.12 or higher."""
|
|
50
|
+
|
|
51
|
+
PY313: Final[bool] = PY_VERSION >= (3, 13)
|
|
52
|
+
"""True if running Python 3.13 or higher."""
|
|
53
|
+
|
|
54
|
+
PY314: Final[bool] = PY_VERSION >= (3, 14)
|
|
55
|
+
"""True if running Python 3.14 or higher."""
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class VersionTier(str, Enum):
|
|
59
|
+
"""Python version tier for optimization profiles."""
|
|
60
|
+
|
|
61
|
+
STABLE = "stable" # 3.11 - fully stable, conservative optimizations
|
|
62
|
+
ENHANCED = "enhanced" # 3.12 - improved features, moderate optimizations
|
|
63
|
+
MODERN = "modern" # 3.13 - JIT/free-threading available (experimental)
|
|
64
|
+
CUTTING_EDGE = "cutting_edge" # 3.14+ - latest optimizations
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# =============================================================================
|
|
68
|
+
# Environment Variables for Experimental Features
|
|
69
|
+
# =============================================================================
|
|
70
|
+
|
|
71
|
+
ENV_ENABLE_EXPERIMENTAL = "STACK_ENABLE_EXPERIMENTAL"
|
|
72
|
+
"""Environment variable to enable experimental features (JIT, free-threading)."""
|
|
73
|
+
|
|
74
|
+
ENV_OPTIMIZATION_LEVEL = "STACK_OPTIMIZATION_LEVEL"
|
|
75
|
+
"""Optimization level: 0=none, 1=safe, 2=aggressive (requires experimental)."""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# =============================================================================
|
|
79
|
+
# Feature Detection Functions
|
|
80
|
+
# =============================================================================
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _check_jit_available() -> bool:
|
|
84
|
+
"""Check if JIT compiler is available and enabled.
|
|
85
|
+
|
|
86
|
+
JIT is available in Python 3.13+ when built with --enable-experimental-jit.
|
|
87
|
+
"""
|
|
88
|
+
if not PY313:
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
# Check if the JIT module exists (Python 3.13+)
|
|
93
|
+
# This is a build-time option, not all builds have it
|
|
94
|
+
return hasattr(sys, "_jit") or "jit" in sys.flags.__class__.__annotations__
|
|
95
|
+
except (AttributeError, TypeError):
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _check_free_threading_available() -> bool:
|
|
100
|
+
"""Check if free-threading (no-GIL) build is being used.
|
|
101
|
+
|
|
102
|
+
Free-threading is available in Python 3.13+ experimental builds.
|
|
103
|
+
"""
|
|
104
|
+
if not PY313:
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
# In free-threaded builds, sys.flags.nogil is True
|
|
109
|
+
# or the build was configured with --disable-gil
|
|
110
|
+
if hasattr(sys.flags, "nogil"):
|
|
111
|
+
return bool(sys.flags.nogil)
|
|
112
|
+
|
|
113
|
+
# Alternative check for 3.13+
|
|
114
|
+
import sysconfig # noqa: PLC0415
|
|
115
|
+
|
|
116
|
+
config_args = sysconfig.get_config_var("CONFIG_ARGS") or ""
|
|
117
|
+
except (AttributeError, TypeError):
|
|
118
|
+
return False
|
|
119
|
+
else:
|
|
120
|
+
return "--disable-gil" in config_args
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _check_mimalloc_available() -> bool:
|
|
124
|
+
"""Check if mimalloc allocator is being used.
|
|
125
|
+
|
|
126
|
+
mimalloc is the default allocator in Python 3.13+ on some platforms.
|
|
127
|
+
"""
|
|
128
|
+
if not PY313:
|
|
129
|
+
return False
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
import sysconfig # noqa: PLC0415 - lazy import for optional module
|
|
133
|
+
|
|
134
|
+
# Check if built with mimalloc
|
|
135
|
+
config_args = sysconfig.get_config_var("CONFIG_ARGS") or ""
|
|
136
|
+
return "mimalloc" in config_args.lower()
|
|
137
|
+
except (AttributeError, TypeError):
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _check_tail_call_interpreter() -> bool:
|
|
142
|
+
"""Check if tail-call interpreter optimization is available.
|
|
143
|
+
|
|
144
|
+
Tail-call interpreter is available in Python 3.14+.
|
|
145
|
+
"""
|
|
146
|
+
return PY314
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def is_experimental_enabled() -> bool:
|
|
150
|
+
"""Check if experimental features are explicitly enabled.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
True if STACK_ENABLE_EXPERIMENTAL=1 is set.
|
|
154
|
+
|
|
155
|
+
"""
|
|
156
|
+
value = os.environ.get(ENV_ENABLE_EXPERIMENTAL, "").lower()
|
|
157
|
+
return value in ("1", "true", "yes", "on")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_optimization_level() -> int:
|
|
161
|
+
"""Get the configured optimization level.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
0 = No optimizations
|
|
165
|
+
1 = Safe optimizations only (default)
|
|
166
|
+
2 = Aggressive optimizations (requires experimental)
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
try:
|
|
170
|
+
level = int(os.environ.get(ENV_OPTIMIZATION_LEVEL, "1"))
|
|
171
|
+
return max(0, min(2, level)) # Clamp to 0-2
|
|
172
|
+
except ValueError:
|
|
173
|
+
return 1
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# =============================================================================
|
|
177
|
+
# Feature Data Classes
|
|
178
|
+
# =============================================================================
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@dataclass(frozen=True, slots=True)
|
|
182
|
+
class PythonFeatures:
|
|
183
|
+
"""Available Python features based on version and build configuration.
|
|
184
|
+
|
|
185
|
+
This dataclass is immutable and optimized for performance with slots.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
version: tuple[int, int, int]
|
|
189
|
+
version_string: str
|
|
190
|
+
tier: VersionTier
|
|
191
|
+
|
|
192
|
+
# Build features
|
|
193
|
+
has_jit: bool = False
|
|
194
|
+
has_free_threading: bool = False
|
|
195
|
+
has_mimalloc: bool = False
|
|
196
|
+
has_tail_call_interpreter: bool = False
|
|
197
|
+
|
|
198
|
+
# Language features by version
|
|
199
|
+
has_exception_groups: bool = False # 3.11+
|
|
200
|
+
has_self_type: bool = False # 3.11+
|
|
201
|
+
has_type_params: bool = False # 3.12+
|
|
202
|
+
has_fstring_improvements: bool = False # 3.12+
|
|
203
|
+
has_override_decorator: bool = False # 3.12+
|
|
204
|
+
has_deprecated_decorator: bool = False # 3.13+
|
|
205
|
+
has_deferred_annotations: bool = False # 3.14+
|
|
206
|
+
|
|
207
|
+
# Experimental features enabled
|
|
208
|
+
experimental_enabled: bool = False
|
|
209
|
+
|
|
210
|
+
def to_dict(self) -> dict[str, object]:
|
|
211
|
+
"""Convert to dictionary for serialization."""
|
|
212
|
+
return {
|
|
213
|
+
"version": ".".join(map(str, self.version)),
|
|
214
|
+
"tier": self.tier.value,
|
|
215
|
+
"features": {
|
|
216
|
+
"jit": self.has_jit,
|
|
217
|
+
"free_threading": self.has_free_threading,
|
|
218
|
+
"mimalloc": self.has_mimalloc,
|
|
219
|
+
"tail_call_interpreter": self.has_tail_call_interpreter,
|
|
220
|
+
},
|
|
221
|
+
"language": {
|
|
222
|
+
"exception_groups": self.has_exception_groups,
|
|
223
|
+
"self_type": self.has_self_type,
|
|
224
|
+
"type_params": self.has_type_params,
|
|
225
|
+
"override_decorator": self.has_override_decorator,
|
|
226
|
+
"deprecated_decorator": self.has_deprecated_decorator,
|
|
227
|
+
"deferred_annotations": self.has_deferred_annotations,
|
|
228
|
+
},
|
|
229
|
+
"experimental_enabled": self.experimental_enabled,
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# =============================================================================
|
|
234
|
+
# Main Detection Functions
|
|
235
|
+
# =============================================================================
|
|
236
|
+
|
|
237
|
+
# Cache the features after first detection
|
|
238
|
+
_cached_features: PythonFeatures | None = None
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_features(*, force_refresh: bool = False) -> PythonFeatures:
|
|
242
|
+
"""Detect and return available Python features.
|
|
243
|
+
|
|
244
|
+
Features are cached after first detection for performance.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
force_refresh: If True, re-detect features instead of using cache.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
PythonFeatures dataclass with all detected features.
|
|
251
|
+
|
|
252
|
+
"""
|
|
253
|
+
global _cached_features # noqa: PLW0603 - intentional cache pattern
|
|
254
|
+
|
|
255
|
+
if _cached_features is not None and not force_refresh:
|
|
256
|
+
return _cached_features
|
|
257
|
+
|
|
258
|
+
# Determine version tier
|
|
259
|
+
if PY314:
|
|
260
|
+
tier = VersionTier.CUTTING_EDGE
|
|
261
|
+
elif PY313:
|
|
262
|
+
tier = VersionTier.MODERN
|
|
263
|
+
elif PY312:
|
|
264
|
+
tier = VersionTier.ENHANCED
|
|
265
|
+
else:
|
|
266
|
+
tier = VersionTier.STABLE
|
|
267
|
+
|
|
268
|
+
experimental = is_experimental_enabled()
|
|
269
|
+
|
|
270
|
+
# Build features (only if experimental is enabled for safety)
|
|
271
|
+
has_jit = _check_jit_available() if experimental else False
|
|
272
|
+
has_free_threading = _check_free_threading_available() if experimental else False
|
|
273
|
+
has_mimalloc = _check_mimalloc_available() # Safe to detect
|
|
274
|
+
|
|
275
|
+
features = PythonFeatures(
|
|
276
|
+
version=(PY_VERSION.major, PY_VERSION.minor, PY_VERSION.micro),
|
|
277
|
+
version_string=f"{PY_VERSION.major}.{PY_VERSION.minor}.{PY_VERSION.micro}",
|
|
278
|
+
tier=tier,
|
|
279
|
+
# Build features
|
|
280
|
+
has_jit=has_jit,
|
|
281
|
+
has_free_threading=has_free_threading,
|
|
282
|
+
has_mimalloc=has_mimalloc,
|
|
283
|
+
has_tail_call_interpreter=_check_tail_call_interpreter(),
|
|
284
|
+
# Language features
|
|
285
|
+
has_exception_groups=PY311,
|
|
286
|
+
has_self_type=PY311,
|
|
287
|
+
has_type_params=PY312,
|
|
288
|
+
has_fstring_improvements=PY312,
|
|
289
|
+
has_override_decorator=PY312,
|
|
290
|
+
has_deprecated_decorator=PY313,
|
|
291
|
+
has_deferred_annotations=PY314,
|
|
292
|
+
# Experimental
|
|
293
|
+
experimental_enabled=experimental,
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
_cached_features = features
|
|
297
|
+
|
|
298
|
+
# Log detected features at DEBUG level
|
|
299
|
+
logger.debug(
|
|
300
|
+
"Python %s detected (tier=%s, experimental=%s)",
|
|
301
|
+
features.version_string,
|
|
302
|
+
tier.value,
|
|
303
|
+
experimental,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
return features
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def get_python_info() -> dict[str, object]:
|
|
310
|
+
"""Get comprehensive Python runtime information.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
Dictionary with version, platform, and feature information.
|
|
314
|
+
|
|
315
|
+
"""
|
|
316
|
+
import platform # noqa: PLC0415 - lazy import for optional module
|
|
317
|
+
|
|
318
|
+
features = get_features()
|
|
319
|
+
|
|
320
|
+
return {
|
|
321
|
+
"version": features.version_string,
|
|
322
|
+
"version_tuple": features.version,
|
|
323
|
+
"tier": features.tier.value,
|
|
324
|
+
"implementation": platform.python_implementation(),
|
|
325
|
+
"platform": platform.platform(),
|
|
326
|
+
"compiler": platform.python_compiler(),
|
|
327
|
+
"features": features.to_dict(),
|
|
328
|
+
"optimization_level": get_optimization_level(),
|
|
329
|
+
}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python Version-Specific Optimization Profiles.
|
|
3
|
+
|
|
4
|
+
This module provides optimization strategies tailored to different Python
|
|
5
|
+
versions, enabling performance improvements while maintaining stability.
|
|
6
|
+
|
|
7
|
+
Following Stack pillars: Security, Stability, Simplicity, Scalability, Compatibility.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import gc
|
|
13
|
+
import logging
|
|
14
|
+
import os
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
17
|
+
|
|
18
|
+
from taipanstack.core.compat import (
|
|
19
|
+
PY312,
|
|
20
|
+
PY313,
|
|
21
|
+
PY314,
|
|
22
|
+
get_features,
|
|
23
|
+
get_optimization_level,
|
|
24
|
+
is_experimental_enabled,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"OptimizationProfile",
|
|
32
|
+
"OptimizationResult",
|
|
33
|
+
"apply_optimizations",
|
|
34
|
+
"get_optimization_profile",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# =============================================================================
|
|
41
|
+
# Optimization Profile
|
|
42
|
+
# =============================================================================
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Optimization Levels
|
|
46
|
+
OPT_LEVEL_NONE = 0
|
|
47
|
+
OPT_LEVEL_SAFE = 1
|
|
48
|
+
OPT_LEVEL_AGGRESSIVE = 2
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass(frozen=True, slots=True)
|
|
52
|
+
class OptimizationProfile:
|
|
53
|
+
"""Version-specific optimization settings.
|
|
54
|
+
|
|
55
|
+
This profile defines recommended settings based on Python version
|
|
56
|
+
and available features. All settings follow the stability-first principle.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
# GC tuning
|
|
60
|
+
gc_threshold_0: int = 700 # Default: 700
|
|
61
|
+
gc_threshold_1: int = 10 # Default: 10
|
|
62
|
+
gc_threshold_2: int = 10 # Default: 10
|
|
63
|
+
gc_freeze_enabled: bool = False # Freeze objects after init
|
|
64
|
+
|
|
65
|
+
# Threading
|
|
66
|
+
thread_pool_multiplier: float = 1.0 # Multiplier for CPU count
|
|
67
|
+
max_thread_pool_size: int = 32 # Absolute maximum
|
|
68
|
+
|
|
69
|
+
# Memory
|
|
70
|
+
prefer_slots: bool = True # Use __slots__ in classes
|
|
71
|
+
use_frozen_dataclasses: bool = True # Prefer frozen dataclasses
|
|
72
|
+
|
|
73
|
+
# Code patterns
|
|
74
|
+
prefer_match_statements: bool = False # 3.10+
|
|
75
|
+
prefer_exception_groups: bool = False # 3.11+
|
|
76
|
+
prefer_type_params: bool = False # 3.12+
|
|
77
|
+
|
|
78
|
+
# Performance hints
|
|
79
|
+
enable_perf_hints: bool = False # JIT hints, etc.
|
|
80
|
+
aggressive_inlining: bool = False # More aggressive optimizations
|
|
81
|
+
|
|
82
|
+
# Experimental
|
|
83
|
+
enable_experimental: bool = False
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass(frozen=True, slots=True)
|
|
87
|
+
class OptimizationResult:
|
|
88
|
+
"""Result of applying optimizations."""
|
|
89
|
+
|
|
90
|
+
success: bool
|
|
91
|
+
applied: tuple[str, ...]
|
|
92
|
+
skipped: tuple[str, ...]
|
|
93
|
+
errors: tuple[str, ...]
|
|
94
|
+
|
|
95
|
+
def to_dict(self) -> dict[str, object]:
|
|
96
|
+
"""Convert to dictionary."""
|
|
97
|
+
return {
|
|
98
|
+
"success": self.success,
|
|
99
|
+
"applied": list(self.applied),
|
|
100
|
+
"skipped": list(self.skipped),
|
|
101
|
+
"errors": list(self.errors),
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# =============================================================================
|
|
106
|
+
# Version-Specific Profiles
|
|
107
|
+
# =============================================================================
|
|
108
|
+
|
|
109
|
+
# Python 3.11 - Stable baseline
|
|
110
|
+
_PROFILE_311 = OptimizationProfile(
|
|
111
|
+
gc_threshold_0=700,
|
|
112
|
+
gc_threshold_1=10,
|
|
113
|
+
gc_threshold_2=10,
|
|
114
|
+
gc_freeze_enabled=False,
|
|
115
|
+
thread_pool_multiplier=1.0,
|
|
116
|
+
max_thread_pool_size=32,
|
|
117
|
+
prefer_slots=True,
|
|
118
|
+
use_frozen_dataclasses=True,
|
|
119
|
+
prefer_match_statements=True,
|
|
120
|
+
prefer_exception_groups=True,
|
|
121
|
+
prefer_type_params=False,
|
|
122
|
+
enable_perf_hints=False,
|
|
123
|
+
aggressive_inlining=False,
|
|
124
|
+
enable_experimental=False,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Python 3.12 - Enhanced
|
|
128
|
+
_PROFILE_312 = OptimizationProfile(
|
|
129
|
+
gc_threshold_0=800, # Slightly higher due to better GC
|
|
130
|
+
gc_threshold_1=10,
|
|
131
|
+
gc_threshold_2=10,
|
|
132
|
+
gc_freeze_enabled=True, # Safe to use
|
|
133
|
+
thread_pool_multiplier=1.0,
|
|
134
|
+
max_thread_pool_size=32,
|
|
135
|
+
prefer_slots=True,
|
|
136
|
+
use_frozen_dataclasses=True,
|
|
137
|
+
prefer_match_statements=True,
|
|
138
|
+
prefer_exception_groups=True,
|
|
139
|
+
prefer_type_params=True,
|
|
140
|
+
enable_perf_hints=False,
|
|
141
|
+
aggressive_inlining=False,
|
|
142
|
+
enable_experimental=False,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Python 3.13 - Modern (with experimental options available)
|
|
146
|
+
_PROFILE_313 = OptimizationProfile(
|
|
147
|
+
gc_threshold_0=900, # Higher with mimalloc
|
|
148
|
+
gc_threshold_1=15,
|
|
149
|
+
gc_threshold_2=15,
|
|
150
|
+
gc_freeze_enabled=True,
|
|
151
|
+
thread_pool_multiplier=1.5, # Can use more threads with better GIL
|
|
152
|
+
max_thread_pool_size=48,
|
|
153
|
+
prefer_slots=True,
|
|
154
|
+
use_frozen_dataclasses=True,
|
|
155
|
+
prefer_match_statements=True,
|
|
156
|
+
prefer_exception_groups=True,
|
|
157
|
+
prefer_type_params=True,
|
|
158
|
+
enable_perf_hints=True, # JIT hints available
|
|
159
|
+
aggressive_inlining=False,
|
|
160
|
+
enable_experimental=False, # Requires explicit opt-in
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Python 3.14 - Cutting edge
|
|
164
|
+
_PROFILE_314 = OptimizationProfile(
|
|
165
|
+
gc_threshold_0=1000, # Optimized incremental GC
|
|
166
|
+
gc_threshold_1=20,
|
|
167
|
+
gc_threshold_2=20,
|
|
168
|
+
gc_freeze_enabled=True,
|
|
169
|
+
thread_pool_multiplier=2.0, # Free-threading ready
|
|
170
|
+
max_thread_pool_size=64,
|
|
171
|
+
prefer_slots=True,
|
|
172
|
+
use_frozen_dataclasses=True,
|
|
173
|
+
prefer_match_statements=True,
|
|
174
|
+
prefer_exception_groups=True,
|
|
175
|
+
prefer_type_params=True,
|
|
176
|
+
enable_perf_hints=True,
|
|
177
|
+
aggressive_inlining=True, # Tail-call interpreter
|
|
178
|
+
enable_experimental=False, # Requires explicit opt-in
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def get_optimization_profile() -> OptimizationProfile:
|
|
183
|
+
"""Get the optimization profile for the current Python version.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
OptimizationProfile suitable for the runtime environment.
|
|
187
|
+
|
|
188
|
+
"""
|
|
189
|
+
_ = get_features() # Warm up cache, validate version
|
|
190
|
+
experimental = is_experimental_enabled()
|
|
191
|
+
opt_level = get_optimization_level()
|
|
192
|
+
|
|
193
|
+
# Select base profile by version
|
|
194
|
+
if PY314:
|
|
195
|
+
profile = _PROFILE_314
|
|
196
|
+
elif PY313:
|
|
197
|
+
profile = _PROFILE_313
|
|
198
|
+
elif PY312:
|
|
199
|
+
profile = _PROFILE_312
|
|
200
|
+
else:
|
|
201
|
+
profile = _PROFILE_311
|
|
202
|
+
|
|
203
|
+
# Adjust for optimization level
|
|
204
|
+
if opt_level == OPT_LEVEL_NONE:
|
|
205
|
+
# Minimal optimizations - use 3.11 baseline
|
|
206
|
+
return _PROFILE_311
|
|
207
|
+
|
|
208
|
+
if opt_level == OPT_LEVEL_AGGRESSIVE and experimental:
|
|
209
|
+
# Aggressive mode - enable experimental features
|
|
210
|
+
return OptimizationProfile(
|
|
211
|
+
gc_threshold_0=profile.gc_threshold_0,
|
|
212
|
+
gc_threshold_1=profile.gc_threshold_1,
|
|
213
|
+
gc_threshold_2=profile.gc_threshold_2,
|
|
214
|
+
gc_freeze_enabled=profile.gc_freeze_enabled,
|
|
215
|
+
thread_pool_multiplier=profile.thread_pool_multiplier,
|
|
216
|
+
max_thread_pool_size=profile.max_thread_pool_size,
|
|
217
|
+
prefer_slots=profile.prefer_slots,
|
|
218
|
+
use_frozen_dataclasses=profile.use_frozen_dataclasses,
|
|
219
|
+
prefer_match_statements=profile.prefer_match_statements,
|
|
220
|
+
prefer_exception_groups=profile.prefer_exception_groups,
|
|
221
|
+
prefer_type_params=profile.prefer_type_params,
|
|
222
|
+
enable_perf_hints=profile.enable_perf_hints,
|
|
223
|
+
aggressive_inlining=profile.aggressive_inlining,
|
|
224
|
+
enable_experimental=True,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
return profile
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# =============================================================================
|
|
231
|
+
# Apply Optimizations
|
|
232
|
+
# =============================================================================
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _apply_gc_tuning(
|
|
236
|
+
profile: OptimizationProfile,
|
|
237
|
+
applied: list[str],
|
|
238
|
+
errors: list[str],
|
|
239
|
+
) -> None:
|
|
240
|
+
"""Apply Garbage Collector tuning."""
|
|
241
|
+
try:
|
|
242
|
+
current = gc.get_threshold()
|
|
243
|
+
gc.set_threshold(
|
|
244
|
+
profile.gc_threshold_0,
|
|
245
|
+
profile.gc_threshold_1,
|
|
246
|
+
profile.gc_threshold_2,
|
|
247
|
+
)
|
|
248
|
+
applied.append(
|
|
249
|
+
f"gc_threshold: {current} -> "
|
|
250
|
+
f"({profile.gc_threshold_0}, {profile.gc_threshold_1}, "
|
|
251
|
+
f"{profile.gc_threshold_2})"
|
|
252
|
+
)
|
|
253
|
+
except Exception as e:
|
|
254
|
+
errors.append(f"gc_threshold: {e}")
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _apply_gc_freeze(
|
|
258
|
+
profile: OptimizationProfile,
|
|
259
|
+
freeze_after: bool,
|
|
260
|
+
applied: list[str],
|
|
261
|
+
skipped: list[str],
|
|
262
|
+
errors: list[str],
|
|
263
|
+
) -> None:
|
|
264
|
+
"""Apply GC freeze if supported."""
|
|
265
|
+
if profile.gc_freeze_enabled and freeze_after and PY312:
|
|
266
|
+
try:
|
|
267
|
+
gc.freeze()
|
|
268
|
+
applied.append("gc_freeze: enabled")
|
|
269
|
+
except Exception as e:
|
|
270
|
+
errors.append(f"gc_freeze: {e}")
|
|
271
|
+
elif profile.gc_freeze_enabled and not PY312:
|
|
272
|
+
skipped.append("gc_freeze: requires Python 3.12+")
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _apply_experimental(
|
|
276
|
+
profile: OptimizationProfile,
|
|
277
|
+
applied: list[str],
|
|
278
|
+
skipped: list[str],
|
|
279
|
+
) -> None:
|
|
280
|
+
"""Check and log experimental features."""
|
|
281
|
+
if profile.enable_experimental:
|
|
282
|
+
features = get_features()
|
|
283
|
+
if features.has_jit:
|
|
284
|
+
applied.append("jit: available")
|
|
285
|
+
if features.has_free_threading:
|
|
286
|
+
applied.append("free_threading: available")
|
|
287
|
+
logger.warning(
|
|
288
|
+
"EXPERIMENTAL FEATURES ENABLED: Stability and security may be affected."
|
|
289
|
+
)
|
|
290
|
+
else:
|
|
291
|
+
skipped.append("experimental: requires STACK_ENABLE_EXPERIMENTAL=1")
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def apply_optimizations(
|
|
295
|
+
*,
|
|
296
|
+
profile: OptimizationProfile | None = None,
|
|
297
|
+
apply_gc: bool = True,
|
|
298
|
+
freeze_after: bool = False,
|
|
299
|
+
) -> OptimizationResult:
|
|
300
|
+
"""Apply runtime optimizations based on profile.
|
|
301
|
+
|
|
302
|
+
This function applies safe, reversible optimizations to the Python
|
|
303
|
+
runtime. It is designed to be called once at application startup.
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
profile: Optimization profile to use (auto-detected if None).
|
|
307
|
+
apply_gc: Whether to apply GC tuning.
|
|
308
|
+
freeze_after: Whether to freeze objects after applying.
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
OptimizationResult with details of what was applied.
|
|
312
|
+
|
|
313
|
+
"""
|
|
314
|
+
if profile is None:
|
|
315
|
+
profile = get_optimization_profile()
|
|
316
|
+
|
|
317
|
+
applied: list[str] = []
|
|
318
|
+
skipped: list[str] = []
|
|
319
|
+
errors: list[str] = []
|
|
320
|
+
|
|
321
|
+
# GC Tuning
|
|
322
|
+
if apply_gc:
|
|
323
|
+
_apply_gc_tuning(profile, applied, errors)
|
|
324
|
+
else:
|
|
325
|
+
skipped.append("gc_threshold: disabled")
|
|
326
|
+
|
|
327
|
+
# GC Freeze (3.12+)
|
|
328
|
+
_apply_gc_freeze(profile, freeze_after, applied, skipped, errors)
|
|
329
|
+
|
|
330
|
+
# Performance hints logging
|
|
331
|
+
if profile.enable_perf_hints:
|
|
332
|
+
applied.append("perf_hints: enabled (JIT-aware patterns)")
|
|
333
|
+
else:
|
|
334
|
+
skipped.append("perf_hints: disabled")
|
|
335
|
+
|
|
336
|
+
# Experimental features
|
|
337
|
+
_apply_experimental(profile, applied, skipped)
|
|
338
|
+
|
|
339
|
+
# Log summary
|
|
340
|
+
success = len(errors) == 0
|
|
341
|
+
if applied:
|
|
342
|
+
logger.debug("Applied optimizations: %s", ", ".join(applied))
|
|
343
|
+
if skipped:
|
|
344
|
+
logger.debug("Skipped optimizations: %s", ", ".join(skipped))
|
|
345
|
+
if errors:
|
|
346
|
+
logger.warning("Optimization errors: %s", ", ".join(errors))
|
|
347
|
+
|
|
348
|
+
return OptimizationResult(
|
|
349
|
+
success=success,
|
|
350
|
+
applied=tuple(applied),
|
|
351
|
+
skipped=tuple(skipped),
|
|
352
|
+
errors=tuple(errors),
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
# =============================================================================
|
|
357
|
+
# Utility Functions
|
|
358
|
+
# =============================================================================
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def get_recommended_thread_pool_size() -> int:
|
|
362
|
+
"""Get recommended thread pool size based on version and features.
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
Recommended number of threads for ThreadPoolExecutor.
|
|
366
|
+
|
|
367
|
+
"""
|
|
368
|
+
profile = get_optimization_profile()
|
|
369
|
+
cpu_count = os.cpu_count() or 4
|
|
370
|
+
|
|
371
|
+
size = int(cpu_count * profile.thread_pool_multiplier)
|
|
372
|
+
return min(size, profile.max_thread_pool_size)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def should_use_slots() -> bool:
|
|
376
|
+
"""Check if __slots__ should be used for new classes.
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
True if slots are recommended for current version.
|
|
380
|
+
|
|
381
|
+
"""
|
|
382
|
+
return get_optimization_profile().prefer_slots
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def should_use_frozen_dataclass() -> bool:
|
|
386
|
+
"""Check if frozen=True should be used for dataclasses.
|
|
387
|
+
|
|
388
|
+
Returns:
|
|
389
|
+
True if frozen dataclasses are recommended.
|
|
390
|
+
|
|
391
|
+
"""
|
|
392
|
+
return get_optimization_profile().use_frozen_dataclasses
|