workers-py 1.2.1__tar.gz → 1.4.0__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.
@@ -2,6 +2,22 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.4.0 (2025-10-10)
6
+
7
+ ### Features
8
+
9
+ - Adds wrangler version check
10
+ ([`ed41bcc`](https://github.com/cloudflare/workers-py/commit/ed41bccf24d5130b2c628edc7c3ece48edf14253))
11
+
12
+
13
+ ## v1.3.0 (2025-10-08)
14
+
15
+ ### Features
16
+
17
+ - Implements python version detection based on wrangler config
18
+ ([`dec6e10`](https://github.com/cloudflare/workers-py/commit/dec6e10a8ff685feffbbd329d26a52212d83e0e3))
19
+
20
+
5
21
  ## v1.2.1 (2025-10-07)
6
22
 
7
23
  ### Bug Fixes
@@ -0,0 +1,6 @@
1
+ This project uses the following tools:
2
+
3
+ * uv for package installation and running of tools
4
+ * pytest for the implementation of tests
5
+
6
+ When implementing tests, try to use features from pytest where possible.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workers-py
3
- Version: 1.2.1
3
+ Version: 1.4.0
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
@@ -9,6 +9,7 @@ Classifier: Operating System :: OS Independent
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Requires-Python: >=3.10
11
11
  Requires-Dist: click<9.0.0,>=8.0.0
12
+ Requires-Dist: pyjson5>=1.6.0
12
13
  Requires-Dist: pyodide-cli
13
14
  Requires-Dist: rich>=13.0.0
14
15
  Provides-Extra: build
@@ -75,7 +76,14 @@ workers-py = { path = "../workers-py" }
75
76
 
76
77
  Then run via `uv run pywrangler`.
77
78
 
78
- ## Tests
79
+ #### Lint
80
+
81
+ ```
82
+ uv run ruff check --fix
83
+ uv run ruff format
84
+ ```
85
+
86
+ #### Tests
79
87
 
80
88
  ```
81
89
  $ uv cache clean
@@ -58,7 +58,14 @@ workers-py = { path = "../workers-py" }
58
58
 
59
59
  Then run via `uv run pywrangler`.
60
60
 
61
- ## Tests
61
+ #### Lint
62
+
63
+ ```
64
+ uv run ruff check --fix
65
+ uv run ruff format
66
+ ```
67
+
68
+ #### Tests
62
69
 
63
70
  ```
64
71
  $ uv cache clean
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "workers-py"
7
- version = "1.2.1"
7
+ version = "1.4.0"
8
8
  description = "A set of libraries and tools for Python Workers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -17,6 +17,7 @@ dependencies = [
17
17
  "click>=8.0.0,<9.0.0",
18
18
  "rich>=13.0.0",
19
19
  "pyodide-cli",
20
+ "pyjson5>=1.6.0",
20
21
  ]
21
22
 
22
23
  [dependency-groups]
@@ -57,6 +57,11 @@ class ProxyToWranglerGroup(click.Group):
57
57
  if cmd_name in ["dev", "publish", "deploy", "versions"]:
58
58
  ctx.invoke(sync_command, force=False, directly_requested=False)
59
59
 
60
+ if cmd_name == "dev":
61
+ from pywrangler.sync import check_wrangler_version
62
+
63
+ check_wrangler_version()
64
+
60
65
  _proxy_to_wrangler(cmd_name, remaining_args)
61
66
  sys.exit(0)
62
67
 
@@ -0,0 +1,16 @@
1
+ from typing import Literal, NamedTuple
2
+ from datetime import datetime
3
+
4
+
5
+ class PythonCompatVersion(NamedTuple):
6
+ version: Literal["3.12", "3.13"]
7
+ compat_flag: str
8
+ compat_date: datetime | None
9
+
10
+
11
+ PYTHON_COMPAT_VERSIONS = [
12
+ PythonCompatVersion(
13
+ "3.13", "python_workers_20250116", datetime.strptime("2025-09-29", "%Y-%m-%d")
14
+ ),
15
+ PythonCompatVersion("3.12", "python_workers", None),
16
+ ]
@@ -1,17 +1,21 @@
1
1
  import logging
2
2
  import os
3
+ import re
3
4
  import shutil
4
5
  import tempfile
5
6
  from contextlib import contextmanager
7
+ from datetime import datetime
6
8
  from pathlib import Path
7
9
  from typing import Literal
8
10
 
9
11
  import click
12
+ import pyjson5
10
13
 
11
14
  from pywrangler.utils import (
12
15
  run_command,
13
16
  find_pyproject_toml,
14
17
  )
18
+ from pywrangler.metadata import PYTHON_COMPAT_VERSIONS
15
19
 
16
20
  try:
17
21
  import tomllib # Standard in Python 3.11+
@@ -60,15 +64,88 @@ def check_wrangler_config():
60
64
  raise click.exceptions.Exit(code=1)
61
65
 
62
66
 
67
+ def _parse_wrangler_config() -> dict:
68
+ """
69
+ Parse wrangler configuration from either wrangler.toml or wrangler.jsonc.
70
+
71
+ Returns:
72
+ dict: Parsed configuration data
73
+ """
74
+ wrangler_toml = PROJECT_ROOT / "wrangler.toml"
75
+ wrangler_jsonc = PROJECT_ROOT / "wrangler.jsonc"
76
+
77
+ if wrangler_toml.is_file():
78
+ try:
79
+ with open(wrangler_toml, "rb") as f:
80
+ return tomllib.load(f)
81
+ except tomllib.TOMLDecodeError as e:
82
+ logger.error(f"Error parsing {wrangler_toml}: {e}")
83
+ raise click.exceptions.Exit(code=1)
84
+
85
+ if wrangler_jsonc.is_file():
86
+ try:
87
+ with open(wrangler_jsonc, "r") as f:
88
+ content = f.read()
89
+ return pyjson5.loads(content)
90
+ except (pyjson5.Json5DecoderError, ValueError) as e:
91
+ logger.error(f"Error parsing {wrangler_jsonc}: {e}")
92
+ raise click.exceptions.Exit(code=1)
93
+
94
+ return {}
95
+
96
+
63
97
  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
- )
98
+ """
99
+ Determine Python version from wrangler configuration.
100
+
101
+ Returns:
102
+ Python version string
103
+ """
104
+ config = _parse_wrangler_config()
105
+
106
+ if not config:
107
+ logger.error("No wrangler config found")
108
+ raise click.exceptions.Exit(code=1)
109
+
110
+ compat_flags = config.get("compatibility_flags", [])
111
+
112
+ if "compatibility_date" not in config:
113
+ logger.error("No compatibility_date specified in wrangler config")
114
+ raise click.exceptions.Exit(code=1)
115
+ try:
116
+ compat_date = datetime.strptime(config.get("compatibility_date"), "%Y-%m-%d")
117
+ except ValueError:
118
+ logger.error(
119
+ f"Invalid compatibility_date format: {config.get('compatibility_date')}"
120
+ )
121
+ raise click.exceptions.Exit(code=1)
122
+
123
+ # Check if python_workers base flag is present (required for Python workers)
124
+ if "python_workers" not in compat_flags:
125
+ logger.error("`python_workers` compat flag not specified in wrangler config")
126
+ raise click.exceptions.Exit(code=1)
127
+
128
+ # Find the most specific Python version based on compat flags and date
129
+ # Sort by version descending to prioritize newer versions
130
+ sorted_versions = sorted(
131
+ PYTHON_COMPAT_VERSIONS, key=lambda x: x.version, reverse=True
132
+ )
133
+
134
+ for py_version in sorted_versions:
135
+ # Check if the specific compat flag is present
136
+ if py_version.compat_flag in compat_flags:
137
+ return py_version.version
138
+
139
+ # For versions with compat_date, also check the date requirement
140
+ if (
141
+ py_version.compat_date
142
+ and compat_date
143
+ and compat_date >= py_version.compat_date
144
+ ):
145
+ return py_version.version
146
+
147
+ logger.error("Could not determine Python version from wrangler config")
148
+ raise click.exceptions.Exit(code=1)
72
149
 
73
150
 
74
151
  def _get_uv_pyodide_interp_name():
@@ -118,7 +195,7 @@ def create_workers_venv():
118
195
  Creates a virtual environment at `VENV_WORKERS_PATH` if it doesn't exist.
119
196
  """
120
197
  wanted_python_version = _get_python_version()
121
- logger.debug(f"Using python version: {wanted_python_version}")
198
+ logger.debug(f"Using python version from wrangler config: {wanted_python_version}")
122
199
 
123
200
  if VENV_WORKERS_PATH.is_dir():
124
201
  installed_version = _get_venv_python_version()
@@ -153,6 +230,7 @@ def create_workers_venv():
153
230
 
154
231
 
155
232
  MIN_UV_VERSION = (0, 8, 10)
233
+ MIN_WRANGLER_VERSION = (4, 42, 1)
156
234
 
157
235
 
158
236
  def check_uv_version():
@@ -167,6 +245,48 @@ def check_uv_version():
167
245
  raise click.exceptions.Exit(code=1)
168
246
 
169
247
 
248
+ def check_wrangler_version():
249
+ """
250
+ Check that the installed wrangler version is at least 4.42.1.
251
+
252
+ Raises:
253
+ click.exceptions.Exit: If wrangler is not installed or version is too old.
254
+ """
255
+ result = run_command(
256
+ ["npx", "--yes", "wrangler", "--version"], capture_output=True, check=False
257
+ )
258
+ if result.returncode != 0:
259
+ logger.error("Failed to get wrangler version. Is wrangler installed?")
260
+ logger.error("Install wrangler with: npm install wrangler@latest")
261
+ raise click.exceptions.Exit(code=1)
262
+
263
+ # Parse version from output like "wrangler 4.42.1" or " ⛅️ wrangler 4.42.1"
264
+ version_line = result.stdout.strip()
265
+ # Extract version number using regex
266
+ version_match = re.search(r"wrangler\s+(\d+)\.(\d+)\.(\d+)", version_line)
267
+
268
+ if not version_match:
269
+ logger.error(f"Could not parse wrangler version from: {version_line}")
270
+ logger.error("Install wrangler with: npm install wrangler@latest")
271
+ raise click.exceptions.Exit(code=1)
272
+
273
+ major, minor, patch = map(int, version_match.groups())
274
+ current_version = (major, minor, patch)
275
+
276
+ if current_version < MIN_WRANGLER_VERSION:
277
+ min_version_str = ".".join(str(x) for x in MIN_WRANGLER_VERSION)
278
+ current_version_str = ".".join(str(x) for x in current_version)
279
+ logger.error(
280
+ f"wrangler version at least {min_version_str} required, have {current_version_str}."
281
+ )
282
+ logger.error("Update wrangler with: npm install wrangler@latest")
283
+ raise click.exceptions.Exit(code=1)
284
+
285
+ logger.debug(
286
+ f"wrangler version {'.'.join(str(x) for x in current_version)} is sufficient"
287
+ )
288
+
289
+
170
290
  def create_pyodide_venv():
171
291
  if PYODIDE_VENV_PATH.is_dir():
172
292
  logger.debug(
@@ -3,7 +3,7 @@ import os
3
3
  import shutil
4
4
  import subprocess
5
5
  from pathlib import Path
6
- from unittest.mock import patch
6
+ from unittest.mock import patch, Mock
7
7
  from textwrap import dedent
8
8
 
9
9
  import pytest
@@ -84,8 +84,14 @@ def create_test_pyproject(dependencies=None):
84
84
  return dependencies
85
85
 
86
86
 
87
- def create_test_wrangler_jsonc(main_path="src/worker.py"):
88
- """Create a test wrangler.jsonc file with the given main path."""
87
+ def create_test_wrangler_jsonc(main_path="src/worker.py", python_version="3.12"):
88
+ """Create a test wrangler.jsonc file with the given main path and Python version."""
89
+ compat_flags = ["python_workers"]
90
+ if python_version == "3.13":
91
+ compat_flags.append("python_workers_20250116")
92
+
93
+ compat_flags_str = ", ".join([f'"{flag}"' for flag in compat_flags])
94
+
89
95
  content = f"""
90
96
  /**
91
97
  * For more details on how to configure Wrangler, refer to:
@@ -99,14 +105,23 @@ def create_test_wrangler_jsonc(main_path="src/worker.py"):
99
105
  "main": "{main_path}",
100
106
 
101
107
  // Compatibility date
102
- "compatibility_date": "2023-10-30"
108
+ "compatibility_date": "2023-10-30",
109
+
110
+ // Compatibility flags
111
+ "compatibility_flags": [{compat_flags_str}]
103
112
  }}
104
113
  """
105
114
  TEST_WRANGLER_JSONC.write_text(content)
106
115
 
107
116
 
108
- def create_test_wrangler_toml(main_path="dist/worker.js"):
109
- """Create a test wrangler.toml file with the given main path."""
117
+ def create_test_wrangler_toml(main_path="dist/worker.js", python_version="3.12"):
118
+ """Create a test wrangler.toml file with the given main path and Python version."""
119
+ compat_flags = ["python_workers"]
120
+ if python_version == "3.13":
121
+ compat_flags.append("python_workers_20250116")
122
+
123
+ compat_flags_str = ", ".join([f'"{flag}"' for flag in compat_flags])
124
+
110
125
  content = dedent(f"""
111
126
  # Name of the worker
112
127
  name = "test-worker-toml"
@@ -116,6 +131,9 @@ def create_test_wrangler_toml(main_path="dist/worker.js"):
116
131
 
117
132
  # Compatibility date
118
133
  compatibility_date = "2023-10-30"
134
+
135
+ # Compatibility flags
136
+ compatibility_flags = [{compat_flags_str}]
119
137
  """)
120
138
  TEST_WRANGLER_TOML.write_text(content)
121
139
 
@@ -217,7 +235,17 @@ def test_sync_command_handles_missing_pyproject():
217
235
  with tempfile.TemporaryDirectory() as temp_dir:
218
236
  temp_path = Path(temp_dir)
219
237
 
220
- # Don't create pyproject.toml file
238
+ # Create a wrangler config but don't create pyproject.toml file
239
+ wrangler_jsonc = temp_path / "wrangler.jsonc"
240
+ wrangler_jsonc.write_text("""
241
+ {
242
+ "name": "test-worker",
243
+ "main": "src/worker.py",
244
+ "compatibility_date": "2023-10-30",
245
+ "compatibility_flags": ["python_workers"]
246
+ }
247
+ """)
248
+
221
249
  assert not (temp_path / "pyproject.toml").exists()
222
250
 
223
251
  # Save original directory
@@ -378,10 +406,13 @@ def test_proxy_to_wrangler_unknown_command(mock_proxy_to_wrangler):
378
406
  )
379
407
 
380
408
 
409
+ @patch("pywrangler.sync.check_wrangler_version")
381
410
  @patch("pywrangler.cli._proxy_to_wrangler")
382
411
  @patch("pywrangler.cli.sync_command")
383
412
  @patch("sys.argv", ["pywrangler", "dev", "--local"])
384
- def test_proxy_auto_sync_commands(mock_sync_command, mock_proxy_to_wrangler):
413
+ def test_proxy_auto_sync_commands(
414
+ mock_sync_command, mock_proxy_to_wrangler, mock_check_wrangler_version
415
+ ):
385
416
  """Test that dev, publish, and deploy commands automatically run sync first."""
386
417
  runner = CliRunner()
387
418
 
@@ -459,18 +490,17 @@ def test_sync_recreates_venv_on_python_version_mismatch(clean_test_dir):
459
490
  """
460
491
  # Create initial files in the clean test directory
461
492
  create_test_pyproject([])
462
- create_test_wrangler_jsonc()
463
493
 
464
494
  project_root = Path.cwd().resolve()
465
495
 
466
496
  sync_cmd = ["uvx", "--from", project_root, "pywrangler", "sync"]
467
497
  venv_path = clean_test_dir / ".venv-workers"
468
498
 
469
- # First run: Create venv with Python 3.12
499
+ # First run: Create venv with Python 3.12 (using basic python_workers flag)
470
500
  print("\nRunning sync to create venv with Python 3.12...")
471
- env = os.environ | {"_PYWRANGLER_PYTHON_VERSION": "3.12"}
501
+ create_test_wrangler_jsonc(python_version="3.12")
472
502
  result1 = subprocess.run(
473
- sync_cmd, capture_output=True, text=True, env=env, cwd=clean_test_dir
503
+ sync_cmd, capture_output=True, text=True, cwd=clean_test_dir
474
504
  )
475
505
 
476
506
  assert result1.returncode == 0, (
@@ -479,11 +509,11 @@ def test_sync_recreates_venv_on_python_version_mismatch(clean_test_dir):
479
509
  assert venv_path.exists(), "Venv was not created on the first run."
480
510
  initial_mtime = venv_path.stat().st_mtime
481
511
 
482
- # Second run: Recreate venv with Python 3.13
512
+ # Second run: Recreate venv with Python 3.13 (using python_workers_20250116 flag)
483
513
  print("\nRunning sync to recreate venv with Python 3.13...")
484
- env = os.environ | {"_PYWRANGLER_PYTHON_VERSION": "3.13"}
514
+ create_test_wrangler_jsonc(python_version="3.13")
485
515
  result2 = subprocess.run(
486
- sync_cmd, capture_output=True, text=True, env=env, cwd=clean_test_dir
516
+ sync_cmd, capture_output=True, text=True, cwd=clean_test_dir
487
517
  )
488
518
 
489
519
  assert result2.returncode == 0, (
@@ -503,3 +533,42 @@ def test_sync_recreates_venv_on_python_version_mismatch(clean_test_dir):
503
533
  assert "3.13" in version_result.stdout, (
504
534
  f"Python version is not 3.13: {version_result.stdout}"
505
535
  )
536
+
537
+
538
+ # Wrangler version check tests
539
+ @patch("pywrangler.sync.run_command")
540
+ def test_check_wrangler_version_sufficient(mock_run_command):
541
+ """Test that check_wrangler_version passes with sufficient version."""
542
+ from pywrangler.sync import check_wrangler_version
543
+
544
+ # Mock successful wrangler version output
545
+ mock_result = Mock()
546
+ mock_result.returncode = 0
547
+ mock_result.stdout = "wrangler 4.42.1"
548
+ mock_run_command.return_value = mock_result
549
+
550
+ # Should not raise an exception
551
+ check_wrangler_version()
552
+
553
+ # Verify the command was called correctly
554
+ mock_run_command.assert_called_once_with(
555
+ ["npx", "--yes", "wrangler", "--version"], capture_output=True, check=False
556
+ )
557
+
558
+
559
+ @patch("pywrangler.sync.run_command")
560
+ def test_check_wrangler_version_insufficient(mock_run_command):
561
+ """Test that check_wrangler_version fails with insufficient version."""
562
+ from pywrangler.sync import check_wrangler_version
563
+
564
+ # Mock wrangler version output with old version
565
+ mock_result = Mock()
566
+ mock_result.returncode = 0
567
+ mock_result.stdout = "⛅️ wrangler 4.40.0"
568
+ mock_run_command.return_value = mock_result
569
+
570
+ # Should raise SystemExit
571
+ import click
572
+
573
+ with pytest.raises(click.exceptions.Exit):
574
+ check_wrangler_version()
@@ -0,0 +1,172 @@
1
+ """Tests for sync module Python version detection."""
2
+
3
+ import click
4
+ import pytest
5
+
6
+ # Import the functions we want to test
7
+ import pywrangler.sync as sync_module
8
+
9
+
10
+ def test_wrangler_toml_with_compat_flag(tmp_path, monkeypatch):
11
+ """Test Python 3.13 detection with python_workers_20250116 compat flag."""
12
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
13
+ wrangler_toml = tmp_path / "wrangler.toml"
14
+ wrangler_toml.write_text("""
15
+ name = "test-worker"
16
+ compatibility_flags = ["python_workers", "python_workers_20250116"]
17
+ compatibility_date = "2024-01-01"
18
+ """)
19
+
20
+ version = sync_module._get_python_version()
21
+ assert version == "3.13"
22
+
23
+
24
+ def test_wrangler_toml_with_compat_date(tmp_path, monkeypatch):
25
+ """Test Python 3.13 detection with compat date >= 2025-09-29."""
26
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
27
+ wrangler_toml = tmp_path / "wrangler.toml"
28
+ wrangler_toml.write_text("""
29
+ name = "test-worker"
30
+ compatibility_flags = ["python_workers"]
31
+ compatibility_date = "2025-10-01"
32
+ """)
33
+
34
+ version = sync_module._get_python_version()
35
+ assert version == "3.13"
36
+
37
+
38
+ def test_wrangler_jsonc_with_compat_flag(tmp_path, monkeypatch):
39
+ """Test Python 3.13 detection with JSONC format."""
40
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
41
+ wrangler_jsonc = tmp_path / "wrangler.jsonc"
42
+ wrangler_jsonc.write_text("""{
43
+ // This is a comment
44
+ "name": "test-worker",
45
+ "compatibility_flags": ["python_workers", "python_workers_20250116"],
46
+ "compatibility_date": "2024-01-01"
47
+ }""")
48
+
49
+ version = sync_module._get_python_version()
50
+ assert version == "3.13"
51
+
52
+
53
+ def test_compat_date_boundary(tmp_path, monkeypatch):
54
+ """Test the exact boundary date for compat_date."""
55
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
56
+ wrangler_toml = tmp_path / "wrangler.toml"
57
+
58
+ # Test exactly on the boundary date
59
+ wrangler_toml.write_text("""
60
+ name = "test-worker"
61
+ compatibility_flags = ["python_workers"]
62
+ compatibility_date = "2025-09-29"
63
+ """)
64
+
65
+ version = sync_module._get_python_version()
66
+ assert version == "3.13"
67
+
68
+ # Test one day before - should return 3.12 (base python_workers)
69
+ wrangler_toml.write_text("""
70
+ name = "test-worker"
71
+ compatibility_flags = ["python_workers"]
72
+ compatibility_date = "2025-09-28"
73
+ """)
74
+
75
+ version = sync_module._get_python_version()
76
+ assert (
77
+ version == "3.12"
78
+ ) # Should be 3.12 because only python_workers flag is present
79
+
80
+
81
+ def test_no_wrangler_config(tmp_path, monkeypatch):
82
+ """Test error when no wrangler config exists."""
83
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
84
+ with pytest.raises(click.exceptions.Exit) as exc_info:
85
+ sync_module._get_python_version()
86
+ assert exc_info.value.exit_code == 1
87
+
88
+
89
+ def test_no_python_workers_flag(tmp_path, monkeypatch):
90
+ """Test error when python_workers flag is missing."""
91
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
92
+ wrangler_toml = tmp_path / "wrangler.toml"
93
+ wrangler_toml.write_text("""
94
+ name = "test-worker"
95
+ compatibility_flags = ["python_workers_20250116"]
96
+ compatibility_date = "2025-10-01"
97
+ """)
98
+
99
+ with pytest.raises(click.exceptions.Exit) as exc_info:
100
+ sync_module._get_python_version()
101
+ assert exc_info.value.exit_code == 1
102
+
103
+
104
+ def test_wrangler_jsonc_with_multiline_comments(tmp_path, monkeypatch):
105
+ """Test Python 3.13 detection with JSONC format including multi-line comments."""
106
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
107
+ wrangler_jsonc = tmp_path / "wrangler.jsonc"
108
+ wrangler_jsonc.write_text("""
109
+ /**
110
+ * For more details on how to configure Wrangler, refer to:
111
+ * https://developers.cloudflare.com/workers/wrangler/configuration/
112
+ */
113
+ {
114
+ "name": "test-worker",
115
+ // Single line comment
116
+ "compatibility_flags": [
117
+ /* Another multi-line comment */ "python_workers", "python_workers_20250116"
118
+ ],
119
+ "compatibility_date": "2024-01-01" /* Inline multi-line comment */
120
+ }""")
121
+
122
+ version = sync_module._get_python_version()
123
+ assert version == "3.13"
124
+
125
+
126
+ def test_wrangler_jsonc_with_trailing_commas(tmp_path, monkeypatch):
127
+ """Test JSONC parsing with trailing commas (JSON5 feature)."""
128
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
129
+ wrangler_jsonc = tmp_path / "wrangler.jsonc"
130
+ wrangler_jsonc.write_text("""{
131
+ "name": "test-worker",
132
+ "compatibility_date": "2025-10-01",
133
+ "compatibility_flags": [
134
+ "python_workers",
135
+ "python_workers_20250116",
136
+ "some_other_flag",
137
+ ], // Trailing comma here
138
+ }""")
139
+
140
+ version = sync_module._get_python_version()
141
+ assert version == "3.13"
142
+
143
+
144
+ def test_main_get_python_version_integration(tmp_path, monkeypatch):
145
+ """Test the main _get_python_version function integration."""
146
+ monkeypatch.setattr(sync_module, "PROJECT_ROOT", tmp_path)
147
+
148
+ # Test with no config - should raise error
149
+ with pytest.raises(click.exceptions.Exit) as exc_info:
150
+ sync_module._get_python_version()
151
+ assert exc_info.value.exit_code == 1
152
+
153
+ # Test with config that specifies 3.13
154
+ wrangler_toml = tmp_path / "wrangler.toml"
155
+ wrangler_toml.write_text("""
156
+ name = "test-worker"
157
+ compatibility_date = "2024-09-09"
158
+ compatibility_flags = ["python_workers", "python_workers_20250116"]
159
+ """)
160
+
161
+ version = sync_module._get_python_version()
162
+ assert version == "3.13"
163
+
164
+ # Test with config that specifies 3.12 (only python_workers flag)
165
+ wrangler_toml.write_text("""
166
+ name = "test-worker"
167
+ compatibility_date = "2024-09-09"
168
+ compatibility_flags = ["python_workers"]
169
+ """)
170
+
171
+ version = sync_module._get_python_version()
172
+ assert version == "3.12"
@@ -275,6 +275,134 @@ wheels = [
275
275
  { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
276
276
  ]
277
277
 
278
+ [[package]]
279
+ name = "pyjson5"
280
+ version = "2.0.0"
281
+ source = { registry = "https://pypi.org/simple" }
282
+ sdist = { url = "https://files.pythonhosted.org/packages/6e/d9/005aaaf5077cde946282b22da9404965477fb140fa6836b52d2e0955a391/pyjson5-2.0.0.tar.gz", hash = "sha256:7ccc98586cf87dfeadfa76de8df4c9cb0c3d21d1b559e28812dd9633748d6e25", size = 305865 }
283
+ wheels = [
284
+ { url = "https://files.pythonhosted.org/packages/32/98/a758a7c7985ea50a0ea9680181070928cc8ea2a0f71a9ad13be3f581ce25/pyjson5-2.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:176099c7db0197039eb70f21dbf072cf5d4be8e0c065e96d6d6171275398a1b1", size = 297332 },
285
+ { url = "https://files.pythonhosted.org/packages/e0/83/ac464728b541489e92f338e7db958ba998fa1bab6d821306ead3d163d09a/pyjson5-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7182c67a6fa58931550d7e1d60e485825e75d0e50592ab8674e3eebe2e75e99", size = 156205 },
286
+ { url = "https://files.pythonhosted.org/packages/06/17/1f3192eca83e191611aabf6b7531acb8cd4fb83688a4202de40d4730b0dd/pyjson5-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:44d5bb544a955aa30016b743fdce88954673df4c1ab72aeae60ca56bc8c0ea1b", size = 150663 },
287
+ { url = "https://files.pythonhosted.org/packages/5b/c7/252d0659ae0b823b48f1432c941c55ddc704863d2d3ae3f7f1517643261f/pyjson5-2.0.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f038bf94aa0e4885d1cbaf67fcb02a34f799185a2df1ac24786b820431ba397", size = 192706 },
288
+ { url = "https://files.pythonhosted.org/packages/eb/82/e90e15cd9399f3d643da07788f31cabae6cdfedd05b73376c700ef4f4a4a/pyjson5-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:54e6cee0282be21a12edf08f9007682bc00b15aa8bf47e5e6af165bce87ecad4", size = 172039 },
289
+ { url = "https://files.pythonhosted.org/packages/2e/48/b90c8c81178f211feeebe270161e3603fcc73e5c1ceece45bb70772f9cc2/pyjson5-2.0.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f63536df8a1626e38ac9d9f764a31fe514289de9787b6c0d9b824acac24bfe97", size = 168962 },
290
+ { url = "https://files.pythonhosted.org/packages/f1/dc/620ab56078b7ba42530b6efe0df880288991e948b805cc0e4f0c781dc8a9/pyjson5-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b5bc1ce2bf8765c9509f4c07c3df8bdbb64052950690e8b624b85eae763b6c0", size = 194931 },
291
+ { url = "https://files.pythonhosted.org/packages/82/50/4eea4b37d825199aef5739397e1ccd1413922f66ae06846a8559f47ad3ea/pyjson5-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05e95dab489ddf85308165ef1d537493b70ae0631311e600a3aa5562c4583f3a", size = 197298 },
292
+ { url = "https://files.pythonhosted.org/packages/51/d9/456a0d08e44b70d39d719dba1b51be64b69a22e7bb01d91857030afd3a8b/pyjson5-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:979090533eb8a37378188c851cb579f3101698a2293eb09c1f1a58cfea236ea4", size = 184148 },
293
+ { url = "https://files.pythonhosted.org/packages/4a/b5/f35560c31834f914d4b01da6bb5915e9eaca06d7e796ea7805aef0c6e65b/pyjson5-2.0.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93403e053c58eb3cda23824664514061d2398990cb7f71e4d6112b9c82eff9ef", size = 182742 },
294
+ { url = "https://files.pythonhosted.org/packages/fb/62/4ee6c2cf29d3edb6f2922b9ca63dc6f73403773b4ed014f6790ec3b72033/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0cfa8d5514a37a6f610116bf140922c635a79aefb0d6e61459320d4dff942140", size = 1153989 },
295
+ { url = "https://files.pythonhosted.org/packages/40/98/7dc3ba18b064bd9b62be48050bd0fc814855f78fa27ee385f8b5c7c93c14/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:acc3810d446edc05c892e1ac43e6b223b11b1ccc1c6b7787f85641695f1b869a", size = 1013908 },
296
+ { url = "https://files.pythonhosted.org/packages/c4/b1/d9af0d2205db46458dd45c0551fc0188b3f8578d4f43e9a8a54357388bc4/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:bfd1e0a4d6155f2cea51ccac5b7eccd506123f7eccddf9c6cd2cd56369fc16a9", size = 1328108 },
297
+ { url = "https://files.pythonhosted.org/packages/06/ae/d29b930bc0ae2b98f2c7c4a7de7afb110b9cde9abe9e6fc853e3b4440176/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2369d36c68fcf016859396ef14a4f6176fa63e2567aff9baf1eb9ef51fb46835", size = 1253739 },
298
+ { url = "https://files.pythonhosted.org/packages/af/69/f4f352cfc0faad6ed25de3485be75c5040ebe6c6c69925ec42e54081dc7e/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c37d4a744eadfe2be569c96ef0acd07ecf021d05b3801c9d7b967e70fb6937e1", size = 1189958 },
299
+ { url = "https://files.pythonhosted.org/packages/de/b0/1b373a9c28a4510a54e868ce707910f5a8fb53fc6d9610d770dfdadb691a/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c4e058bb5626940266c55a52d49233fd94d8f7f3b0ca491ea356cd6aab3d09bb", size = 1366103 },
300
+ { url = "https://files.pythonhosted.org/packages/0e/16/3e94e78254c2d035ad66767d5d7afbdaf249d69e24f72137b7be1a72a3ed/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0d9f4167e11a57b4366f9a6dc0fe1fa573ff95b30eb8bffcc4f0da183680452", size = 1216945 },
301
+ { url = "https://files.pythonhosted.org/packages/6c/a6/d810dda12512905fb716e3199230b60cc8c3f9951a804f74a7463b4c991e/pyjson5-2.0.0-cp310-cp310-win32.whl", hash = "sha256:7d4a839694ef4e7e3729d3b9d82da3ab6458b075678b2f1603dd46c85ad93923", size = 114285 },
302
+ { url = "https://files.pythonhosted.org/packages/b1/5b/4695d0a529bee729510f349dfad545cff0923807177f74607d5bc9c5dd7f/pyjson5-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:4f2ce61b582edf57e10c3181ff4e3c59d13382adb22e9810665def9d60d077f7", size = 133126 },
303
+ { url = "https://files.pythonhosted.org/packages/97/d3/2d68a7f743fd5151f2317796306423afd85620b86bb8c1d4efabe3deb824/pyjson5-2.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:e9e686faff89765ad99c7f5602a99703bd7432db04e0f541b7c91ff7d3499cd8", size = 116698 },
304
+ { url = "https://files.pythonhosted.org/packages/c2/2b/2cb73dba9ffeabd91d67577f5fc7fa67040eae6876c632214145893844da/pyjson5-2.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1e6870507311765249f6cb533d8d53e0c9b1837f2e1b0b2ba7825181bd980a48", size = 299572 },
305
+ { url = "https://files.pythonhosted.org/packages/e1/1b/ebf7d13d57fffccb2d5b7bbf609800ccf8ff09678a8a7ae6c0764b04b1c8/pyjson5-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68f931934d736bfd0d9d9c666b9495a10807821c44a7c58069b2f6a12ceb47ae", size = 157385 },
306
+ { url = "https://files.pythonhosted.org/packages/29/7c/eb6fcb6e94075bea4ab56c50d1bfb8a66d43fdc2fb67001181928dd7ddb1/pyjson5-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:47eda4d30024bfa8074a6f17145e55e60cf74a43215db99685fe6998cd0130aa", size = 151838 },
307
+ { url = "https://files.pythonhosted.org/packages/c2/7c/478456b8683bc3d964cf1ca060188b1d4bc03d01548d1449d033542aee91/pyjson5-2.0.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5cc27c08bf33c7be0622ada8ff6dc7aa203287d1e585e343e90d2f2c19f31977", size = 192102 },
308
+ { url = "https://files.pythonhosted.org/packages/0f/17/bce2b2641aa140c761807d50cf30a7e09c53d0bd8737bf63dada0e8613f4/pyjson5-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3af072ff4cb1046c17d6108fd01f4c39519c95e8aa5b2084fd6fea57379eafc", size = 176766 },
309
+ { url = "https://files.pythonhosted.org/packages/30/61/7e51cd104e4514edd21b6e0c7e841da14ba80d3372d028b62719d8cb3f9e/pyjson5-2.0.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:eec8b9067aa041a177a07596c8e800e7616e5ad87ce97836c3489f977231dc1a", size = 170313 },
310
+ { url = "https://files.pythonhosted.org/packages/7e/7e/2398eeffafc924809d4a708588f7f697398ca095b6c399849bfd0867780a/pyjson5-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e91417ead40a468698d0eb6654685986c03afc53290b8dd58d51f28803451506", size = 196097 },
311
+ { url = "https://files.pythonhosted.org/packages/98/70/550d7d634e46a71bf00b93ec2c4a8a7d63f9629e1a5117cbf249995c0e3a/pyjson5-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:023466521ce06f314979589fcd7fa01cdcff4d7a0cd32d1545ca0d566bca7761", size = 198474 },
312
+ { url = "https://files.pythonhosted.org/packages/0f/3c/e4ef8f3ef83254de96aba69f24fa613bc1277cf34802c6b4e82cc311121f/pyjson5-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:913488fb34610b900bef4244bf99d8585b3d1431a7ba28d9538fb6b3bc34150c", size = 186299 },
313
+ { url = "https://files.pythonhosted.org/packages/e7/35/60c473c7970e4239149e7e4dcf7b10ca8712779e47be47b9d9fd076e54ea/pyjson5-2.0.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e25ca44bcb3ce47938d739c5b2bbecdefca919132b7f46a3f57a6d06a38c02f0", size = 185624 },
314
+ { url = "https://files.pythonhosted.org/packages/b5/15/876e53cc43c98ff036c05c90fa8a9ccbf704478a69ffc6efe2c9f898bf77/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c3192eaf57cd17c367dd1726354e992c10dfb810b4c2b87284f55f00840b2245", size = 1158339 },
315
+ { url = "https://files.pythonhosted.org/packages/82/57/2ef4f05a29c04ae1beceae2739b3428bca064f963758284b1633fccc5190/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6ecc3f3216aa9795a80836a1f206fc87c4d2d71f0d90228ff10f1f55b16f72c2", size = 1013974 },
316
+ { url = "https://files.pythonhosted.org/packages/fb/9a/28b8655c6c6715e15c20ab98574a793f6b3435badd0ddf67ba3ea1bd420c/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0e9f21938060afe6f6cd64e76f2f4849c22a7aa61ee794e9885b0a760064deb4", size = 1329463 },
317
+ { url = "https://files.pythonhosted.org/packages/6a/6a/e427b03a02ff45cc7432a7d1e16066512321f643457039c2b955449f4148/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:78133797816d47780b25a1cf55e66ee9cd3e00a9e3abae66040fb975c39b1d23", size = 1255206 },
318
+ { url = "https://files.pythonhosted.org/packages/28/2b/d2b4a3137842de3ba66195fa5e3da96ac8c93790c77a8d76b1d30245b327/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:19d7dfb9d5d32839e1b77506c6b8023f83c72f531e2d6248400ca832efdb2349", size = 1190884 },
319
+ { url = "https://files.pythonhosted.org/packages/7c/6a/e590e10b7e9f145d0e7b02fde0b0b3ffec45998fc7d454e5c64f98aff6d5/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:95012228c10803512f515e70af06ec11a8621ce3742226ba507ebf6e91020d8d", size = 1367769 },
320
+ { url = "https://files.pythonhosted.org/packages/df/3b/705305653470ef31f177ba8f70df6d5d85858e2f2bf3df7624a1c454b7cb/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4facf0fc1bcdd7d57308bbc3dfa2ad0498c8e4d76672c35f1e7976f02d3f7df8", size = 1219001 },
321
+ { url = "https://files.pythonhosted.org/packages/ca/b9/1a072afcfba936d3dabc9db08d18ca3aec03b82002be7b1d6d781019b317/pyjson5-2.0.0-cp311-cp311-win32.whl", hash = "sha256:6fb1bba20ebd3a0b26bca5ee906757a9d82652ca31730d40cd921b88245ec780", size = 114294 },
322
+ { url = "https://files.pythonhosted.org/packages/28/4d/303b9ad667d7440cfd4a45c75408cb868281b60864b917b285aba668a6f3/pyjson5-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:58b17386a96a308c8295e2c2a82526aefaa33ed2abaff84a916f90484b047cc4", size = 134665 },
323
+ { url = "https://files.pythonhosted.org/packages/8a/eb/29d8d48730b1ad0a6b3762190dd2c3f43c39f4f89e20be1b8c0015b24246/pyjson5-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:4f4cde947ea68da7df8fb91b682491bcc0b916e3adb942febe866703853d8301", size = 117666 },
324
+ { url = "https://files.pythonhosted.org/packages/d0/25/429e6cc1b6ba7a1ce730f172d8653f16dfff991de7c1122627b5d9a7dfd6/pyjson5-2.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dbb701b2b19ef5860a2409baf7fd576af8619fdaffa96ca37e0e8e0b2f030be8", size = 300589 },
325
+ { url = "https://files.pythonhosted.org/packages/1f/58/251cc5bfcced1f18dbe36ad54b25f376ab47e8a4bcd6239c7bd69b86218e/pyjson5-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c0f29297836f4a4f8090f5bfc7b0e2b70af235c8dcfd9476a159814f734441d3", size = 159389 },
326
+ { url = "https://files.pythonhosted.org/packages/aa/4b/4e69ccbf34f2f303e32dc0dc8853d82282f109ba41b7a9366d518751e500/pyjson5-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76d4c8d8bf56696c5b9bc3b18f51c840499e7b485817ddba89ae399fcc25c923", size = 150788 },
327
+ { url = "https://files.pythonhosted.org/packages/49/67/caa7dd84ab554d83bb68a7a27f09ed750681cd305d13feb38c2df90ccdbe/pyjson5-2.0.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e94e1a05c8a42a4828a50c520eb2330fe5732d5d04f3ebe771680f7db16f7df3", size = 188298 },
328
+ { url = "https://files.pythonhosted.org/packages/ba/39/26fffaff9ebf720a05e2867c40e2023cebe33a41e1f511e3c1b42452fe7d/pyjson5-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ab533ccd75bfda9ffd34a818f283b481e78c5c315919c4f620f69639044bdd3", size = 168159 },
329
+ { url = "https://files.pythonhosted.org/packages/cd/c9/f7170d4903cb1526836a458f7e4650f0ff465001b7ef7066bc4b0577e601/pyjson5-2.0.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:16e9295bf9f80fc5fb63046a0df4a3adef4e945d27f61f0f6e5db0a4f1510a15", size = 169039 },
330
+ { url = "https://files.pythonhosted.org/packages/2c/d1/b84322897a861e85528c9621372441c4db57b8af615a647a9a8223e7e00a/pyjson5-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4191eced0e77207afc2f82782ef3dbee88c38ec386da8c0af9190653e8c8557f", size = 185596 },
331
+ { url = "https://files.pythonhosted.org/packages/56/3c/fea02294217c0b93f017ddc032bbacc805e669014c784b42b5cf366d4aa1/pyjson5-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9efc441991cd31a5d1fea04d8a024649bbd9a005d7e0ec6a870670b47adf43e8", size = 187665 },
332
+ { url = "https://files.pythonhosted.org/packages/10/39/de2423e6a13fb2f44ecf068df41ff1c7368ecd8b06f728afa1fb30f4ff0a/pyjson5-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:467c5e0856152bbe539e38f126f698189f1ecc4feb5292d47ad0f20472d24b6d", size = 178950 },
333
+ { url = "https://files.pythonhosted.org/packages/d4/9c/3de848f4441b95ad5f8499f7aed9b86da1c7eee776b0e673d85703416f15/pyjson5-2.0.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a2fc21d0f59c75dd3cc0a9943fface3729a4cf2e4dfbd14a90680a97bbfe23d1", size = 175149 },
334
+ { url = "https://files.pythonhosted.org/packages/44/b8/fb33760617875852f299e06aa9cd9bbaf68d2f939189736ebf9099f4f305/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4887291c830dbc30528833eb8cdcc44d0531626a61ac9bac80b17df369cb33", size = 1149408 },
335
+ { url = "https://files.pythonhosted.org/packages/8c/b2/ea1806e14704b5087a637a0b126ce63376f39e3762099614bca446dc7fa4/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:4a1497408a18ddd2501b1c6bdd1dd01d69809450d145c13c42913f98dfa59d20", size = 1012047 },
336
+ { url = "https://files.pythonhosted.org/packages/8d/79/bbd9e037d2758b3da79a4bf02d6234e88908ad62fd6fc299144d4efe7466/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9617abb9022fcd3d1034a5e07972dc0440af3d91da86c45f81750b6c324e9bcf", size = 1324907 },
337
+ { url = "https://files.pythonhosted.org/packages/e0/5d/f984d6008fa0dcf64624eed4334c88cdae31b48d0546a17017beea6f6978/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:247a8f29e4fecdf7ff894dd3b5759a21c5336b5e3c21ba2ee31a03b52b73a98c", size = 1243097 },
338
+ { url = "https://files.pythonhosted.org/packages/14/dc/c07f02d3e5f307540f884cb9ae1c2b17849ebcbf112f81663abe8ca04511/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6a464e605113b09d2f235fc6d7df8425831bbe40078fe6755b30058b8a904694", size = 1181197 },
339
+ { url = "https://files.pythonhosted.org/packages/1a/59/6cf634b199a4e71cb11cc8157d3c8c0baea1d8c89b2bea3bf83a482ac742/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d355134c9735f3eb3724f3985551203976c823909aec118f616b8da096ffd9b5", size = 1356466 },
340
+ { url = "https://files.pythonhosted.org/packages/1d/f1/ae443709da9396396545c1ecfc30fd2f69629a65e894341a72fa286f0c26/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c3353d214db15d6b05d941cdb2fc2e3d1c94650e5baecc6986424f20ebe76d1", size = 1211084 },
341
+ { url = "https://files.pythonhosted.org/packages/28/a7/291e4ac2890dd94f773aa7fe606ffb7b5424ad5c21d888feccb0b0fbf76b/pyjson5-2.0.0-cp312-cp312-win32.whl", hash = "sha256:9f164c973f0d6b79ed3c92a4bb5506b04c810dcf84dc48b543d968ec0acfbfc8", size = 115425 },
342
+ { url = "https://files.pythonhosted.org/packages/af/cb/cf69e6e080149b8993d553c683d364e714c6646f70f55b7c135efe942366/pyjson5-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:296cb2e2c6f64dc61397bd48f04569f1532cd9062d8ebca29ed02644b298e4fc", size = 135552 },
343
+ { url = "https://files.pythonhosted.org/packages/3c/f7/b7784d5dd52a34f23efd4118bf856877a8f15bb2a53c43c192e4dee7d10f/pyjson5-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:b36fa4a4b6f632bbc2afc4caaa16e7f585cd2345de85a439e6ce734f915b8018", size = 116874 },
344
+ { url = "https://files.pythonhosted.org/packages/74/f0/a0273fa863a96fb450336f5c8f3126cd1fefe17bd60451fd66dc58d0ab6c/pyjson5-2.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6840b70981cb838e025a9f952004c6b59655c91076067abf01317fc10681cd7b", size = 299171 },
345
+ { url = "https://files.pythonhosted.org/packages/e0/8c/402811e522cbed81f414056c1683c129127034a9f567fa707200c3c67cf7/pyjson5-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd89ea40f33d1d835493ab0fc3b7b4d7c0c40254e0ddeefde08e0e9d98aebbde", size = 158725 },
346
+ { url = "https://files.pythonhosted.org/packages/2f/00/f2392fe52b50aadf5037381a52f9eda0081be6c429d9d85b47f387ecda38/pyjson5-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dc47fe45e5c20137ac10e8f2d27985d97e67fa71410819a576fa21f181b8e94b", size = 150027 },
347
+ { url = "https://files.pythonhosted.org/packages/36/5c/e3f18bb7059e4e4992b76bf2e9d8594615361313df2fb78b4c08d441a8a3/pyjson5-2.0.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eb4e885db6fe2421735b913f43028578a30dbf9f4c86673649b52bbee91231a9", size = 187241 },
348
+ { url = "https://files.pythonhosted.org/packages/ae/96/1d9cf5bf5ea863d61ab977f6e9842c8519ff430dbceb58580e06deb1dd4a/pyjson5-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b56f404b77f6b6d4a53b74c4d3f989d33b33ec451d7b178dad43d2fb81204dc", size = 168678 },
349
+ { url = "https://files.pythonhosted.org/packages/f5/f4/d0704fef397d0d28d1fc16f4577883331d46b6a2f2eb59c4cc1a364b19f9/pyjson5-2.0.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:20db35f29815572130ec8d539c2465c1e4e7c7677298d6f79216bda611577709", size = 169324 },
350
+ { url = "https://files.pythonhosted.org/packages/df/8c/84eeafe750d04016aedb24cb02959e65a42ef09de675d0dca96013baf199/pyjson5-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:445a21f0a6333f352251e7cb5a8f471ce44e7d74892558bd256e0bb889c1961e", size = 184377 },
351
+ { url = "https://files.pythonhosted.org/packages/9a/80/119b2b01ae625d06ab1d6d5b021f4988fea28cf0ce8921b83ee6f944a1ab/pyjson5-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1bbabb12147f85850ba3b6a5813a3e9cc417ac9d0a66d57af42dd714f563b51e", size = 186931 },
352
+ { url = "https://files.pythonhosted.org/packages/d8/d3/82f366ccadbe8a250e1b810ffa4a33006f66ec287e382632765b63758835/pyjson5-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49f490d68bebfccb1aa01b612beef3abffa720c4069d82d74af8b55cf15cd214", size = 180127 },
353
+ { url = "https://files.pythonhosted.org/packages/65/e2/8b96a72e8ab2e92c3748feafcec79f3e6219bf5289e5b053da7fe7fcb3f3/pyjson5-2.0.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:06cd493d607d94e841b6a8452f33bb45f55430ff33c992b8c4b671f8bebd2a14", size = 175413 },
354
+ { url = "https://files.pythonhosted.org/packages/f8/9d/ea8542d9184616bedc3c7d8d8ac32d7e82fa4e347da08744b81cbffe00e3/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9eea8981d20bf6c37939c013c51ea1e7c9252429b01002a51afce59081b9ae0f", size = 1150022 },
355
+ { url = "https://files.pythonhosted.org/packages/6d/af/8b8060bb9609bf4ad0bfc6fb9f52373aada55c93880c9597e41aecc2d266/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:863a0688a090e8c0add0d769ddf51e2cd48edd1d585f34272e7b4f095593175b", size = 1011750 },
356
+ { url = "https://files.pythonhosted.org/packages/14/3a/9e49bbecc03ebc21c0b45a4f51e74c87c5250822e6bcffb8f8bcf9e800fd/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a4a0e0835d7a5c7b18c3333dd01940ee2d160560e50851803cfaab27cc298df3", size = 1324079 },
357
+ { url = "https://files.pythonhosted.org/packages/2f/94/951c1f531a5369d8859e42a5ac60c7dacf4d8585bb25f37ca7bdd46b9cb1/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:42f3d404367f7365325be1f1460c515d40022d41bece841d47cf00e616967308", size = 1243622 },
358
+ { url = "https://files.pythonhosted.org/packages/99/0b/edb91338101501f1ec18f003e2a8da7650409537f446c7db96d302c7870d/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:3765c07dc1cd5b954a3e793c73c5725bac5431b83f7c807d695d73bbf78ae431", size = 1182052 },
359
+ { url = "https://files.pythonhosted.org/packages/64/f2/54e28fd04aa27375ec4baa447fd58a894cf3cfd20c6a0dad160ee8ec115c/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:51d33381fc268989d6ba3b6ff44e45b634ee490fc658704d04eca59ed9f8b53d", size = 1357131 },
360
+ { url = "https://files.pythonhosted.org/packages/ac/1a/80b50d0fae42cf58e1a37f5b87543c445bb1781ffcc69c94cc73ed397d67/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f42e70d01668ccff505de17a9358fd09b26f9de037dbc8f1476215f217d3dc1", size = 1212220 },
361
+ { url = "https://files.pythonhosted.org/packages/39/fc/44fb44d5b915fc1c871aea2947d87b4cfd77c9f6673ffdaf4e41b7365a46/pyjson5-2.0.0-cp313-cp313-win32.whl", hash = "sha256:62e02fd3a4aa7bc48d9ad04dbd22076d4c33c8161df2f72cdbd8588b8634cb5d", size = 115225 },
362
+ { url = "https://files.pythonhosted.org/packages/e9/60/d28dcdc482ed36196ee7523f47b1869f92a998777d46c80cf84ec1c8c962/pyjson5-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:5318cd5e7d130fb2532c0d295a5c914ee1ab629bc0c57b1ef625bddb272442c4", size = 135384 },
363
+ { url = "https://files.pythonhosted.org/packages/79/3e/14be4a4efa651dab867057d81b4d56b1c9d5328418ca0b1d08d5e953e8d7/pyjson5-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:b274a6c6affca4a3210359bf486940ee08dbc9875f896ab19a14e344d9bbf322", size = 116783 },
364
+ { url = "https://files.pythonhosted.org/packages/79/25/4a81e6d5611b38806e8f87a5b1cf4cbac21b9781c1cbba02c8e43ebd9664/pyjson5-2.0.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:6ae6b65bc5a45e853b462d840fc32be1df4dab8dbd48b1ff3078b8dac2df2f09", size = 301159 },
365
+ { url = "https://files.pythonhosted.org/packages/a6/f4/8c948e8a8b1a518fe87a114df1d58ab5f80b55b6601b64f8649438293bfd/pyjson5-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6b24990927f723c2fff183ec7e14507f8ae3ce22743ac312aa9bf1327f9153dd", size = 159730 },
366
+ { url = "https://files.pythonhosted.org/packages/39/1b/9cd7acea4c0e5a4ed44a79b99fc7e3a50b69639ea9f926efc35d660bef04/pyjson5-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a84949318c52844ced26622a733ca54215ccfa9ee87eb38f1c92ee1ed5994827", size = 151029 },
367
+ { url = "https://files.pythonhosted.org/packages/c4/ff/136636d1ab42f98c55011d2b25a45b3f1107bef10248506d6bf549c8eabd/pyjson5-2.0.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:10fa949fd41e8583170e2b8404c026d8e088d370428b87270a3a8df5a09ffac5", size = 187718 },
368
+ { url = "https://files.pythonhosted.org/packages/e0/97/e104682432b02f1458de22478d2b62caa607426e8284bec4680a3537cadd/pyjson5-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ccbc7a0cf1d9b8c0851b84601650ce9772e526a1a444633be6827aa162c20b54", size = 171291 },
369
+ { url = "https://files.pythonhosted.org/packages/a2/91/bf4eacd990f93f8b5afe717f915ed248595261fcfb47e7718e17c55f5069/pyjson5-2.0.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4e193346ab7c49605be4ec240c81d91014a276a163d5bba67eb53e64f425cecf", size = 168555 },
370
+ { url = "https://files.pythonhosted.org/packages/24/70/fc2147cade7bd91c4d3726a200ae9556bcb45e294d8c57a904f15da16eea/pyjson5-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:25e9b32e21d4928201e2c410bafd196b0a4f0034761378821e99fc80c21ed0e3", size = 185817 },
371
+ { url = "https://files.pythonhosted.org/packages/01/48/a8c396f25b53880bd06beb11ea8f63a42a6b8f9b82d42cc0cf6b0df8ca9f/pyjson5-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:63b0300e5ea302c107e518ef185c6f4ab8af49a5d4a52ed93e3e287fa8a6c69f", size = 188903 },
372
+ { url = "https://files.pythonhosted.org/packages/7c/a3/8ffe10a49652bfd769348c6eca577463c2b3938baab5e62f3896fc5da0b7/pyjson5-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:72f5b5832d2c3055be492cf9853ce7fe57b57cc5e664f1327f10211cbd1114ef", size = 180252 },
373
+ { url = "https://files.pythonhosted.org/packages/7f/f0/801b0523f679a9bd5356210be9a9b074fc14e0e969f2ed1f789cf6af3c45/pyjson5-2.0.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da790aeb2dd88be1c94ea95b5ff4915614109e9e025df7f0936dadc01ae21e0b", size = 175965 },
374
+ { url = "https://files.pythonhosted.org/packages/ea/04/ab703bccebc02c31056a525b7f06c473f141dc5bf96fe314893911a7b9ad/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ee211f71e3d0e7550c09b407dc75d01bbe6d5ed2ac7ee6aa54f870ebe17541aa", size = 1151968 },
375
+ { url = "https://files.pythonhosted.org/packages/70/18/5c665a34ef6123d4c4f70173e30f533bbcf36ca76e3fa7c03b8400b2e34c/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:bf8e84ac6d58380b5fda77985f7acea5afe45bd45e24e77aca0a6912d25222fc", size = 1009858 },
376
+ { url = "https://files.pythonhosted.org/packages/f1/bb/7641ee31fedbe337f5c7ed505b8491a96a94fdcc1567b0b1b2b3633ec755/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f0dd8b38187d0c2e741d40b9b348328172d0c894a90457f53b22e0f470b19009", size = 1324909 },
377
+ { url = "https://files.pythonhosted.org/packages/aa/7f/4cd19d65074d85ad583ff0517e3771af8dd3e87a40d6c25bdb81d38ff0b4/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4ac06acc8ffa5686abad2220dbbef89f99694f1f6ddb70e4ec5455bf9fd91176", size = 1245254 },
378
+ { url = "https://files.pythonhosted.org/packages/54/26/0b96502136c4e74fa508e5a129119bd2df235dfd165acb0d74043e7fe6f0/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:34d2700a9472817c043a18d711ee8fd7bb6270dbd4013473d9aac51cef6a7d77", size = 1182526 },
379
+ { url = "https://files.pythonhosted.org/packages/4c/34/e704bb86cd56092771589a08d1705d1e1310bdb955a752b26f483f7cd7c9/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:daf0e3ecf4f7888735050e1e4dc6f25f2f523706cf42de5c3f665042311db9dc", size = 1359472 },
380
+ { url = "https://files.pythonhosted.org/packages/0d/fe/d9b6e1a1e4e4d08b3f9b022e92b93abf7baab5c959296faf10aa89cf17b2/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:93580c6dcfb3f4f189c2a8477d9bf262cbc31878cd809c118ddc6b1bb8d6f645", size = 1212271 },
381
+ { url = "https://files.pythonhosted.org/packages/0b/0d/c4de90f7b1aecbc24bacc2ea4582e344043e8587c18596649950e877f5aa/pyjson5-2.0.0-cp314-cp314-win32.whl", hash = "sha256:dc53188059c2a73c8ddd0d17eaf970210a0ba48805e2178dfc8e71c063668d80", size = 118268 },
382
+ { url = "https://files.pythonhosted.org/packages/52/8c/1bb60288c4d480a0b51e376a17d6c4d932dc8420989d1db440e3b284aad5/pyjson5-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:36ab5b8fcf1585623d12519f55e3efddbcbba6a0072e7168b4a3f48e3d4c64bb", size = 137772 },
383
+ { url = "https://files.pythonhosted.org/packages/53/ea/c5e9e5a44b194851347698b5065df642d42852641d32da0c71626f60f3fc/pyjson5-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:371a8ee3d8c5f128f8024c5afc776b661043c2b2672de83a22ed6a4a289522f9", size = 121372 },
384
+ { url = "https://files.pythonhosted.org/packages/05/13/1391b985d3cded0038816d07a5d68e9f525a2b304a258e890bb5a4e2c64a/pyjson5-2.0.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:111d4f3b384a41eae225bce1709c745c1aeafd51214bcd850469c5c34167856c", size = 322542 },
385
+ { url = "https://files.pythonhosted.org/packages/24/c9/391def485564be4700e8baaa9a67292ed64a316050f625b84ef43358fbcc/pyjson5-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:15bc0bc456d2b101c469f57d0301a9624be682302d9ded569d5976c2c3b1130e", size = 169901 },
386
+ { url = "https://files.pythonhosted.org/packages/d7/9c/2612e236a40eac86fba453dc9db1c334b4fb77ac5d1630498b0e3a0fd8d3/pyjson5-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:151ea53ec2ce1c014c58ee755d3113af80dc44cb8ca1008eabb829cd1001ea7b", size = 161759 },
387
+ { url = "https://files.pythonhosted.org/packages/42/6f/f62b823d2e52ee7ddb25761b4bc8286c08199f6d42ddd1f01e8cb48a55a0/pyjson5-2.0.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:92fb2ae9e367fc585f93573222bfa2512c6fe85703658f96adbebd8459b16d0c", size = 184972 },
388
+ { url = "https://files.pythonhosted.org/packages/02/72/2bca65d3ad6f19386fd0e350f66c7153c09173ca9a4742d4108d07e73f78/pyjson5-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a59fcaf3927277a385f17863077d474f7451b1471ddcf6acdd28c76950d4c868", size = 172446 },
389
+ { url = "https://files.pythonhosted.org/packages/48/ec/752cf626a6caa69bf63fea4a7a47c9c57130578de502198105c3e2c5a55f/pyjson5-2.0.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10cc1d0afd26479b2643ad3a67211e98fa72aa66030bbb695bb03d34cea2f801", size = 165790 },
390
+ { url = "https://files.pythonhosted.org/packages/80/a6/1b41a3f87e899d7b1c48e5fb45d1d306c478708806286f113a0495c13261/pyjson5-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c69f3b28b669e26b11766a200b7d0d8bbfbd9a48735e39b9675e8fb8d6a99744", size = 188500 },
391
+ { url = "https://files.pythonhosted.org/packages/c1/da/c9769cff5ce6b1c7e4b7e169fa1191bb2b6562849069ca11f79be6ed98d1/pyjson5-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05d08aeb21bf547e1de4749d22b5638405aca12ba866b762d25d84575d327327", size = 193060 },
392
+ { url = "https://files.pythonhosted.org/packages/31/ef/a97738263b05d91189df4e081d2331389ec95f662d26242f678b53b7d9d7/pyjson5-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:321e107c7df19d281e858bcfdbb39282b8cc1163a1e8c142b9d91af1e1db8573", size = 181832 },
393
+ { url = "https://files.pythonhosted.org/packages/f0/15/2170f05792bddace7136100c30bdf73ec54fbed7ae86eb17f42e882238ec/pyjson5-2.0.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66dceb6b83990bf81accbbc1a56897f1bb302b7da063d5eb2d756f26c4e98389", size = 178943 },
394
+ { url = "https://files.pythonhosted.org/packages/0f/e6/a7f40e1bfa312f1987577c583b4dc1008e05f016585f0858d527e7d6e48d/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2de1242c168735ac589c2ca5708f95bd3d47c50f59464042316b56d77d807cae", size = 1153787 },
395
+ { url = "https://files.pythonhosted.org/packages/cc/e3/4efcc86258a63c5c8af79fd8fe06e0ff98cebcc56facf473dba3318455a3/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:505dd929b620886c4bcf2ba19ca842dc5606ed1ad1fe5003cc09fbd2d910b0ef", size = 1014990 },
396
+ { url = "https://files.pythonhosted.org/packages/e5/15/e7f1bc7aeb2c9f008a83c3e9129b4b16e1e27b2ae463efe05cfc8320ea68/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:48fb751c641fd03b5f002dc47a040aca9eec0a8a9bc11bc77e86dc40a6c3f10e", size = 1322761 },
397
+ { url = "https://files.pythonhosted.org/packages/37/30/d937dfcb8386841571f7eda2b78b716ece4d62a10ce9a71f9dc8e02269fe/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d67186c0a70308da9752202e8dcc6fcf63991d8a2aa4cfa463a587a3cbb6416c", size = 1247709 },
398
+ { url = "https://files.pythonhosted.org/packages/6a/d6/ca54b0953f45bd89317f5069c8cb096df33c391ae2166259c273981c4884/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:0a9c0901313c8cf36f6f72cfc76b3ef335723fd240c869bc80a8711567573252", size = 1185323 },
399
+ { url = "https://files.pythonhosted.org/packages/46/eb/eaa0c7eef752ea2afb192ff3f15cb79fa5229ab22cf84c0b941a0671364f/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:918175822878b4a48949af6fa236ccb2189b6548df14077b97246b61baff2ba7", size = 1360604 },
400
+ { url = "https://files.pythonhosted.org/packages/5f/ca/192931f334270fa941977a9beb2590d40fe460711d932b825c3882f100de/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7a09dac1228517792d8941718194ee5e4aa55ed604e0616938e55d75aedcb0c1", size = 1214048 },
401
+ { url = "https://files.pythonhosted.org/packages/c2/61/63bd6351bd88e7158380eabf182beb377b53c4812175db3cde82fb2ad16e/pyjson5-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:caeee4168841a4d061f0e33cd162ae45fedbe9be9ed3dbd839d76d7791858dcf", size = 138873 },
402
+ { url = "https://files.pythonhosted.org/packages/f6/ee/f856f8e18336a96ad7a7561dc482f776fa3c236ca278820f1ad4d7e04bba/pyjson5-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7121183c7be324bdb6e824fc047ac29ad676025506e3cdbad6def5c4af9247d4", size = 168332 },
403
+ { url = "https://files.pythonhosted.org/packages/62/9d/17ac8aacb439c79a912a57ee105bb060c6c10d40eab587928215e2022e5e/pyjson5-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f5e151599913b0c6e3bc3e176951f48039457e8a4b14f59c1ffffb8580ab58ea", size = 127386 },
404
+ ]
405
+
278
406
  [[package]]
279
407
  name = "pyodide-cli"
280
408
  version = "0.2.4"
@@ -522,11 +650,12 @@ wheels = [
522
650
 
523
651
  [[package]]
524
652
  name = "workers-py"
525
- version = "1.2.1"
653
+ version = "1.4.0"
526
654
  source = { editable = "." }
527
655
  dependencies = [
528
656
  { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
529
657
  { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
658
+ { name = "pyjson5" },
530
659
  { name = "pyodide-cli", version = "0.2.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
531
660
  { name = "pyodide-cli", version = "0.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
532
661
  { name = "rich" },
@@ -551,6 +680,7 @@ dev = [
551
680
  [package.metadata]
552
681
  requires-dist = [
553
682
  { name = "click", specifier = ">=8.0.0,<9.0.0" },
683
+ { name = "pyjson5", specifier = ">=1.6.0" },
554
684
  { name = "pyodide-cli" },
555
685
  { name = "rich", specifier = ">=13.0.0" },
556
686
  { name = "uv", marker = "extra == 'build'", specifier = "~=0.5.23" },
File without changes
File without changes
File without changes
File without changes