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 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
- logger.debug(f"Virtual environment at {VENV_WORKERS_PATH} already exists.")
68
- return
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
- ["uv", "venv", str(VENV_WORKERS_PATH), "--python", f"python{python_version}"]
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 VENV_WORKERS_PATH.is_dir():
328
+ if not VENV_WORKERS_TOKEN.exists():
276
329
  return True
277
330
 
278
- venv_mtime = VENV_WORKERS_PATH.stat().st_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
- vendor_path = PROJECT_ROOT / "python_modules"
285
- if not vendor_path.is_dir():
337
+ if not VENDOR_TOKEN.exists():
286
338
  return True
287
339
 
288
- vendor_mtime = vendor_path.stat().st_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
- stdout=subprocess.PIPE,
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.6
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,,