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.
@@ -0,0 +1,316 @@
1
+ """
2
+ Configuration models with Pydantic validation.
3
+
4
+ This module provides type-safe configuration models that validate
5
+ all inputs at runtime, preventing errors and AI hallucinations.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ import sys
12
+ from pathlib import Path
13
+ from typing import Literal
14
+
15
+ from pydantic import (
16
+ BaseModel,
17
+ ConfigDict,
18
+ Field,
19
+ field_validator,
20
+ model_validator,
21
+ )
22
+
23
+ # Constants to avoid magic values (PLR2004)
24
+ PYTHON_MAJOR_VERSION = 3
25
+ MIN_PYTHON_MINOR_VERSION = 10
26
+
27
+
28
+ class SecurityConfig(BaseModel):
29
+ """Security-related configuration options.
30
+
31
+ Attributes:
32
+ level: Security strictness level.
33
+ enable_bandit: Enable Bandit SAST scanner.
34
+ enable_safety: Enable Safety dependency checker.
35
+ enable_semgrep: Enable Semgrep analysis.
36
+ enable_detect_secrets: Enable secret detection.
37
+ bandit_severity: Minimum severity level for Bandit.
38
+
39
+ """
40
+
41
+ level: Literal["standard", "strict", "paranoid"] = Field(
42
+ default="strict",
43
+ description="Security strictness level",
44
+ )
45
+ enable_bandit: bool = Field(default=True, description="Enable Bandit SAST")
46
+ enable_safety: bool = Field(default=True, description="Enable Safety SCA")
47
+ enable_semgrep: bool = Field(default=True, description="Enable Semgrep")
48
+ enable_detect_secrets: bool = Field(
49
+ default=True, description="Enable secret detection"
50
+ )
51
+ bandit_severity: Literal["low", "medium", "high"] = Field(
52
+ default="low",
53
+ description="Minimum Bandit severity",
54
+ )
55
+
56
+ model_config = ConfigDict(frozen=True, extra="forbid")
57
+
58
+
59
+ class DependencyConfig(BaseModel):
60
+ """Dependency management configuration.
61
+
62
+ Attributes:
63
+ install_runtime_deps: Install pydantic, orjson, uvloop.
64
+ install_dev_deps: Install development dependencies.
65
+ dev_dependencies: List of dev dependencies to install.
66
+ runtime_dependencies: List of runtime dependencies to install.
67
+
68
+ """
69
+
70
+ install_runtime_deps: bool = Field(
71
+ default=False,
72
+ description="Install runtime dependencies (pydantic, orjson, uvloop)",
73
+ )
74
+ install_dev_deps: bool = Field(
75
+ default=True,
76
+ description="Install development dependencies",
77
+ )
78
+ dev_dependencies: list[str] = Field(
79
+ default_factory=lambda: [
80
+ "ruff",
81
+ "mypy",
82
+ "bandit",
83
+ "safety",
84
+ "pre-commit",
85
+ "pytest",
86
+ "pytest-cov",
87
+ "py-spy",
88
+ "semgrep",
89
+ ],
90
+ description="Development dependencies to install",
91
+ )
92
+ runtime_dependencies: list[str] = Field(
93
+ default_factory=lambda: ["pydantic>=2.0", "orjson"],
94
+ description="Runtime dependencies to install",
95
+ )
96
+
97
+ model_config = ConfigDict(frozen=True, extra="forbid")
98
+
99
+
100
+ class LoggingConfig(BaseModel):
101
+ """Logging configuration options.
102
+
103
+ Attributes:
104
+ level: Log level.
105
+ format: Log format type.
106
+ enable_structured: Use structured logging (JSON).
107
+
108
+ """
109
+
110
+ level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = Field(
111
+ default="INFO",
112
+ description="Logging level",
113
+ )
114
+ format: Literal["simple", "detailed", "json"] = Field(
115
+ default="detailed",
116
+ description="Log output format",
117
+ )
118
+ enable_structured: bool = Field(
119
+ default=False,
120
+ description="Enable JSON structured logging",
121
+ )
122
+
123
+ model_config = ConfigDict(frozen=True, extra="forbid")
124
+
125
+
126
+ class StackConfig(BaseModel):
127
+ """Main Stack configuration with full validation.
128
+
129
+ This is the primary configuration model that validates all Stack
130
+ settings at runtime, preventing configuration errors and catching
131
+ AI hallucinations early.
132
+
133
+ Attributes:
134
+ project_name: Name of the project (alphanumeric, _, -).
135
+ python_version: Target Python version (e.g., "3.12").
136
+ project_dir: Directory to initialize project in.
137
+ dry_run: Simulate execution without changes.
138
+ force: Overwrite existing files without backup.
139
+ verbose: Enable verbose logging.
140
+ security: Security configuration.
141
+ dependencies: Dependency configuration.
142
+ logging: Logging configuration.
143
+
144
+ Example:
145
+ >>> config = StackConfig(
146
+ ... project_name="my_project",
147
+ ... python_version="3.12",
148
+ ... )
149
+ >>> config.project_name
150
+ 'my_project'
151
+
152
+ """
153
+
154
+ project_name: str = Field(
155
+ default="my_project",
156
+ min_length=1,
157
+ max_length=100,
158
+ description="Project name (alphanumeric, underscore, hyphen only)",
159
+ )
160
+ python_version: str = Field(
161
+ default_factory=lambda: f"{sys.version_info.major}.{sys.version_info.minor}",
162
+ description="Target Python version",
163
+ )
164
+ project_dir: Path = Field(
165
+ default_factory=Path.cwd,
166
+ description="Project directory",
167
+ )
168
+ dry_run: bool = Field(
169
+ default=False,
170
+ description="Simulate execution without making changes",
171
+ )
172
+ force: bool = Field(
173
+ default=False,
174
+ description="Overwrite existing files without backup",
175
+ )
176
+ verbose: bool = Field(
177
+ default=False,
178
+ description="Enable verbose output",
179
+ )
180
+ security: SecurityConfig = Field(
181
+ default_factory=SecurityConfig,
182
+ description="Security configuration",
183
+ )
184
+ dependencies: DependencyConfig = Field(
185
+ default_factory=DependencyConfig,
186
+ description="Dependency configuration",
187
+ )
188
+ logging: LoggingConfig = Field(
189
+ default_factory=LoggingConfig,
190
+ description="Logging configuration",
191
+ )
192
+
193
+ model_config = ConfigDict(
194
+ frozen=True,
195
+ extra="forbid",
196
+ validate_default=True,
197
+ )
198
+
199
+ @field_validator("project_name")
200
+ @classmethod
201
+ def validate_project_name(cls, value: str) -> str:
202
+ """Validate that project name is safe.
203
+
204
+ Args:
205
+ value: The project name to validate.
206
+
207
+ Returns:
208
+ The validated project name.
209
+
210
+ Raises:
211
+ ValueError: If project name contains invalid characters.
212
+
213
+ """
214
+ pattern = r"^[a-zA-Z][a-zA-Z0-9_-]*$"
215
+ if not re.match(pattern, value):
216
+ msg = (
217
+ f"Project name '{value}' is invalid. "
218
+ "Must start with a letter and contain only alphanumeric, "
219
+ "underscore, or hyphen characters."
220
+ )
221
+ raise ValueError(msg)
222
+ return value
223
+
224
+ @field_validator("python_version")
225
+ @classmethod
226
+ def validate_python_version(cls, value: str) -> str:
227
+ """Validate Python version format.
228
+
229
+ Args:
230
+ value: The Python version string.
231
+
232
+ Returns:
233
+ The validated Python version.
234
+
235
+ Raises:
236
+ ValueError: If version format is invalid.
237
+
238
+ """
239
+ pattern = r"^\d+\.\d+$"
240
+ if not re.match(pattern, value):
241
+ msg = (
242
+ f"Python version '{value}' is invalid. Use format 'X.Y' (e.g., '3.12')."
243
+ )
244
+ raise ValueError(msg)
245
+
246
+ major, minor = map(int, value.split("."))
247
+ is_old_python = major < PYTHON_MAJOR_VERSION or (
248
+ major == PYTHON_MAJOR_VERSION and minor < MIN_PYTHON_MINOR_VERSION
249
+ )
250
+ if is_old_python:
251
+ msg = (
252
+ f"Python version {value} is not supported. "
253
+ f"Minimum is {PYTHON_MAJOR_VERSION}.{MIN_PYTHON_MINOR_VERSION}."
254
+ )
255
+ raise ValueError(msg)
256
+
257
+ return value
258
+
259
+ @field_validator("project_dir")
260
+ @classmethod
261
+ def validate_project_dir(cls, value: Path) -> Path:
262
+ """Validate project directory is safe.
263
+
264
+ Args:
265
+ value: The project directory path.
266
+
267
+ Returns:
268
+ The validated and resolved path.
269
+
270
+ Raises:
271
+ ValueError: If path is unsafe or contains traversal.
272
+
273
+ """
274
+ resolved = value.resolve()
275
+
276
+ # Check for path traversal attempts
277
+ if ".." in str(value):
278
+ msg = f"Path traversal detected in project_dir: {value}"
279
+ raise ValueError(msg)
280
+
281
+ return resolved
282
+
283
+ @model_validator(mode="after")
284
+ def validate_config_consistency(self) -> StackConfig:
285
+ """Validate configuration consistency.
286
+
287
+ Returns:
288
+ The validated configuration.
289
+
290
+ Raises:
291
+ ValueError: If configuration is inconsistent.
292
+
293
+ """
294
+ # If paranoid security, ensure all security tools are enabled
295
+ all_tools_enabled = all(
296
+ [
297
+ self.security.enable_bandit,
298
+ self.security.enable_safety,
299
+ self.security.enable_semgrep,
300
+ self.security.enable_detect_secrets,
301
+ ]
302
+ )
303
+ if self.security.level == "paranoid" and not all_tools_enabled:
304
+ msg = "Paranoid security level requires all security tools enabled."
305
+ raise ValueError(msg)
306
+
307
+ return self
308
+
309
+ def to_target_version(self) -> str:
310
+ """Get Python version in Ruff target format.
311
+
312
+ Returns:
313
+ Version string like 'py312'.
314
+
315
+ """
316
+ return f"py{self.python_version.replace('.', '')}"
@@ -0,0 +1,227 @@
1
+ """
2
+ Version-Specific Configuration Recommendations.
3
+
4
+ This module provides configuration templates optimized for different
5
+ Python versions, helping users get the best performance while
6
+ maintaining stability.
7
+
8
+ Following Stack pillars: Security, Stability, Simplicity, Scalability, Compatibility.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import logging
14
+ from dataclasses import dataclass
15
+ from typing import TYPE_CHECKING
16
+
17
+ from taipanstack.core.compat import (
18
+ PY312,
19
+ PY313,
20
+ PY314,
21
+ VersionTier,
22
+ get_features,
23
+ )
24
+ from taipanstack.core.optimizations import get_recommended_thread_pool_size
25
+
26
+ if TYPE_CHECKING:
27
+ pass
28
+
29
+ __all__ = [
30
+ "VersionRecommendations",
31
+ "get_version_recommendations",
32
+ ]
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+
37
+ # =============================================================================
38
+ # Version Recommendations
39
+ # =============================================================================
40
+
41
+
42
+ @dataclass(frozen=True, slots=True)
43
+ class VersionRecommendations:
44
+ """Configuration recommendations for a Python version.
45
+
46
+ These recommendations help users configure their Stack-based
47
+ applications for optimal performance on their Python version.
48
+ """
49
+
50
+ version_tier: VersionTier
51
+ min_version: str
52
+ max_version: str | None
53
+
54
+ # Threading recommendations
55
+ recommended_thread_pool_size: int
56
+ supports_true_parallelism: bool
57
+
58
+ # Memory recommendations
59
+ recommended_gc_mode: str
60
+ use_mimalloc: bool
61
+
62
+ # Code style recommendations
63
+ use_type_params: bool # PEP 695 type parameter syntax
64
+ use_exception_groups: bool # PEP 654 exception groups
65
+ use_match_statements: bool # PEP 634 structural matching
66
+ use_override_decorator: bool # PEP 698 @override
67
+ use_deprecated_decorator: bool # PEP 702 @deprecated
68
+
69
+ # Performance recommendations
70
+ jit_available: bool
71
+ recommended_optimization_level: int
72
+
73
+ # Notes for user
74
+ notes: tuple[str, ...]
75
+
76
+ def to_dict(self) -> dict[str, object]:
77
+ """Convert to dictionary for serialization."""
78
+ return {
79
+ "version_tier": self.version_tier.value,
80
+ "version_range": f"{self.min_version} - {self.max_version or 'latest'}",
81
+ "threading": {
82
+ "pool_size": self.recommended_thread_pool_size,
83
+ "true_parallelism": self.supports_true_parallelism,
84
+ },
85
+ "memory": {
86
+ "gc_mode": self.recommended_gc_mode,
87
+ "mimalloc": self.use_mimalloc,
88
+ },
89
+ "code_style": {
90
+ "type_params": self.use_type_params,
91
+ "exception_groups": self.use_exception_groups,
92
+ "match_statements": self.use_match_statements,
93
+ "override_decorator": self.use_override_decorator,
94
+ "deprecated_decorator": self.use_deprecated_decorator,
95
+ },
96
+ "performance": {
97
+ "jit_available": self.jit_available,
98
+ "optimization_level": self.recommended_optimization_level,
99
+ },
100
+ "notes": list(self.notes),
101
+ }
102
+
103
+
104
+ # =============================================================================
105
+ # Recommendation Generators
106
+ # =============================================================================
107
+
108
+
109
+ def _get_311_recommendations() -> VersionRecommendations:
110
+ """Get recommendations for Python 3.11."""
111
+ return VersionRecommendations(
112
+ version_tier=VersionTier.STABLE,
113
+ min_version="3.11.0",
114
+ max_version="3.11.x",
115
+ recommended_thread_pool_size=get_recommended_thread_pool_size(),
116
+ supports_true_parallelism=False,
117
+ recommended_gc_mode="default",
118
+ use_mimalloc=False,
119
+ use_type_params=False,
120
+ use_exception_groups=True,
121
+ use_match_statements=True,
122
+ use_override_decorator=False,
123
+ use_deprecated_decorator=False,
124
+ jit_available=False,
125
+ recommended_optimization_level=1,
126
+ notes=(
127
+ "Stable baseline with 25% speedup from specialized bytecode",
128
+ "Use exception groups (PEP 654) for better error handling",
129
+ "Self type available for type hints",
130
+ ),
131
+ )
132
+
133
+
134
+ def _get_312_recommendations() -> VersionRecommendations:
135
+ """Get recommendations for Python 3.12."""
136
+ return VersionRecommendations(
137
+ version_tier=VersionTier.ENHANCED,
138
+ min_version="3.12.0",
139
+ max_version="3.12.x",
140
+ recommended_thread_pool_size=get_recommended_thread_pool_size(),
141
+ supports_true_parallelism=False,
142
+ recommended_gc_mode="default",
143
+ use_mimalloc=False,
144
+ use_type_params=True,
145
+ use_exception_groups=True,
146
+ use_match_statements=True,
147
+ use_override_decorator=True,
148
+ use_deprecated_decorator=False,
149
+ jit_available=False,
150
+ recommended_optimization_level=1,
151
+ notes=(
152
+ "Use type parameter syntax (PEP 695) for cleaner generics",
153
+ "Use @override decorator (PEP 698) for method overrides",
154
+ "Improved f-string parsing and error messages",
155
+ ),
156
+ )
157
+
158
+
159
+ def _get_313_recommendations() -> VersionRecommendations:
160
+ """Get recommendations for Python 3.13."""
161
+ features = get_features()
162
+ return VersionRecommendations(
163
+ version_tier=VersionTier.MODERN,
164
+ min_version="3.13.0",
165
+ max_version="3.13.x",
166
+ recommended_thread_pool_size=get_recommended_thread_pool_size(),
167
+ supports_true_parallelism=features.has_free_threading,
168
+ recommended_gc_mode="tuned" if features.has_mimalloc else "default",
169
+ use_mimalloc=features.has_mimalloc,
170
+ use_type_params=True,
171
+ use_exception_groups=True,
172
+ use_match_statements=True,
173
+ use_override_decorator=True,
174
+ use_deprecated_decorator=True,
175
+ jit_available=features.has_jit,
176
+ recommended_optimization_level=2 if features.experimental_enabled else 1,
177
+ notes=(
178
+ "Use @deprecated decorator (PEP 702) for deprecation warnings",
179
+ "JIT compiler available (experimental) with STACK_ENABLE_EXPERIMENTAL=1",
180
+ "Free-threading available on special builds (no GIL)",
181
+ "mimalloc allocator provides better memory performance",
182
+ ),
183
+ )
184
+
185
+
186
+ def _get_314_recommendations() -> VersionRecommendations:
187
+ """Get recommendations for Python 3.14."""
188
+ features = get_features()
189
+ return VersionRecommendations(
190
+ version_tier=VersionTier.CUTTING_EDGE,
191
+ min_version="3.14.0",
192
+ max_version=None,
193
+ recommended_thread_pool_size=get_recommended_thread_pool_size(),
194
+ supports_true_parallelism=features.has_free_threading,
195
+ recommended_gc_mode="incremental",
196
+ use_mimalloc=True,
197
+ use_type_params=True,
198
+ use_exception_groups=True,
199
+ use_match_statements=True,
200
+ use_override_decorator=True,
201
+ use_deprecated_decorator=True,
202
+ jit_available=features.has_jit,
203
+ recommended_optimization_level=2 if features.experimental_enabled else 1,
204
+ notes=(
205
+ "Tail-call interpreter provides 9-15% speedup",
206
+ "Deferred annotations (PEP 649) for faster startup",
207
+ "Stable free-threading support available",
208
+ "JIT compiler significantly improved from 3.13",
209
+ "Incremental GC reduces pause times",
210
+ ),
211
+ )
212
+
213
+
214
+ def get_version_recommendations() -> VersionRecommendations:
215
+ """Get configuration recommendations for the current Python version.
216
+
217
+ Returns:
218
+ VersionRecommendations with optimal settings.
219
+
220
+ """
221
+ if PY314:
222
+ return _get_314_recommendations()
223
+ if PY313:
224
+ return _get_313_recommendations()
225
+ if PY312:
226
+ return _get_312_recommendations()
227
+ return _get_311_recommendations()
@@ -0,0 +1,47 @@
1
+ """Stack Core Module.
2
+
3
+ Provides core functionality including Result types, version compatibility,
4
+ and optimization utilities.
5
+ """
6
+
7
+ from taipanstack.core.compat import (
8
+ PY311,
9
+ PY312,
10
+ PY313,
11
+ PY314,
12
+ PY_VERSION,
13
+ PythonFeatures,
14
+ VersionTier,
15
+ get_features,
16
+ get_python_info,
17
+ is_experimental_enabled,
18
+ )
19
+ from taipanstack.core.optimizations import (
20
+ OptimizationProfile,
21
+ OptimizationResult,
22
+ apply_optimizations,
23
+ get_optimization_profile,
24
+ get_recommended_thread_pool_size,
25
+ )
26
+ from taipanstack.core.result import Err, Ok, Result
27
+
28
+ __all__ = [
29
+ "PY311",
30
+ "PY312",
31
+ "PY313",
32
+ "PY314",
33
+ "PY_VERSION",
34
+ "Err",
35
+ "Ok",
36
+ "OptimizationProfile",
37
+ "OptimizationResult",
38
+ "PythonFeatures",
39
+ "Result",
40
+ "VersionTier",
41
+ "apply_optimizations",
42
+ "get_features",
43
+ "get_optimization_profile",
44
+ "get_python_info",
45
+ "get_recommended_thread_pool_size",
46
+ "is_experimental_enabled",
47
+ ]