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.
Files changed (51) hide show
  1. infrakit/__init__.py +0 -0
  2. infrakit/cli/__init__.py +1 -0
  3. infrakit/cli/commands/__init__.py +1 -0
  4. infrakit/cli/commands/deps.py +530 -0
  5. infrakit/cli/commands/init.py +129 -0
  6. infrakit/cli/commands/llm.py +295 -0
  7. infrakit/cli/commands/logger.py +160 -0
  8. infrakit/cli/commands/module.py +342 -0
  9. infrakit/cli/commands/time.py +81 -0
  10. infrakit/cli/main.py +65 -0
  11. infrakit/core/__init__.py +0 -0
  12. infrakit/core/config/__init__.py +0 -0
  13. infrakit/core/config/converter.py +480 -0
  14. infrakit/core/config/exporter.py +304 -0
  15. infrakit/core/config/loader.py +713 -0
  16. infrakit/core/config/validator.py +389 -0
  17. infrakit/core/logger/__init__.py +21 -0
  18. infrakit/core/logger/formatters.py +143 -0
  19. infrakit/core/logger/handlers.py +322 -0
  20. infrakit/core/logger/retention.py +176 -0
  21. infrakit/core/logger/setup.py +314 -0
  22. infrakit/deps/__init__.py +239 -0
  23. infrakit/deps/clean.py +141 -0
  24. infrakit/deps/depfile.py +405 -0
  25. infrakit/deps/health.py +357 -0
  26. infrakit/deps/optimizer.py +642 -0
  27. infrakit/deps/scanner.py +550 -0
  28. infrakit/llm/__init__.py +35 -0
  29. infrakit/llm/batch.py +165 -0
  30. infrakit/llm/client.py +575 -0
  31. infrakit/llm/key_manager.py +728 -0
  32. infrakit/llm/llm_readme.md +306 -0
  33. infrakit/llm/models.py +148 -0
  34. infrakit/llm/providers/__init__.py +5 -0
  35. infrakit/llm/providers/base.py +112 -0
  36. infrakit/llm/providers/gemini.py +164 -0
  37. infrakit/llm/providers/openai.py +168 -0
  38. infrakit/llm/rate_limiter.py +54 -0
  39. infrakit/scaffolder/__init__.py +31 -0
  40. infrakit/scaffolder/ai.py +508 -0
  41. infrakit/scaffolder/backend.py +555 -0
  42. infrakit/scaffolder/cli_tool.py +386 -0
  43. infrakit/scaffolder/generator.py +338 -0
  44. infrakit/scaffolder/pipeline.py +562 -0
  45. infrakit/scaffolder/registry.py +121 -0
  46. infrakit/time/__init__.py +60 -0
  47. infrakit/time/profiler.py +511 -0
  48. python_infrakit_dev-0.1.0.dist-info/METADATA +124 -0
  49. python_infrakit_dev-0.1.0.dist-info/RECORD +51 -0
  50. python_infrakit_dev-0.1.0.dist-info/WHEEL +4 -0
  51. python_infrakit_dev-0.1.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,338 @@
