workers-py 1.1.6__py3-none-any.whl → 1.1.8__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/__init__.py +0 -1
- pywrangler/sync.py +61 -9
- pywrangler/utils.py +17 -4
- {workers_py-1.1.6.dist-info → workers_py-1.1.8.dist-info}/METADATA +2 -2
- workers_py-1.1.8.dist-info/RECORD +9 -0
- workers_py-1.1.6.dist-info/RECORD +0 -9
- {workers_py-1.1.6.dist-info → workers_py-1.1.8.dist-info}/WHEEL +0 -0
- {workers_py-1.1.6.dist-info → workers_py-1.1.8.dist-info}/entry_points.txt +0 -0
pywrangler/__init__.py
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
pywrangler/sync.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
+
import shutil
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
import tempfile
|
|
5
6
|
|
|
@@ -21,7 +22,9 @@ logger = logging.getLogger(__name__)
|
|
|
21
22
|
PYPROJECT_TOML_PATH = find_pyproject_toml()
|
|
22
23
|
PROJECT_ROOT = PYPROJECT_TOML_PATH.parent
|
|
23
24
|
VENV_WORKERS_PATH = PROJECT_ROOT / ".venv-workers"
|
|
25
|
+
VENV_WORKERS_TOKEN = PROJECT_ROOT / ".venv-workers/.synced"
|
|
24
26
|
PYODIDE_VENV_PATH = VENV_WORKERS_PATH / "pyodide-venv"
|
|
27
|
+
VENDOR_TOKEN = PROJECT_ROOT / "python_modules/.synced"
|
|
25
28
|
VENV_REQUIREMENTS_PATH = VENV_WORKERS_PATH / "temp-venv-requirements.txt"
|
|
26
29
|
|
|
27
30
|
|
|
@@ -59,18 +62,66 @@ def _get_python_version():
|
|
|
59
62
|
return os.environ.get("_PYWRANGLER_PYTHON_VERSION", "3.12")
|
|
60
63
|
|
|
61
64
|
|
|
65
|
+
def _get_venv_python_version() -> str | None:
|
|
66
|
+
"""
|
|
67
|
+
Retrieves the Python version from the virtual environment.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The Python version string or None if it cannot be determined.
|
|
71
|
+
"""
|
|
72
|
+
venv_python = (
|
|
73
|
+
VENV_WORKERS_PATH / "Scripts" / "python.exe"
|
|
74
|
+
if os.name == "nt"
|
|
75
|
+
else VENV_WORKERS_PATH / "bin" / "python"
|
|
76
|
+
)
|
|
77
|
+
if not venv_python.is_file():
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
result = run_command(
|
|
81
|
+
[str(venv_python), "--version"], check=False, capture_output=True
|
|
82
|
+
)
|
|
83
|
+
if result.returncode != 0:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
return result.stdout.strip()
|
|
87
|
+
|
|
88
|
+
|
|
62
89
|
def create_workers_venv():
|
|
63
90
|
"""
|
|
64
91
|
Creates a virtual environment at `VENV_WORKERS_PATH` if it doesn't exist.
|
|
65
92
|
"""
|
|
93
|
+
wanted_python_version = _get_python_version()
|
|
94
|
+
logger.debug(f"Using python version: {wanted_python_version}")
|
|
95
|
+
|
|
66
96
|
if VENV_WORKERS_PATH.is_dir():
|
|
67
|
-
|
|
68
|
-
|
|
97
|
+
installed_version = _get_venv_python_version()
|
|
98
|
+
if installed_version:
|
|
99
|
+
if wanted_python_version in installed_version:
|
|
100
|
+
logger.debug(
|
|
101
|
+
f"Virtual environment at {VENV_WORKERS_PATH} already exists."
|
|
102
|
+
)
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
logger.warning(
|
|
106
|
+
f"Recreating virtual environment at {VENV_WORKERS_PATH} due to Python version mismatch. "
|
|
107
|
+
f"Found {installed_version}, expected {wanted_python_version}"
|
|
108
|
+
)
|
|
109
|
+
else:
|
|
110
|
+
logger.warning(
|
|
111
|
+
f"Could not determine python version for {VENV_WORKERS_PATH}, recreating."
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
shutil.rmtree(VENV_WORKERS_PATH)
|
|
69
115
|
|
|
70
116
|
logger.debug(f"Creating virtual environment at {VENV_WORKERS_PATH}...")
|
|
71
|
-
python_version = _get_python_version()
|
|
72
117
|
run_command(
|
|
73
|
-
[
|
|
118
|
+
[
|
|
119
|
+
"uv",
|
|
120
|
+
"venv",
|
|
121
|
+
str(VENV_WORKERS_PATH),
|
|
122
|
+
"--python",
|
|
123
|
+
f"python{wanted_python_version}",
|
|
124
|
+
]
|
|
74
125
|
)
|
|
75
126
|
|
|
76
127
|
|
|
@@ -194,6 +245,7 @@ def _install_requirements_to_vendor(requirements: list[str]):
|
|
|
194
245
|
|
|
195
246
|
# Create a pyvenv.cfg file in python_modules to mark it as a virtual environment
|
|
196
247
|
(vendor_path / "pyvenv.cfg").touch()
|
|
248
|
+
VENDOR_TOKEN.write_text("")
|
|
197
249
|
|
|
198
250
|
logger.info(
|
|
199
251
|
f"Packages installed in [bold]{relative_vendor_path}[/bold].",
|
|
@@ -241,6 +293,7 @@ def _install_requirements_to_venv(requirements: list[str]):
|
|
|
241
293
|
str(temp_file_path),
|
|
242
294
|
]
|
|
243
295
|
)
|
|
296
|
+
VENV_WORKERS_TOKEN.write_text("")
|
|
244
297
|
logger.info(
|
|
245
298
|
f"Packages installed in [bold]{relative_venv_workers_path}[/bold].",
|
|
246
299
|
extra={"markup": True},
|
|
@@ -272,19 +325,18 @@ def is_sync_needed():
|
|
|
272
325
|
pyproject_mtime = PYPROJECT_TOML_PATH.stat().st_mtime
|
|
273
326
|
|
|
274
327
|
# Check if .venv-workers exists and get its timestamp
|
|
275
|
-
if not
|
|
328
|
+
if not VENV_WORKERS_TOKEN.exists():
|
|
276
329
|
return True
|
|
277
330
|
|
|
278
|
-
venv_mtime =
|
|
331
|
+
venv_mtime = VENV_WORKERS_TOKEN.stat().st_mtime
|
|
279
332
|
venv_needs_update = pyproject_mtime > venv_mtime
|
|
280
333
|
if venv_needs_update:
|
|
281
334
|
return True
|
|
282
335
|
|
|
283
336
|
# Check if vendor directory exists and get its timestamp
|
|
284
|
-
|
|
285
|
-
if not vendor_path.is_dir():
|
|
337
|
+
if not VENDOR_TOKEN.exists():
|
|
286
338
|
return True
|
|
287
339
|
|
|
288
|
-
vendor_mtime =
|
|
340
|
+
vendor_mtime = VENDOR_TOKEN.stat().st_mtime
|
|
289
341
|
vendor_needs_update = pyproject_mtime > vendor_mtime
|
|
290
342
|
return vendor_needs_update
|
pywrangler/utils.py
CHANGED
|
@@ -50,7 +50,21 @@ def run_command(
|
|
|
50
50
|
cwd: Path | None = None,
|
|
51
51
|
env: dict | None = None,
|
|
52
52
|
check: bool = True,
|
|
53
|
+
capture_output: bool = False,
|
|
53
54
|
):
|
|
55
|
+
"""
|
|
56
|
+
Runs a command and handles logging and errors.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
command: The command to run as a list of strings.
|
|
60
|
+
cwd: The working directory.
|
|
61
|
+
env: Environment variables.
|
|
62
|
+
check: If True, raise an exception on non-zero exit codes.
|
|
63
|
+
capture_output: If True, capture and return stdout/stderr.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
A subprocess.CompletedProcess instance.
|
|
67
|
+
"""
|
|
54
68
|
logger.log(RUNNING_LEVEL, f"{' '.join(str(arg) for arg in command)}")
|
|
55
69
|
try:
|
|
56
70
|
process = subprocess.run(
|
|
@@ -58,16 +72,15 @@ def run_command(
|
|
|
58
72
|
cwd=cwd,
|
|
59
73
|
env=env,
|
|
60
74
|
check=check,
|
|
61
|
-
|
|
62
|
-
stderr=subprocess.STDOUT,
|
|
75
|
+
capture_output=capture_output,
|
|
63
76
|
text=True,
|
|
64
77
|
)
|
|
65
|
-
if process.stdout:
|
|
78
|
+
if process.stdout and not capture_output:
|
|
66
79
|
logger.log(OUTPUT_LEVEL, f"{process.stdout.strip()}")
|
|
67
80
|
return process
|
|
68
81
|
except subprocess.CalledProcessError as e:
|
|
69
82
|
logger.error(
|
|
70
|
-
f"Error running command: {' '.join(str(arg) for arg in command)}\nExit code: {e.returncode}\nOutput:\n{e.stdout.strip()}"
|
|
83
|
+
f"Error running command: {' '.join(str(arg) for arg in command)}\nExit code: {e.returncode}\nOutput:\n{e.stdout.strip() if e.stdout else ''}{e.stderr.strip() if e.stderr else ''}"
|
|
71
84
|
)
|
|
72
85
|
raise click.exceptions.Exit(code=e.returncode)
|
|
73
86
|
except FileNotFoundError:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workers-py
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.8
|
|
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
|
|
@@ -20,7 +20,7 @@ Description-Content-Type: text/markdown
|
|
|
20
20
|
A set of libraries and tools for Python Workers.
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
## Pywrangler
|
|
23
|
+
## Pywrangler
|
|
24
24
|
|
|
25
25
|
A CLI tool for managing vendored packages in a Python Workers project.
|
|
26
26
|
|
|
@@ -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=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,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
pywrangler/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
2
|
-
pywrangler/__main__.py,sha256=BnrUM7YiBmlM4HAn2MI9hP1kVNtzeK_kEgQhRy5HTq0,38
|
|
3
|
-
pywrangler/cli.py,sha256=BnGGrdksWP-qBj-b0ipji-61Q0kZJohyr2KZZz-XG5s,5150
|
|
4
|
-
pywrangler/sync.py,sha256=80pPCz-DTTAk5xTQ0j4ufrh3wv1nQ8y_-zpdPkaLVfw,9740
|
|
5
|
-
pywrangler/utils.py,sha256=6mR3kst-Y0w1DMQc5LQ2M9xiNWcVezctTKIWXKQXMJ8,2781
|
|
6
|
-
workers_py-1.1.6.dist-info/METADATA,sha256=rI1Ka0dZmdZPfLyanLGulrUewvzy0wnWeUZi9sMdMCI,1750
|
|
7
|
-
workers_py-1.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
8
|
-
workers_py-1.1.6.dist-info/entry_points.txt,sha256=pt6X-Nv5-gSiKUwrnvLwzlSXs9yP37m7zdTAi8f6nAM,50
|
|
9
|
-
workers_py-1.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|