shipit-cli 0.4.1__py3-none-any.whl → 0.5.1__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.
- shipit/cli.py +12 -6
- shipit/providers/python.py +70 -14
- shipit/version.py +2 -2
- {shipit_cli-0.4.1.dist-info → shipit_cli-0.5.1.dist-info}/METADATA +1 -1
- {shipit_cli-0.4.1.dist-info → shipit_cli-0.5.1.dist-info}/RECORD +7 -7
- {shipit_cli-0.4.1.dist-info → shipit_cli-0.5.1.dist-info}/WHEEL +0 -0
- {shipit_cli-0.4.1.dist-info → shipit_cli-0.5.1.dist-info}/entry_points.txt +0 -0
shipit/cli.py
CHANGED
|
@@ -499,12 +499,18 @@ class LocalBuilder:
|
|
|
499
499
|
ignore_matches = step.ignore if step.ignore else []
|
|
500
500
|
ignore_matches.append(".shipit")
|
|
501
501
|
ignore_matches.append("Shipit")
|
|
502
|
-
|
|
503
|
-
(
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
502
|
+
if (self.src_dir / step.source).is_dir():
|
|
503
|
+
copytree(
|
|
504
|
+
(self.src_dir / step.source),
|
|
505
|
+
(build_path / step.target),
|
|
506
|
+
dirs_exist_ok=True,
|
|
507
|
+
ignore=ignore_patterns(*ignore_matches),
|
|
508
|
+
)
|
|
509
|
+
else:
|
|
510
|
+
copy(
|
|
511
|
+
(self.src_dir / step.source),
|
|
512
|
+
(build_path / step.target),
|
|
513
|
+
)
|
|
508
514
|
elif isinstance(step, EnvStep):
|
|
509
515
|
print(f"Setting environment variables: {step}")
|
|
510
516
|
env.update(step.variables)
|
shipit/providers/python.py
CHANGED
|
@@ -16,9 +16,11 @@ from .base import (
|
|
|
16
16
|
|
|
17
17
|
class PythonFramework(Enum):
|
|
18
18
|
Django = "django"
|
|
19
|
+
Streamlit = "streamlit"
|
|
19
20
|
FastAPI = "fastapi"
|
|
20
21
|
Flask = "flask"
|
|
21
22
|
FastHTML = "python-fasthtml"
|
|
23
|
+
MCP = "mcp"
|
|
22
24
|
|
|
23
25
|
|
|
24
26
|
class PythonServer(Enum):
|
|
@@ -58,7 +60,9 @@ class PythonProvider:
|
|
|
58
60
|
"psycopg2-binary"}
|
|
59
61
|
mysql_deps = {"mysqlclient", "pymysql", "mysql-connector-python", "aiomysql"}
|
|
60
62
|
found_deps = self.check_deps(
|
|
63
|
+
"streamlit",
|
|
61
64
|
"django",
|
|
65
|
+
"mcp",
|
|
62
66
|
"fastapi",
|
|
63
67
|
"flask",
|
|
64
68
|
"python-fasthtml",
|
|
@@ -105,6 +109,11 @@ class PythonProvider:
|
|
|
105
109
|
# gunicorn can't run with Wasmer atm
|
|
106
110
|
self.extra_dependencies = {"uvicorn"}
|
|
107
111
|
self.server = PythonServer.Uvicorn
|
|
112
|
+
elif "streamlit" in found_deps:
|
|
113
|
+
framework = PythonFramework.Streamlit
|
|
114
|
+
elif "mcp" in found_deps:
|
|
115
|
+
framework = PythonFramework.MCP
|
|
116
|
+
self.extra_dependencies = {"mcp[cli]"}
|
|
108
117
|
elif "fastapi" in found_deps:
|
|
109
118
|
framework = PythonFramework.FastAPI
|
|
110
119
|
if not self.server:
|
|
@@ -112,10 +121,9 @@ class PythonProvider:
|
|
|
112
121
|
self.server = PythonServer.Uvicorn
|
|
113
122
|
elif "flask" in found_deps:
|
|
114
123
|
framework = PythonFramework.Flask
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
framework = PythonFramework.Flask
|
|
124
|
+
if not self.server:
|
|
125
|
+
self.extra_dependencies = {"uvicorn"}
|
|
126
|
+
self.server = PythonServer.Uvicorn
|
|
119
127
|
elif "python-fasthtml" in found_deps:
|
|
120
128
|
framework = PythonFramework.FastHTML
|
|
121
129
|
else:
|
|
@@ -200,6 +208,7 @@ class PythonProvider:
|
|
|
200
208
|
"workdir(app[\"build\"])"
|
|
201
209
|
]
|
|
202
210
|
|
|
211
|
+
extra_deps = ", ".join([f"{dep}" for dep in self.extra_dependencies])
|
|
203
212
|
if _exists(self.path, "pyproject.toml"):
|
|
204
213
|
input_files = ["pyproject.toml"]
|
|
205
214
|
extra_args = ""
|
|
@@ -207,23 +216,22 @@ class PythonProvider:
|
|
|
207
216
|
input_files.append("uv.lock")
|
|
208
217
|
extra_args = " --locked"
|
|
209
218
|
inputs = ", ".join([f"\"{input}\"" for input in input_files])
|
|
210
|
-
|
|
211
|
-
steps += list(filter(None, [
|
|
219
|
+
steps += [
|
|
212
220
|
"env(UV_PROJECT_ENVIRONMENT=local_venv[\"build\"] if cross_platform else venv[\"build\"])",
|
|
213
|
-
"run(f\"uv sync --compile --python python{python_version} --no-managed-python
|
|
221
|
+
f"run(f\"uv sync --compile --python python{{python_version}} --no-managed-python{extra_args}\", inputs=[{inputs}], group=\"install\")",
|
|
214
222
|
"copy(\"pyproject.toml\", \"pyproject.toml\")",
|
|
215
223
|
f"run(\"uv add {extra_deps}\", group=\"install\")" if extra_deps else None,
|
|
216
224
|
"run(f\"uv pip compile pyproject.toml --python-version={python_version} --universal --extra-index-url {python_extra_index_url} --index-url=https://pypi.org/simple --emit-index-url --only-binary :all: -o cross-requirements.txt\", outputs=[\"cross-requirements.txt\"]) if cross_platform else None",
|
|
217
225
|
f"run(f\"uvx pip install -r cross-requirements.txt {extra_deps} --target {{python_cross_packages_path}} --platform {{cross_platform}} --only-binary=:all: --python-version={{python_version}} --compile\") if cross_platform else None",
|
|
218
226
|
"run(\"rm cross-requirements.txt\") if cross_platform else None",
|
|
219
|
-
]
|
|
227
|
+
]
|
|
220
228
|
if _exists(self.path, "requirements.txt"):
|
|
221
229
|
steps += [
|
|
222
230
|
"env(UV_PROJECT_ENVIRONMENT=local_venv[\"build\"] if cross_platform else venv[\"build\"])",
|
|
223
|
-
"run(f\"uv init --no-managed-python --python python{python_version}\", inputs=[], outputs=[\"uv.lock\"], group=\"install\")",
|
|
224
|
-
"run(
|
|
231
|
+
"run(f\"uv init --no-workspace --no-managed-python --python python{python_version}\", inputs=[], outputs=[\"uv.lock\"], group=\"install\")",
|
|
232
|
+
f"run(\"uv add -r requirements.txt {extra_deps}\", inputs=[\"requirements.txt\"], group=\"install\")",
|
|
225
233
|
"run(f\"uv pip compile requirements.txt --python-version={python_version} --universal --extra-index-url {python_extra_index_url} --index-url=https://pypi.org/simple --emit-index-url --only-binary :all: -o cross-requirements.txt\", inputs=[\"requirements.txt\"], outputs=[\"cross-requirements.txt\"]) if cross_platform else None",
|
|
226
|
-
"run(f\"uvx pip install -r cross-requirements.txt --target {python_cross_packages_path} --platform {cross_platform} --only-binary=:all: --python-version={python_version} --compile\") if cross_platform else None",
|
|
234
|
+
f"run(f\"uvx pip install -r cross-requirements.txt {extra_deps} --target {{python_cross_packages_path}} --platform {{cross_platform}} --only-binary=:all: --python-version={{python_version}} --compile\") if cross_platform else None",
|
|
227
235
|
"run(\"rm cross-requirements.txt\") if cross_platform else None",
|
|
228
236
|
]
|
|
229
237
|
|
|
@@ -231,7 +239,12 @@ class PythonProvider:
|
|
|
231
239
|
"path((local_venv[\"build\"] if cross_platform else venv[\"build\"]) + \"/bin\")",
|
|
232
240
|
"copy(\".\", \".\", ignore=[\".venv\", \".git\", \"__pycache__\"])",
|
|
233
241
|
]
|
|
234
|
-
|
|
242
|
+
if self.framework == PythonFramework.MCP:
|
|
243
|
+
steps += [
|
|
244
|
+
"run(\"mkdir -p {}/bin\".format(venv[\"build\"])) if cross_platform else None",
|
|
245
|
+
"run(\"cp {}/bin/mcp {}/bin/mcp\".format(local_venv[\"build\"], venv[\"build\"])) if cross_platform else None",
|
|
246
|
+
]
|
|
247
|
+
return list(filter(None, steps))
|
|
235
248
|
|
|
236
249
|
def prepare_steps(self) -> Optional[list[str]]:
|
|
237
250
|
return [
|
|
@@ -274,6 +287,42 @@ class PythonProvider:
|
|
|
274
287
|
else:
|
|
275
288
|
start_cmd = '"python -c \'print(\\\"No start command detected, please provide a start command manually\\\")\'"'
|
|
276
289
|
return {"start": start_cmd}
|
|
290
|
+
elif self.framework == PythonFramework.Streamlit:
|
|
291
|
+
if _exists(self.path, "main.py"):
|
|
292
|
+
path = "main.py"
|
|
293
|
+
elif _exists(self.path, "src/main.py"):
|
|
294
|
+
path = "src/main.py"
|
|
295
|
+
if _exists(self.path, "app.py"):
|
|
296
|
+
path = "app.py"
|
|
297
|
+
elif _exists(self.path, "src/app.py"):
|
|
298
|
+
path = "src/app.py"
|
|
299
|
+
elif _exists(self.path, "src/streamlit_app.py"):
|
|
300
|
+
path = "src/streamlit_app.py"
|
|
301
|
+
elif _exists(self.path, "streamlit_app.py"):
|
|
302
|
+
path = "streamlit_app.py"
|
|
303
|
+
elif _exists(self.path, "Home.py"):
|
|
304
|
+
path = "Home.py"
|
|
305
|
+
|
|
306
|
+
start_cmd = f'"python -m streamlit run {path} --server.port 8000 --server.address 0.0.0.0 --server.headless true"'
|
|
307
|
+
elif self.framework == PythonFramework.Flask:
|
|
308
|
+
if _exists(self.path, "main.py"):
|
|
309
|
+
path = "main:app"
|
|
310
|
+
if _exists(self.path, "app.py"):
|
|
311
|
+
path = "app:app"
|
|
312
|
+
elif _exists(self.path, "src/main.py"):
|
|
313
|
+
path = "src.main:app"
|
|
314
|
+
# start_cmd = f'"python -m flask --app {path} run --debug --host 0.0.0.0 --port 8000"'
|
|
315
|
+
start_cmd = f'"python -m uvicorn {path} --interface=wsgi --host 0.0.0.0 --port 8000"'
|
|
316
|
+
elif self.framework == PythonFramework.MCP:
|
|
317
|
+
if _exists(self.path, "main.py"):
|
|
318
|
+
path = "main.py"
|
|
319
|
+
else:
|
|
320
|
+
path = next(self.path.glob( "**/main.py"))
|
|
321
|
+
if path:
|
|
322
|
+
path = path.relative_to(self.path)
|
|
323
|
+
else:
|
|
324
|
+
path = "main.py"
|
|
325
|
+
start_cmd = f'"python {{}}/bin/mcp run {path} --transport=streamable-http".format(venv[\"serve\"])'
|
|
277
326
|
elif self.framework == PythonFramework.FastHTML:
|
|
278
327
|
if _exists(self.path, "main.py"):
|
|
279
328
|
path = "main:app"
|
|
@@ -301,9 +350,16 @@ class PythonProvider:
|
|
|
301
350
|
def env(self) -> Optional[Dict[str, str]]:
|
|
302
351
|
# For Django projects, generate an empty env dict to surface the field
|
|
303
352
|
# in the Shipit file. Other Python projects omit it by default.
|
|
304
|
-
|
|
305
|
-
"PYTHONPATH": "python_serve_path"
|
|
353
|
+
env_vars = {
|
|
354
|
+
"PYTHONPATH": "python_serve_path",
|
|
355
|
+
"HOME": "app[\"serve\"]"
|
|
306
356
|
}
|
|
357
|
+
if self.framework == PythonFramework.Streamlit:
|
|
358
|
+
env_vars["STREAMLIT_SERVER_HEADLESS"] = '"true"'
|
|
359
|
+
elif self.framework == PythonFramework.MCP:
|
|
360
|
+
env_vars["FASTMCP_HOST"] = "\"0.0.0.0\""
|
|
361
|
+
env_vars["FASTMCP_PORT"] = "\"8000\""
|
|
362
|
+
return env_vars
|
|
307
363
|
|
|
308
364
|
def format_app_import(asgi_application: str) -> str:
|
|
309
365
|
# Transform "mysite.asgi.application" to "mysite.asgi:application" using regex
|
shipit/version.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
shipit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
shipit/cli.py,sha256=
|
|
2
|
+
shipit/cli.py,sha256=BdkuFvLD3MCTs0nXw3DDOIMkJ4p4eohH3v2jfgFRXeg,49849
|
|
3
3
|
shipit/generator.py,sha256=4pezEo4OzpDFSFqiFpGCpdwo72VkItS490R_f2rIz2k,5755
|
|
4
|
-
shipit/version.py,sha256=
|
|
4
|
+
shipit/version.py,sha256=hST8ZDPXWcVn83WCgIB61TSxClfCr1MtDM7hisBESS8,95
|
|
5
5
|
shipit/assets/php/php.ini,sha256=f4irndAjB4GuuouEImRkNV22Q-yw1KqR-43jAMDw730,2531
|
|
6
6
|
shipit/providers/base.py,sha256=a_5VA1tV4_QbH83yjPCTHsNR23EJT2CiKUpWA_pu_lo,2373
|
|
7
7
|
shipit/providers/gatsby.py,sha256=uwNjIJloS9JwKXqkbhihgdTTpJL4iL4bLCZ5kuzqqNs,2138
|
|
@@ -10,10 +10,10 @@ shipit/providers/laravel.py,sha256=rDpfx7RyF4sK0xxDAWefX0IiguU2xdgEXP2jJp1Jdzo,2
|
|
|
10
10
|
shipit/providers/mkdocs.py,sha256=QJFNt7QWMvYbWeo7WjOgFVKGVcdUnUmUNfFbe4c8ThM,2812
|
|
11
11
|
shipit/providers/node_static.py,sha256=K55BXkNz4QXSXR2wdg5diP6HLpmksC70ph16zox7v6Y,2309
|
|
12
12
|
shipit/providers/php.py,sha256=Hmtv47K5qtYbQ3v9SSk-_KTNlhXedStg2MxhTTOK9ac,2594
|
|
13
|
-
shipit/providers/python.py,sha256=
|
|
13
|
+
shipit/providers/python.py,sha256=HFH9cFoPvSuJbkVzU0VspFYhOB3X1_IBoi-LodxSHOg,16159
|
|
14
14
|
shipit/providers/registry.py,sha256=UisII1dr24ZxmDD8GnpTsyNwPN9W8MnAHQ1Px1iJ-OQ,661
|
|
15
15
|
shipit/providers/staticfile.py,sha256=Y4oqw6dNDU2crzcWQ5SEgnXHoDy0CXRntABwlgdf1mo,1827
|
|
16
|
-
shipit_cli-0.
|
|
17
|
-
shipit_cli-0.
|
|
18
|
-
shipit_cli-0.
|
|
19
|
-
shipit_cli-0.
|
|
16
|
+
shipit_cli-0.5.1.dist-info/METADATA,sha256=CCYO1muggGxpLHIW_oS_dod1zGJO89CXCTG0lO3vOrE,462
|
|
17
|
+
shipit_cli-0.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
18
|
+
shipit_cli-0.5.1.dist-info/entry_points.txt,sha256=7AE1NjSrHaSDfbfsRRO50KKnHFTbB0Imsccd1WynzAQ,72
|
|
19
|
+
shipit_cli-0.5.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|