Skip to content

Commit fb634a6

Browse files
authored
fix: parse yarn files with multiple dependencies on the same line (#337)
1 parent e8ba101 commit fb634a6

File tree

5 files changed

+16
-8
lines changed

5 files changed

+16
-8
lines changed

dependencies/npm.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/twyn/dependency_parser/parsers/yarn_lock_parser.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,29 @@ def parse(self) -> set[str]:
3030

3131
def _parse_v1(self, fp: TextIO) -> set[str]:
3232
"""Parse a yarn.lock file and return all the dependencies in it."""
33-
key_line_re = re.compile(r"^(?P<key>[^ \t].*?):\s*$", re.MULTILINE)
33+
# Match the entire line up to the colon (allows multiple quoted keys)
34+
key_line_re = re.compile(r"^(?P<key>[^ \t].*?):\s*$")
3435
names = set()
36+
3537
for line in fp:
3638
match = key_line_re.match(line)
3739
if not match:
3840
continue
3941
key = match.group("key").strip()
40-
# Remove surrounding quotes if present
41-
if (key.startswith('"') and key.endswith('"')) or (key.startswith("'") and key.endswith("'")):
42-
key = key[1:-1]
4342

44-
# Split selectors (comma-separated)
43+
# Split on commas at the top level (handles multiple quoted keys)
4544
parts = [p.strip() for p in key.split(",")]
4645

4746
for part in parts:
47+
# Remove surrounding quotes if present
4848
if (part.startswith('"') and part.endswith('"')) or (part.startswith("'") and part.endswith("'")):
4949
part = part[1:-1] # noqa: PLW2901
50+
51+
# Skip anything without '@' (not a valid package selector)
5052
if "@" not in part:
5153
continue
52-
# Package name is everything before the last '@'
54+
55+
# Get everything before the last '@' as the package name
5356
pkg_name = part.rsplit("@", 1)[0]
5457
names.add(pkg_name)
5558

src/twyn/trusted_packages/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@
4040
"b": ["g", "h", "v", "n"],
4141
"n": ["h", "j", "b", "m"],
4242
"m": ["j", "k", "n"],
43+
"@": ["1", "2", "3", "q", "w"],
4344
}

tests/conftest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ def yarn_lock_file_v1(tmp_path: Path) -> Iterator[Path]:
413413
dependencies:
414414
loose-envify "^1.1.0"
415415
react "^18.2.0"
416+
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.8.0":
417+
version "7.26.5"
418+
resolved "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35"
419+
integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==
416420
"""
417421
with create_tmp_file(yarn_file, data) as tmp_file:
418422
yield tmp_file

tests/dependency_parser/test_dependency_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class TestYarnLockParser:
9696
def test_parse_yarn_lock_v1(self, yarn_lock_file_v1: Path) -> None:
9797
parser = YarnLockParser(file_path=str(yarn_lock_file_v1))
9898

99-
assert parser.parse() == {"lodash", "react", "react-dom"}
99+
assert parser.parse() == {"lodash", "react", "react-dom", "@babel/helper-plugin-utils"}
100100

101101
def test_parse_yarn_lock_v2(self, yarn_lock_file_v2: Path) -> None:
102102
parser = YarnLockParser(file_path=str(yarn_lock_file_v2))

0 commit comments

Comments
 (0)