spawnio 1.0.5__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 (56) hide show
  1. spawn/__init__.py +6 -0
  2. spawn/cli/__init__.py +0 -0
  3. spawn/cli/app.py +218 -0
  4. spawn/cli/noninteractive.py +204 -0
  5. spawn/cli/prompts.py +267 -0
  6. spawn/core/__init__.py +0 -0
  7. spawn/core/exceptions.py +7 -0
  8. spawn/core/models.py +21 -0
  9. spawn/core/registry.py +152 -0
  10. spawn/generators/__init__.py +0 -0
  11. spawn/generators/custom_structure.py +508 -0
  12. spawn/generators/project_generator.py +115 -0
  13. spawn/github/__init__.py +0 -0
  14. spawn/github/exceptions.py +5 -0
  15. spawn/github/publisher.py +69 -0
  16. spawn/github/validators.py +23 -0
  17. spawn/templates/__init__.py +0 -0
  18. spawn/templates/agent/__init__.py +182 -0
  19. spawn/templates/agent/content.py +374 -0
  20. spawn/templates/automation/__init__.py +100 -0
  21. spawn/templates/automation/content.py +181 -0
  22. spawn/templates/backend_api/__init__.py +243 -0
  23. spawn/templates/backend_api/content.py +509 -0
  24. spawn/templates/base.py +58 -0
  25. spawn/templates/chatbot/__init__.py +243 -0
  26. spawn/templates/chatbot/content.py +668 -0
  27. spawn/templates/cli_application/__init__.py +211 -0
  28. spawn/templates/cli_application/content.py +512 -0
  29. spawn/templates/data_project/__init__.py +125 -0
  30. spawn/templates/data_project/analysis/__init__.py +74 -0
  31. spawn/templates/data_project/analysis/content.py +190 -0
  32. spawn/templates/data_project/dashboard/__init__.py +61 -0
  33. spawn/templates/data_project/dashboard/content.py +135 -0
  34. spawn/templates/data_project/etl/__init__.py +66 -0
  35. spawn/templates/data_project/etl/content.py +239 -0
  36. spawn/templates/data_project/ml/__init__.py +62 -0
  37. spawn/templates/data_project/ml/content.py +239 -0
  38. spawn/templates/mcp_server/__init__.py +83 -0
  39. spawn/templates/mcp_server/content.py +161 -0
  40. spawn/templates/rag/__init__.py +124 -0
  41. spawn/templates/rag/content.py +463 -0
  42. spawn/templates/shared_content.py +89 -0
  43. spawn/utils/__init__.py +0 -0
  44. spawn/utils/banner.py +41 -0
  45. spawn/utils/console.py +3 -0
  46. spawn/utils/doctor.py +594 -0
  47. spawn/utils/git.py +132 -0
  48. spawn/utils/success.py +47 -0
  49. spawn/utils/theme.py +25 -0
  50. spawn/utils/uv.py +61 -0
  51. spawn/utils/validators.py +15 -0
  52. spawnio-1.0.5.dist-info/METADATA +798 -0
  53. spawnio-1.0.5.dist-info/RECORD +56 -0
  54. spawnio-1.0.5.dist-info/WHEEL +4 -0
  55. spawnio-1.0.5.dist-info/entry_points.txt +2 -0
  56. spawnio-1.0.5.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,243 @@
