funcd-bundle 0.3.3__tar.gz → 0.3.4__tar.gz
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.
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/PKG-INFO +1 -1
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/pyproject.toml +1 -1
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/src/funcd_bundle/bundle.py +13 -1
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/tests/test_bundle.py +43 -0
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/.gitignore +0 -0
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/README.md +0 -0
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/src/funcd_bundle/__init__.py +0 -0
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/src/funcd_bundle/cli.py +0 -0
- {funcd_bundle-0.3.3 → funcd_bundle-0.3.4}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: funcd-bundle
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Bundle a Python funcd function and its locked dependencies for the funcd runtime
|
|
5
5
|
Project-URL: Homepage, https://github.com/pyvvo/funcd-python
|
|
6
6
|
Project-URL: Repository, https://github.com/pyvvo/funcd-python
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "funcd-bundle"
|
|
3
3
|
# Not bumped per release: the vX.Y.Z git tag is the version, stamped into the build at publish time.
|
|
4
|
-
version = "0.3.
|
|
4
|
+
version = "0.3.4"
|
|
5
5
|
description = "Bundle a Python funcd function and its locked dependencies for the funcd runtime"
|
|
6
6
|
authors = [{ name = "The funcd Authors" }]
|
|
7
7
|
readme = "README.md"
|
|
@@ -84,7 +84,10 @@ def discover(project: Path) -> dict[str, Function]:
|
|
|
84
84
|
defaults = {project.resolve().name: DEFAULT_HANDLER}
|
|
85
85
|
functions = {}
|
|
86
86
|
for name, manifest in manifests.items():
|
|
87
|
-
|
|
87
|
+
try:
|
|
88
|
+
data = yaml.safe_load(manifest.read_text()) or {}
|
|
89
|
+
except yaml.YAMLError as err:
|
|
90
|
+
raise BundleError(f"{manifest}: {err}") from err
|
|
88
91
|
if not isinstance(data, dict):
|
|
89
92
|
raise BundleError(f"{manifest} is not a mapping")
|
|
90
93
|
main = data.get("main") or defaults[name]
|
|
@@ -347,6 +350,15 @@ def _with_main(text: str, handler: str) -> str:
|
|
|
347
350
|
if text[start:end].endswith("\n"):
|
|
348
351
|
entry += "\n"
|
|
349
352
|
return text[:start] + entry + text[end:]
|
|
353
|
+
if root.flow_style:
|
|
354
|
+
# a block line after a flow mapping is a second root: the key goes inside, after its brace
|
|
355
|
+
brace = next(
|
|
356
|
+
t
|
|
357
|
+
for t in yaml.scan(text, Loader=yaml.SafeLoader)
|
|
358
|
+
if isinstance(t, yaml.FlowMappingStartToken)
|
|
359
|
+
)
|
|
360
|
+
at = brace.end_mark.index
|
|
361
|
+
return text[:at] + entry + (", " if root.value else "") + text[at:]
|
|
350
362
|
if text and not text.endswith("\n"):
|
|
351
363
|
text += "\n"
|
|
352
364
|
return text + entry + "\n"
|
|
@@ -16,6 +16,7 @@ from collections.abc import Iterator
|
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
|
|
18
18
|
import pytest
|
|
19
|
+
import yaml
|
|
19
20
|
|
|
20
21
|
from funcd_bundle import BundleError, bundle, discover, host_platform
|
|
21
22
|
from funcd_bundle.bundle import _check
|
|
@@ -302,7 +303,49 @@ def test_issue_r29_main_key_is_rewritten_not_duplicated(tmp_path: Path, main: st
|
|
|
302
303
|
)
|
|
303
304
|
|
|
304
305
|
|
|
306
|
+
@pytest.mark.parametrize(
|
|
307
|
+
("manifest", "want"),
|
|
308
|
+
[
|
|
309
|
+
("{runtime: python314, handler: handle}\n", {"runtime": "python314", "handler": "handle"}),
|
|
310
|
+
("!!map &m {\n runtime: python314,\n}\n", {"runtime": "python314"}),
|
|
311
|
+
("{}\n", {}),
|
|
312
|
+
],
|
|
313
|
+
ids=["one-line", "tagged-multi-line", "empty"],
|
|
314
|
+
)
|
|
315
|
+
def test_issue_r49_flow_mapping_manifest_gets_main(
|
|
316
|
+
tmp_path: Path, manifest: str, want: dict[str, str]
|
|
317
|
+
) -> None:
|
|
318
|
+
project = tmp_path / "reader"
|
|
319
|
+
_write(
|
|
320
|
+
project,
|
|
321
|
+
{
|
|
322
|
+
"pyproject.toml": '[project]\nname = "reader"\nversion = "0.1.0"\nrequires-python = ">=3.12"\n',
|
|
323
|
+
"funcdctl.yaml": manifest,
|
|
324
|
+
"handler.py": "def handle(ctx, event): ...\n",
|
|
325
|
+
},
|
|
326
|
+
)
|
|
327
|
+
_uv("lock", "--offline", "--python", "3.14", cwd=project)
|
|
328
|
+
out = bundle(project, "reader", host_platform(), tmp_path / "out", hermetic=False, check=False)
|
|
329
|
+
|
|
330
|
+
assert yaml.safe_load((out / "funcdctl.yaml").read_text()) == want | {"main": "handler.py"}, (
|
|
331
|
+
"the bundle's manifest is valid YAML whose main names the bundled handler"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
|
|
305
335
|
def test_missing_handler_is_named(tmp_path: Path) -> None:
|
|
306
336
|
_write(tmp_path, {"funcdctl.yaml": "runtime: python314\nmain: src/nope.py\n"})
|
|
307
337
|
with pytest.raises(BundleError, match="nope.py"):
|
|
308
338
|
bundle(tmp_path, tmp_path.name, host_platform(), tmp_path / "out", hermetic=False, check=False)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def test_issue_r48_invalid_manifest_yaml_is_reported(
|
|
342
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
|
343
|
+
) -> None:
|
|
344
|
+
_write(tmp_path, {"funcdctl.yaml": "runtime: [\n", "handler.py": ""})
|
|
345
|
+
monkeypatch.chdir(tmp_path)
|
|
346
|
+
|
|
347
|
+
assert main(["--no-check", "--out", str(tmp_path / "out")]) == 1, "a manifest that does not parse fails"
|
|
348
|
+
err = capsys.readouterr().err
|
|
349
|
+
assert err.startswith(f"funcd-bundle: {tmp_path / 'funcdctl.yaml'}: "), err
|
|
350
|
+
assert "while parsing a flow node" in err, "the parser message names the problem"
|
|
351
|
+
assert "Traceback" not in err
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|