workers-py 1.6.1__tar.gz → 1.6.2__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.
Files changed (28) hide show
  1. {workers_py-1.6.1 → workers_py-1.6.2}/.pre-commit-config.yaml +7 -0
  2. {workers_py-1.6.1 → workers_py-1.6.2}/CHANGELOG.md +9 -0
  3. {workers_py-1.6.1 → workers_py-1.6.2}/PKG-INFO +3 -2
  4. {workers_py-1.6.1 → workers_py-1.6.2}/pyproject.toml +28 -14
  5. {workers_py-1.6.1 → workers_py-1.6.2}/src/pywrangler/cli.py +17 -54
  6. workers_py-1.6.2/src/pywrangler/sync.py +299 -0
  7. {workers_py-1.6.1 → workers_py-1.6.2}/src/pywrangler/types.py +5 -4
  8. workers_py-1.6.2/src/pywrangler/utils.py +321 -0
  9. {workers_py-1.6.1 → workers_py-1.6.2}/tests/test_cli.py +95 -122
  10. {workers_py-1.6.1 → workers_py-1.6.2}/tests/test_py_version_detect.py +45 -39
  11. {workers_py-1.6.1 → workers_py-1.6.2}/tests/test_types.py +15 -14
  12. {workers_py-1.6.1 → workers_py-1.6.2}/uv.lock +25 -207
  13. workers_py-1.6.1/src/pywrangler/sync.py +0 -433
  14. workers_py-1.6.1/src/pywrangler/utils.py +0 -114
  15. {workers_py-1.6.1 → workers_py-1.6.2}/.gitattributes +0 -0
  16. {workers_py-1.6.1 → workers_py-1.6.2}/.github/workflows/commitlint.yml +0 -0
  17. {workers_py-1.6.1 → workers_py-1.6.2}/.github/workflows/lint.yml +0 -0
  18. {workers_py-1.6.1 → workers_py-1.6.2}/.github/workflows/release.yml +0 -0
  19. {workers_py-1.6.1 → workers_py-1.6.2}/.github/workflows/tests.yml +0 -0
  20. {workers_py-1.6.1 → workers_py-1.6.2}/.gitignore +0 -0
  21. {workers_py-1.6.1 → workers_py-1.6.2}/CLAUDE.md +0 -0
  22. {workers_py-1.6.1 → workers_py-1.6.2}/CONTRIBUTING.md +0 -0
  23. {workers_py-1.6.1 → workers_py-1.6.2}/README.md +0 -0
  24. {workers_py-1.6.1 → workers_py-1.6.2}/src/pywrangler/__init__.py +0 -0
  25. {workers_py-1.6.1 → workers_py-1.6.2}/src/pywrangler/__main__.py +0 -0
  26. {workers_py-1.6.1 → workers_py-1.6.2}/src/pywrangler/metadata.py +1 -1
  27. /workers_py-1.6.1/tests/__init__.py → /workers_py-1.6.2/src/pywrangler/py.typed +0 -0
  28. {workers_py-1.6.1 → workers_py-1.6.2}/workers.py +0 -0
@@ -37,5 +37,12 @@ repos:
37
37
  "--ignore-words-list",
38
38
  "ommit",
39
39
  ]
40
+ - repo: https://github.com/pre-commit/mirrors-mypy
41
+ rev: "v1.14.1"
42
+ hooks:
43
+ - id: mypy
44
+ exclude: (.*test.*)
45
+ additional_dependencies:
46
+ - click
40
47
  ci:
41
48
  autoupdate_schedule: "quarterly"
