python-infrakit-dev 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.
- infrakit/__init__.py +0 -0
- infrakit/cli/__init__.py +1 -0
- infrakit/cli/commands/__init__.py +1 -0
- infrakit/cli/commands/deps.py +530 -0
- infrakit/cli/commands/init.py +129 -0
- infrakit/cli/commands/llm.py +295 -0
- infrakit/cli/commands/logger.py +160 -0
- infrakit/cli/commands/module.py +342 -0
- infrakit/cli/commands/time.py +81 -0
- infrakit/cli/main.py +65 -0
- infrakit/core/__init__.py +0 -0
- infrakit/core/config/__init__.py +0 -0
- infrakit/core/config/converter.py +480 -0
- infrakit/core/config/exporter.py +304 -0
- infrakit/core/config/loader.py +713 -0
- infrakit/core/config/validator.py +389 -0
- infrakit/core/logger/__init__.py +21 -0
- infrakit/core/logger/formatters.py +143 -0
- infrakit/core/logger/handlers.py +322 -0
- infrakit/core/logger/retention.py +176 -0
- infrakit/core/logger/setup.py +314 -0
- infrakit/deps/__init__.py +239 -0
- infrakit/deps/clean.py +141 -0
- infrakit/deps/depfile.py +405 -0
- infrakit/deps/health.py +357 -0
- infrakit/deps/optimizer.py +642 -0
- infrakit/deps/scanner.py +550 -0
- infrakit/llm/__init__.py +35 -0
- infrakit/llm/batch.py +165 -0
- infrakit/llm/client.py +575 -0
- infrakit/llm/key_manager.py +728 -0
- infrakit/llm/llm_readme.md +306 -0
- infrakit/llm/models.py +148 -0
- infrakit/llm/providers/__init__.py +5 -0
- infrakit/llm/providers/base.py +112 -0
- infrakit/llm/providers/gemini.py +164 -0
- infrakit/llm/providers/openai.py +168 -0
- infrakit/llm/rate_limiter.py +54 -0
- infrakit/scaffolder/__init__.py +31 -0
- infrakit/scaffolder/ai.py +508 -0
- infrakit/scaffolder/backend.py +555 -0
- infrakit/scaffolder/cli_tool.py +386 -0
- infrakit/scaffolder/generator.py +338 -0
- infrakit/scaffolder/pipeline.py +562 -0
- infrakit/scaffolder/registry.py +121 -0
- infrakit/time/__init__.py +60 -0
- infrakit/time/profiler.py +511 -0
- python_infrakit_dev-0.1.0.dist-info/METADATA +124 -0
- python_infrakit_dev-0.1.0.dist-info/RECORD +51 -0
- python_infrakit_dev-0.1.0.dist-info/WHEEL +4 -0
- python_infrakit_dev-0.1.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""
|
|
2
|
+
infrakit.core.config.exporter
|
|
3
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
4
|
+
Export a config file or dict with all values replaced by YOUR_VALUE_HERE —
|
|
5
|
+
safe to share without leaking real credentials.
|
|
6
|
+
|
|
7
|
+
The output format is always an explicit input — nothing is inferred.
|
|
8
|
+
|
|
9
|
+
Output style:
|
|
10
|
+
DATABASE_URL=YOUR_VALUE_HERE
|
|
11
|
+
PORT=YOUR_VALUE_HERE
|
|
12
|
+
DEBUG=YOUR_VALUE_HERE
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
from infrakit.core.config.exporter import export_file, export_dict, export_string
|
|
16
|
+
|
|
17
|
+
# File -> sanitized file, choose output format explicitly
|
|
18
|
+
export_file("config.yaml", ".env.example", to_format="env")
|
|
19
|
+
export_file(".env", "config.example.yaml", to_format="yaml")
|
|
20
|
+
|
|
21
|
+
# Dict -> sanitized string
|
|
22
|
+
result = export_dict({"PORT": 8080, "DEBUG": True}, to_format="env")
|
|
23
|
+
print(result)
|
|
24
|
+
|
|
25
|
+
# Raw string -> sanitized string
|
|
26
|
+
result = export_string(raw_env_text, from_format="env", to_format="ini")
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import json
|
|
32
|
+
from configparser import ConfigParser
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from typing import Any
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
import yaml
|
|
38
|
+
_YAML_AVAILABLE = True
|
|
39
|
+
except ImportError:
|
|
40
|
+
_YAML_AVAILABLE = False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
# Public types
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
ConfigDict = dict[str, Any]
|
|
48
|
+
Format = str # "json" | "yaml" | "ini" | "env"
|
|
49
|
+
|
|
50
|
+
SUPPORTED_FORMATS = {"json", "yaml", "ini", "env"}
|
|
51
|
+
|
|
52
|
+
PLACEHOLDER = "YOUR_VALUE_HERE"
|
|
53
|
+
|
|
54
|
+
_EXT_TO_FORMAT: dict[str, Format] = {
|
|
55
|
+
".json": "json",
|
|
56
|
+
".yaml": "yaml",
|
|
57
|
+
".yml": "yaml",
|
|
58
|
+
".ini": "ini",
|
|
59
|
+
".cfg": "ini",
|
|
60
|
+
".env": "env",
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# ---------------------------------------------------------------------------
|
|
65
|
+
# Public API
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
def export_file(
|
|
69
|
+
source: str | Path,
|
|
70
|
+
target: str | Path,
|
|
71
|
+
*,
|
|
72
|
+
to_format: Format,
|
|
73
|
+
overwrite: bool = False,
|
|
74
|
+
) -> None:
|
|
75
|
+
"""Read *source*, replace all values with YOUR_VALUE_HERE, write to *target*.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
source:
|
|
80
|
+
Path to the real config file (e.g. ``.env``, ``config.yaml``).
|
|
81
|
+
target:
|
|
82
|
+
Path to write the sanitized output (e.g. ``.env.example``).
|
|
83
|
+
to_format:
|
|
84
|
+
Output format — one of ``"env"``, ``"ini"``, ``"json"``, ``"yaml"``.
|
|
85
|
+
Always required; never inferred from the filename.
|
|
86
|
+
overwrite:
|
|
87
|
+
If False (default), raises :exc:`FileExistsError` when *target* exists.
|
|
88
|
+
|
|
89
|
+
Raises
|
|
90
|
+
------
|
|
91
|
+
FileNotFoundError
|
|
92
|
+
If *source* does not exist.
|
|
93
|
+
FileExistsError
|
|
94
|
+
If *target* exists and *overwrite* is False.
|
|
95
|
+
ValueError
|
|
96
|
+
If *to_format* is not a supported format.
|
|
97
|
+
"""
|
|
98
|
+
source = Path(source)
|
|
99
|
+
target = Path(target)
|
|
100
|
+
|
|
101
|
+
if not source.exists():
|
|
102
|
+
raise FileNotFoundError(f"Source config not found: '{source}'")
|
|
103
|
+
if target.exists() and not overwrite:
|
|
104
|
+
raise FileExistsError(
|
|
105
|
+
f"Target '{target}' already exists. Pass overwrite=True to replace."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
_validate_format(to_format)
|
|
109
|
+
from_fmt = _infer_format(source)
|
|
110
|
+
|
|
111
|
+
raw = source.read_text(encoding="utf-8")
|
|
112
|
+
data = _parse(raw, from_fmt)
|
|
113
|
+
output = export_dict(data, to_format=to_format)
|
|
114
|
+
|
|
115
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
116
|
+
target.write_text(output, encoding="utf-8")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def export_string(
|
|
120
|
+
raw: str,
|
|
121
|
+
*,
|
|
122
|
+
from_format: Format,
|
|
123
|
+
to_format: Format,
|
|
124
|
+
) -> str:
|
|
125
|
+
"""Parse *raw* as *from_format*, sanitize all values, return as *to_format*.
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
raw:
|
|
130
|
+
The raw config string to sanitize.
|
|
131
|
+
from_format:
|
|
132
|
+
Format of *raw* — one of ``"env"``, ``"ini"``, ``"json"``, ``"yaml"``.
|
|
133
|
+
to_format:
|
|
134
|
+
Desired output format — one of ``"env"``, ``"ini"``, ``"json"``, ``"yaml"``.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
str
|
|
139
|
+
Sanitized config string in *to_format*.
|
|
140
|
+
"""
|
|
141
|
+
_validate_format(from_format)
|
|
142
|
+
_validate_format(to_format)
|
|
143
|
+
data = _parse(raw, from_format)
|
|
144
|
+
return export_dict(data, to_format=to_format)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def export_dict(data: ConfigDict, *, to_format: Format) -> str:
|
|
148
|
+
"""Sanitize *data* and serialize to *to_format*.
|
|
149
|
+
|
|
150
|
+
All values — at every nesting level — are replaced with YOUR_VALUE_HERE.
|
|
151
|
+
Keys and structure are preserved exactly.
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
data:
|
|
156
|
+
A config dict, as returned by the loader.
|
|
157
|
+
to_format:
|
|
158
|
+
Output format — one of ``"env"``, ``"ini"``, ``"json"``, ``"yaml"``.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
str
|
|
163
|
+
The sanitized, serialized config string.
|
|
164
|
+
|
|
165
|
+
Raises
|
|
166
|
+
------
|
|
167
|
+
ValueError
|
|
168
|
+
If *to_format* is not supported.
|
|
169
|
+
"""
|
|
170
|
+
_validate_format(to_format)
|
|
171
|
+
if to_format == "env":
|
|
172
|
+
return _export_as_env(data)
|
|
173
|
+
if to_format == "ini":
|
|
174
|
+
return _export_as_ini(data)
|
|
175
|
+
if to_format == "json":
|
|
176
|
+
return _export_as_json(data)
|
|
177
|
+
if to_format == "yaml":
|
|
178
|
+
return _export_as_yaml(data)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# ---------------------------------------------------------------------------
|
|
182
|
+
# Format serializers
|
|
183
|
+
# ---------------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
def _export_as_env(data: ConfigDict) -> str:
|
|
186
|
+
lines: list[str] = []
|
|
187
|
+
|
|
188
|
+
def _add(key: str) -> None:
|
|
189
|
+
lines.append(f"{key}={PLACEHOLDER}")
|
|
190
|
+
|
|
191
|
+
for k, v in data.items():
|
|
192
|
+
if isinstance(v, dict):
|
|
193
|
+
lines.append(f"\n# [{k}]")
|
|
194
|
+
for nested_k in v:
|
|
195
|
+
_add(f"{k.upper()}__{nested_k.upper()}")
|
|
196
|
+
else:
|
|
197
|
+
_add(k)
|
|
198
|
+
|
|
199
|
+
return "\n".join(lines) + "\n"
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _export_as_ini(data: ConfigDict) -> str:
|
|
203
|
+
lines: list[str] = []
|
|
204
|
+
|
|
205
|
+
for k, v in data.items():
|
|
206
|
+
if isinstance(v, dict):
|
|
207
|
+
lines.append(f"[{k}]")
|
|
208
|
+
for nested_k in v:
|
|
209
|
+
lines.append(f"{nested_k} = {PLACEHOLDER}")
|
|
210
|
+
lines.append("")
|
|
211
|
+
else:
|
|
212
|
+
lines.append(f"{k} = {PLACEHOLDER}")
|
|
213
|
+
|
|
214
|
+
return "\n".join(lines).rstrip() + "\n"
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _export_as_json(data: ConfigDict) -> str:
|
|
218
|
+
return json.dumps(_sanitize_dict(data), indent=2) + "\n"
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _export_as_yaml(data: ConfigDict) -> str:
|
|
222
|
+
if not _YAML_AVAILABLE:
|
|
223
|
+
raise ValueError("PyYAML is required for YAML export. pip install pyyaml")
|
|
224
|
+
header = "# generated by infrakit exporter — safe to share\n"
|
|
225
|
+
return header + yaml.dump(
|
|
226
|
+
_sanitize_dict(data),
|
|
227
|
+
default_flow_style=False,
|
|
228
|
+
allow_unicode=True,
|
|
229
|
+
sort_keys=False,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _sanitize_dict(data: ConfigDict) -> ConfigDict:
|
|
234
|
+
"""Recursively replace every leaf value with PLACEHOLDER."""
|
|
235
|
+
result: ConfigDict = {}
|
|
236
|
+
for k, v in data.items():
|
|
237
|
+
if isinstance(v, dict):
|
|
238
|
+
result[k] = _sanitize_dict(v)
|
|
239
|
+
else:
|
|
240
|
+
result[k] = PLACEHOLDER
|
|
241
|
+
return result
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# ---------------------------------------------------------------------------
|
|
245
|
+
# Internal helpers
|
|
246
|
+
# ---------------------------------------------------------------------------
|
|
247
|
+
|
|
248
|
+
def _validate_format(fmt: Format) -> None:
|
|
249
|
+
if fmt not in SUPPORTED_FORMATS:
|
|
250
|
+
raise ValueError(
|
|
251
|
+
f"Unsupported format '{fmt}'. "
|
|
252
|
+
f"Choose one of: {', '.join(sorted(SUPPORTED_FORMATS))}"
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _infer_format(path: Path) -> Format:
|
|
257
|
+
"""Infer format from file extension, handling dotfiles like .env."""
|
|
258
|
+
suffix = path.suffix.lower()
|
|
259
|
+
if not suffix:
|
|
260
|
+
name = path.name.lower()
|
|
261
|
+
if name.startswith(".") and "." not in name[1:]:
|
|
262
|
+
suffix = name
|
|
263
|
+
fmt = _EXT_TO_FORMAT.get(suffix)
|
|
264
|
+
if fmt is None:
|
|
265
|
+
raise ValueError(
|
|
266
|
+
f"Cannot infer format from '{path.name}'. "
|
|
267
|
+
f"Supported extensions: {', '.join(sorted(_EXT_TO_FORMAT))}"
|
|
268
|
+
)
|
|
269
|
+
return fmt
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _parse(raw: str, fmt: Format) -> ConfigDict:
|
|
273
|
+
if fmt == "json":
|
|
274
|
+
data = json.loads(raw)
|
|
275
|
+
return data if isinstance(data, dict) else {}
|
|
276
|
+
if fmt == "yaml":
|
|
277
|
+
if not _YAML_AVAILABLE:
|
|
278
|
+
raise ValueError("PyYAML required. pip install pyyaml")
|
|
279
|
+
return yaml.safe_load(raw) or {}
|
|
280
|
+
if fmt == "ini":
|
|
281
|
+
parser = ConfigParser()
|
|
282
|
+
parser.read_string(raw)
|
|
283
|
+
result: ConfigDict = {}
|
|
284
|
+
if parser.defaults():
|
|
285
|
+
result["DEFAULT"] = dict(parser.defaults())
|
|
286
|
+
for section in parser.sections():
|
|
287
|
+
result[section] = {
|
|
288
|
+
k: parser.get(section, k)
|
|
289
|
+
for k in parser.options(section)
|
|
290
|
+
if k not in parser.defaults()
|
|
291
|
+
}
|
|
292
|
+
return result
|
|
293
|
+
if fmt == "env":
|
|
294
|
+
result = {}
|
|
295
|
+
for line in raw.splitlines():
|
|
296
|
+
line = line.strip()
|
|
297
|
+
if not line or line.startswith("#"):
|
|
298
|
+
continue
|
|
299
|
+
if "=" not in line:
|
|
300
|
+
continue
|
|
301
|
+
key, _, value = line.partition("=")
|
|
302
|
+
result[key.strip()] = value.strip().strip('"').strip("'")
|
|
303
|
+
return result
|
|
304
|
+
raise ValueError(f"Unknown format '{fmt}'")
|