Skip to content

Commit ef393e6

Browse files
committed
lock: add --output-file
1 parent 9bc25c1 commit ef393e6

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

Diff for: src/pip/_internal/commands/lock.py

+31-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
with_cleanup,
1111
)
1212
from pip._internal.cli.status_codes import SUCCESS
13-
from pip._internal.models.pylock import Pylock
13+
from pip._internal.models.pylock import Pylock, is_valid_pylock_file_name
1414
from pip._internal.operations.build.build_tracker import get_build_tracker
1515
from pip._internal.req.req_install import (
1616
check_legacy_setup_py_options,
@@ -45,6 +45,18 @@ class LockCommand(RequirementCommand):
4545
%prog [options] <archive url/path> ..."""
4646

4747
def add_options(self) -> None:
48+
self.cmd_opts.add_option(
49+
cmdoptions.PipOption(
50+
"--output-file",
51+
"--output",
52+
"-o",
53+
dest="output_file",
54+
metavar="path",
55+
type="path",
56+
default="pylock.toml",
57+
help="Lock file name (default=pylock.toml). Use - for stdout.",
58+
)
59+
)
4860
self.cmd_opts.add_option(cmdoptions.requirements())
4961
self.cmd_opts.add_option(cmdoptions.constraints())
5062
self.cmd_opts.add_option(cmdoptions.no_deps())
@@ -131,9 +143,23 @@ def run(self, options: Values, args: List[str]) -> int:
131143

132144
requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
133145

134-
pyproject_lock = Pylock.from_install_requirements(
135-
requirement_set.requirements.values(), base_dir=Path.cwd()
136-
)
137-
sys.stdout.write(pyproject_lock.as_toml())
146+
if options.output_file == "-":
147+
base_dir = Path.cwd()
148+
else:
149+
output_file_path = Path(options.output_file)
150+
if not is_valid_pylock_file_name(output_file_path):
151+
logger.warning(
152+
"%s is not a valid lock file name.",
153+
output_file_path,
154+
)
155+
base_dir = output_file_path.parent.absolute()
156+
pyproject_lock_toml = Pylock.from_install_requirements(
157+
requirement_set.requirements.values(), base_dir=base_dir
158+
).as_toml()
159+
if options.output_file == "-":
160+
sys.stdout.write(pyproject_lock_toml)
161+
else:
162+
with output_file_path.open("w", encoding="utf-8") as f:
163+
f.write(pyproject_lock_toml)
138164

139165
return SUCCESS

Diff for: src/pip/_internal/models/pylock.py

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import dataclasses
2+
import re
23
from dataclasses import dataclass
34
from pathlib import Path
45
from typing import Any, Dict, Iterable, List, Optional, Tuple
@@ -11,6 +12,12 @@
1112
from pip._internal.req.req_install import InstallRequirement
1213
from pip._internal.utils.urls import url_to_path
1314

15+
PYLOCK_FILE_NAME_RE = re.compile(r"^pylock\.([^.]+)\.toml$")
16+
17+
18+
def is_valid_pylock_file_name(path: Path) -> bool:
19+
return path.name == "pylock.toml" or bool(re.match(PYLOCK_FILE_NAME_RE, path.name))
20+
1421

1522
def _toml_dict_factory(data: Iterable[Tuple[str, Any]]) -> Dict[str, Any]:
1623
return {key.replace("_", "-"): value for key, value in data if value is not None}

0 commit comments

Comments
 (0)