1
+ """
2
+ infrakit.scaffolder.generator
3
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
+ Core scaffolding logic for the ``basic`` project template.
5
+
6
+ Idempotent — any file or directory that already exists is left untouched.
7
+ Every action (created / skipped) is reported back to the caller via
8
+ ``ScaffoldResult`` so the CLI can render it however it likes.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass, field
14
+ from pathlib import Path
15
+ from typing import Literal
16
+
17
+ # ── types ─────────────────────────────────────────────────────────────────────
18
+
19
+ Status = Literal["created", "skipped"]
20
+
21
+
22
+ @dataclass
23
+ class ScaffoldEntry:
24
+ path: Path
25
+ status: Status
26
+ kind: Literal["file", "dir"]
27
+
28
+
29
+ @dataclass
30
+ class ScaffoldResult:
31
+ project_dir: Path
32
+ entries: list[ScaffoldEntry] = field(default_factory=list)
33
+
34
+ # convenience views
35
+ @property
36
+ def created(self) -> list[ScaffoldEntry]:
37
+ return [e for e in self.entries if e.status == "created"]
38
+
39
+ @property
40
+ def skipped(self) -> list[ScaffoldEntry]:
41
+ return [e for e in self.entries if e.status == "skipped"]
42
+
43
+
44
+ # ── helpers ───────────────────────────────────────────────────────────────────
45
+
46
+
47
+ def _write(result: ScaffoldResult, path: Path, content: str) -> None:
48
+ """Write a file only if it doesn't exist yet; record the outcome."""
49
+ if path.exists():
50
+ result.entries.append(ScaffoldEntry(path=path, status="skipped", kind="file"))
51
+ return
52
+ path.parent.mkdir(parents=True, exist_ok=True)
53
+ path.write_text(content, encoding="utf-8")
54
+ result.entries.append(ScaffoldEntry(path=path, status="created", kind="file"))
55
+
56
+
57
+ def _mkdir(result: ScaffoldResult, path: Path) -> None:
58
+ """Create a directory only if it doesn't exist yet; record the outcome."""
59
+ if path.exists():
60
+ result.entries.append(ScaffoldEntry(path=path, status="skipped", kind="dir"))
61
+ return
62
+ path.mkdir(parents=True, exist_ok=True)
63
+ result.entries.append(ScaffoldEntry(path=path, status="created", kind="dir"))
64
+
65
+
66
+ # ── template content ──────────────────────────────────────────────────────────
67
+
68
+ def _pyproject_toml(
69
+ project_name: str,
70
+ version: str,
71
+ description: str,
72
+ author: str,
73
+ ) -> str:
74
+ author_line = f' "{author}",' if author else ' # "Your Name <you@example.com>",'
75
+ return f"""\
76
+ [project]
77
+ name = "{project_name}"
78
+ version = "{version}"
79
+ description = "{description}"
80
+ readme = "README.md"
81
+ requires-python = ">=3.10"
82
+ authors = [
83
+ {author_line}
84
+ ]
85
+
86
+ dependencies = [
87
+ "infrakit",
88
+ ]
89
+
90
+ [project.optional-dependencies]
91
+ dev = [
92
+ "pytest",
93
+ "pytest-cov",
94
+ ]
95
+ """
96
+
97
+
98
+ def _requirements_txt(project_name: str) -> str:
99
+ return f"""\
100
+ # requirements.txt — {project_name}
101
+ # Add your dependencies below.
102
+ infrakit
103
+ """
104
+
105
+
106
+ def _env_config() -> str:
107
+ return """\
108
+ # Application configuration
109
+ # Copy this file to .env and fill in the values.
110
+ APP_ENV=development
111
+ APP_DEBUG=false
112
+ APP_SECRET=YOUR_VALUE_HERE
113
+ """
114
+
115
+
116
+ def _yaml_config() -> str:
117
+ return """\
118
+ # Application configuration
119
+ app:
120
+ env: development
121
+ debug: false
122
+ secret: YOUR_VALUE_HERE
123
+ """
124
+
125
+
126
+ def _json_config() -> str:
127
+ return """\
128
+ {
129
+ "app": {
130
+ "env": "development",
131
+ "debug": false,
132
+ "secret": "YOUR_VALUE_HERE"
133
+ }
134
+ }
135
+ """
136
+
137
+
138
+ def _config_content(fmt: str) -> tuple[str, str]:
139
+ """Return (filename, content) for the chosen config format."""
140
+ if fmt == "yaml":
141
+ return "config.yaml", _yaml_config()
142
+ if fmt == "json":
143
+ return "config.json", _json_config()
144
+ return ".env", _env_config() # default
145
+
146
+
147
+ def _logger_util() -> str:
148
+ return """\
149
+ \"\"\"
150
+ utils.logger
151
+ ~~~~~~~~~~~~
152
+ Thin wrapper that boots the infrakit logger once and exports ``get_logger``.
153
+
154
+ Usage
155
+ -----
156
+ from utils.logger import get_logger
157
+
158
+ log = get_logger(__name__)
159
+ log.info("hello")
160
+ \"\"\"
161
+
162
+ import os
163
+ from infrakit.core.logger import setup, get_logger # re-export get_logger
164
+
165
+ _booted = False
166
+
167
+
168
+ def _boot() -> None:
169
+ global _booted
170
+ if _booted:
171
+ return
172
+ setup(
173
+ log_dir=os.getenv("LOG_DIR", "logs"),
174
+ strategy=os.getenv("LOG_STRATEGY", "date"),
175
+ stream=os.getenv("LOG_STREAM", "stdout"),
176
+ fmt=os.getenv("LOG_FORMAT", "human"),
177
+ level=os.getenv("LOG_LEVEL", "DEBUG"),
178
+ )
179
+ _booted = True
180
+
181
+
182
+ _boot()
183
+
184
+ __all__ = ["get_logger"]
185
+ """
186
+
187
+
188
+ def _readme(project_name: str, description: str) -> str:
189
+ title = project_name.replace("-", " ").replace("_", " ").title()
190
+ desc_line = f"\n{description}\n" if description else ""
191
+ return f"""\
192
+ # {title}
193
+ {desc_line}
194
+ ## Setup
195
+
196
+ ```bash
197
+ pip install -e .
198
+ ```
199
+
200
+ ## Usage
201
+
202
+ ```python
203
+ from utils.logger import get_logger
204
+
205
+ log = get_logger(__name__)
206
+ log.info("hello")
207
+ ```
208
+
209
+ ## Development
210
+
211
+ ```bash
212
+ pip install -e ".[dev]"
213
+ pytest
214
+ ```
215
+ """
216
+
217
+
218
+ def _gitignore() -> str:
219
+ return """\
220
+ # Python
221
+ __pycache__/
222
+ *.py[cod]
223
+ *.pyo
224
+ *.pyd
225
+ .Python
226
+ *.egg-info/
227
+ dist/
228
+ build/
229
+ .eggs/
230
+
231
+ # Virtual envs
232
+ .venv/
233
+ venv/
234
+ env/
235
+
236
+ # Logs
237
+ logs/
238
+ *.log
239
+
240
+ # Env files
241
+ .env
242
+ .env.*.local
243
+
244
+ # IDE
245
+ .vscode/
246
+ .idea/
247
+ *.swp
248
+
249
+ # Testing
250
+ .pytest_cache/
251
+ .coverage
252
+ htmlcov/
253
+
254
+ # uv
255
+ uv.lock
256
+ """
257
+
258
+
259
+ def _src_init(version: str) -> str:
260
+ return f'__version__ = "{version}"\n'
261
+
262
+
263
+ def _tests_init() -> str:
264
+ return '"""Test suite."""\n'
265
+
266
+
267
+ # ── public API ────────────────────────────────────────────────────────────────
268
+
269
+ def scaffold_basic(
270
+ project_dir: Path,
271
+ *,
272
+ version: str = "0.1.0",
273
+ description: str = "",
274
+ author: str = "",
275
+ config_fmt: str = "env",
276
+ deps: str = "toml",
277
+ include_llm: bool = False,
278
+ ) -> ScaffoldResult:
279
+ """
280
+ Scaffold a basic project layout under ``project_dir``.
281
+
282
+ Parameters
283
+ ----------
284
+ project_dir:
285
+ Root directory for the project (will be created if absent).
286
+ version:
287
+ Starting version string, e.g. ``"0.1.0"``.
288
+ description:
289
+ Short project description used in pyproject.toml / README.
290
+ author:
291
+ Author string, e.g. ``"Jane Doe <jane@example.com>"``.
292
+ config_fmt:
293
+ Config file format — ``"env"`` (default), ``"yaml"``, or ``"json"``.
294
+ deps:
295
+ Dependency file style — ``"toml"`` (default) or ``"requirements"``.
296
+ """
297
+ result = ScaffoldResult(project_dir=project_dir)
298
+ project_name = project_dir.name
299
+
300
+ # ── directories ───────────────────────────────────────────────────────────
301
+ _mkdir(result, project_dir)
302
+ _mkdir(result, project_dir / "src")
303
+ _mkdir(result, project_dir / "utils")
304
+ _mkdir(result, project_dir / "tests")
305
+ _mkdir(result, project_dir / "logs")
306
+
307
+ # ── src ───────────────────────────────────────────────────────────────────
308
+ _write(result, project_dir / "src" / "__init__.py", _src_init(version))
309
+
310
+ # ── utils ─────────────────────────────────────────────────────────────────
311
+ _write(result, project_dir / "utils" / "__init__.py", '"""Shared utilities."""\n')
312
+ _write(result, project_dir / "utils" / "logger.py", _logger_util())
313
+ if include_llm:
314
+ from infrakit.scaffolder.ai import _llm_util, _keys_json_template
315
+ _write(result, project_dir / "utils" / "llm.py", _llm_util(project_name))
316
+ _write(result, project_dir / "keys.json", _keys_json_template())
317
+ # ── tests ─────────────────────────────────────────────────────────────────
318
+ _write(result, project_dir / "tests" / "__init__.py", _tests_init())
319
+
320
+ # ── config file ───────────────────────────────────────────────────────────
321
+ cfg_name, cfg_content = _config_content(config_fmt)
322
+ _write(result, project_dir / cfg_name, cfg_content)
323
+
324
+ # ── dependency file ───────────────────────────────────────────────────────
325
+ if deps == "requirements":
326
+ _write(result, project_dir / "requirements.txt", _requirements_txt(project_name))
327
+ else:
328
+ _write(
329
+ result,
330
+ project_dir / "pyproject.toml",
331
+ _pyproject_toml(project_name, version, description, author),
332
+ )
333
+
334
+ # ── repo files ────────────────────────────────────────────────────────────
335
+ _write(result, project_dir / "README.md", _readme(project_name, description))
336
+ _write(result, project_dir / ".gitignore", _gitignore())
337
+
338
+ return result