workers-py 1.4.0__tar.gz → 1.5.1__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.
- {workers_py-1.4.0 → workers_py-1.5.1}/CHANGELOG.md +18 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/PKG-INFO +2 -1
- {workers_py-1.4.0 → workers_py-1.5.1}/pyproject.toml +2 -1
- {workers_py-1.4.0 → workers_py-1.5.1}/src/pywrangler/cli.py +21 -3
- {workers_py-1.4.0 → workers_py-1.5.1}/src/pywrangler/sync.py +1 -2
- workers_py-1.5.1/src/pywrangler/types.py +45 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/src/pywrangler/utils.py +2 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/tests/test_cli.py +1 -4
- workers_py-1.5.1/tests/test_types.py +61 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/uv.lock +47 -4
- {workers_py-1.4.0 → workers_py-1.5.1}/.github/workflows/commitlint.yml +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/.github/workflows/lint.yml +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/.github/workflows/release.yml +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/.github/workflows/tests.yml +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/.gitignore +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/.pre-commit-config.yaml +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/CLAUDE.md +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/CONTRIBUTING.md +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/README.md +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/src/pywrangler/__init__.py +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/src/pywrangler/__main__.py +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/src/pywrangler/metadata.py +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/tests/__init__.py +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/tests/test_py_version_detect.py +0 -0
- {workers_py-1.4.0 → workers_py-1.5.1}/workers.py +0 -0
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v1.5.1 (2025-10-13)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Fix default value for --outdir in help message
|
|
10
|
+
([#39](https://github.com/cloudflare/workers-py/pull/39),
|
|
11
|
+
[`7aded7a`](https://github.com/cloudflare/workers-py/commit/7aded7a43580fc50b6408baee0184fa814481c9b))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## v1.5.0 (2025-10-10)
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
- Implement pywrangler types to generate Python type stubs
|
|
19
|
+
([#38](https://github.com/cloudflare/workers-py/pull/38),
|
|
20
|
+
[`39b67bd`](https://github.com/cloudflare/workers-py/commit/39b67bd24ed3916de12aa9025703ed18fe4a73cd))
|
|
21
|
+
|
|
22
|
+
|
|
5
23
|
## v1.4.0 (2025-10-10)
|
|
6
24
|
|
|
7
25
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workers-py
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.1
|
|
4
4
|
Summary: A set of libraries and tools for Python Workers
|
|
5
5
|
Project-URL: Homepage, https://github.com/cloudflare/workers-py
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/cloudflare/workers-py/issues
|
|
@@ -11,6 +11,7 @@ Requires-Python: >=3.10
|
|
|
11
11
|
Requires-Dist: click<9.0.0,>=8.0.0
|
|
12
12
|
Requires-Dist: pyjson5>=1.6.0
|
|
13
13
|
Requires-Dist: pyodide-cli
|
|
14
|
+
Requires-Dist: pyodide-py
|
|
14
15
|
Requires-Dist: rich>=13.0.0
|
|
15
16
|
Provides-Extra: build
|
|
16
17
|
Requires-Dist: uv~=0.5.23; extra == 'build'
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "workers-py"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.5.1"
|
|
8
8
|
description = "A set of libraries and tools for Python Workers"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -18,6 +18,7 @@ dependencies = [
|
|
|
18
18
|
"rich>=13.0.0",
|
|
19
19
|
"pyodide-cli",
|
|
20
20
|
"pyjson5>=1.6.0",
|
|
21
|
+
"pyodide-py",
|
|
21
22
|
]
|
|
22
23
|
|
|
23
24
|
[dependency-groups]
|
|
@@ -4,13 +4,11 @@ import sys
|
|
|
4
4
|
import textwrap
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from .utils import setup_logging, write_success, WRANGLER_COMMAND
|
|
8
8
|
|
|
9
9
|
setup_logging()
|
|
10
10
|
logger = logging.getLogger("pywrangler")
|
|
11
11
|
|
|
12
|
-
WRANGLER_COMMAND = ["npx", "--yes", "wrangler"]
|
|
13
|
-
|
|
14
12
|
|
|
15
13
|
class ProxyToWranglerGroup(click.Group):
|
|
16
14
|
def get_help(self, ctx):
|
|
@@ -95,6 +93,26 @@ def app(ctx, debug=False):
|
|
|
95
93
|
logger.setLevel(logging.DEBUG)
|
|
96
94
|
|
|
97
95
|
|
|
96
|
+
@app.command("types")
|
|
97
|
+
@click.option(
|
|
98
|
+
"-o",
|
|
99
|
+
"--outdir",
|
|
100
|
+
type=click.Path(writable=True),
|
|
101
|
+
help="The output directory to write the generated types. Default: ./src",
|
|
102
|
+
)
|
|
103
|
+
@click.option(
|
|
104
|
+
"-c",
|
|
105
|
+
"--config",
|
|
106
|
+
type=click.Path(exists=True, dir_okay=False, readable=True),
|
|
107
|
+
help="Path to Wrangler configuration file",
|
|
108
|
+
)
|
|
109
|
+
def types_command(outdir=None, config=None):
|
|
110
|
+
from .types import wrangler_types
|
|
111
|
+
|
|
112
|
+
wrangler_types(outdir, config)
|
|
113
|
+
raise click.exceptions.Exit(code=0)
|
|
114
|
+
|
|
115
|
+
|
|
98
116
|
@app.command("sync")
|
|
99
117
|
@click.option("--force", is_flag=True, help="Force sync even if no changes detected")
|
|
100
118
|
def sync_command(force=False, directly_requested=True):
|
|
@@ -377,10 +377,9 @@ def _install_requirements_to_vendor(requirements: list[str]):
|
|
|
377
377
|
|
|
378
378
|
|
|
379
379
|
def _install_requirements_to_venv(requirements: list[str]):
|
|
380
|
-
# Create a requirements file for .venv-workers that includes
|
|
380
|
+
# Create a requirements file for .venv-workers that includes pyodide-py
|
|
381
381
|
relative_venv_workers_path = VENV_WORKERS_PATH.relative_to(PROJECT_ROOT)
|
|
382
382
|
requirements = requirements.copy()
|
|
383
|
-
requirements.append("webtypy")
|
|
384
383
|
requirements.append("pyodide-py")
|
|
385
384
|
|
|
386
385
|
logger.info(
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from .utils import WRANGLER_COMMAND, run_command
|
|
2
|
+
from tempfile import TemporaryDirectory
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
TSCONFIG = """
|
|
9
|
+
{
|
|
10
|
+
"compilerOptions": {
|
|
11
|
+
"target": "esnext",
|
|
12
|
+
"module": "esnext",
|
|
13
|
+
"moduleResolution": "nodenext",
|
|
14
|
+
"lib": ["esnext"]
|
|
15
|
+
},
|
|
16
|
+
"include": ["worker-configuration.d.ts"]
|
|
17
|
+
}
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
PACKAGE_JSON = """
|
|
21
|
+
{
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"typescript": "^5.3.2"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def wrangler_types(outdir_arg: str | None, config: str | None, /):
|
|
30
|
+
args = ["types"]
|
|
31
|
+
if config:
|
|
32
|
+
args += ["--config", config]
|
|
33
|
+
if outdir_arg is None:
|
|
34
|
+
outdir = Path("src")
|
|
35
|
+
else:
|
|
36
|
+
outdir = Path(outdir_arg)
|
|
37
|
+
stubs_dir = outdir / "js-stubs"
|
|
38
|
+
stubs_dir.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
with TemporaryDirectory() as tmp_str:
|
|
40
|
+
tmp = Path(tmp_str)
|
|
41
|
+
run_command(WRANGLER_COMMAND + args + [tmp / "worker-configuration.d.ts"])
|
|
42
|
+
(tmp / "tsconfig.json").write_text(TSCONFIG)
|
|
43
|
+
(tmp / "package.json").write_text(PACKAGE_JSON)
|
|
44
|
+
run_command(["npm", "-C", tmp, "install"])
|
|
45
|
+
run_command(["npx", "@pyodide/ts-to-python", tmp, stubs_dir / "__init__.pyi"])
|
|
@@ -213,10 +213,7 @@ def test_sync_command_integration(dependencies, clean_test_dir):
|
|
|
213
213
|
"site-packages directory does not exist in .venv-workers"
|
|
214
214
|
)
|
|
215
215
|
|
|
216
|
-
# Check that
|
|
217
|
-
assert is_package_installed(site_packages_path, "webtypy"), (
|
|
218
|
-
"webtypy package was not installed in .venv-workers"
|
|
219
|
-
)
|
|
216
|
+
# Check that pyodide-py is installed (should always be installed, even if no deps are specified)
|
|
220
217
|
assert is_package_installed(site_packages_path, "pyodide-py"), (
|
|
221
218
|
"pyodide-py package was not installed in .venv-workers"
|
|
222
219
|
)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from contextlib import chdir
|
|
2
|
+
from subprocess import run
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# Import the full module so we can patch constants
|
|
6
|
+
from pywrangler.types import wrangler_types
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
WRANGLER_TOML = """
|
|
10
|
+
compatibility_date = "2025-08-14"
|
|
11
|
+
|
|
12
|
+
kv_namespaces = [
|
|
13
|
+
{ binding = "FOO", id = "<YOUR_KV_NAMESPACE_ID>" }
|
|
14
|
+
]
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
PYPROJECT_TOML = """
|
|
18
|
+
[dependency-groups]
|
|
19
|
+
dev = [
|
|
20
|
+
"mypy>=1.17.1",
|
|
21
|
+
"pyodide-py",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[tool.mypy]
|
|
25
|
+
files = [
|
|
26
|
+
"src",
|
|
27
|
+
]
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
WORKER = """
|
|
31
|
+
from typing import TYPE_CHECKING
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from js import Env
|
|
34
|
+
|
|
35
|
+
class Default:
|
|
36
|
+
env: "Env"
|
|
37
|
+
async def fetch(self) -> None:
|
|
38
|
+
reveal_type(self.env.FOO) # Revealed type is "js.KVNamespace_iface"
|
|
39
|
+
bar = await self.env.FOO.get("bar")
|
|
40
|
+
reveal_type(bar) # Revealed type is "builtins.str | None"
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_types(tmp_path):
|
|
45
|
+
config_path = tmp_path / "wrangler.toml"
|
|
46
|
+
pyproject_path = tmp_path / "pyproject.toml"
|
|
47
|
+
worker_dir = tmp_path / "src/worker"
|
|
48
|
+
worker_path = worker_dir / "entry.py"
|
|
49
|
+
|
|
50
|
+
worker_dir.mkdir(parents=True)
|
|
51
|
+
worker_path.write_text(WORKER)
|
|
52
|
+
config_path.write_text(WRANGLER_TOML)
|
|
53
|
+
pyproject_path.write_text(PYPROJECT_TOML)
|
|
54
|
+
|
|
55
|
+
with chdir(tmp_path):
|
|
56
|
+
wrangler_types(None, None)
|
|
57
|
+
result = run(["uv", "run", "mypy"], capture_output=True, text=True)
|
|
58
|
+
|
|
59
|
+
assert 'Revealed type is "js.KVNamespace_iface"' in result.stdout
|
|
60
|
+
assert 'Revealed type is "builtins.str | None"' in result.stdout
|
|
61
|
+
assert "Success: no issues found" in result.stdout
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
version = 1
|
|
2
2
|
requires-python = ">=3.10"
|
|
3
3
|
resolution-markers = [
|
|
4
|
-
"python_full_version >= '3.
|
|
4
|
+
"python_full_version >= '3.13'",
|
|
5
|
+
"python_full_version == '3.12.*'",
|
|
5
6
|
"python_full_version < '3.12'",
|
|
6
7
|
]
|
|
7
8
|
|
|
@@ -54,7 +55,8 @@ name = "click"
|
|
|
54
55
|
version = "8.1.8"
|
|
55
56
|
source = { registry = "https://pypi.org/simple" }
|
|
56
57
|
resolution-markers = [
|
|
57
|
-
"python_full_version >= '3.
|
|
58
|
+
"python_full_version >= '3.13'",
|
|
59
|
+
"python_full_version == '3.12.*'",
|
|
58
60
|
]
|
|
59
61
|
dependencies = [
|
|
60
62
|
{ name = "colorama", marker = "python_full_version >= '3.12' and sys_platform == 'win32'" },
|
|
@@ -424,7 +426,8 @@ name = "pyodide-cli"
|
|
|
424
426
|
version = "0.3.0"
|
|
425
427
|
source = { registry = "https://pypi.org/simple" }
|
|
426
428
|
resolution-markers = [
|
|
427
|
-
"python_full_version >= '3.
|
|
429
|
+
"python_full_version >= '3.13'",
|
|
430
|
+
"python_full_version == '3.12.*'",
|
|
428
431
|
]
|
|
429
432
|
dependencies = [
|
|
430
433
|
{ name = "rich", marker = "python_full_version >= '3.12'" },
|
|
@@ -435,6 +438,42 @@ wheels = [
|
|
|
435
438
|
{ url = "https://files.pythonhosted.org/packages/b4/93/b9815f6f4ef30dd8490bea2a82aa664e5aa9162fa38986b35a0898522d22/pyodide_cli-0.3.0-py3-none-any.whl", hash = "sha256:9d2736e04ddb380fd7eac664e5e4ba23d2c1dd29ed38a98b6246ec529ffc834a", size = 11630 },
|
|
436
439
|
]
|
|
437
440
|
|
|
441
|
+
[[package]]
|
|
442
|
+
name = "pyodide-py"
|
|
443
|
+
version = "0.25.1"
|
|
444
|
+
source = { registry = "https://pypi.org/simple" }
|
|
445
|
+
resolution-markers = [
|
|
446
|
+
"python_full_version < '3.12'",
|
|
447
|
+
]
|
|
448
|
+
sdist = { url = "https://files.pythonhosted.org/packages/06/b5/bd547175f2f91ff9afb79d5fcd8604c8b59295ae2161985a782194f220e6/pyodide-py-0.25.1.tar.gz", hash = "sha256:844fc310585118efbc1daeb4390bb7aecdf1d9fb508c4aa9f21588842c1c8a4e", size = 43322 }
|
|
449
|
+
wheels = [
|
|
450
|
+
{ url = "https://files.pythonhosted.org/packages/1c/e6/f16847dae08ce4e1d544c66336561c38b883613e1bb6fa61491bae7a1b5c/pyodide_py-0.25.1-py3-none-any.whl", hash = "sha256:bfd93301ee0ee022e6cbcee5a3a9a28b34a2f7348ebb06186df1514be79e5499", size = 48290 },
|
|
451
|
+
]
|
|
452
|
+
|
|
453
|
+
[[package]]
|
|
454
|
+
name = "pyodide-py"
|
|
455
|
+
version = "0.27.7"
|
|
456
|
+
source = { registry = "https://pypi.org/simple" }
|
|
457
|
+
resolution-markers = [
|
|
458
|
+
"python_full_version == '3.12.*'",
|
|
459
|
+
]
|
|
460
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9d/99/d7b3c9137de5a76a63f2ef89d43c878dcb4dce8118866fb58d26290698f9/pyodide_py-0.27.7.tar.gz", hash = "sha256:afb68f8abf503f691a4ab5d2ffdbf6dd05117920508e1161e04a34737c649d36", size = 52051 }
|
|
461
|
+
wheels = [
|
|
462
|
+
{ url = "https://files.pythonhosted.org/packages/24/c5/825f73fb815a17838bef3342999247bea1100a0b2e576e5c17b2bdd68766/pyodide_py-0.27.7-py3-none-any.whl", hash = "sha256:2fa7db63a14720e548eb6174d492643424f8b5f21d43b7c9fecb6d712187fe6a", size = 57930 },
|
|
463
|
+
]
|
|
464
|
+
|
|
465
|
+
[[package]]
|
|
466
|
+
name = "pyodide-py"
|
|
467
|
+
version = "0.28.3"
|
|
468
|
+
source = { registry = "https://pypi.org/simple" }
|
|
469
|
+
resolution-markers = [
|
|
470
|
+
"python_full_version >= '3.13'",
|
|
471
|
+
]
|
|
472
|
+
sdist = { url = "https://files.pythonhosted.org/packages/2d/59/95d573e0d967af70d8823552c1efee19eb2dfbca23de9ca139516c98c5d1/pyodide_py-0.28.3.tar.gz", hash = "sha256:e521d9714eb57b163e0aadca40b85870a8ea949cb03443c0e5f3ed7d45cd3a98", size = 52898 }
|
|
473
|
+
wheels = [
|
|
474
|
+
{ url = "https://files.pythonhosted.org/packages/4a/2a/2cca0a4e52a9495f21cab634b58dc413fddf72faf5baed9d2c8741544631/pyodide_py-0.28.3-py3-none-any.whl", hash = "sha256:de6ba9db35ed1ef75b80a70cf11dafa373ad786f95f72e9dbe46ffaf8cdea23c", size = 58853 },
|
|
475
|
+
]
|
|
476
|
+
|
|
438
477
|
[[package]]
|
|
439
478
|
name = "pytest"
|
|
440
479
|
version = "8.3.5"
|
|
@@ -650,7 +689,7 @@ wheels = [
|
|
|
650
689
|
|
|
651
690
|
[[package]]
|
|
652
691
|
name = "workers-py"
|
|
653
|
-
version = "1.
|
|
692
|
+
version = "1.5.1"
|
|
654
693
|
source = { editable = "." }
|
|
655
694
|
dependencies = [
|
|
656
695
|
{ name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
|
|
@@ -658,6 +697,9 @@ dependencies = [
|
|
|
658
697
|
{ name = "pyjson5" },
|
|
659
698
|
{ name = "pyodide-cli", version = "0.2.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
|
|
660
699
|
{ name = "pyodide-cli", version = "0.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
|
|
700
|
+
{ name = "pyodide-py", version = "0.25.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
|
|
701
|
+
{ name = "pyodide-py", version = "0.27.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.12.*'" },
|
|
702
|
+
{ name = "pyodide-py", version = "0.28.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" },
|
|
661
703
|
{ name = "rich" },
|
|
662
704
|
]
|
|
663
705
|
|
|
@@ -682,6 +724,7 @@ requires-dist = [
|
|
|
682
724
|
{ name = "click", specifier = ">=8.0.0,<9.0.0" },
|
|
683
725
|
{ name = "pyjson5", specifier = ">=1.6.0" },
|
|
684
726
|
{ name = "pyodide-cli" },
|
|
727
|
+
{ name = "pyodide-py" },
|
|
685
728
|
{ name = "rich", specifier = ">=13.0.0" },
|
|
686
729
|
{ name = "uv", marker = "extra == 'build'", specifier = "~=0.5.23" },
|
|
687
730
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|