diff --git a/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_lockedversion.lock b/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_lockedversion.lock new file mode 100644 index 0000000000000000000000000000000000000000..0919fa551afa669480dee618384f41cde89645e1 --- /dev/null +++ b/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_lockedversion.lock @@ -0,0 +1,147 @@ +# This file is @generated by PDM. +# It is not intended for manual editing. + +[metadata] +groups = ["default"] +strategy = ["cross_platform", "inherit_metadata"] +lock_version = "4.4.1" +content_hash = "sha256:19234b27486d54cb9ed56ee0f874329ee04094d0c5ac1e2cd37aee1a606a7693" + +[[package]] +name = "cffi" +version = "1.16.0" +requires_python = ">=3.8" +summary = "Foreign Function Interface for Python calling C code." +groups = ["default"] +dependencies = [ + "pycparser", +] +files = [ + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[[package]] +name = "cryptography" +version = "41.0.7" +requires_python = ">=3.7" +summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +groups = ["default"] +dependencies = [ + "cffi>=1.12", +] +files = [ + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"}, + {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"}, + {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"}, + {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"}, +] + +[[package]] +name = "deprecated" +version = "1.2.14" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +summary = "Python @deprecated decorator to deprecate old python classes, functions or methods." +groups = ["default"] +dependencies = [ + "wrapt<2,>=1.10", +] +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[[package]] +name = "jwcrypto" +version = "1.4.1" +requires_python = ">= 3.6" +summary = "Implementation of JOSE Web standards" +groups = ["default"] +dependencies = [ + "cryptography>=2.3", + "deprecated", +] +files = [ + {file = "jwcrypto-1.4.1.tar.gz", hash = "sha256:9561d57f3e67f845bcc5bcb378d07e958d9b1ec2b7d9d2a9266296dabf27f4f4"}, +] + +[[package]] +name = "pycparser" +version = "2.21" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +summary = "C parser in Python" +groups = ["default"] +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] + +[[package]] +name = "wrapt" +version = "1.16.0" +requires_python = ">=3.6" +summary = "Module for decorators, wrappers and monkey patching." +groups = ["default"] +files = [ + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] diff --git a/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_lockedversion.toml b/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_lockedversion.toml new file mode 100644 index 0000000000000000000000000000000000000000..a86d46f668b3847735c6025d573a98d89d95bcd7 --- /dev/null +++ b/lib/modules/manager/pep621/__fixtures__/pyproject_pdm_lockedversion.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["pdm-backend"] +build-backend = "pdm.backend" + +[project] +name = "pep621-pdm" +version = "0.1.0" +description = "Default template for PDM package" +authors = [ + {name = "", email = ""}, +] +dependencies = [ + "jwcrypto>=1.4.1" +] +requires-python = ">=3.11" +readme = "README.md" +license = {text = "MIT"} diff --git a/lib/modules/manager/pep621/extract.spec.ts b/lib/modules/manager/pep621/extract.spec.ts index ff75c374d5e3fd4f409dcc78638d6c94206047e0..e7147e912b4b724d583708766f88da1f8f08234f 100644 --- a/lib/modules/manager/pep621/extract.spec.ts +++ b/lib/modules/manager/pep621/extract.spec.ts @@ -1,19 +1,22 @@ import { codeBlock } from 'common-tags'; import { Fixtures } from '../../../../test/fixtures'; +import { fs } from '../../../../test/util'; import { extractPackageFile } from '.'; +jest.mock('../../../util/fs'); + const pdmPyProject = Fixtures.get('pyproject_with_pdm.toml'); const pdmSourcesPyProject = Fixtures.get('pyproject_pdm_sources.toml'); describe('modules/manager/pep621/extract', () => { describe('extractPackageFile()', () => { - it('should return null for empty content', function () { - const result = extractPackageFile('', 'pyproject.toml'); + it('should return null for empty content', async () => { + const result = await extractPackageFile('', 'pyproject.toml'); expect(result).toBeNull(); }); - it('should return null for invalid toml', function () { - const result = extractPackageFile( + it('should return null for invalid toml', async () => { + const result = await extractPackageFile( codeBlock` [project] name = @@ -23,8 +26,8 @@ describe('modules/manager/pep621/extract', () => { expect(result).toBeNull(); }); - it('should return dependencies for valid content', function () { - const result = extractPackageFile(pdmPyProject, 'pyproject.toml'); + it('should return dependencies for valid content', async () => { + const result = await extractPackageFile(pdmPyProject, 'pyproject.toml'); expect(result).toMatchObject({ extractedConstraints: { @@ -177,8 +180,11 @@ describe('modules/manager/pep621/extract', () => { ]); }); - it('should return dependencies with overwritten pypi registryUrl', function () { - const result = extractPackageFile(pdmSourcesPyProject, 'pyproject.toml'); + it('should return dependencies with overwritten pypi registryUrl', async () => { + const result = await extractPackageFile( + pdmSourcesPyProject, + 'pyproject.toml', + ); expect(result?.deps).toEqual([ { @@ -239,8 +245,8 @@ describe('modules/manager/pep621/extract', () => { ]); }); - it('should return dependencies with original pypi registryUrl', function () { - const result = extractPackageFile( + it('should return dependencies with original pypi registryUrl', async () => { + const result = await extractPackageFile( codeBlock` [project] dependencies = [ @@ -270,9 +276,9 @@ describe('modules/manager/pep621/extract', () => { ]); }); - it('should extract dependencies from hatch environments', function () { + it('should extract dependencies from hatch environments', async () => { const hatchPyProject = Fixtures.get('pyproject_with_hatch.toml'); - const result = extractPackageFile(hatchPyProject, 'pyproject.toml'); + const result = await extractPackageFile(hatchPyProject, 'pyproject.toml'); expect(result?.deps).toEqual([ { @@ -322,7 +328,7 @@ describe('modules/manager/pep621/extract', () => { ]); }); - it('should extract project version', () => { + it('should extract project version', async () => { const content = codeBlock` [project] name = "test" @@ -330,11 +336,11 @@ describe('modules/manager/pep621/extract', () => { dependencies = [ "requests==2.30.0" ] `; - const res = extractPackageFile(content, 'pyproject.toml'); + const res = await extractPackageFile(content, 'pyproject.toml'); expect(res?.packageFileVersion).toBe('0.0.2'); }); - it('should extract dependencies from build-system.requires', function () { + it('should extract dependencies from build-system.requires', async () => { const content = codeBlock` [build-system] requires = ["hatchling==1.18.0", "setuptools==69.0.3"] @@ -345,7 +351,7 @@ describe('modules/manager/pep621/extract', () => { version = "0.0.2" dependencies = [ "requests==2.30.0" ] `; - const result = extractPackageFile(content, 'pyproject.toml'); + const result = await extractPackageFile(content, 'pyproject.toml'); expect(result?.deps).toEqual([ { @@ -374,5 +380,36 @@ describe('modules/manager/pep621/extract', () => { }, ]); }); + + it('should resolve lockedVersions from pdm.lock', async () => { + fs.readLocalFile.mockResolvedValue( + Fixtures.get('pyproject_pdm_lockedversion.lock'), + ); + + const res = await extractPackageFile( + Fixtures.get('pyproject_pdm_lockedversion.toml'), + 'pyproject.toml', + ); + expect(res).toMatchObject({ + extractedConstraints: { python: '>=3.11' }, + deps: [ + { + packageName: 'jwcrypto', + depName: 'jwcrypto', + datasource: 'pypi', + depType: 'project.dependencies', + currentValue: '>=1.4.1', + lockedVersion: '1.4.1', + }, + { + packageName: 'pdm-backend', + depName: 'pdm-backend', + datasource: 'pypi', + depType: 'build-system.requires', + skipReason: 'unspecified-version', + }, + ], + }); + }); }); }); diff --git a/lib/modules/manager/pep621/extract.ts b/lib/modules/manager/pep621/extract.ts index 66648663dcddafaca6189e24e99bb114c655a7d7..12a7c1803d4c374dec794b0aaea76957461756ea 100644 --- a/lib/modules/manager/pep621/extract.ts +++ b/lib/modules/manager/pep621/extract.ts @@ -13,11 +13,11 @@ import { parsePyProject, } from './utils'; -export function extractPackageFile( +export async function extractPackageFile( content: string, packageFile: string, _config?: ExtractConfig, -): PackageFileContent | null { +): Promise<PackageFileContent | null> { logger.trace(`pep621.extractPackageFile(${packageFile})`); const deps: PackageDependency[] = []; @@ -54,6 +54,11 @@ export function extractPackageFile( let processedDeps = deps; for (const processor of processors) { processedDeps = processor.process(def, processedDeps); + processedDeps = await processor.extractLockedVersions( + def, + processedDeps, + packageFile, + ); } return processedDeps.length diff --git a/lib/modules/manager/pep621/processors/hatch.ts b/lib/modules/manager/pep621/processors/hatch.ts index b482cb5b18cfc0519c0ee3d78b3a1f6a59280285..0cb8cbe149452575b7556594c4196cf67a18de14 100644 --- a/lib/modules/manager/pep621/processors/hatch.ts +++ b/lib/modules/manager/pep621/processors/hatch.ts @@ -32,6 +32,14 @@ export class HatchProcessor implements PyProjectProcessor { return deps; } + extractLockedVersions( + project: PyProject, + deps: PackageDependency[], + packageFile: string, + ): Promise<PackageDependency[]> { + return Promise.resolve(deps); + } + updateArtifacts( updateArtifact: UpdateArtifact, project: PyProject, diff --git a/lib/modules/manager/pep621/processors/pdm.ts b/lib/modules/manager/pep621/processors/pdm.ts index b4ead1f4bdb0a8cb1523ebb69baf71e453c2002c..c060e8af23b1a618fe6a6e53c51d2af5a3671464 100644 --- a/lib/modules/manager/pep621/processors/pdm.ts +++ b/lib/modules/manager/pep621/processors/pdm.ts @@ -5,6 +5,7 @@ import { logger } from '../../../../logger'; import { exec } from '../../../../util/exec'; import type { ExecOptions, ToolConstraint } from '../../../../util/exec/types'; import { getSiblingFileName, readLocalFile } from '../../../../util/fs'; +import { Result } from '../../../../util/result'; import { PypiDatasource } from '../../../datasource/pypi'; import type { PackageDependency, @@ -12,7 +13,7 @@ import type { UpdateArtifactsResult, Upgrade, } from '../../types'; -import type { PyProject } from '../schema'; +import { PdmLockfileSchema, type PyProject } from '../schema'; import { depTypes, parseDependencyGroupRecord } from '../utils'; import type { PyProjectProcessor } from './types'; @@ -53,6 +54,37 @@ export class PdmProcessor implements PyProjectProcessor { return deps; } + async extractLockedVersions( + project: PyProject, + deps: PackageDependency[], + packageFile: string, + ): Promise<PackageDependency[]> { + if ( + is.nullOrUndefined(project.tool?.pdm) && + project['build-system']?.['build-backend'] !== 'pdm.backend' + ) { + return Promise.resolve(deps); + } + + const lockFileName = getSiblingFileName(packageFile, 'pdm.lock'); + const lockFileContent = await readLocalFile(lockFileName, 'utf8'); + if (lockFileContent) { + const lockFileMapping = Result.parse( + lockFileContent, + PdmLockfileSchema.transform(({ lock }) => lock), + ).unwrapOrElse({}); + + for (const dep of deps) { + const packageName = dep.packageName; + if (packageName && packageName in lockFileMapping) { + dep.lockedVersion = lockFileMapping[packageName]; + } + } + } + + return Promise.resolve(deps); + } + async updateArtifacts( updateArtifact: UpdateArtifact, project: PyProject, diff --git a/lib/modules/manager/pep621/processors/types.ts b/lib/modules/manager/pep621/processors/types.ts index 16a382ce08f788efb1852e124bace09f301a2a0d..cc4c9861e58521fa87e6d3fd8225694d225ae6f6 100644 --- a/lib/modules/manager/pep621/processors/types.ts +++ b/lib/modules/manager/pep621/processors/types.ts @@ -18,4 +18,10 @@ export interface PyProjectProcessor { * @param deps List of already extracted/processed dependencies */ process(project: PyProject, deps: PackageDependency[]): PackageDependency[]; + + extractLockedVersions( + project: PyProject, + deps: PackageDependency[], + packageFile: string, + ): Promise<PackageDependency[]>; } diff --git a/lib/modules/manager/pep621/schema.ts b/lib/modules/manager/pep621/schema.ts index 212a1301c1b25763bcb126c0b0ada0747281796d..43e16362db9d8f1c3f089efcce319a4242b5830c 100644 --- a/lib/modules/manager/pep621/schema.ts +++ b/lib/modules/manager/pep621/schema.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; +import { LooseArray, Toml } from '../../../util/schema-utils'; export type PyProject = z.infer<typeof PyProjectSchema>; @@ -19,6 +20,7 @@ export const PyProjectSchema = z.object({ 'build-system': z .object({ requires: DependencyListSchema, + 'build-backend': z.string().optional(), }) .optional(), tool: z @@ -55,3 +57,18 @@ export const PyProjectSchema = z.object({ }) .optional(), }); + +export const PdmLockfileSchema = Toml.pipe( + z.object({ + package: LooseArray( + z + .object({ + name: z.string(), + version: z.string(), + }) + .transform(({ name, version }): [string, string] => [name, version]), + ) + .transform((entries) => Object.fromEntries(entries)) + .catch({}), + }), +).transform(({ package: lock }) => ({ lock }));