workers-py 1.1.8__py3-none-any.whl → 1.2.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.
- pywrangler/cli.py +0 -2
- pywrangler/sync.py +112 -140
- {workers_py-1.1.8.dist-info → workers_py-1.2.1.dist-info}/METADATA +3 -3
- workers_py-1.2.1.dist-info/RECORD +9 -0
- workers_py-1.1.8.dist-info/RECORD +0 -9
- {workers_py-1.1.8.dist-info → workers_py-1.2.1.dist-info}/WHEEL +0 -0
- {workers_py-1.1.8.dist-info → workers_py-1.2.1.dist-info}/entry_points.txt +0 -0
pywrangler/cli.py
CHANGED
|
@@ -106,7 +106,6 @@ def sync_command(force=False, directly_requested=True):
|
|
|
106
106
|
create_pyodide_venv,
|
|
107
107
|
create_workers_venv,
|
|
108
108
|
parse_requirements,
|
|
109
|
-
install_pyodide_build,
|
|
110
109
|
install_requirements,
|
|
111
110
|
)
|
|
112
111
|
|
|
@@ -129,7 +128,6 @@ def sync_command(force=False, directly_requested=True):
|
|
|
129
128
|
create_workers_venv()
|
|
130
129
|
|
|
131
130
|
# Set up Pyodide virtual env
|
|
132
|
-
install_pyodide_build()
|
|
133
131
|
create_pyodide_venv()
|
|
134
132
|
|
|
135
133
|
# Generate requirements.txt from pyproject.toml by directly parsing the TOML file then install into vendor folder.
|
pywrangler/sync.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
3
|
import shutil
|
|
4
|
-
from pathlib import Path
|
|
5
4
|
import tempfile
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Literal
|
|
6
8
|
|
|
7
9
|
import click
|
|
8
10
|
|
|
@@ -58,8 +60,33 @@ def check_wrangler_config():
|
|
|
58
60
|
raise click.exceptions.Exit(code=1)
|
|
59
61
|
|
|
60
62
|
|
|
61
|
-
def _get_python_version():
|
|
62
|
-
|
|
63
|
+
def _get_python_version() -> Literal["3.12", "3.13"]:
|
|
64
|
+
res = os.environ.get("_PYWRANGLER_PYTHON_VERSION", "3.12")
|
|
65
|
+
match res:
|
|
66
|
+
case "3.12" | "3.13":
|
|
67
|
+
return res
|
|
68
|
+
case _:
|
|
69
|
+
raise ValueError(
|
|
70
|
+
f"Unexpected value for Python version '{res}', expected '3.12' or '3.13'"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _get_uv_pyodide_interp_name():
|
|
75
|
+
match _get_python_version():
|
|
76
|
+
case "3.12":
|
|
77
|
+
v = "3.12.7"
|
|
78
|
+
case "3.13":
|
|
79
|
+
v = "3.13.2"
|
|
80
|
+
return f"cpython-{v}-emscripten-wasm32-musl"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _get_pyodide_index():
|
|
84
|
+
match _get_python_version():
|
|
85
|
+
case "3.12":
|
|
86
|
+
v = "0.27.7"
|
|
87
|
+
case "3.13":
|
|
88
|
+
v = "0.28.3"
|
|
89
|
+
return "https://index.pyodide.org/" + v
|
|
63
90
|
|
|
64
91
|
|
|
65
92
|
def _get_venv_python_version() -> str | None:
|
|
@@ -125,65 +152,34 @@ def create_workers_venv():
|
|
|
125
152
|
)
|
|
126
153
|
|
|
127
154
|
|
|
128
|
-
|
|
129
|
-
venv_bin_path = VENV_WORKERS_PATH / ("Scripts" if os.name == "nt" else "bin")
|
|
130
|
-
pyodide_cli_path = venv_bin_path / ("pyodide.exe" if os.name == "nt" else "pyodide")
|
|
131
|
-
return pyodide_cli_path
|
|
155
|
+
MIN_UV_VERSION = (0, 8, 10)
|
|
132
156
|
|
|
133
157
|
|
|
134
|
-
def
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
f"pyodide-build CLI already found at {pyodide_cli_path} (skipping install.)"
|
|
140
|
-
)
|
|
158
|
+
def check_uv_version():
|
|
159
|
+
res = run_command(["uv", "--version"], capture_output=True)
|
|
160
|
+
ver_str = res.stdout.split(" ")[1]
|
|
161
|
+
ver = tuple(int(x) for x in ver_str.split("."))
|
|
162
|
+
if ver >= MIN_UV_VERSION:
|
|
141
163
|
return
|
|
142
|
-
|
|
143
|
-
logger.
|
|
144
|
-
|
|
145
|
-
)
|
|
146
|
-
venv_bin_path = pyodide_cli_path.parent
|
|
147
|
-
|
|
148
|
-
# Ensure the python executable path is correct for the venv
|
|
149
|
-
venv_python_executable = venv_bin_path / (
|
|
150
|
-
"python.exe" if os.name == "nt" else "python"
|
|
151
|
-
)
|
|
152
|
-
if not venv_python_executable.is_file():
|
|
153
|
-
logger.error(f"Python executable not found at {venv_python_executable}")
|
|
154
|
-
raise click.exceptions.Exit(code=1)
|
|
155
|
-
|
|
156
|
-
run_command(["uv", "pip", "install", "-p", str(venv_python_executable), "pip"])
|
|
157
|
-
|
|
158
|
-
run_command(
|
|
159
|
-
[
|
|
160
|
-
"uv",
|
|
161
|
-
"pip",
|
|
162
|
-
"install",
|
|
163
|
-
"-p",
|
|
164
|
-
str(venv_python_executable),
|
|
165
|
-
"pyodide-build==0.30.7",
|
|
166
|
-
]
|
|
167
|
-
)
|
|
164
|
+
min_version_str = ".".join(str(x) for x in MIN_UV_VERSION)
|
|
165
|
+
logger.error(f"uv version at least {min_version_str} required, have {ver_str}.")
|
|
166
|
+
logger.error("Update uv with `uv self update`.")
|
|
167
|
+
raise click.exceptions.Exit(code=1)
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
def create_pyodide_venv():
|
|
171
|
-
pyodide_cli_path = _get_pyodide_cli_path()
|
|
172
171
|
if PYODIDE_VENV_PATH.is_dir():
|
|
173
172
|
logger.debug(
|
|
174
173
|
f"Pyodide virtual environment at {PYODIDE_VENV_PATH} already exists."
|
|
175
174
|
)
|
|
176
175
|
return
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
#
|
|
180
|
-
# Fix is here: pyodide/pyodide-build#239
|
|
181
|
-
logger.debug("Installing xbuildenv...")
|
|
182
|
-
run_command([str(pyodide_cli_path), "xbuildenv", "install"])
|
|
183
|
-
|
|
177
|
+
check_uv_version()
|
|
184
178
|
logger.debug(f"Creating Pyodide virtual environment at {PYODIDE_VENV_PATH}...")
|
|
185
179
|
PYODIDE_VENV_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
186
|
-
|
|
180
|
+
interp_name = _get_uv_pyodide_interp_name()
|
|
181
|
+
run_command(["uv", "python", "install", interp_name])
|
|
182
|
+
run_command(["uv", "venv", PYODIDE_VENV_PATH, "--python", interp_name])
|
|
187
183
|
|
|
188
184
|
|
|
189
185
|
def parse_requirements() -> list[str]:
|
|
@@ -202,6 +198,15 @@ def parse_requirements() -> list[str]:
|
|
|
202
198
|
raise click.exceptions.Exit(code=1)
|
|
203
199
|
|
|
204
200
|
|
|
201
|
+
@contextmanager
|
|
202
|
+
def temp_requirements_file(requirements: list[str]):
|
|
203
|
+
# Write dependencies to a requirements.txt-style temp file.
|
|
204
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt") as temp_file:
|
|
205
|
+
temp_file.write("\n".join(requirements))
|
|
206
|
+
temp_file.flush()
|
|
207
|
+
yield temp_file.name
|
|
208
|
+
|
|
209
|
+
|
|
205
210
|
def _install_requirements_to_vendor(requirements: list[str]):
|
|
206
211
|
vendor_path = PROJECT_ROOT / "python_modules"
|
|
207
212
|
logger.debug(f"Using vendor path: {vendor_path}")
|
|
@@ -212,97 +217,72 @@ def _install_requirements_to_vendor(requirements: list[str]):
|
|
|
212
217
|
)
|
|
213
218
|
return
|
|
214
219
|
|
|
215
|
-
#
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
# Install packages into vendor directory
|
|
224
|
-
vendor_path.mkdir(parents=True, exist_ok=True)
|
|
225
|
-
pyodide_venv_pip_path = (
|
|
226
|
-
PYODIDE_VENV_PATH
|
|
227
|
-
/ ("Scripts" if os.name == "nt" else "bin")
|
|
228
|
-
/ ("pip.exe" if os.name == "nt" else "pip")
|
|
229
|
-
)
|
|
230
|
-
relative_vendor_path = vendor_path.relative_to(PROJECT_ROOT)
|
|
231
|
-
logger.info(
|
|
232
|
-
f"Installing packages into [bold]{relative_vendor_path}[/bold] using Pyodide pip...",
|
|
233
|
-
extra={"markup": True},
|
|
234
|
-
)
|
|
220
|
+
# Install packages into vendor directory
|
|
221
|
+
vendor_path.mkdir(parents=True, exist_ok=True)
|
|
222
|
+
relative_vendor_path = vendor_path.relative_to(PROJECT_ROOT)
|
|
223
|
+
logger.info(
|
|
224
|
+
f"Installing packages into [bold]{relative_vendor_path}[/bold]...",
|
|
225
|
+
extra={"markup": True},
|
|
226
|
+
)
|
|
227
|
+
with temp_requirements_file(requirements) as requirements_file:
|
|
235
228
|
run_command(
|
|
236
229
|
[
|
|
237
|
-
|
|
230
|
+
"uv",
|
|
231
|
+
"pip",
|
|
238
232
|
"install",
|
|
239
|
-
"-
|
|
240
|
-
str(vendor_path),
|
|
233
|
+
"--no-build",
|
|
241
234
|
"-r",
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
requirements_file,
|
|
236
|
+
"--extra-index-url",
|
|
237
|
+
_get_pyodide_index(),
|
|
238
|
+
"--index-strategy",
|
|
239
|
+
"unsafe-best-match",
|
|
240
|
+
],
|
|
241
|
+
env=os.environ | {"VIRTUAL_ENV": PYODIDE_VENV_PATH},
|
|
242
|
+
)
|
|
243
|
+
pyv = _get_python_version()
|
|
244
|
+
shutil.rmtree(vendor_path)
|
|
245
|
+
shutil.copytree(
|
|
246
|
+
PYODIDE_VENV_PATH / f"lib/python{pyv}/site-packages", vendor_path
|
|
244
247
|
)
|
|
245
248
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
+
# Create a pyvenv.cfg file in python_modules to mark it as a virtual environment
|
|
250
|
+
(vendor_path / "pyvenv.cfg").touch()
|
|
251
|
+
VENDOR_TOKEN.touch()
|
|
249
252
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
253
|
+
logger.info(
|
|
254
|
+
f"Packages installed in [bold]{relative_vendor_path}[/bold].",
|
|
255
|
+
extra={"markup": True},
|
|
256
|
+
)
|
|
254
257
|
|
|
255
258
|
|
|
256
259
|
def _install_requirements_to_venv(requirements: list[str]):
|
|
257
260
|
# Create a requirements file for .venv-workers that includes webtypy and pyodide-py
|
|
258
|
-
|
|
259
|
-
|
|
261
|
+
relative_venv_workers_path = VENV_WORKERS_PATH.relative_to(PROJECT_ROOT)
|
|
260
262
|
requirements = requirements.copy()
|
|
261
263
|
requirements.append("webtypy")
|
|
262
264
|
requirements.append("pyodide-py")
|
|
263
265
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
266
|
+
logger.info(
|
|
267
|
+
f"Installing packages into [bold]{relative_venv_workers_path}[/bold]...",
|
|
268
|
+
extra={"markup": True},
|
|
269
|
+
)
|
|
270
|
+
with temp_requirements_file(requirements) as requirements_file:
|
|
271
|
+
run_command(
|
|
272
|
+
[
|
|
273
|
+
"uv",
|
|
274
|
+
"pip",
|
|
275
|
+
"install",
|
|
276
|
+
"-r",
|
|
277
|
+
requirements_file,
|
|
278
|
+
],
|
|
279
|
+
env=os.environ | {"VIRTUAL_ENV": VENV_WORKERS_PATH},
|
|
276
280
|
)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
f"Installing packages into [bold]{relative_venv_workers_path}[/bold] using uv pip...",
|
|
283
|
-
extra={"markup": True},
|
|
284
|
-
)
|
|
285
|
-
run_command(
|
|
286
|
-
[
|
|
287
|
-
"uv",
|
|
288
|
-
"pip",
|
|
289
|
-
"install",
|
|
290
|
-
"-p",
|
|
291
|
-
venv_python_executable,
|
|
292
|
-
"-r",
|
|
293
|
-
str(temp_file_path),
|
|
294
|
-
]
|
|
295
|
-
)
|
|
296
|
-
VENV_WORKERS_TOKEN.write_text("")
|
|
297
|
-
logger.info(
|
|
298
|
-
f"Packages installed in [bold]{relative_venv_workers_path}[/bold].",
|
|
299
|
-
extra={"markup": True},
|
|
300
|
-
)
|
|
301
|
-
else:
|
|
302
|
-
logger.warning(
|
|
303
|
-
f"Python executable not found at {venv_python_executable}. Skipping installation in [bold]{relative_venv_workers_path}[/bold].",
|
|
304
|
-
extra={"markup": True},
|
|
305
|
-
)
|
|
281
|
+
VENV_WORKERS_TOKEN.touch()
|
|
282
|
+
logger.info(
|
|
283
|
+
f"Packages installed in [bold]{relative_venv_workers_path}[/bold].",
|
|
284
|
+
extra={"markup": True},
|
|
285
|
+
)
|
|
306
286
|
|
|
307
287
|
|
|
308
288
|
def install_requirements(requirements: list[str]):
|
|
@@ -310,6 +290,12 @@ def install_requirements(requirements: list[str]):
|
|
|
310
290
|
_install_requirements_to_venv(requirements)
|
|
311
291
|
|
|
312
292
|
|
|
293
|
+
def _is_out_of_date(token: Path, time: float) -> bool:
|
|
294
|
+
if not token.exists():
|
|
295
|
+
return True
|
|
296
|
+
return time > token.stat().st_mtime
|
|
297
|
+
|
|
298
|
+
|
|
313
299
|
def is_sync_needed():
|
|
314
300
|
"""
|
|
315
301
|
Checks if pyproject.toml has been modified since the last sync.
|
|
@@ -323,20 +309,6 @@ def is_sync_needed():
|
|
|
323
309
|
return True
|
|
324
310
|
|
|
325
311
|
pyproject_mtime = PYPROJECT_TOML_PATH.stat().st_mtime
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return True
|
|
330
|
-
|
|
331
|
-
venv_mtime = VENV_WORKERS_TOKEN.stat().st_mtime
|
|
332
|
-
venv_needs_update = pyproject_mtime > venv_mtime
|
|
333
|
-
if venv_needs_update:
|
|
334
|
-
return True
|
|
335
|
-
|
|
336
|
-
# Check if vendor directory exists and get its timestamp
|
|
337
|
-
if not VENDOR_TOKEN.exists():
|
|
338
|
-
return True
|
|
339
|
-
|
|
340
|
-
vendor_mtime = VENDOR_TOKEN.stat().st_mtime
|
|
341
|
-
vendor_needs_update = pyproject_mtime > vendor_mtime
|
|
342
|
-
return vendor_needs_update
|
|
312
|
+
return _is_out_of_date(VENDOR_TOKEN, pyproject_mtime) or _is_out_of_date(
|
|
313
|
+
VENV_WORKERS_TOKEN, pyproject_mtime
|
|
314
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workers-py
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.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
|
|
@@ -29,7 +29,7 @@ A CLI tool for managing vendored packages in a Python Workers project.
|
|
|
29
29
|
On Linux, you may be able to install the tool globally by running:
|
|
30
30
|
|
|
31
31
|
```
|
|
32
|
-
uv
|
|
32
|
+
uv tool install workers-py
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Alternatively, you can add `workers-py` to your pyproject.toml:
|
|
@@ -60,7 +60,7 @@ uv run --project $REPO_ROOT $REPO_ROOT/src/pywrangler --help
|
|
|
60
60
|
On Linux, to install it globally, you may also be able to run:
|
|
61
61
|
|
|
62
62
|
```
|
|
63
|
-
uv
|
|
63
|
+
uv tool install -e .
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
Alternatively, you can add `workers-py` to your pyproject.toml:
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
pywrangler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
pywrangler/__main__.py,sha256=BnrUM7YiBmlM4HAn2MI9hP1kVNtzeK_kEgQhRy5HTq0,38
|
|
3
|
+
pywrangler/cli.py,sha256=3hMjtOOib3HaTqCkuMGQe7MbBZNnim2ByHcDY4JxFlw,5091
|
|
4
|
+
pywrangler/sync.py,sha256=zTX-zZ5OJ7701N07zGnE0GeSebXGeBKJlFRrhNwBy4M,9961
|
|
5
|
+
pywrangler/utils.py,sha256=wfkT7GbKtgtjHXtV3AjNeb25ohdAfrprdZIlqqidiQU,3269
|
|
6
|
+
workers_py-1.2.1.dist-info/METADATA,sha256=o50STsChreiwJ1o3SxrVVUM1vbz4yIrSPLPR495b1_s,1733
|
|
7
|
+
workers_py-1.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
8
|
+
workers_py-1.2.1.dist-info/entry_points.txt,sha256=pt6X-Nv5-gSiKUwrnvLwzlSXs9yP37m7zdTAi8f6nAM,50
|
|
9
|
+
workers_py-1.2.1.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
pywrangler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
pywrangler/__main__.py,sha256=BnrUM7YiBmlM4HAn2MI9hP1kVNtzeK_kEgQhRy5HTq0,38
|
|
3
|
-
pywrangler/cli.py,sha256=BnGGrdksWP-qBj-b0ipji-61Q0kZJohyr2KZZz-XG5s,5150
|
|
4
|
-
pywrangler/sync.py,sha256=vcaL_jOWCC6vWEaJnTnbnxgdgFeW30pndRcMRWOv5pw,11286
|
|
5
|
-
pywrangler/utils.py,sha256=wfkT7GbKtgtjHXtV3AjNeb25ohdAfrprdZIlqqidiQU,3269
|
|
6
|
-
workers_py-1.1.8.dist-info/METADATA,sha256=rE874u2Io40CgLK1JPBMO5eMTwyychzO14K_jO5Emrc,1749
|
|
7
|
-
workers_py-1.1.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
8
|
-
workers_py-1.1.8.dist-info/entry_points.txt,sha256=pt6X-Nv5-gSiKUwrnvLwzlSXs9yP37m7zdTAi8f6nAM,50
|
|
9
|
-
workers_py-1.1.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|