Skip to content

Commit 2e56efe

Browse files
committed
pylock: parse environments
1 parent 7a2cb8b commit 2e56efe

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

src/pip/_internal/models/pylock.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,19 @@ def _toml_key(key: str) -> str:
4949
return key.replace("_", "-")
5050

5151

52-
def _toml_value(value: T) -> Union[str, T]:
52+
def _toml_value(key: str, value: T) -> Union[str, List[str], T]:
5353
if isinstance(value, (Version, Marker, SpecifierSet)):
5454
return str(value)
55+
if isinstance(value, list) and key == "environments":
56+
return [str(v) for v in value]
5557
return value
5658

5759

5860
def _toml_dict_factory(data: List[Tuple[str, Any]]) -> Dict[str, Any]:
5961
return {
60-
_toml_key(key): _toml_value(value) for key, value in data if value is not None
62+
_toml_key(key): _toml_value(key, value)
63+
for key, value in data
64+
if value is not None
6165
}
6266

6367

@@ -110,6 +114,27 @@ def _get_marker(d: Dict[str, Any], key: str) -> Optional[Marker]:
110114
raise PylockValidationError(f"invalid marker {value!r}")
111115

112116

117+
def _get_list_of_markers(d: Dict[str, Any], key: str) -> Optional[List[Marker]]:
118+
"""Get list value from dictionary and verify expected items type."""
119+
if key not in d:
120+
return None
121+
value = d[key]
122+
if not isinstance(value, list):
123+
raise PylockValidationError(f"{key!r} is not a list")
124+
result = []
125+
for i, item in enumerate(value):
126+
if not isinstance(item, str):
127+
raise PylockValidationError(f"Item {i} in list {key!r} is not a string")
128+
try:
129+
result.append(Marker(item))
130+
except InvalidMarker:
131+
raise PylockValidationError(
132+
f"Item {i} in list {key!r} "
133+
f"is not a valid environment marker: {item!r}"
134+
)
135+
return result
136+
137+
113138
def _get_specifier_set(d: Dict[str, Any], key: str) -> Optional[SpecifierSet]:
114139
value = _get(d, str, key)
115140
if value is None:
@@ -418,7 +443,7 @@ def from_install_requirement(cls, ireq: InstallRequirement, base_dir: Path) -> S
418443
@dataclass
419444
class Pylock:
420445
lock_version: Version = Version("1.0")
421-
# (not supported) environments: Optional[List[str]]
446+
environments: Optional[List[Marker]] = None
422447
requires_python: Optional[SpecifierSet] = None
423448
# (not supported) extras: List[str] = []
424449
# (not supported) dependency_groups: List[str] = []
@@ -449,6 +474,7 @@ def to_dict(self) -> Dict[str, Any]:
449474
def from_dict(cls, d: Dict[str, Any]) -> Self:
450475
return cls(
451476
lock_version=_get_required_version(d, "lock-version"),
477+
environments=_get_list_of_markers(d, "environments"),
452478
created_by=_get_required(d, str, "created-by"),
453479
requires_python=_get_specifier_set(d, "requires-python"),
454480
packages=_get_required_list_of_objects(d, Package, "packages"),

tests/unit/test_pylock.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def test_pylock_basic_package() -> None:
9191
"lock-version": "1.0",
9292
"created-by": "pip",
9393
"requires-python": ">=3.10",
94+
"environments": ['os_name == "posix"'],
9495
"packages": [
9596
{
9697
"name": "example",
@@ -105,6 +106,7 @@ def test_pylock_basic_package() -> None:
105106
],
106107
}
107108
pylock = Pylock.from_dict(data)
109+
assert pylock.environments == [Marker('os_name == "posix"')]
108110
package = pylock.packages[0]
109111
assert package.version == Version("1.0")
110112
assert package.marker == Marker('os_name == "posix"')

0 commit comments

Comments
 (0)