Skip to content

Commit

Permalink
add handling for more path-based version specifiers
Browse files Browse the repository at this point in the history
These are all valid version specifiers for path-style packages in
package.json/yarn.lock:

./some/relative/path
../some/relative/path
file:some/relative/path
file:../some/relative/path
link:some/relative/path
link:../some/relative/path\
/some/absolute/path

Ensure that the Package class provides a path in each of these cases.

Signed-off-by: Taylor Madore <[email protected]>
  • Loading branch information
taylormadore committed Oct 14, 2024
1 parent 5e364b1 commit 5311bec
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 6 deletions.
21 changes: 18 additions & 3 deletions pyarn/lockfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
import json
import logging
import re
from typing import Pattern
from pathlib import Path
from typing import Optional, Pattern

from ply import lex, yacc

Expand Down Expand Up @@ -63,8 +64,8 @@ def from_dict(cls, raw_name, data):
alias = name
name, _version = _must_match(name_at_version, _remove_prefix(_version, "npm:")).groups()

if _version and _version.startswith("file:"):
path = _remove_prefix(_version, "file:")
if _version:
path = cls.get_path_from_version_specifier(_version)

return cls(
name=name,
Expand All @@ -76,6 +77,20 @@ def from_dict(cls, raw_name, data):
alias=alias,
)

@staticmethod
def get_path_from_version_specifier(version: str) -> Optional[str]:
"Return the path from a package.json file dependency version specifier."
version_path = Path(version)

if version.startswith("file:"):
return _remove_prefix(version, "file:")
elif version.startswith("link:"):
return _remove_prefix(version, "link:")
elif version_path.is_absolute() or version.startswith(("./", "../")):
return str(version_path)
else:
return None


def _remove_prefix(s: str, prefix: str) -> str:
return s[len(prefix) :]
Expand Down
35 changes: 32 additions & 3 deletions tests/test_lockfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,45 @@ def test_packages_checksum():
assert packages[0].path is None


def test_path():
data = '"breakfast@file:some/relative/path":\n version "0.0.0"'
@pytest.mark.parametrize(
"data, expected_path",
[
pytest.param(
'"breakfast@file:some/relative/path":\n version "0.0.0"',
"some/relative/path",
id="relpath_with_file_prefix",
),
pytest.param(
'"breakfast@link:some/relative/path":\n version "0.0.0"',
"some/relative/path",
id="relpath_with_link_prefix",
),
pytest.param(
'"breakfast@./some/relative/path":\n version "0.0.0"',
"some/relative/path",
id="relpath_with_dot_prefix",
),
pytest.param(
'"breakfast@../some/relative/path":\n version "0.0.0"',
"../some/relative/path",
id="relpath_to_parent_dir",
),
pytest.param(
'"breakfast@/some/absolute/path":\n version "0.0.0"',
"/some/absolute/path",
id="absolute_path",
),
],
)
def test_package_with_path(data: str, expected_path: str) -> None:
lock = lockfile.Lockfile.from_str(data)
packages = lock.packages()
assert len(packages) == 1
assert packages[0].name == "breakfast"
assert packages[0].version == "0.0.0"
assert packages[0].checksum is None
assert packages[0].url is None
assert packages[0].path == "some/relative/path"
assert packages[0].path == expected_path


def test_package_with_comma():
Expand Down

0 comments on commit 5311bec

Please sign in to comment.