1
+ from pathlib import Path
2
+
3
+ from spawn.templates.base import BaseTemplate
4
+ from spawn.templates.backend_api.content import (
5
+ # FastAPI
6
+ MAIN_CONTENT,
7
+ HEALTH_ROUTER_CONTENT,
8
+ CONFIG_CONTENT,
9
+ TEST_HEALTH_CONTENT,
10
+ ENV_EXAMPLE_CONTENT,
11
+ BACKEND_API_README_CONTENT,
12
+ BACKEND_API_AGENTS_MD_CONTENT,
13
+ INIT_CONTENT,
14
+ # Flask
15
+ FLASK_APP_INIT_CONTENT,
16
+ FLASK_CONFIG_CONTENT,
17
+ FLASK_HEALTH_CONTENT,
18
+ FLASK_RUN_CONTENT,
19
+ FLASK_TEST_HEALTH_CONTENT,
20
+ FLASK_ENV_EXAMPLE_CONTENT,
21
+ FLASK_README_CONTENT,
22
+ FLASK_AGENTS_MD_CONTENT,
23
+ # Django
24
+ DJANGO_MANAGE_CONTENT,
25
+ DJANGO_SETTINGS_CONTENT,
26
+ DJANGO_URLS_CONTENT,
27
+ DJANGO_ASGI_CONTENT,
28
+ DJANGO_WSGI_CONTENT,
29
+ DJANGO_HEALTH_VIEWS_CONTENT,
30
+ DJANGO_HEALTH_URLS_CONTENT,
31
+ DJANGO_HEALTH_TESTS_CONTENT,
32
+ DJANGO_README_CONTENT,
33
+ DJANGO_AGENTS_MD_CONTENT,
34
+ # Docker
35
+ DOCKERFILE_FASTAPI_CONTENT,
36
+ DOCKERFILE_FLASK_CONTENT,
37
+ DOCKERFILE_DJANGO_CONTENT,
38
+ DOCKERIGNORE_CONTENT,
39
+ # GitHub Actions
40
+ GITHUB_ACTIONS_CI_BASE,
41
+ GITHUB_ACTIONS_CI_RUFF_STEP,
42
+ GITHUB_ACTIONS_CI_PYTEST_STEP,
43
+ )
44
+
45
+ # ---------------------------------------------------------------------------
46
+ # Framework definitions
47
+ # ---------------------------------------------------------------------------
48
+
49
+ FASTAPI_FOLDERS = [
50
+ "app/api/routes",
51
+ "app/core",
52
+ "app/models",
53
+ "app/schemas",
54
+ "app/services",
55
+ "tests",
56
+ ]
57
+
58
+ FASTAPI_FILES = [
59
+ ("app/__init__.py", INIT_CONTENT),
60
+ ("app/api/__init__.py", INIT_CONTENT),
61
+ ("app/api/routes/__init__.py", INIT_CONTENT),
62
+ ("app/api/routes/health.py", HEALTH_ROUTER_CONTENT),
63
+ ("app/main.py", MAIN_CONTENT),
64
+ ("app/core/__init__.py", INIT_CONTENT),
65
+ ("app/core/config.py", CONFIG_CONTENT),
66
+ ("tests/__init__.py", INIT_CONTENT),
67
+ ("tests/test_health.py", TEST_HEALTH_CONTENT),
68
+ (".env.example", ENV_EXAMPLE_CONTENT),
69
+ ]
70
+
71
+ FASTAPI_DEPS = [
72
+ "fastapi",
73
+ "uvicorn[standard]",
74
+ "pydantic-settings",
75
+ ]
76
+
77
+ FLASK_FOLDERS = [
78
+ "app/routes",
79
+ "app/models",
80
+ "app/services",
81
+ "tests",
82
+ ]
83
+
84
+ FLASK_FILES = [
85
+ ("app/__init__.py", FLASK_APP_INIT_CONTENT),
86
+ ("app/routes/__init__.py", INIT_CONTENT),
87
+ ("app/routes/health.py", FLASK_HEALTH_CONTENT),
88
+ ("app/models/__init__.py", INIT_CONTENT),
89
+ ("app/services/__init__.py", INIT_CONTENT),
90
+ ("app/config.py", FLASK_CONFIG_CONTENT),
91
+ ("run.py", FLASK_RUN_CONTENT),
92
+ ("tests/__init__.py", INIT_CONTENT),
93
+ ("tests/test_health.py", FLASK_TEST_HEALTH_CONTENT),
94
+ (".env.example", FLASK_ENV_EXAMPLE_CONTENT),
95
+ ]
96
+
97
+ FLASK_DEPS = [
98
+ "flask",
99
+ "python-dotenv",
100
+ ]
101
+
102
+ DJANGO_FOLDERS = [
103
+ "config",
104
+ "apps/health",
105
+ ]
106
+
107
+ DJANGO_FILES = [
108
+ ("manage.py", DJANGO_MANAGE_CONTENT),
109
+ ("config/__init__.py", INIT_CONTENT),
110
+ ("config/settings.py", DJANGO_SETTINGS_CONTENT),
111
+ ("config/urls.py", DJANGO_URLS_CONTENT),
112
+ ("config/asgi.py", DJANGO_ASGI_CONTENT),
113
+ ("config/wsgi.py", DJANGO_WSGI_CONTENT),
114
+ ("apps/__init__.py", INIT_CONTENT),
115
+ ("apps/health/__init__.py", INIT_CONTENT),
116
+ ("apps/health/views.py", DJANGO_HEALTH_VIEWS_CONTENT),
117
+ ("apps/health/urls.py", DJANGO_HEALTH_URLS_CONTENT),
118
+ ("apps/health/tests.py", DJANGO_HEALTH_TESTS_CONTENT),
119
+ ]
120
+
121
+ DJANGO_DEPS = [
122
+ "django",
123
+ ]
124
+
125
+
126
+ class BackendAPITemplate(BaseTemplate):
127
+ def __init__(
128
+ self,
129
+ framework: str | None = None,
130
+ extras: list[str] | None = None,
131
+ ):
132
+ self.framework = framework
133
+ self.extras = extras or []
134
+
135
+ if framework == "flask":
136
+ folders = FLASK_FOLDERS
137
+ files = FLASK_FILES
138
+ elif framework == "django":
139
+ folders = DJANGO_FOLDERS
140
+ files = DJANGO_FILES
141
+ else:
142
+ # Default to fastapi for None or "fastapi"
143
+ folders = FASTAPI_FOLDERS
144
+ files = FASTAPI_FILES
145
+
146
+ super().__init__(
147
+ name="Backend API",
148
+ folders=folders,
149
+ starter_files=files,
150
+ )
151
+
152
+ if framework == "flask":
153
+ self.next_steps = [
154
+ "cd {project_name}",
155
+ "uv run python run.py",
156
+ ]
157
+ elif framework == "django":
158
+ self.next_steps = [
159
+ "cd {project_name}",
160
+ "uv run python manage.py runserver",
161
+ ]
162
+ else:
163
+ self.next_steps = [
164
+ "cd {project_name}",
165
+ "uv run uvicorn app.main:app --reload",
166
+ ]
167
+
168
+ def get_readme_content(self, context: dict) -> str | None:
169
+ if self.framework == "flask":
170
+ return FLASK_README_CONTENT.format_map(context)
171
+ if self.framework == "django":
172
+ return DJANGO_README_CONTENT.format_map(context)
173
+ return BACKEND_API_README_CONTENT.format_map(context)
174
+
175
+ def get_agents_md_content(self, context: dict) -> str | None:
176
+ if self.framework == "flask":
177
+ return FLASK_AGENTS_MD_CONTENT.format_map(context)
178
+ if self.framework == "django":
179
+ return DJANGO_AGENTS_MD_CONTENT.format_map(context)
180
+ return BACKEND_API_AGENTS_MD_CONTENT.format_map(context)
181
+
182
+ def get_dependencies(self) -> list[str]:
183
+ if self.framework == "flask":
184
+ base_deps = list(FLASK_DEPS)
185
+ elif self.framework == "django":
186
+ base_deps = list(DJANGO_DEPS)
187
+ else:
188
+ base_deps = list(FASTAPI_DEPS)
189
+
190
+ if "pytest" in self.extras:
191
+ base_deps += ["pytest", "httpx"]
192
+
193
+ if "ruff" in self.extras:
194
+ base_deps += ["ruff"]
195
+
196
+ return base_deps
197
+
198
+ def post_install(self, project_path: Path) -> None:
199
+ pyproject = project_path / "pyproject.toml"
200
+ current = pyproject.read_text(encoding="utf-8")
201
+ additions = ""
202
+
203
+ if "pytest" in self.extras:
204
+ additions += (
205
+ "\n[tool.pytest.ini_options]\n"
206
+ 'filterwarnings = [\n'
207
+ ' "ignore::DeprecationWarning:starlette",\n'
208
+ ' "ignore::DeprecationWarning:httpx",\n'
209
+ "]\n"
210
+ )
211
+
212
+ if "ruff" in self.extras:
213
+ additions += "\n[tool.ruff]\nline-length = 88\n"
214
+
215
+ if additions:
216
+ pyproject.write_text(current + additions, encoding="utf-8")
217
+
218
+ if "docker" in self.extras:
219
+ if self.framework == "flask":
220
+ dockerfile_content = DOCKERFILE_FLASK_CONTENT
221
+ elif self.framework == "django":
222
+ dockerfile_content = DOCKERFILE_DJANGO_CONTENT
223
+ else:
224
+ dockerfile_content = DOCKERFILE_FASTAPI_CONTENT
225
+
226
+ (project_path / "Dockerfile").write_text(
227
+ dockerfile_content, encoding="utf-8"
228
+ )
229
+ (project_path / ".dockerignore").write_text(
230
+ DOCKERIGNORE_CONTENT, encoding="utf-8"
231
+ )
232
+
233
+ if "github-actions" in self.extras:
234
+ workflows_path = project_path / ".github" / "workflows"
235
+ workflows_path.mkdir(parents=True, exist_ok=True)
236
+ ci_content = GITHUB_ACTIONS_CI_BASE
237
+ if "ruff" in self.extras:
238
+ ci_content += GITHUB_ACTIONS_CI_RUFF_STEP
239
+ if "pytest" in self.extras:
240
+ ci_content += GITHUB_ACTIONS_CI_PYTEST_STEP
241
+ (workflows_path / "ci.yml").write_text(
242
+ ci_content, encoding="utf-8"
243
+ )