123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- import pytest
- import io
- from build.plugins.lib.nots.package_manager.pnpm.lockfile import PnpmLockfile, PnpmLockfileHelper
- @pytest.fixture()
- def patch_open_v6(monkeypatch):
- def mock_open(a, b):
- file_like = io.BytesIO(b'lockfileVersion: "6.0"')
- return io.BufferedReader(file_like)
- monkeypatch.setattr(io, "open", mock_open)
- @pytest.fixture()
- def patch_open_v9(monkeypatch):
- def mock_open(a, b):
- file_like = io.BytesIO(b'lockfileVersion: "9.0"')
- return io.BufferedReader(file_like)
- monkeypatch.setattr(io, "open", mock_open)
- @pytest.fixture()
- def patch_open_incorrect_version(monkeypatch):
- def mock_open(a, b):
- file_like = io.BytesIO(b'lockfileVersion: 0')
- return io.BufferedReader(file_like)
- monkeypatch.setattr(io, "open", mock_open)
- @pytest.fixture()
- def patch_open_no_version(monkeypatch):
- def mock_open(a, b):
- file_like = io.BytesIO(b'some text')
- return io.BufferedReader(file_like)
- monkeypatch.setattr(io, "open", mock_open)
- def test_lockfile_read_v6(patch_open_v6):
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.read()
- assert lf.data == {"lockfileVersion": "9.0"}
- def test_lockfile_read_v9(patch_open_v9):
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.read()
- assert lf.data == {"lockfileVersion": "9.0"}
- def test_lockfile_read_yaml_error_incorrect_lockfile_version(patch_open_incorrect_version):
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- with pytest.raises(Exception) as e:
- lf.read()
- assert str(e.value) == (
- 'Error of project configuration: /pnpm-lock.yaml has lockfileVersion: 0.\n'
- + 'This version is not supported. Please, delete pnpm-lock.yaml and regenerate it using `ya tool nots --clean update-lockfile`'
- )
- def test_lockfile_read_yaml_error_no_lockfile_version(patch_open_no_version):
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- with pytest.raises(Exception) as e:
- lf.read()
- assert str(e.value) == (
- 'Error of project configuration: /pnpm-lock.yaml has lockfileVersion: <no-version>.\n'
- + 'This version is not supported. Please, delete pnpm-lock.yaml and regenerate it using `ya tool nots --clean update-lockfile`'
- )
- def test_lockfile_get_packages_meta_ok():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {
- "packages": {
- "/@babel/cli/7.6.2_@babel+core@7.6.2": {
- "resolution": {
- "integrity": "sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ==",
- "tarball": "@babel%2fcli/-/cli-7.6.2.tgz?rbtorrent=cb1849da3e4947e56a8f6bde6a1ec42703ddd187",
- },
- },
- },
- }
- packages = list(lf.get_packages_meta())
- pkg = packages[0]
- assert len(packages) == 1
- assert pkg.tarball_url == "@babel%2fcli/-/cli-7.6.2.tgz"
- assert pkg.sky_id == "rbtorrent:cb1849da3e4947e56a8f6bde6a1ec42703ddd187"
- assert pkg.integrity == "JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ=="
- assert pkg.integrity_algorithm == "sha512"
- def test_lockfile_get_packages_empty():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {}
- assert len(list(lf.get_packages_meta())) == 0
- def test_package_meta_invalid_key():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {
- "packages": {
- "in/valid": {},
- },
- }
- with pytest.raises(TypeError) as e:
- list(lf.get_packages_meta())
- assert str(e.value) == "Invalid package meta for 'in/valid', missing 'resolution' key"
- def test_package_meta_missing_resolution():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {
- "packages": {
- "/valid@1.2.3": {},
- },
- }
- with pytest.raises(TypeError) as e:
- list(lf.get_packages_meta())
- assert str(e.value) == "Invalid package meta for '/valid@1.2.3', missing 'resolution' key"
- def test_package_meta_missing_tarball():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {
- "packages": {
- "/valid@1.2.3": {
- "resolution": {},
- },
- },
- }
- with pytest.raises(TypeError) as e:
- list(lf.get_packages_meta())
- assert str(e.value) == "Invalid package meta for '/valid@1.2.3', missing 'tarball' key"
- def test_lockfile_convertion_to_v9_simple():
- data = {
- "lockfileVersion": "6.0",
- "packages": {
- "/abc@1.2.3": {
- "resolution": {
- "integrity": "some-integrity",
- "tarball": "https://npm.yandex-team.ru/some/module/path",
- },
- "dependencies": {
- "dep1": "2.3.4",
- "dep2": "3.4.5",
- },
- "dev": False,
- }
- },
- }
- converted_data = PnpmLockfileHelper.ensure_v9(data)
- assert converted_data == {
- "lockfileVersion": "9.0",
- "packages": {
- "abc@1.2.3": {
- "resolution": {"integrity": "some-integrity", "tarball": "https://npm.yandex-team.ru/some/module/path"}
- }
- },
- "snapshots": {"abc@1.2.3": {"dependencies": {"dep1": "2.3.4", "dep2": "3.4.5"}}},
- }
- def test_lockfile_convertion_to_v9_dependencies():
- data = {
- "lockfileVersion": "6.0",
- "dependencies": {
- "@yandex-int/static-uploader": {
- "specifier": "^1.0.1",
- "version": "1.0.3",
- }
- },
- "packages": {
- "/abc@1.2.3": {
- "resolution": {
- "integrity": "some-integrity",
- "tarball": "https://npm.yandex-team.ru/some/module/path",
- },
- "dependencies": {
- "dep1": "2.3.4",
- "dep2": "3.4.5",
- },
- "dev": False,
- }
- },
- }
- converted_data = PnpmLockfileHelper.ensure_v9(data)
- assert converted_data == {
- "lockfileVersion": "9.0",
- "packages": {
- "abc@1.2.3": {
- "resolution": {"integrity": "some-integrity", "tarball": "https://npm.yandex-team.ru/some/module/path"}
- }
- },
- "importers": {
- ".": {"dependencies": {"@yandex-int/static-uploader": {"specifier": "^1.0.1", "version": "1.0.3"}}}
- },
- "snapshots": {"abc@1.2.3": {"dependencies": {"dep1": "2.3.4", "dep2": "3.4.5"}}},
- }
- def test_lockfile_convertion_to_v9():
- data = {
- "lockfileVersion": "6.0",
- "packages": {
- "/ajv@6.12.6": {
- "resolution": {
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "tarball": "https://npm.yandex-team.ru/ajv/-/ajv-6.12.6.tgz?rbtorrent=8700a2f2e42ac5b59b5c6d8142cd2bfd19a56001",
- },
- "dependencies": {
- "fast-deep-equal": "3.1.3",
- "fast-json-stable-stringify": "2.1.0",
- },
- "engines": {"node": '>=10'},
- "dev": False,
- },
- "/@typescript-eslint/visitor-keys@8.7.0": {
- "resolution": {
- "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==",
- "tarball": "https://npm.yandex-team.ru/@typescript-eslint%2fvisitor-keys/-/visitor-keys-8.7.0.tgz?rbtorrent=",
- },
- "dependencies": {
- "@typescript-eslint/types": "8.7.0",
- "eslint-visitor-keys": "3.4.3",
- },
- "engines": {"node": ">=12"},
- "dev": False,
- },
- "/@csstools/media-query-list-parser@3.0.1(@csstools/css-parser-algorithms@3.0.1)(@csstools/css-tokenizer@3.0.1)": {
- "resolution": {
- "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==",
- "tarball": "https://npm.yandex-team.ru/@csstools%2fmedia-query-list-parser/-/media-query-list-parser-3.0.1.tgz?rbtorrent=",
- },
- "engines": {"node": ">=18"},
- "peerDependencies": {
- "@csstools/css-parser-algorithms": "^3.0.1",
- "@csstools/css-tokenizer": "^3.0.1",
- },
- "dependencies": {
- "@csstools/css-parser-algorithms": "3.0.1(@csstools/css-tokenizer@3.0.1)",
- "@csstools/css-tokenizer": "3.0.1",
- },
- "dev": False,
- },
- },
- }
- converted_data = PnpmLockfileHelper.ensure_v9(data)
- assert converted_data == {
- "lockfileVersion": "9.0",
- "packages": {
- "ajv@6.12.6": {
- "resolution": {
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "tarball": "https://npm.yandex-team.ru/ajv/-/ajv-6.12.6.tgz?rbtorrent=8700a2f2e42ac5b59b5c6d8142cd2bfd19a56001",
- },
- "engines": {"node": ">=10"},
- },
- "@typescript-eslint/visitor-keys@8.7.0": {
- "resolution": {
- "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==",
- "tarball": "https://npm.yandex-team.ru/@typescript-eslint%2fvisitor-keys/-/visitor-keys-8.7.0.tgz?rbtorrent=",
- },
- "engines": {"node": ">=12"},
- },
- "@csstools/media-query-list-parser@3.0.1": {
- "resolution": {
- "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==",
- "tarball": "https://npm.yandex-team.ru/@csstools%2fmedia-query-list-parser/-/media-query-list-parser-3.0.1.tgz?rbtorrent=",
- },
- "engines": {"node": ">=18"},
- "peerDependencies": {"@csstools/css-parser-algorithms": "^3.0.1", "@csstools/css-tokenizer": "^3.0.1"},
- },
- },
- "snapshots": {
- "ajv@6.12.6": {"dependencies": {"fast-deep-equal": "3.1.3", "fast-json-stable-stringify": "2.1.0"}},
- "@typescript-eslint/visitor-keys@8.7.0": {
- "dependencies": {"@typescript-eslint/types": "8.7.0", "eslint-visitor-keys": "3.4.3"}
- },
- "@csstools/media-query-list-parser@3.0.1(@csstools/css-parser-algorithms@3.0.1)(@csstools/css-tokenizer@3.0.1)": {
- "dependencies": {
- "@csstools/css-parser-algorithms": "3.0.1(@csstools/css-tokenizer@3.0.1)",
- "@csstools/css-tokenizer": "3.0.1",
- }
- },
- },
- }
- def test_package_meta_missing_rbtorrent():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {
- "packages": {
- "/valid@1.2.3": {
- "resolution": {
- "integrity": "sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ==",
- "tarball": "valid-without-rbtorrent-1.2.3.tgz",
- },
- },
- },
- }
- packages = list(lf.get_packages_meta())
- pkg = packages[0]
- assert len(packages) == 1
- assert pkg.sky_id == ""
- def test_lockfile_meta_file_tarball_prohibits_file_protocol():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {
- "packages": {
- "/@babel/cli@7.6.2": {
- "resolution": {
- "integrity": "sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ==",
- "tarball": "file:/some/abs/path.tgz",
- },
- },
- },
- }
- with pytest.raises(TypeError) as e:
- list(lf.get_packages_meta())
- assert (
- str(e.value)
- == "Invalid package meta for '/@babel/cli@7.6.2', parse error: tarball cannot point to a file, got 'file:/some/abs/path.tgz'"
- )
- def test_lockfile_update_tarball_resolutions_ok():
- lf = PnpmLockfile(path="/pnpm-lock.yaml")
- lf.data = {
- "packages": {
- "/@babel/cli@7.6.2_@babel+core@7.6.2": {
- "resolution": {
- "integrity": "sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ==",
- "tarball": "@babel%2fcli/-/cli-7.6.2.tgz?rbtorrent=cb1849da3e4947e56a8f6bde6a1ec42703ddd187",
- },
- },
- },
- }
- lf.update_tarball_resolutions(lambda p: p.tarball_url)
- assert (
- lf.data["packages"]["/@babel/cli@7.6.2_@babel+core@7.6.2"]["resolution"]["tarball"]
- == "@babel%2fcli/-/cli-7.6.2.tgz"
- )
- def test_lockfile_merge():
- lf1 = PnpmLockfile(path="/foo/pnpm-lock.yaml")
- lf1.data = {
- "lockfileVersion": "9.0",
- "dependencies": {
- "a": "1.0.0",
- },
- "packages": {
- "a@1.0.0": {},
- },
- "snapshots": {
- "a@1.0.0": {},
- },
- }
- lf2 = PnpmLockfile(path="/bar/pnpm-lock.yaml")
- lf2.data = {
- "lockfileVersion": "9.0",
- "dependencies": {
- "b": "1.0.0",
- },
- "packages": {
- "b@1.0.0": {},
- },
- "snapshots": {
- "b@1.0.0": {},
- },
- }
- lf3 = PnpmLockfile(path="/another/baz/pnpm-lock.yaml")
- lf3.data = {
- "lockfileVersion": "9.0",
- "importers": {
- ".": {
- "dependencies": {
- "@a/qux": "link:../qux",
- "a": "1.0.0",
- },
- "specifiers": {
- "@a/qux": "workspace:../qux",
- "a": "1.0.0",
- },
- },
- "../qux": {
- "dependencies": {
- "b": "1.0.1",
- },
- "specifiers": {
- "b": "1.0.1",
- },
- },
- },
- "packages": {
- "a@1.0.0": {},
- "b@1.0.1": {},
- },
- "snapshots": {
- "a@1.0.0": {},
- "b@1.0.1": {},
- },
- }
- lf4 = PnpmLockfile(path="/another/quux/pnpm-lock.yaml")
- lf4.data = {
- "lockfileVersion": "9.0",
- "importers": {
- ".": {
- "dependencies": {
- "@a/bar": "link:../../bar",
- }
- }
- },
- "specifiers": {
- "@a/bar": "workspace:../../bar",
- },
- }
- lf1.merge(lf2)
- lf1.merge(lf3)
- lf1.merge(lf4)
- assert lf1.data == {
- "lockfileVersion": "9.0",
- "packages": {"a@1.0.0": {}, "b@1.0.0": {}, "b@1.0.1": {}},
- "snapshots": {"a@1.0.0": {}, "b@1.0.0": {}, "b@1.0.1": {}},
- "importers": {
- ".": {"dependencies": {"a": "1.0.0"}},
- "../bar": {"dependencies": {"b": "1.0.0"}},
- "../another/baz": {
- "dependencies": {"@a/qux": "link:../qux", "a": "1.0.0"},
- "specifiers": {"@a/qux": "workspace:../qux", "a": "1.0.0"},
- },
- "../another/qux": {"dependencies": {"b": "1.0.1"}, "specifiers": {"b": "1.0.1"}},
- "../another/quux": {"dependencies": {"@a/bar": "link:../../bar"}},
- },
- }
- def test_lockfile_merge_dont_overrides_packages():
- lf1 = PnpmLockfile(path="/foo/pnpm-lock.yaml")
- lf1.data = {
- "lockfileVersion": "9.0",
- "dependencies": {
- "a": "1.0.0",
- },
- "importers": {
- ".": {
- "dependencies": {
- "a": "1.0.0",
- }
- }
- },
- "packages": {
- "a@1.0.0": {},
- },
- "snapshots": {
- "a@1.0.0": {},
- },
- }
- lf2 = PnpmLockfile(path="/bar/pnpm-lock.yaml")
- lf2.data = {
- "lockfileVersion": "9.0",
- "dependencies": {
- "a": "1.0.0",
- "b": "1.0.0",
- },
- "specifiers": {
- "a": "1.0.0",
- "b": "1.0.0",
- },
- "packages": {
- "a@1.0.0": {
- "overriden": True,
- },
- "b@1.0.0": {},
- },
- "snapshots": {
- "a@1.0.0": {
- "overriden": True,
- },
- "b@1.0.0": {},
- },
- }
- lf1.merge(lf2)
- assert lf1.data == {
- "lockfileVersion": "9.0",
- "importers": {
- ".": {
- "dependencies": {
- "a": "1.0.0",
- },
- },
- "../bar": {
- "dependencies": {
- "a": "1.0.0",
- "b": "1.0.0",
- },
- "specifiers": {
- "a": "1.0.0",
- "b": "1.0.0",
- },
- },
- },
- "packages": {
- "a@1.0.0": {},
- "b@1.0.0": {},
- },
- "snapshots": {
- "a@1.0.0": {},
- "b@1.0.0": {},
- },
- }
|