shipit-cli 0.4.0__py3-none-any.whl → 0.5.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.
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
- copytree(
503
- (self.src_dir / step.source),
504
- (build_path / step.target),
505
- dirs_exist_ok=True,
506
- ignore=ignore_patterns(*ignore_matches),
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)
@@ -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
- elif "fastapi" in found_deps:
116
- framework = PythonFramework.FastAPI
117
- elif "flask" in found_deps:
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,22 +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
- extra_deps = ", ".join([f"{dep}" for dep in self.extra_dependencies])
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" + extra_args + "\", inputs=[" + inputs + "], group=\"install\")",
214
- f"run(\"uv add {extra_deps}\", inputs=[\"pyproject.toml\"], group=\"install\")" if extra_deps else None,
215
- "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\", inputs=[\"pyproject.toml\"], outputs=[\"cross-requirements.txt\"]) if cross_platform else None",
221
+ f"run(f\"uv sync --compile --python python{{python_version}} --no-managed-python{extra_args}\", inputs=[{inputs}], group=\"install\")",
222
+ "copy(\"pyproject.toml\", \"pyproject.toml\")",
223
+ f"run(\"uv add {extra_deps}\", group=\"install\")" if extra_deps else None,
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",
216
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",
217
226
  "run(\"rm cross-requirements.txt\") if cross_platform else None",
218
- ]))
227
+ ]
219
228
  if _exists(self.path, "requirements.txt"):
220
229
  steps += [
221
230
  "env(UV_PROJECT_ENVIRONMENT=local_venv[\"build\"] if cross_platform else venv[\"build\"])",
222
231
  "run(f\"uv init --no-managed-python --python python{python_version}\", inputs=[], outputs=[\"uv.lock\"], group=\"install\")",
223
- "run(f\"uv add -r requirements.txt\", inputs=[\"requirements.txt\"], group=\"install\")",
232
+ f"run(\"uv add -r requirements.txt {extra_deps}\", inputs=[\"requirements.txt\"], group=\"install\")",
224
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",
225
- "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",
226
235
  "run(\"rm cross-requirements.txt\") if cross_platform else None",
227
236
  ]
228
237
 
@@ -230,7 +239,12 @@ class PythonProvider:
230
239
  "path((local_venv[\"build\"] if cross_platform else venv[\"build\"]) + \"/bin\")",
231
240
  "copy(\".\", \".\", ignore=[\".venv\", \".git\", \"__pycache__\"])",
232
241
  ]
233
- return steps
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))
234
248
 
235
249
  def prepare_steps(self) -> Optional[list[str]]:
236
250
  return [
@@ -273,6 +287,42 @@ class PythonProvider:
273
287
  else:
274
288
  start_cmd = '"python -c \'print(\\\"No start command detected, please provide a start command manually\\\")\'"'
275
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\"])'
276
326
  elif self.framework == PythonFramework.FastHTML:
277
327
  if _exists(self.path, "main.py"):
278
328
  path = "main:app"
@@ -300,9 +350,16 @@ class PythonProvider:
300
350
  def env(self) -> Optional[Dict[str, str]]:
301
351
  # For Django projects, generate an empty env dict to surface the field
302
352
  # in the Shipit file. Other Python projects omit it by default.
303
- return {
304
- "PYTHONPATH": "python_serve_path"
353
+ env_vars = {
354
+ "PYTHONPATH": "python_serve_path",
355
+ "HOME": "app[\"serve\"]"
305
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
306
363
 
307
364
  def format_app_import(asgi_application: str) -> str:
308
365
  # Transform "mysite.asgi.application" to "mysite.asgi:application" using regex
shipit/version.py CHANGED
@@ -1,5 +1,5 @@
1
1
  __all__ = ["version", "version_info"]
2
2
 
3
3
 
4
- version = "0.4.0"
5
- version_info = (0, 4, 0, "final", 0)
4
+ version = "0.5.0"
5
+ version_info = (0, 5, 0, "final", 0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shipit-cli
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Add your description here
5
5
  Project-URL: homepage, https://wasmer.io
6
6
  Project-URL: repository, https://github.com/wasmerio/shipit
@@ -1,7 +1,7 @@
1
1
  shipit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- shipit/cli.py,sha256=5b5e1H-SscXBraZXxJ5cVs_IJSNqjWUt2IjcZtOdALE,49615
2
+ shipit/cli.py,sha256=BdkuFvLD3MCTs0nXw3DDOIMkJ4p4eohH3v2jfgFRXeg,49849
3
3
  shipit/generator.py,sha256=4pezEo4OzpDFSFqiFpGCpdwo72VkItS490R_f2rIz2k,5755
4
- shipit/version.py,sha256=zmMUF3ZPl6yX0INjIEDY59a3aBdXE4OLXagX09Ji9cE,95
4
+ shipit/version.py,sha256=7LADd6VkfRRaf0yUBXWBinR53BLXrVIb62KGQUoJCrE,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=KnDH7nB1Ipz_oAqXPBz7FbEo3s7kwvQOhOZSHKCpltw,13430
13
+ shipit/providers/python.py,sha256=cSixhFaK6NcdLfkDvv2J-ji_w4LBxH5xYa8-Gawbcf8,16144
14
14
  shipit/providers/registry.py,sha256=UisII1dr24ZxmDD8GnpTsyNwPN9W8MnAHQ1Px1iJ-OQ,661
15
15
  shipit/providers/staticfile.py,sha256=Y4oqw6dNDU2crzcWQ5SEgnXHoDy0CXRntABwlgdf1mo,1827
16
- shipit_cli-0.4.0.dist-info/METADATA,sha256=_B-0rn-0ASJDMFL4faoV5mTzOSpi5ge5bdJuFjio3tc,462
17
- shipit_cli-0.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
- shipit_cli-0.4.0.dist-info/entry_points.txt,sha256=7AE1NjSrHaSDfbfsRRO50KKnHFTbB0Imsccd1WynzAQ,72
19
- shipit_cli-0.4.0.dist-info/RECORD,,
16
+ shipit_cli-0.5.0.dist-info/METADATA,sha256=ze0G1vnNXqWdh3Ob_tAKnVghCPLMKbHP0qRmX2x_6XA,462
17
+ shipit_cli-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
+ shipit_cli-0.5.0.dist-info/entry_points.txt,sha256=7AE1NjSrHaSDfbfsRRO50KKnHFTbB0Imsccd1WynzAQ,72
19
+ shipit_cli-0.5.0.dist-info/RECORD,,