uv-pack 0.0.1__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uv_pack/__init__.py +195 -239
- uv_pack/_build.py +46 -0
- uv_pack/_download.py +44 -150
- uv_pack/_export.py +48 -0
- uv_pack/_files.py +56 -0
- uv_pack/_logging.py +46 -0
- uv_pack/_process.py +33 -17
- uv_pack/_python.py +203 -0
- uv_pack/{_unpack.py → _scripts.py} +19 -2
- uv_pack-0.1.1.dist-info/METADATA +210 -0
- uv_pack-0.1.1.dist-info/RECORD +19 -0
- {uv_pack-0.0.1.dist-info → uv_pack-0.1.1.dist-info}/WHEEL +1 -1
- uv_pack-0.0.1.dist-info/METADATA +0 -140
- uv_pack-0.0.1.dist-info/RECORD +0 -14
- {uv_pack-0.0.1.dist-info → uv_pack-0.1.1.dist-info}/entry_points.txt +0 -0
uv_pack/__init__.py
CHANGED
|
@@ -1,218 +1,113 @@
|
|
|
1
1
|
"""uv-pack: Bundle a locked uv environment into an offline-installable bundle.
|
|
2
2
|
|
|
3
3
|
Pipeline:
|
|
4
|
-
1.
|
|
5
|
-
2.
|
|
6
|
-
3.
|
|
7
|
-
4.
|
|
4
|
+
1. Clean the output directory
|
|
5
|
+
2. Export locked requirements via uv
|
|
6
|
+
3. Download third-party wheels into ./wheels
|
|
7
|
+
4. Build local workspace packages into ./vendor
|
|
8
8
|
5. Download a python interpreter to ./python
|
|
9
9
|
|
|
10
10
|
Result:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
pack/
|
|
12
|
+
├── requirements.txt
|
|
13
|
+
├── wheels/ # third-party wheels
|
|
14
|
+
│ └── requirements.txt # index packages
|
|
15
|
+
├── vendor/ # locally built wheels
|
|
16
|
+
│ └── requirements.txt # local packages
|
|
17
|
+
├── python/ # python interpreter
|
|
18
|
+
├── unpack.sh
|
|
19
|
+
├── unpack.ps1
|
|
20
|
+
├── unpack.bat
|
|
21
|
+
├── .gitignore
|
|
22
|
+
└── README.md
|
|
16
23
|
"""
|
|
17
24
|
|
|
18
25
|
import shutil
|
|
19
|
-
import
|
|
26
|
+
from collections.abc import Iterable
|
|
27
|
+
from enum import Enum
|
|
20
28
|
from pathlib import Path
|
|
21
|
-
from typing import Literal
|
|
22
29
|
|
|
23
30
|
import typer
|
|
24
|
-
from packaging.utils import parse_wheel_filename
|
|
25
|
-
from rich.console import Console
|
|
26
31
|
|
|
27
|
-
from .
|
|
28
|
-
from .
|
|
29
|
-
from .
|
|
32
|
+
from uv_pack._build import build_requirements, build_src_wheel
|
|
33
|
+
from uv_pack._download import download_third_party_wheels
|
|
34
|
+
from uv_pack._export import export_local_requirements, export_requirements
|
|
35
|
+
from uv_pack._files import PackLayout
|
|
36
|
+
from uv_pack._logging import ConsoleError, Verbosity, console_print, set_verbosity
|
|
37
|
+
from uv_pack._process import run_step
|
|
38
|
+
from uv_pack._python import download_latest_python_build
|
|
39
|
+
from uv_pack._scripts import copy_unpack_scripts
|
|
30
40
|
|
|
31
41
|
# -----------------------------------------------------------------------------
|
|
32
42
|
# CLI setup
|
|
33
43
|
# -----------------------------------------------------------------------------
|
|
34
44
|
|
|
35
|
-
app: typer.Typer = typer.Typer()
|
|
36
|
-
console = Console(force_terminal=True, legacy_windows=False)
|
|
45
|
+
app: typer.Typer = typer.Typer(add_completion=True)
|
|
37
46
|
|
|
38
47
|
|
|
39
48
|
def main() -> None:
|
|
40
|
-
"""Main entry point
|
|
41
|
-
app()
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def get_version() -> str:
|
|
45
|
-
"""Return the package version or "unknown" if no version can be found."""
|
|
46
|
-
from importlib import metadata # noqa: PLC0415
|
|
47
|
-
|
|
49
|
+
"""Main entry point for uv-pack CLI."""
|
|
48
50
|
try:
|
|
49
|
-
|
|
50
|
-
except
|
|
51
|
-
|
|
51
|
+
app()
|
|
52
|
+
except ConsoleError:
|
|
53
|
+
raise # already formatted for user
|
|
54
|
+
except KeyboardInterrupt as err:
|
|
55
|
+
console_print("[yellow]Interrupted by user[/yellow]")
|
|
56
|
+
raise typer.Exit(130) from err
|
|
57
|
+
except Exception as err:
|
|
58
|
+
msg = (
|
|
59
|
+
"[bold red]✘ An unexpected internal error occurred, please try again or"
|
|
60
|
+
" open an issue https://github.com/davnn/uv-pack/issues.[/bold red]"
|
|
61
|
+
)
|
|
62
|
+
raise ConsoleError(msg) from err
|
|
52
63
|
|
|
53
64
|
|
|
54
65
|
# -----------------------------------------------------------------------------
|
|
55
|
-
#
|
|
66
|
+
# Step model
|
|
56
67
|
# -----------------------------------------------------------------------------
|
|
57
68
|
|
|
58
69
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
output_directory: Path,
|
|
62
|
-
include_dev: bool,
|
|
63
|
-
other_args: str,
|
|
64
|
-
) -> Path:
|
|
65
|
-
"""Export a frozen requirements.txt using uv and prepend index URLs."""
|
|
66
|
-
output_directory.mkdir(parents=True, exist_ok=True)
|
|
67
|
-
requirements_file = output_directory / "requirements.txt"
|
|
68
|
-
|
|
69
|
-
cmd: list[str] = [
|
|
70
|
-
"uv",
|
|
71
|
-
"export",
|
|
72
|
-
"--quiet",
|
|
73
|
-
"--no-hashes",
|
|
74
|
-
"--no-emit-local",
|
|
75
|
-
"--format=requirements.txt",
|
|
76
|
-
f"--output-file={requirements_file}",
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
if not include_dev:
|
|
80
|
-
cmd.append("--no-dev")
|
|
81
|
-
for arg in other_args.split():
|
|
82
|
-
cmd.append(arg)
|
|
83
|
-
|
|
84
|
-
result = run_cmd(cmd, cmd_name="uv export")
|
|
85
|
-
exit_on_error(result, console)
|
|
86
|
-
|
|
87
|
-
return requirements_file
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def download_third_party_wheels(
|
|
91
|
-
*,
|
|
92
|
-
requirements_file: Path,
|
|
93
|
-
wheels_directory: Path,
|
|
94
|
-
other_args: str,
|
|
95
|
-
) -> None:
|
|
96
|
-
"""Download third-party binary wheels using pip via uv.
|
|
97
|
-
|
|
98
|
-
Wheels are stored in ./wheels.
|
|
99
|
-
"""
|
|
100
|
-
wheels_directory.mkdir(parents=True, exist_ok=True)
|
|
101
|
-
|
|
102
|
-
cmd = [
|
|
103
|
-
"uv", "run", "--with", "pip",
|
|
104
|
-
"python", "-m", "pip", "download",
|
|
105
|
-
"--prefer-binary",
|
|
106
|
-
"--no-deps",
|
|
107
|
-
"--disable-pip-version-check",
|
|
108
|
-
"-r", str(requirements_file),
|
|
109
|
-
"-d", str(wheels_directory),
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
for arg in other_args.split():
|
|
113
|
-
cmd.append(arg)
|
|
114
|
-
|
|
115
|
-
result = run_cmd(cmd, cmd_name="pip download")
|
|
116
|
-
exit_on_error(result, console)
|
|
70
|
+
class Step(str, Enum):
|
|
71
|
+
"""Steps to be performed in the pack pipeline."""
|
|
117
72
|
|
|
73
|
+
clean = "clean"
|
|
74
|
+
export = "export"
|
|
75
|
+
download = "download"
|
|
76
|
+
build = "build"
|
|
77
|
+
python = "python"
|
|
118
78
|
|
|
119
|
-
def build_vendor_wheels(*, vendor_directory: Path, other_args: str) -> None:
|
|
120
|
-
"""Build wheels for all local workspace packages.
|
|
121
79
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
80
|
+
PIPELINE_ORDER: tuple[Step, ...] = (
|
|
81
|
+
Step.clean,
|
|
82
|
+
Step.export,
|
|
83
|
+
Step.download,
|
|
84
|
+
Step.build,
|
|
85
|
+
Step.python,
|
|
86
|
+
)
|
|
125
87
|
|
|
126
|
-
cmd = [
|
|
127
|
-
"uv",
|
|
128
|
-
"build",
|
|
129
|
-
"--all-packages",
|
|
130
|
-
"--wheel",
|
|
131
|
-
"--out-dir",
|
|
132
|
-
str(vendor_directory),
|
|
133
|
-
]
|
|
134
88
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
result = run_cmd(cmd, cmd_name="uv build")
|
|
139
|
-
exit_on_error(result, console)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def build_src_wheel(*, sdist_file: Path, other_args: str) -> None:
|
|
143
|
-
"""Build wheel for all identified source distribution.
|
|
89
|
+
# -----------------------------------------------------------------------------
|
|
90
|
+
# Helper operations
|
|
91
|
+
# -----------------------------------------------------------------------------
|
|
144
92
|
|
|
145
|
-
Wheels is stored in ./wheels.
|
|
146
|
-
"""
|
|
147
|
-
wheels_dir = sdist_file.parent
|
|
148
|
-
cmd = [
|
|
149
|
-
"uv",
|
|
150
|
-
"build",
|
|
151
|
-
str(sdist_file),
|
|
152
|
-
"--wheel",
|
|
153
|
-
"--out-dir",
|
|
154
|
-
str(wheels_dir),
|
|
155
|
-
]
|
|
156
93
|
|
|
157
|
-
|
|
158
|
-
|
|
94
|
+
def _additional_cli_args(cmd_name: str) -> str:
|
|
95
|
+
return f"Additional command line arguments to be provided to '{cmd_name}'"
|
|
159
96
|
|
|
160
|
-
result = run_cmd(cmd, cmd_name="uv build")
|
|
161
|
-
exit_on_error(result, console)
|
|
162
97
|
|
|
98
|
+
def _normalize_steps(
|
|
99
|
+
steps: Iterable[Step] | None,
|
|
100
|
+
skip: Iterable[Step] | None,
|
|
101
|
+
) -> list[Step]:
|
|
102
|
+
selected = set(PIPELINE_ORDER) if steps is None else set(steps)
|
|
103
|
+
selected = selected.difference([] if skip is None else set(skip))
|
|
104
|
+
return [step for step in PIPELINE_ORDER if step in selected]
|
|
163
105
|
|
|
164
|
-
def finalize_requirements(
|
|
165
|
-
*,
|
|
166
|
-
requirements_file: Path,
|
|
167
|
-
vendor_directory: Path,
|
|
168
|
-
) -> None:
|
|
169
|
-
"""Finalize requirements.txt to pin vendor wheels."""
|
|
170
|
-
vendor_pins: list[str] = []
|
|
171
|
-
|
|
172
|
-
for wheel in vendor_directory.glob("*.whl"):
|
|
173
|
-
name, version, *_ = parse_wheel_filename(wheel.name)
|
|
174
|
-
vendor_pins.append(f"{name}=={version}")
|
|
175
|
-
|
|
176
|
-
original = requirements_file.read_text(encoding="utf-8")
|
|
177
|
-
footer = "\n".join(
|
|
178
|
-
[
|
|
179
|
-
"# This part was autogenerated by uv-pack via the following command:",
|
|
180
|
-
f"# uv-pack {' '.join(sys.argv[1:])}",
|
|
181
|
-
*sorted(set(vendor_pins)),
|
|
182
|
-
],
|
|
183
|
-
)
|
|
184
106
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
def download_latest_python_build(
|
|
192
|
-
*,
|
|
193
|
-
python_version: str,
|
|
194
|
-
target_arch: str,
|
|
195
|
-
dest_dir: Path,
|
|
196
|
-
target_format: Literal["install_only", "install_only_stripped"] = "install_only_stripped",
|
|
197
|
-
) -> Path:
|
|
198
|
-
"""Resolve and download the latest python-build-standalone artifact.
|
|
199
|
-
|
|
200
|
-
Returns the downloaded file path.
|
|
201
|
-
"""
|
|
202
|
-
session = session_with_retries()
|
|
203
|
-
url = find_latest_python_build(
|
|
204
|
-
python_version=python_version,
|
|
205
|
-
target_arch=target_arch,
|
|
206
|
-
target_format=target_format,
|
|
207
|
-
session=session,
|
|
208
|
-
)
|
|
209
|
-
console.print(f"[dim]Resolved asset:[/dim] {url}")
|
|
210
|
-
return download_with_progress(
|
|
211
|
-
url=url,
|
|
212
|
-
dest_dir=dest_dir,
|
|
213
|
-
console=console,
|
|
214
|
-
session=session,
|
|
215
|
-
)
|
|
107
|
+
def _raise_requirement_txt_missing(path: Path) -> None:
|
|
108
|
+
if not path.exists():
|
|
109
|
+
msg = f"[bold red]✘ No requirements file found:[/bold red] '{path}', did you skip the 'export' step?"
|
|
110
|
+
raise ConsoleError(msg)
|
|
216
111
|
|
|
217
112
|
|
|
218
113
|
# -----------------------------------------------------------------------------
|
|
@@ -223,80 +118,141 @@ def download_latest_python_build(
|
|
|
223
118
|
@app.command()
|
|
224
119
|
def pack(
|
|
225
120
|
*,
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
121
|
+
steps: list[Step] | None = typer.Argument(
|
|
122
|
+
PIPELINE_ORDER,
|
|
123
|
+
help="Pipeline steps to run (multiple can be whitespace-separated)",
|
|
124
|
+
),
|
|
125
|
+
skip: list[Step] | None = typer.Option(
|
|
126
|
+
None,
|
|
127
|
+
"--skip",
|
|
128
|
+
"-s",
|
|
129
|
+
help="Pipeline steps to skip (can be supplied multiple times)",
|
|
130
|
+
),
|
|
131
|
+
output_directory: Path = typer.Option(
|
|
132
|
+
Path("./pack"),
|
|
133
|
+
"--output-directory",
|
|
134
|
+
"-o",
|
|
135
|
+
help="Path to output directory",
|
|
136
|
+
),
|
|
137
|
+
uv_export: str = typer.Option(
|
|
138
|
+
default="",
|
|
139
|
+
help=_additional_cli_args("uv export"),
|
|
140
|
+
),
|
|
141
|
+
pip_download: str = typer.Option(
|
|
142
|
+
default="",
|
|
143
|
+
help=_additional_cli_args("pip download"),
|
|
144
|
+
),
|
|
145
|
+
uv_build: str = typer.Option(
|
|
146
|
+
default="",
|
|
147
|
+
help=_additional_cli_args("uv build"),
|
|
148
|
+
),
|
|
149
|
+
verbose: bool = typer.Option(
|
|
150
|
+
False,
|
|
151
|
+
"--verbose",
|
|
152
|
+
"-v",
|
|
153
|
+
help="Enable verbose output",
|
|
154
|
+
),
|
|
234
155
|
) -> None:
|
|
235
156
|
"""Pack a locked uv environment into an offline-installable bundle."""
|
|
236
|
-
if
|
|
237
|
-
|
|
238
|
-
|
|
157
|
+
set_verbosity(Verbosity.verbose if verbose else Verbosity.normal)
|
|
158
|
+
selected_steps = _normalize_steps(steps, skip)
|
|
159
|
+
console_print(
|
|
160
|
+
f"[dim]Running steps:[/dim] {[step.value for step in selected_steps]}",
|
|
161
|
+
)
|
|
239
162
|
|
|
240
|
-
|
|
241
|
-
|
|
163
|
+
if Step.clean in selected_steps:
|
|
164
|
+
with run_step("clean"):
|
|
165
|
+
shutil.rmtree(output_directory, ignore_errors=True)
|
|
242
166
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
)
|
|
248
|
-
console.print(f"[green]✔ Exported[/green] requirements file to '{requirements_file}'")
|
|
167
|
+
console_print(
|
|
168
|
+
f"[green]✔ Cleaned[/green] output directory '{output_directory}'",
|
|
169
|
+
level=Verbosity.verbose,
|
|
170
|
+
)
|
|
249
171
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
172
|
+
# initialize pack directory structure and copy unpack scripts
|
|
173
|
+
pack = PackLayout.create(output_directory=output_directory)
|
|
174
|
+
copy_unpack_scripts(output_directory=output_directory)
|
|
253
175
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
console.print(f"[green]✔ Downloaded[/green] third party wheels to '{wheels_dir}'")
|
|
260
|
-
|
|
261
|
-
sdist_files = list(wheels_dir.glob("*.tar.gz"))
|
|
262
|
-
if (n_src := len(sdist_files)) > 0:
|
|
263
|
-
console.print(f"[dim]Identified {n_src} source distributions to build...[/dim]'")
|
|
264
|
-
for file in sdist_files:
|
|
265
|
-
build_src_wheel(
|
|
266
|
-
sdist_file=file,
|
|
267
|
-
other_args=uv_build_sdist,
|
|
176
|
+
if Step.export in selected_steps:
|
|
177
|
+
with run_step("export"):
|
|
178
|
+
export_requirements(
|
|
179
|
+
requirements_file=pack.requirements_export_txt,
|
|
180
|
+
other_args=uv_export,
|
|
268
181
|
)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
182
|
+
export_local_requirements(
|
|
183
|
+
requirements_file=pack.requirements_local_txt,
|
|
184
|
+
other_args=uv_export,
|
|
185
|
+
)
|
|
186
|
+
console_print(
|
|
187
|
+
f"[green]✔ Exported[/green] requirements '{pack.requirements_export_txt}'",
|
|
188
|
+
level=Verbosity.verbose,
|
|
189
|
+
)
|
|
190
|
+
console_print(
|
|
191
|
+
f"[green]✔ Exported[/green] requirements '{pack.requirements_local_txt}'",
|
|
192
|
+
level=Verbosity.verbose,
|
|
193
|
+
)
|
|
277
194
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
vendor_directory=vendor_dir,
|
|
281
|
-
)
|
|
195
|
+
if Step.download in selected_steps:
|
|
196
|
+
_raise_requirement_txt_missing(pack.requirements_export_txt)
|
|
282
197
|
|
|
283
|
-
|
|
284
|
-
|
|
198
|
+
with run_step("download"):
|
|
199
|
+
download_third_party_wheels(
|
|
200
|
+
requirements_file=pack.requirements_export_txt,
|
|
201
|
+
wheels_directory=pack.wheels_dir,
|
|
202
|
+
other_args=pip_download,
|
|
203
|
+
)
|
|
285
204
|
|
|
286
|
-
|
|
287
|
-
|
|
205
|
+
if Step.build in selected_steps:
|
|
206
|
+
_raise_requirement_txt_missing(pack.requirements_local_txt)
|
|
207
|
+
_raise_requirement_txt_missing(pack.requirements_export_txt)
|
|
208
|
+
|
|
209
|
+
# show the progress for each package in verbose mode, otherwise a single progress report is shown
|
|
210
|
+
with run_step("build", should_run=not verbose):
|
|
211
|
+
for line in pack.requirements_local_txt.read_text(
|
|
212
|
+
encoding="utf-8",
|
|
213
|
+
).splitlines():
|
|
214
|
+
with run_step("build", should_run=verbose):
|
|
215
|
+
build_src_wheel(
|
|
216
|
+
source_path=Path(line),
|
|
217
|
+
out_path=pack.vendor_dir,
|
|
218
|
+
other_args=uv_build,
|
|
219
|
+
)
|
|
220
|
+
console_print(
|
|
221
|
+
f"[green]✔ Built[/green] wheel: '{line}'",
|
|
222
|
+
level=Verbosity.verbose,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
for sdist in pack.wheels_dir.glob("*.tar.gz"):
|
|
226
|
+
with run_step("build", should_run=verbose):
|
|
227
|
+
build_src_wheel(
|
|
228
|
+
source_path=sdist,
|
|
229
|
+
out_path=pack.wheels_dir,
|
|
230
|
+
other_args=uv_build,
|
|
231
|
+
)
|
|
232
|
+
sdist.unlink(missing_ok=True)
|
|
233
|
+
console_print(
|
|
234
|
+
f"[green]✔ Built[/green] wheel: '{sdist}'",
|
|
235
|
+
level=Verbosity.verbose,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
build_requirements(
|
|
239
|
+
requirements_txt=pack.requirements_txt,
|
|
240
|
+
requirements_export_txt=pack.requirements_export_txt,
|
|
241
|
+
vendor_directory=pack.vendor_dir,
|
|
242
|
+
)
|
|
243
|
+
console_print(
|
|
244
|
+
f"[green]✔ Built[/green] requirements: '{pack.requirements_txt}'",
|
|
245
|
+
level=Verbosity.verbose,
|
|
246
|
+
)
|
|
288
247
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
console.print("[dim]Found '--system', skipping Python interpreter download[/dim]")
|
|
292
|
-
else:
|
|
248
|
+
if Step.python in selected_steps:
|
|
249
|
+
pack.python_dir.mkdir(exist_ok=True)
|
|
293
250
|
python_path = download_latest_python_build(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
251
|
+
dest_dir=pack.python_dir,
|
|
252
|
+
)
|
|
253
|
+
console_print(
|
|
254
|
+
f"[green]✔ Python[/green] archive: '{python_path}'",
|
|
255
|
+
level=Verbosity.verbose,
|
|
297
256
|
)
|
|
298
|
-
console.print(f"[green]✔ Downloaded[/green] interpreter to '{python_path}'")
|
|
299
257
|
|
|
300
|
-
|
|
301
|
-
console.print(f"[green]✔ Unpack[/green] scripts copied to '{output_directory}'")
|
|
302
|
-
console.print(f"[green]✔ Packed[/green] environment '{output_directory}'")
|
|
258
|
+
console_print("[green]✔ Done[/green]")
|
uv_pack/_build.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from packaging.utils import parse_wheel_filename
|
|
5
|
+
|
|
6
|
+
from uv_pack._process import exit_on_error, run_cmd
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def build_src_wheel(*, source_path: Path, out_path: Path, other_args: str) -> None:
|
|
10
|
+
cmd = [
|
|
11
|
+
"uv",
|
|
12
|
+
"build",
|
|
13
|
+
str(source_path),
|
|
14
|
+
"--wheel",
|
|
15
|
+
"--out-dir",
|
|
16
|
+
str(out_path),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
cmd.extend(other_args.split())
|
|
20
|
+
exit_on_error(run_cmd(cmd, "uv build"))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def build_requirements(
|
|
24
|
+
*,
|
|
25
|
+
requirements_txt: Path,
|
|
26
|
+
requirements_export_txt: Path,
|
|
27
|
+
vendor_directory: Path,
|
|
28
|
+
) -> None:
|
|
29
|
+
vendor_pins: list[str] = []
|
|
30
|
+
|
|
31
|
+
for wheel in vendor_directory.glob("*.whl"):
|
|
32
|
+
name, version, *_ = parse_wheel_filename(wheel.name)
|
|
33
|
+
vendor_pins.append(f"{name}=={version}")
|
|
34
|
+
|
|
35
|
+
header = "\n".join(
|
|
36
|
+
[
|
|
37
|
+
"# This file was autogenerated by uv-pack via the following command:",
|
|
38
|
+
f"# uv-pack {' '.join(sys.argv[1:])}",
|
|
39
|
+
*sorted(set(vendor_pins)),
|
|
40
|
+
],
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
requirements_txt.write_text(
|
|
44
|
+
header + "\n" + requirements_export_txt.read_text(encoding="utf-8"),
|
|
45
|
+
encoding="utf-8",
|
|
46
|
+
)
|