python-skills 1.0.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.
Files changed (105) hide show
  1. python_skills/__init__.py +10 -0
  2. python_skills/__main__.py +6 -0
  3. python_skills/adapters/__init__.py +48 -0
  4. python_skills/adapters/agent_skills.py +415 -0
  5. python_skills/adapters/aider_adapter.py +226 -0
  6. python_skills/adapters/base.py +153 -0
  7. python_skills/adapters/claude.py +474 -0
  8. python_skills/adapters/cline.py +332 -0
  9. python_skills/adapters/codex.py +24 -0
  10. python_skills/adapters/continue_adapter.py +198 -0
  11. python_skills/adapters/cursor.py +327 -0
  12. python_skills/adapters/gemini.py +26 -0
  13. python_skills/adapters/goose.py +26 -0
  14. python_skills/adapters/junie.py +25 -0
  15. python_skills/adapters/kiro.py +382 -0
  16. python_skills/adapters/opencode.py +27 -0
  17. python_skills/adapters/roo.py +25 -0
  18. python_skills/adapters/universal.py +203 -0
  19. python_skills/adapters/vscode.py +27 -0
  20. python_skills/adapters/windsurf.py +26 -0
  21. python_skills/adapters/zed.py +27 -0
  22. python_skills/cli.py +326 -0
  23. python_skills/config.py +160 -0
  24. python_skills/detector.py +152 -0
  25. python_skills/installer.py +163 -0
  26. python_skills/markers.py +115 -0
  27. python_skills/skills/__init__.py +14 -0
  28. python_skills/skills/loader.py +171 -0
  29. python_skills/skills/metadata.py +152 -0
  30. python_skills/skills/registry.py +101 -0
  31. python_skills/state.py +204 -0
  32. python_skills-1.0.0.dist-info/METADATA +99 -0
  33. python_skills-1.0.0.dist-info/RECORD +105 -0
  34. python_skills-1.0.0.dist-info/WHEEL +4 -0
  35. python_skills-1.0.0.dist-info/entry_points.txt +2 -0
  36. python_skills-1.0.0.dist-info/licenses/LICENSE +21 -0
  37. skills/advanced_python.md +239 -0
  38. skills/anti_patterns/index.md +406 -0
  39. skills/comprehensions.md +167 -0
  40. skills/control_flow.md +175 -0
  41. skills/data_structures.md +243 -0
  42. skills/debugging/common_bugs.md +222 -0
  43. skills/debugging/inspection_techniques.md +249 -0
  44. skills/debugging/root_cause.md +203 -0
  45. skills/engineering/application_logging.md +195 -0
  46. skills/engineering/cli_apps.md +207 -0
  47. skills/engineering/configuration.md +218 -0
  48. skills/engineering/database.md +240 -0
  49. skills/engineering/dependency_management.md +205 -0
  50. skills/engineering/http_clients.md +267 -0
  51. skills/engineering/modules_packages.md +211 -0
  52. skills/engineering/packaging.md +197 -0
  53. skills/engineering/project_structure.md +155 -0
  54. skills/engineering/pyproject_toml.md +302 -0
  55. skills/engineering/virtual_environments.md +206 -0
  56. skills/functions.md +244 -0
  57. skills/generation/async_concurrency.md +291 -0
  58. skills/generation/error_handling.md +276 -0
  59. skills/generation/protocols_generics.md +243 -0
  60. skills/generation/type_hints.md +290 -0
  61. skills/generation/validation_pipeline.md +274 -0
  62. skills/generation/workflow.md +190 -0
  63. skills/oop.md +228 -0
  64. skills/quality/abstractions.md +154 -0
  65. skills/quality/comments.md +177 -0
  66. skills/quality/documentation.md +176 -0
  67. skills/quality/duplication.md +137 -0
  68. skills/quality/maintainability.md +142 -0
  69. skills/quality/naming.md +171 -0
  70. skills/quality/quality_functions.md +245 -0
  71. skills/quality/readability.md +239 -0
  72. skills/quality/type_annotations.md +192 -0
  73. skills/refactoring/behavior_preservation.md +157 -0
  74. skills/refactoring/incremental.md +187 -0
  75. skills/refactoring/interface_stability.md +199 -0
  76. skills/refactoring/safe_refactoring.md +206 -0
  77. skills/security/auth_boundaries.md +200 -0
  78. skills/security/command_injection.md +207 -0
  79. skills/security/dependency_risks.md +282 -0
  80. skills/security/file_handling.md +156 -0
  81. skills/security/input_validation.md +190 -0
  82. skills/security/path_traversal.md +172 -0
  83. skills/security/secrets.md +171 -0
  84. skills/security/sql_injection.md +188 -0
  85. skills/security/unsafe_deserialization.md +164 -0
  86. skills/stdlib/argparse.md +178 -0
  87. skills/stdlib/collections.md +212 -0
  88. skills/stdlib/datetime.md +187 -0
  89. skills/stdlib/functools.md +238 -0
  90. skills/stdlib/itertools.md +183 -0
  91. skills/stdlib/json.md +162 -0
  92. skills/stdlib/logging.md +185 -0
  93. skills/stdlib/os_sys.md +184 -0
  94. skills/stdlib/pathlib.md +218 -0
  95. skills/stdlib/re.md +171 -0
  96. skills/stdlib/statistics.md +112 -0
  97. skills/stdlib/subprocess.md +211 -0
  98. skills/testing/async_tests.md +249 -0
  99. skills/testing/coverage.md +168 -0
  100. skills/testing/edge_cases.md +197 -0
  101. skills/testing/fixtures_mocks.md +203 -0
  102. skills/testing/organization.md +205 -0
  103. skills/testing/parameterized.md +174 -0
  104. skills/testing/regression_tests.md +165 -0
  105. skills/variables_types.md +107 -0