@@ -2,6 +2,15 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.6.2 (2025-10-22)
6
+
7
+ ### Bug Fixes
8
+
9
+ - Add workers-runtime-sdk as a dependency, update type test
10
+ ([#41](https://github.com/cloudflare/workers-py/pull/41),
11
+ [`f381505`](https://github.com/cloudflare/workers-py/commit/f381505e4c9b40ddb602928d964aa3fe38936e5c))
12
+
13
+
5
14
  ## v1.6.1 (2025-10-15)
6
15
 
7
16
  ### Bug Fixes
@@ -1,18 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workers-py
3
- Version: 1.6.1
3
+ Version: 1.6.2
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
7
7
  Classifier: License :: OSI Approved :: MIT License
8
8
  Classifier: Operating System :: OS Independent
9
9
  Classifier: Programming Language :: Python :: 3
10
- Requires-Python: >=3.10
10
+ Requires-Python: >=3.12
11
11
  Requires-Dist: click<9.0.0,>=8.0.0
12
12
  Requires-Dist: pyjson5>=1.6.0
13
13
  Requires-Dist: pyodide-cli
14
14
  Requires-Dist: pyodide-py
15
15
  Requires-Dist: rich>=13.0.0
16
+ Requires-Dist: workers-runtime-sdk>=0.1.0
16
17
  Provides-Extra: build
17
18
  Requires-Dist: uv~=0.5.23; extra == 'build'
18
19
  Description-Content-Type: text/markdown
@@ -4,10 +4,10 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "workers-py"
7
- version = "1.6.1"
7
+ version = "1.6.2"
8
8
  description = "A set of libraries and tools for Python Workers"
9
9
  readme = "README.md"
10
- requires-python = ">=3.10"
10
+ requires-python = ">=3.12"
11
11
  classifiers = [
12
12
  "Programming Language :: Python :: 3",
13
13
  "License :: OSI Approved :: MIT License",
@@ -19,6 +19,7 @@ dependencies = [
19
19
  "pyodide-cli",
20
20
  "pyjson5>=1.6.0",
21
21
  "pyodide-py",
22
+ "workers-runtime-sdk>=0.1.0",
22
23
  ]
23
24
 
24
25
  [dependency-groups]
@@ -42,20 +43,33 @@ pywrangler = "pywrangler.cli:app"
42
43
  "Bug Tracker" = "https://github.com/cloudflare/workers-py/issues"
43
44
 
44
45
  [tool.ruff]
45
- target-version = "py38"
46
- src = ["src", "tests"]
47
- lint.select = ["E", "F"]
48
- lint.ignore = ["E501"] # Line too long
46
+ target-version = "py312"
47
+ lint.select = [
48
+ "B0", # bugbear (all B0* checks enabled by default)
49
+ "B904", # bugbear (Within an except clause, raise exceptions with raise ... from err)
50
+ "B905", # bugbear (zip() without an explicit strict= parameter set.)
51
+ "C4", # flake8-comprehensions
52
+ "C9", # mccabe complexity
53
+ "E", # pycodestyles
54
+ "F", # pyflakes
55
+ "I", # isort
56
+ "PERF", # Perflint
57
+ "PGH", # pygrep-hooks
58
+ "PL", # Pylint
59
+ "UP", # pyupgrade
60
+ "W", # pycodestyles
61
+ ]
62
+ lint.ignore = ["E402", "E501", "E731", "E741", "PLW2901", "UP031"]
63
+ lint.flake8-comprehensions.allow-dict-calls-with-keyword-arguments = true
49
64
 
50
65
  [tool.mypy]
51
- python_version = "3.8"
52
- warn_return_any = true
53
- warn_unused_configs = true
54
- disallow_untyped_defs = true
55
- disallow_incomplete_defs = true
56
- disallow_untyped_decorators = false
57
- check_untyped_defs = true
58
- disallow_any_generics = false
66
+ packages = ["pywrangler"]
67
+ python_version = "3.12"
68
+
69
+ show_error_codes = true
70
+
71
+ strict = true
72
+ warn_unreachable = true
59
73
  no_implicit_optional = true
60
74
 
61
75
  [[tool.mypy.overrides]]
@@ -2,13 +2,17 @@ import logging
2
2
  import subprocess
3
3
  import sys
4
4
  import textwrap
5
+ from typing import Never
6
+
5
7
  import click
6
8
 
9
+ from .sync import sync
7
10
  from .utils import (
8
- setup_logging,
9
- write_success,
10
11
  WRANGLER_COMMAND,
11
12
  WRANGLER_CREATE_COMMAND,
13
+ check_wrangler_version,
14
+ setup_logging,
15
+ write_success,
12
16
  )
13
17
 
14
18
  setup_logging()
@@ -16,7 +20,7 @@ logger = logging.getLogger("pywrangler")
16
20
 
17
21
 
18
22
  class ProxyToWranglerGroup(click.Group):
19
- def get_help(self, ctx):
23
+ def get_help(self, ctx: click.Context) -> str:
20
24
  """Override to add custom help content."""
21
25
  # Get the default help text
22
26
  help_text = super().get_help(ctx)
@@ -28,6 +32,7 @@ class ProxyToWranglerGroup(click.Group):
28
32
  capture_output=True,
29
33
  text=True,
30
34
  timeout=10,
35
+ check=False,
31
36
  )
32
37
  if result.returncode == 0:
33
38
  wrangler_help = result.stdout
@@ -47,7 +52,7 @@ class ProxyToWranglerGroup(click.Group):
47
52
 
48
53
  return help_text
49
54
 
50
- def get_command(self, ctx, cmd_name):
55
+ def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command:
51
56
  command = super().get_command(ctx, cmd_name)
52
57
 
53
58
  if command is None:
@@ -58,11 +63,9 @@ class ProxyToWranglerGroup(click.Group):
58
63
  remaining_args = []
59
64
 
60
65
  if cmd_name in ["dev", "publish", "deploy", "versions"]:
61
- ctx.invoke(sync_command, force=False, directly_requested=False)
66
+ sync(force=False)
62
67
 
63
68
  if cmd_name == "dev":
64
- from .sync import check_wrangler_version
65
-
66
69
  check_wrangler_version()
67
70
 
68
71
  if cmd_name == "init":
@@ -78,7 +81,7 @@ class ProxyToWranglerGroup(click.Group):
78
81
  return command
79
82
 
80
83
 
81
- def get_version():
84
+ def get_version() -> str:
82
85
  """Get the version of pywrangler."""
83
86
  try:
84
87
  from importlib.metadata import version
@@ -91,8 +94,7 @@ def get_version():
91
94
  @click.group(cls=ProxyToWranglerGroup)
92
95
  @click.option("--debug", is_flag=True, help="Enable debug logging")
93
96
  @click.version_option(version=get_version(), prog_name="pywrangler")
94
- @click.pass_context
95
- def app(ctx, debug=False):
97
+ def app(debug: bool = False) -> None:
96
98
  """
97
99
  A CLI tool for Cloudflare Workers.
98
100
  Use 'sync' command for Python package setup.
@@ -118,7 +120,7 @@ def app(ctx, debug=False):
118
120
  type=click.Path(exists=True, dir_okay=False, readable=True),
119
121
  help="Path to Wrangler configuration file",
120
122
  )
121
- def types_command(outdir=None, config=None):
123
+ def types_command(outdir: str | None, config: str | None) -> Never:
122
124
  from .types import wrangler_types
123
125
 
124
126
  wrangler_types(outdir, config)
@@ -127,56 +129,17 @@ def types_command(outdir=None, config=None):
127
129
 
128
130
  @app.command("sync")
129
131
  @click.option("--force", is_flag=True, help="Force sync even if no changes detected")
130
- def sync_command(force=False, directly_requested=True):
132
+ def sync_command(force: bool = False) -> None:
131
133
  """
132
134
  Installs Python packages from pyproject.toml into src/vendor.
133
135
 
134
136
  Also creates a virtual env for Workers that you can use for testing.
135
137
  """
136
- # This module is imported locally because it searches for pyproject.toml at the top-level.
137
- from .sync import (
138
- check_requirements_txt,
139
- check_wrangler_config,
140
- is_sync_needed,
141
- create_pyodide_venv,
142
- create_workers_venv,
143
- parse_requirements,
144
- install_requirements,
145
- )
146
-
147
- # Check if requirements.txt does not exist.
148
- check_requirements_txt()
149
-
150
- # Check if sync is needed based on file timestamps
151
- sync_needed = force or is_sync_needed()
152
- if not sync_needed:
153
- if directly_requested:
154
- logger.warning(
155
- "pyproject.toml hasn't changed since last sync, use --force to ignore timestamp check"
156
- )
157
- return
158
-
159
- # Check to make sure a wrangler config file exists.
160
- check_wrangler_config()
161
-
162
- # Create .venv-workers if it doesn't exist
163
- create_workers_venv()
164
-
165
- # Set up Pyodide virtual env
166
- create_pyodide_venv()
167
-
168
- # Generate requirements.txt from pyproject.toml by directly parsing the TOML file then install into vendor folder.
169
- requirements = parse_requirements()
170
- if not requirements:
171
- logger.warning(
172
- "No dependencies found in [project.dependencies] section of pyproject.toml."
173
- )
174
- install_requirements(requirements)
175
-
138
+ sync(force, directly_requested=True)
176
139
  write_success("Sync process completed successfully.")
177
140
 
178
141
 
179
- def _proxy_to_wrangler(command_name, args_list):
142
+ def _proxy_to_wrangler(command_name: str, args_list: list[str]) -> Never:
180
143
  command_to_run = WRANGLER_COMMAND + [command_name] + args_list
181
144
  logger.info(f"Passing command to npx wrangler: {' '.join(command_to_run)}")
182
145
  try:
@@ -189,7 +152,7 @@ def _proxy_to_wrangler(command_name, args_list):
189
152
  click.get_current_context().exit(1)
190
153
 
191
154
 
192
- def _proxy_to_create_cloudflare(args_list):
155
+ def _proxy_to_create_cloudflare(args_list: list[str]) -> Never:
193
156
  command_to_run = WRANGLER_CREATE_COMMAND + args_list
194
157
  logger.info(f"Passing command to npx create-cloudflare: {' '.join(command_to_run)}")
195
158
  try:
@@ -0,0 +1,299 @@
1
+ import logging
2
+ import os
3
+ import shutil
4
+ import tempfile
5
+ from collections.abc import Iterator
6
+ from contextlib import contextmanager
7
+ from pathlib import Path
8
+
9
+ import click
10
+
11
+ from .utils import (
12
+ check_uv_version,
13
+ check_wrangler_config,
14
+ find_pyproject_toml,
15
+ get_project_root,
16
+ get_pyodide_index,
17
+ get_python_version,
18
+ get_uv_pyodide_interp_name,
19
+ read_pyproject_toml,
20
+ run_command,
21
+ )
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ def get_venv_workers_path() -> Path:
27
+ return get_project_root() / ".venv-workers"
28
+
29
+
30
+ def get_venv_workers_token_path() -> Path:
31
+ return get_venv_workers_path() / ".synced"
32
+
33
+
34
+ def get_vendor_token_path() -> Path:
35
+ return get_project_root() / "python_modules/.synced"
36
+
37
+
38
+ def get_pyodide_venv_path() -> Path:
39
+ return get_venv_workers_path() / "pyodide-venv"
40
+
41
+
42
+ def check_requirements_txt() -> None:
43
+ old_requirements_txt = get_project_root() / "requirements.txt"
44
+ if old_requirements_txt.is_file():
45
+ with open(old_requirements_txt) as f:
46
+ requirements = f.read().splitlines()
47
+ logger.warning(
48
+ "Specifying Python Packages in requirements.txt is no longer supported, please use pyproject.toml instead.\n"
49
+ + "Put the following in your pyproject.toml to vendor the packages currently in your requirements.txt:"
50
+ )
51
+ pyproject_text = "dependencies = [\n"
52
+ pyproject_text += ",\n".join([f' "{x}"' for x in requirements])
53
+ pyproject_text += "\n]"
54
+ logger.warning(pyproject_text)
55
+
56
+ logger.error(
57
+ f"{old_requirements_txt} exists. Delete the file to continue. Exiting."
58
+ )
59
+ raise click.exceptions.Exit(code=1)
60
+
61
+
62
+ def _get_venv_python_version() -> str | None:
63
+ """
64
+ Retrieves the Python version from the virtual environment.
65
+
66
+ Returns:
67
+ The Python version string or None if it cannot be determined.
68
+ """
69
+ venv_workers_path = get_venv_workers_path()
70
+ venv_python = (
71
+ venv_workers_path / "Scripts" / "python.exe"
72
+ if os.name == "nt"
73
+ else venv_workers_path / "bin" / "python"
74
+ )
75
+ if not venv_python.is_file():
76
+ return None
77
+
78
+ result = run_command(
79
+ [str(venv_python), "--version"], check=False, capture_output=True
80
+ )
81
+ if result.returncode != 0:
82
+ return None
83
+
84
+ return result.stdout.strip()
85
+
86
+
87
+ def create_workers_venv() -> None:
88
+ """
89
+ Creates a virtual environment at `venv_workers_path` if it doesn't exist.
90
+ """
91
+ wanted_python_version = get_python_version()
92
+ logger.debug(f"Using python version from wrangler config: {wanted_python_version}")
93
+
94
+ venv_workers_path = get_venv_workers_path()
95
+ if venv_workers_path.is_dir():
96
+ installed_version = _get_venv_python_version()
97
+ if installed_version:
98
+ if wanted_python_version in installed_version:
99
+ logger.debug(
100
+ f"Virtual environment at {venv_workers_path} already exists."
101
+ )
102
+ return
103
+
104
+ logger.warning(
105
+ f"Recreating virtual environment at {venv_workers_path} due to Python version mismatch. "
106
+ f"Found {installed_version}, expected {wanted_python_version}"
107
+ )
108
+ else:
109
+ logger.warning(
110
+ f"Could not determine python version for {venv_workers_path}, recreating."
111
+ )
112
+
113
+ shutil.rmtree(venv_workers_path)
114
+
115
+ logger.debug(f"Creating virtual environment at {venv_workers_path}...")
116
+ run_command(
117
+ [
118
+ "uv",
119
+ "venv",
120
+ str(venv_workers_path),
121
+ "--python",
122
+ f"python{wanted_python_version}",
123
+ ]
124
+ )
125
+
126
+
127
+ def create_pyodide_venv() -> None:
128
+ pyodide_venv_path = get_pyodide_venv_path()
129
+ if pyodide_venv_path.is_dir():
130
+ logger.debug(
131
+ f"Pyodide virtual environment at {pyodide_venv_path} already exists."
132
+ )
133
+ return
134
+
135
+ check_uv_version()
136
+ logger.debug(f"Creating Pyodide virtual environment at {pyodide_venv_path}...")
137
+ pyodide_venv_path.parent.mkdir(parents=True, exist_ok=True)
138
+ interp_name = get_uv_pyodide_interp_name()
139
+ run_command(["uv", "python", "install", interp_name])
140
+ run_command(["uv", "venv", pyodide_venv_path, "--python", interp_name])
141
+
142
+
143
+ def parse_requirements() -> list[str]:
144
+ pyproject_data = read_pyproject_toml()
145
+
146
+ # Extract dependencies from [project.dependencies]
147
+ dependencies = pyproject_data.get("project", {}).get("dependencies", [])
148
+
149
+ logger.info(f"Found {len(dependencies)} dependencies.")
150
+ return dependencies
151
+
152
+
153
+ @contextmanager
154
+ def temp_requirements_file(requirements: list[str]) -> Iterator[str]:
155
+ # Write dependencies to a requirements.txt-style temp file.
156
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".txt") as temp_file:
157
+ temp_file.write("\n".join(requirements))
158
+ temp_file.flush()
159
+ yield temp_file.name
160
+
161
+
162
+ def _install_requirements_to_vendor(requirements: list[str]) -> None:
163
+ vendor_path = get_project_root() / "python_modules"
164
+ logger.debug(f"Using vendor path: {vendor_path}")
165
+
166
+ if len(requirements) == 0:
167
+ logger.warning(
168
+ f"Requirements list is empty. No dependencies to install in {vendor_path}."
169
+ )
170
+ return
171
+
172
+ # Install packages into vendor directory
173
+ vendor_path.mkdir(parents=True, exist_ok=True)
174
+ relative_vendor_path = vendor_path.relative_to(get_project_root())
175
+ logger.info(
176
+ f"Installing packages into [bold]{relative_vendor_path}[/bold]...",
177
+ extra={"markup": True},
178
+ )
179
+ with temp_requirements_file(requirements) as requirements_file:
180
+ run_command(
181
+ [
182
+ "uv",
183
+ "pip",
184
+ "install",
185
+ "--no-build",
186
+ "-r",
187
+ requirements_file,
188
+ "--extra-index-url",
189
+ get_pyodide_index(),
190
+ "--index-strategy",
191
+ "unsafe-best-match",
192
+ ],
193
+ env=os.environ | {"VIRTUAL_ENV": get_pyodide_venv_path()},
194
+ )
195
+ pyv = get_python_version()
196
+ shutil.rmtree(vendor_path)
197
+ shutil.copytree(
198
+ get_pyodide_venv_path() / f"lib/python{pyv}/site-packages", vendor_path
199
+ )
200
+
201
+ # Create a pyvenv.cfg file in python_modules to mark it as a virtual environment
202
+ (vendor_path / "pyvenv.cfg").touch()
203
+ get_vendor_token_path().touch()
204
+
205
+ logger.info(
206
+ f"Packages installed in [bold]{relative_vendor_path}[/bold].",
207
+ extra={"markup": True},
208
+ )
209
+
210
+
211
+ def _install_requirements_to_venv(requirements: list[str]) -> None:
212
+ # Create a requirements file for .venv-workers that includes pyodide-py
213
+ venv_workers_path = get_venv_workers_path()
214
+ project_root = get_project_root()
215
+ relative_venv_workers_path = venv_workers_path.relative_to(project_root)
216
+ requirements = requirements.copy()
217
+ requirements.append("pyodide-py")
218
+
219
+ logger.info(
220
+ f"Installing packages into [bold]{relative_venv_workers_path}[/bold]...",
221
+ extra={"markup": True},
222
+ )
223
+ with temp_requirements_file(requirements) as requirements_file:
224
+ run_command(
225
+ [
226
+ "uv",
227
+ "pip",
228
+ "install",
229
+ "-r",
230
+ requirements_file,
231
+ ],
232
+ env=os.environ | {"VIRTUAL_ENV": venv_workers_path},
233
+ )
234
+
235
+ get_venv_workers_token_path().touch()
236
+ logger.info(
237
+ f"Packages installed in [bold]{relative_venv_workers_path}[/bold].",
238
+ extra={"markup": True},
239
+ )
240
+
241
+
242
+ def install_requirements(requirements: list[str]) -> None:
243
+ _install_requirements_to_vendor(requirements)
244
+ _install_requirements_to_venv(requirements)
245
+
246
+
247
+ def _is_out_of_date(token: Path, time: float) -> bool:
248
+ if not token.exists():
249
+ return True
250
+ return time > token.stat().st_mtime
251
+
252
+
253
+ def is_sync_needed() -> bool:
254
+ """
255
+ Checks if pyproject.toml has been modified since the last sync.
256
+
257
+ Returns:
258
+ bool: True if sync is needed, False otherwise
259
+ """
260
+ pyproject_toml_path = find_pyproject_toml()
261
+ if not pyproject_toml_path.is_file():
262
+ # If pyproject.toml doesn't exist, we need to abort anyway
263
+ return True
264
+
265
+ pyproject_mtime = pyproject_toml_path.stat().st_mtime
266
+ return _is_out_of_date(get_vendor_token_path(), pyproject_mtime) or _is_out_of_date(
267
+ get_venv_workers_token_path(), pyproject_mtime
268
+ )
269
+
270
+
271
+ def sync(force: bool = False, directly_requested: bool = False) -> None:
272
+ # Check if requirements.txt does not exist.
273
+ check_requirements_txt()
274
+
275
+ # Check if sync is needed based on file timestamps
276
+ sync_needed = force or is_sync_needed()
277
+ if not sync_needed:
278
+ if directly_requested:
279
+ logger.warning(
280
+ "pyproject.toml hasn't changed since last sync, use --force to ignore timestamp check"
281
+ )
282
+ return
283
+
284
+ # Check to make sure a wrangler config file exists.
285
+ check_wrangler_config()
286
+
287
+ # Create .venv-workers if it doesn't exist
288
+ create_workers_venv()
289
+
290
+ # Set up Pyodide virtual env
291
+ create_pyodide_venv()
292
+
293
+ # Generate requirements.txt from pyproject.toml by directly parsing the TOML file then install into vendor folder.
294
+ requirements = parse_requirements()
295
+ if not requirements:
296
+ logger.warning(
297
+ "No dependencies found in [project.dependencies] section of pyproject.toml."
298
+ )
299
+ install_requirements(requirements)
@@ -1,7 +1,8 @@
1
- from .utils import WRANGLER_COMMAND, run_command
2
- from tempfile import TemporaryDirectory
3
- from pathlib import Path
4
1
  import logging
2
+ from pathlib import Path
3
+ from tempfile import TemporaryDirectory
4
+
5
+ from .utils import WRANGLER_COMMAND, run_command
5
6
 
6
7
  logger = logging.getLogger(__name__)
7
8
 
@@ -26,7 +27,7 @@ PACKAGE_JSON = """
26
27
  """
27
28
 
28
29
 
29
- def wrangler_types(outdir_arg: str | None, config: str | None, /):
30
+ def wrangler_types(outdir_arg: str | None, config: str | None, /) -> None:
30
31
  args = ["types"]
31
32
  if config:
32
33
  args += ["--config", config]