skills/stdlib/json.md ADDED
@@ -0,0 +1,162 @@
1
+ # Stdlib: json
2
+
3
+ **Purpose**: JSON encoding/decoding with Python objects.
4
+
5
+ **When to use**: Serialization, config, APIs, data exchange.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### Basic Usage
12
+ ```python
13
+ import json
14
+
15
+ # Encode
16
+ json_str = json.dumps(obj, indent=2, ensure_ascii=False)
17
+ json_bytes = json.dumps(obj).encode("utf-8")
18
+
19
+ # Decode
20
+ obj = json.loads(json_str)
21
+ obj = json.load(file_obj)
22
+ ```
23
+
24
+ ### Default Serialization
25
+ | Python | JSON |
26
+ |--------|------|
27
+ | `dict` | object |
28
+ | `list`, `tuple` | array |
29
+ | `str` | string |
30
+ | `int`, `float` | number |
31
+ | `True`, `False` | `true`, `false` |
32
+ | `None` | `null` |
33
+
34
+ ### Custom Serialization
35
+ ```python
36
+ # default= callable for unsupported types
37
+ json.dumps(obj, default=lambda o: o.isoformat() if hasattr(o, "isoformat") else str(o))
38
+
39
+ # Or subclass JSONEncoder
40
+ class CustomEncoder(json.JSONEncoder):
41
+ def default(self, obj):
42
+ if isinstance(obj, datetime):
43
+ return obj.isoformat()
44
+ if isinstance(obj, UUID):
45
+ return str(obj)
46
+ return super().default(obj)
47
+
48
+ json.dumps(obj, cls=CustomEncoder)
49
+ ```
50
+
51
+ ### Custom Deserialization
52
+ ```python
53
+ # object_hook for dicts
54
+ def decode_datetime(d):
55
+ for key, value in d.items():
56
+ if key.endswith("_at") and isinstance(value, str):
57
+ try:
58
+ d[key] = datetime.fromisoformat(value)
59
+ except ValueError:
60
+ pass
61
+ return d
62
+
63
+ json.loads(json_str, object_hook=decode_datetime)
64
+
65
+ # object_pairs_hook for ordered pairs (preserves duplicate keys)
66
+ json.loads(json_str, object_pairs_hook=OrderedDict)
67
+ ```
68
+
69
+ ### Streaming (Large Data)
70
+ ```python
71
+ # Incremental encoding
72
+ encoder = json.JSONEncoder()
73
+ for chunk in encoder.iterencode(large_obj):
74
+ write(chunk)
75
+
76
+ # Incremental decoding
77
+ decoder = json.JSONDecoder()
78
+ for obj in decoder.raw_decode(stream):
79
+ ...
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Decision Rules
85
+
86
+ | Situation | Approach |
87
+ |-----------|----------|
88
+ | Simple dict/list | `json.dumps` / `json.loads` |
89
+ | Datetime, UUID, Decimal | Custom `JSONEncoder` + `object_hook` |
90
+ | Large data (streaming) | `JSONEncoder.iterencode` / `JSONDecoder.raw_decode` |
91
+ | Preserve order | Default (Python 3.7+) or `object_pairs_hook` |
92
+ | Non-ASCII chars | `ensure_ascii=False` |
93
+ | Compact output | `separators=(",", ":")` |
94
+ | Human-readable | `indent=2` |
95
+
96
+ ---
97
+
98
+ ## Preferred Patterns
99
+
100
+ ```python
101
+ # Standard API response
102
+ def to_json(data: Any) -> str:
103
+ return json.dumps(
104
+ data,
105
+ default=json_default,
106
+ ensure_ascii=False,
107
+ separators=(",", ":"),
108
+ )
109
+
110
+ def json_default(obj):
111
+ if isinstance(obj, (datetime, date)):
112
+ return obj.isoformat()
113
+ if isinstance(obj, UUID):
114
+ return str(obj)
115
+ if isinstance(obj, Decimal):
116
+ return str(obj)
117
+ if hasattr(obj, "__dict__"):
118
+ return obj.__dict__
119
+ raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
120
+
121
+ # Safe loading with schema validation
122
+ def load_json(path: Path, schema: type) -> Any:
123
+ data = json.loads(path.read_text(encoding="utf-8"))
124
+ # Validate with pydantic, attrs, or manual check
125
+ return validate(data, schema)
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Security
131
+
132
+ - **Never** use `json.load` on untrusted input without validation
133
+ - `json` module is safe (no code execution) unlike `pickle`/`yaml`
134
+ - Large inputs can cause DoS (billions of nested objects) — consider `defusedxml`-style limits
135
+ - `object_hook` runs on every dict — avoid expensive operations
136
+
137
+ ---
138
+
139
+ ## Avoid
140
+
141
+ - `pickle` for data exchange (unsafe, Python-specific)
142
+ - `yaml.load` without `Loader=yaml.SafeLoader` (unsafe)
143
+ - Custom encoders that mutate input
144
+ - `default=str` (silently converts everything to string, loses type info)
145
+ - Large `indent` in production (wastes bandwidth)
146
+
147
+ ---
148
+
149
+ ## Validation Considerations
150
+
151
+ - Schema validation after decode (pydantic, jsonschema, manual)
152
+ - Round-trip test: `json.loads(json.dumps(obj)) == obj`
153
+ - `json.JSONDecodeError` for parse errors (includes position)
154
+
155
+ ---
156
+
157
+ ## Related Skills
158
+
159
+ - `security/unsafe_deserialization.md`
160
+ - `engineering/configuration.md`
161
+ - `stdlib/datetime.md`
162
+ - `generation/type_hints.md` (TypedDict for JSON shapes)
@@ -0,0 +1,185 @@
1
+ # Stdlib: logging
2
+
3
+ **Purpose**: Structured application logging.
4
+
5
+ **When to use**: All application logging. Never `print()` in production code.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### Basic Setup
12
+ ```python
13
+ import logging
14
+
15
+ # Module-level logger (standard pattern)
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # Logging levels
19
+ logger.debug("Detailed diagnostic")
20
+ logger.info("General operation")
21
+ logger.warning("Unexpected, but handled")
22
+ logger.error("Function failed")
23
+ logger.critical("System may fail")
24
+
25
+ # With context
26
+ logger.info("User login", extra={"user_id": 123, "ip": "1.2.3.4"})
27
+ ```
28
+
29
+ ### Configuration (Application Entry Point)
30
+ ```python
31
+ import logging
32
+ import logging.config
33
+
34
+ LOGGING_CONFIG = {
35
+ "version": 1,
36
+ "disable_existing_loggers": False,
37
+ "formatters": {
38
+ "standard": {
39
+ "format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s",
40
+ "datefmt": "%Y-%m-%d %H:%M:%S",
41
+ },
42
+ "json": {
43
+ "()": "pythonjsonlogger.jsonlogger.JsonFormatter",
44
+ "format": "%(asctime)s %(levelname)s %(name)s %(message)s",
45
+ },
46
+ },
47
+ "handlers": {
48
+ "console": {
49
+ "class": "logging.StreamHandler",
50
+ "formatter": "standard",
51
+ "stream": "ext://sys.stdout",
52
+ },
53
+ "file": {
54
+ "class": "logging.handlers.RotatingFileHandler",
55
+ "formatter": "json",
56
+ "filename": "app.log",
57
+ "maxBytes": 10_000_000,
58
+ "backupCount": 5,
59
+ },
60
+ },
61
+ "root": {
62
+ "level": "INFO",
63
+ "handlers": ["console", "file"],
64
+ },
65
+ "loggers": {
66
+ "myapp": {"level": "DEBUG", "propagate": True},
67
+ "httpx": {"level": "WARNING"}, # Quiet noisy libs
68
+ },
69
+ }
70
+
71
+ logging.config.dictConfig(LOGGING_CONFIG)
72
+ ```
73
+
74
+ ### Structured Logging (Recommended)
75
+ ```python
76
+ # Use extra for structured data
77
+ logger.info("Order processed", extra={
78
+ "order_id": "ORD-123",
79
+ "amount": 99.99,
80
+ "currency": "USD",
81
+ "customer_id": "CUST-456",
82
+ })
83
+
84
+ # Or use a structured logging library (structlog)
85
+ import structlog
86
+
87
+ log = structlog.get_logger()
88
+ log.info("order_processed", order_id="ORD-123", amount=99.99)
89
+ ```
90
+
91
+ ### Exception Logging
92
+ ```python
93
+ try:
94
+ risky()
95
+ except Exception:
96
+ logger.exception("Operation failed") # Includes traceback
97
+ # Or:
98
+ logger.error("Operation failed", exc_info=True)
99
+ ```
100
+
101
+ ### Lazy Evaluation (Performance)
102
+ ```python
103
+ # Arguments evaluated only if level enabled
104
+ logger.debug("Expensive: %s", expensive_computation) # Not f-string!
105
+
106
+ # For complex objects
107
+ logger.debug("Data: %s", lambda: repr(large_object))
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Decision Rules
113
+
114
+ | Situation | Approach |
115
+ |-----------|----------|
116
+ | Application code | `logger = logging.getLogger(__name__)` |
117
+ | Library code | Same, but don't configure — let app configure |
118
+ | Structured data | `extra={...}` or `structlog` |
119
+ | Exceptions | `logger.exception()` or `exc_info=True` |
120
+ | High-volume debug | Lazy `%s` formatting |
121
+ | Production | JSON format, file rotation |
122
+ | Development | Human-readable, console |
123
+
124
+ ---
125
+
126
+ ## Preferred Patterns
127
+
128
+ ```python
129
+ # Library: just get logger, don't configure
130
+ # mylib/__init__.py
131
+ import logging
132
+ log = logging.getLogger(__name__)
133
+
134
+ # Application: configure once at startup
135
+ # main.py
136
+ def setup_logging(level: str = "INFO", json_format: bool = False):
137
+ import logging.config
138
+ # ... dictConfig as above
139
+
140
+ # Context injection (middleware, decorators)
141
+ def with_context(func):
142
+ @functools.wraps(func)
143
+ def wrapper(*args, **kwargs):
144
+ old_factory = logging.getLogRecordFactory()
145
+ def factory(*a, **kw):
146
+ record = old_factory(*a, **kw)
147
+ record.request_id = getattr(request_context, "id", None)
148
+ return record
149
+ logging.setLogRecordFactory(factory)
150
+ try:
151
+ return func(*args, **kwargs)
152
+ finally:
153
+ logging.setLogRecordFactory(old_factory)
154
+ return wrapper
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Avoid
160
+
161
+ - `print()` in production code
162
+ - `logging.basicConfig()` in libraries (configures root globally)
163
+ - `logging.getLogger()` without name (root logger)
164
+ - f-strings in logging calls (evaluates always)
165
+ - Logging sensitive data (secrets, PII, tokens)
166
+ - Excessive DEBUG in production
167
+ - Catching and logging then re-raising without context
168
+
169
+ ---
170
+
171
+ ## Validation Considerations
172
+
173
+ - Test log output format
174
+ - Verify log levels in different environments
175
+ - Check log rotation works
176
+ - Ensure no PII in logs (automated scanning)
177
+
178
+ ---
179
+
180
+ ## Related Skills
181
+
182
+ - `engineering/configuration.md`
183
+ - `security/secrets.md`
184
+ - `stdlib/os_sys.md` (environment config)
185
+ - `generation/error_handling.md` (exception logging)
@@ -0,0 +1,184 @@
1
+ # Stdlib: os and sys
2
+
3
+ **Purpose**: Operating system interfaces and Python runtime.
4
+
5
+ **When to use**: Process environment, filesystem, Python internals. Prefer `pathlib` for paths.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### os — Environment and Process
12
+ ```python
13
+ import os
14
+
15
+ # Environment variables
16
+ os.environ # Mapping (str -> str)
17
+ os.getenv("KEY", "default")
18
+ os.environ["KEY"] = "value" # Set
19
+ del os.environ["KEY"] # Unset
20
+
21
+ # Process
22
+ os.getpid() # Current PID
23
+ os.getppid() # Parent PID
24
+ os.cpu_count() # CPU count
25
+ os.urandom(n) # Cryptographic random bytes
26
+
27
+ # Working directory
28
+ os.getcwd() # Str
29
+ os.chdir(path) # Change
30
+
31
+ # Filesystem (prefer pathlib)
32
+ os.listdir(path) # Names only
33
+ os.scandir(path) # DirEntry objects (efficient)
34
+ os.makedirs(path, exist_ok=True)
35
+ os.remove(path)
36
+ os.rmdir(path)
37
+ os.rename(src, dst)
38
+ os.replace(src, dst) # Atomic
39
+ os.symlink(src, dst)
40
+ os.readlink(path)
41
+ os.stat(path) # stat_result
42
+ os.path.isfile(path) # Legacy — use pathlib
43
+
44
+ # Path manipulation (legacy — use pathlib)
45
+ os.path.join(*parts)
46
+ os.path.split(path)
47
+ os.path.dirname(path)
48
+ os.path.basename(path)
49
+ os.path.splitext(path)
50
+ os.path.abspath(path)
51
+ os.path.relpath(path, start)
52
+ os.path.normpath(path)
53
+ os.path.expanduser("~/path")
54
+ os.path.expandvars("$VAR/path")
55
+ ```
56
+
57
+ ### sys — Python Runtime
58
+ ```python
59
+ import sys
60
+
61
+ # Version
62
+ sys.version # String
63
+ sys.version_info # Named tuple (major, minor, micro, ...)
64
+ sys.version_info >= (3, 12)
65
+
66
+ # Paths
67
+ sys.path # Module search path (list)
68
+ sys.prefix # Install prefix
69
+ sys.exec_prefix # Platform-specific prefix
70
+ sys.executable # Python interpreter path
71
+
72
+ # Arguments
73
+ sys.argv # CLI args (list[str])
74
+ sys.flags # Interpreter flags
75
+
76
+ # I/O
77
+ sys.stdin # TextIOWrapper
78
+ sys.stdout
79
+ sys.stderr
80
+ sys.stdin.buffer # Binary
81
+ sys.stdout.buffer
82
+ sys.stderr.buffer
83
+
84
+ # Exit
85
+ sys.exit(code) # SystemExit
86
+ sys.exit("message") # Prints to stderr, exit 1
87
+
88
+ # Modules
89
+ sys.modules # Loaded modules dict
90
+ sys.builtin_module_names
91
+ ```
92
+
93
+ ### Platform Detection
94
+ ```python
95
+ import sys, os
96
+
97
+ sys.platform # "linux", "darwin", "win32", "cygwin"
98
+ os.name # "posix", "nt", "java"
99
+
100
+ # Better: platform module
101
+ import platform
102
+ platform.system() # "Linux", "Darwin", "Windows"
103
+ platform.release() # Kernel version
104
+ platform.machine() # "x86_64", "arm64"
105
+ platform.python_implementation() # "CPython", "PyPy"
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Decision Rules
111
+
112
+ | Need | Module | Function |
113
+ |------|--------|----------|
114
+ | Env vars | `os` | `os.getenv`, `os.environ` |
115
+ | CWD | `os` | `os.getcwd`, `os.chdir` |
116
+ | CLI args | `sys` | `sys.argv` |
117
+ | Python version | `sys` | `sys.version_info` |
118
+ | Module path | `sys` | `sys.path` |
119
+ | Std I/O | `sys` | `sys.std*` |
120
+ | Exit | `sys` | `sys.exit` |
121
+ | Random bytes | `os` | `os.urandom` |
122
+ | Platform | `platform` | `platform.system()` |
123
+
124
+ ---
125
+
126
+ ## Preferred Patterns
127
+
128
+ ```python
129
+ # Environment-based config
130
+ def get_config() -> Config:
131
+ return Config(
132
+ database_url=os.getenv("DATABASE_URL", "sqlite:///local.db"),
133
+ debug=os.getenv("DEBUG", "false").lower() == "true",
134
+ port=int(os.getenv("PORT", "8000")),
135
+ )
136
+
137
+ # Platform-specific paths
138
+ def get_data_dir() -> Path:
139
+ if sys.platform == "win32":
140
+ base = Path(os.getenv("LOCALAPPDATA", Path.home() / "AppData" / "Local"))
141
+ elif sys.platform == "darwin":
142
+ base = Path.home() / "Library" / "Application Support"
143
+ else: # Linux/Unix
144
+ base = Path(os.getenv("XDG_DATA_HOME", Path.home() / ".local" / "share"))
145
+ return base / "myapp"
146
+
147
+ # Safe subprocess with clean env
148
+ def run_clean(cmd: list[str]):
149
+ clean_env = {
150
+ "PATH": "/usr/bin:/bin",
151
+ "LANG": "C.UTF-8",
152
+ "HOME": "/tmp",
153
+ }
154
+ return subprocess.run(cmd, env=clean_env, ...)
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Avoid
160
+
161
+ - `os.path` for new code (use `pathlib`)
162
+ - `os.system`, `os.popen` (use `subprocess`)
163
+ - Modifying `sys.path` at runtime (use proper packaging)
164
+ - `sys.exit()` in library code (raise exceptions)
165
+ - Hardcoding paths (`/tmp`, `C:\\Temp`)
166
+ - Assuming Unix paths on Windows
167
+
168
+ ---
169
+
170
+ ## Validation Considerations
171
+
172
+ - Test on target platforms (Windows vs Unix)
173
+ - Verify env var handling with missing/empty values
174
+ - Check path handling with spaces, unicode
175
+
176
+ ---
177
+
178
+ ## Related Skills
179
+
180
+ - `stdlib/pathlib.md`
181
+ - `stdlib/subprocess.md`
182
+ - `engineering/configuration.md`
183
+ - `engineering/virtual_environments.md`
184
+ - `security/secrets.md`