Skip to content

Commit cb19215

Browse files
authored
Merge pull request #125 from nexB/fix_124
Fix resolution of setup files which partially have dynamic dependencies
2 parents 271921d + 3bf0a3a commit cb19215

11 files changed

+350
-431
lines changed

src/python_inspector/api.py

+22-13
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from python_inspector.resolution import get_environment_marker_from_environment
3838
from python_inspector.resolution import get_package_list
3939
from python_inspector.resolution import get_python_version_from_env_tag
40+
from python_inspector.resolution import get_reqs_insecurely
4041
from python_inspector.resolution import get_requirements_from_python_manifest
4142
from python_inspector.utils_pypi import PLATFORMS_BY_OS
4243
from python_inspector.utils_pypi import PYPI_SIMPLE_URL
@@ -175,22 +176,30 @@ def resolve_dependencies(
175176
f"is not compatible with setup.py {setup_py_file} "
176177
f"python_requires {python_requires}",
177178
)
178-
179-
setup_py_file_deps = package_data.dependencies
180-
for dep in package_data.dependencies:
181-
# TODO : we need to handle to all the scopes
182-
if dep.scope == "install":
183-
direct_dependencies.append(dep)
184-
185-
if not package_data.dependencies:
186-
reqs = get_requirements_from_python_manifest(
187-
sdist_location=os.path.dirname(setup_py_file),
188-
setup_py_location=setup_py_file,
189-
files=[setup_py_file],
190-
analyze_setup_py_insecurely=analyze_setup_py_insecurely,
179+
if analyze_setup_py_insecurely:
180+
reqs = list(
181+
get_reqs_insecurely(
182+
setup_py_location=setup_py_file,
183+
)
191184
)
192185
setup_py_file_deps = list(get_dependent_packages_from_reqs(reqs))
193186
direct_dependencies.extend(setup_py_file_deps)
187+
else:
188+
setup_py_file_deps = package_data.dependencies
189+
for dep in package_data.dependencies:
190+
# TODO : we need to handle to all the scopes
191+
if dep.scope == "install":
192+
direct_dependencies.append(dep)
193+
194+
if not package_data.dependencies:
195+
reqs = get_requirements_from_python_manifest(
196+
sdist_location=os.path.dirname(setup_py_file),
197+
setup_py_location=setup_py_file,
198+
files=[setup_py_file],
199+
analyze_setup_py_insecurely=analyze_setup_py_insecurely,
200+
)
201+
setup_py_file_deps = list(get_dependent_packages_from_reqs(reqs))
202+
direct_dependencies.extend(setup_py_file_deps)
194203

195204
package_data.dependencies = setup_py_file_deps
196205
file_package_data = [package_data.to_dict()]

src/python_inspector/resolution.py

+20-15
Original file line numberDiff line numberDiff line change
@@ -493,25 +493,30 @@ def get_requirements_for_package_from_pypi_simple(
493493
"setup.cfg",
494494
)
495495

496-
requirements = list(
497-
get_setup_requirements(
498-
sdist_location=sdist_location,
496+
if self.analyze_setup_py_insecurely:
497+
yield from get_reqs_insecurely(
499498
setup_py_location=setup_py_location,
500-
setup_cfg_location=setup_cfg_location,
501499
)
502-
)
503-
if requirements:
504-
yield from requirements
505500
else:
506-
# Look in requirements file if and only if thy are refered in setup.py or setup.cfg
507-
# And no deps have been yielded by requirements file
508-
509-
yield from get_requirements_from_python_manifest(
510-
sdist_location=sdist_location,
511-
setup_py_location=setup_py_location,
512-
files=[setup_cfg_location, setup_py_location],
513-
analyze_setup_py_insecurely=self.analyze_setup_py_insecurely,
501+
requirements = list(
502+
get_setup_requirements(
503+
sdist_location=sdist_location,
504+
setup_py_location=setup_py_location,
505+
setup_cfg_location=setup_cfg_location,
506+
)
514507
)
508+
if requirements:
509+
yield from requirements
510+
else:
511+
# Look in requirements file if and only if thy are refered in setup.py or setup.cfg
512+
# And no deps have been yielded by requirements file
513+
514+
yield from get_requirements_from_python_manifest(
515+
sdist_location=sdist_location,
516+
setup_py_location=setup_py_location,
517+
files=[setup_cfg_location, setup_py_location],
518+
analyze_setup_py_insecurely=self.analyze_setup_py_insecurely,
519+
)
515520

516521
def get_requirements_for_package_from_pypi_json_api(
517522
self, purl: PackageURL

tests/data/azure-devops.req-310-expected.json

+40-40
Large diffs are not rendered by default.

tests/data/azure-devops.req-38-expected.json

+40-40
Large diffs are not rendered by default.

tests/data/insecure-setup-2/setup.py-expected.json

+35-299
Large diffs are not rendered by default.

tests/data/partial-setup.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from setuptools import setup
2+
3+
semver_version = "2.13.0"
4+
5+
setup(
6+
name="example",
7+
version="0.0.1",
8+
install_requires=[
9+
f"semver @ git+https://github.com/python-semver/python-semver.git@{semver_version}",
10+
],
11+
extras_require={"test": ["botocore==1.27.76"]},
12+
)

tests/data/setup/spdx-setup.py-expected.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
"purl": "pkg:pypi/ply",
7676
"extracted_requirement": "ply",
7777
"scope": "install",
78-
"is_runtime": true,
78+
"is_runtime": false,
7979
"is_optional": false,
8080
"is_resolved": false,
8181
"resolved_package": {},
@@ -85,7 +85,7 @@
8585
"purl": "pkg:pypi/rdflib",
8686
"extracted_requirement": "rdflib",
8787
"scope": "install",
88-
"is_runtime": true,
88+
"is_runtime": false,
8989
"is_optional": false,
9090
"is_resolved": false,
9191
"resolved_package": {},
@@ -95,7 +95,7 @@
9595
"purl": "pkg:pypi/six",
9696
"extracted_requirement": "six",
9797
"scope": "install",
98-
"is_runtime": true,
98+
"is_runtime": false,
9999
"is_optional": false,
100100
"is_resolved": false,
101101
"resolved_package": {},

tests/data/single-url-except-simple-expected.json

+18-18
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,12 @@
276276
"type": "pypi",
277277
"namespace": null,
278278
"name": "importlib-metadata",
279-
"version": "6.1.0",
279+
"version": "6.3.0",
280280
"qualifiers": {},
281281
"subpath": null,
282282
"primary_language": "Python",
283283
"description": "Read metadata from Python packages\n.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg\n :target: https://pypi.org/project/importlib_metadata\n\n.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg\n\n.. image:: https://github.com/python/importlib_metadata/workflows/tests/badge.svg\n :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest\n :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata\n :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme\n\nLibrary to access the metadata for a Python package.\n\nThis package supplies third-party access to the functionality of\n`importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_\nincluding improvements added to subsequent Python versions.\n\n\nCompatibility\n=============\n\nNew features are introduced in this third-party library and later merged\ninto CPython. The following table indicates which versions of this library\nwere contributed to different versions in the standard library:\n\n.. list-table::\n :header-rows: 1\n\n * - importlib_metadata\n - stdlib\n * - 5.0\n - 3.12\n * - 4.13\n - 3.11\n * - 4.6\n - 3.10\n * - 1.4\n - 3.8\n\n\nUsage\n=====\n\nSee the `online documentation <https://importlib_metadata.readthedocs.io/>`_\nfor usage details.\n\n`Finder authors\n<https://docs.python.org/3/reference/import.html#finders-and-loaders>`_ can\nalso add support for custom package installers. See the above documentation\nfor details.\n\n\nCaveats\n=======\n\nThis project primarily supports third-party packages installed by PyPA\ntools (or other conforming packages). It does not support:\n\n- Packages in the stdlib.\n- Packages installed without metadata.\n\nProject details\n===============\n\n * Project home: https://github.com/python/importlib_metadata\n * Report bugs at: https://github.com/python/importlib_metadata/issues\n * Code hosting: https://github.com/python/importlib_metadata\n * Documentation: https://importlib_metadata.readthedocs.io/\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more <https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=referral&utm_campaign=github>`_.\n\nSecurity Contact\n================\n\nTo report a security vulnerability, please use the\n`Tidelift security contact <https://tidelift.com/security>`_.\nTidelift will coordinate the fix and disclosure.",
284-
"release_date": "2023-03-18T17:10:47",
284+
"release_date": "2023-04-10T02:27:40",
285285
"parties": [
286286
{
287287
"type": "person",
@@ -298,11 +298,11 @@
298298
"Programming Language :: Python :: 3 :: Only"
299299
],
300300
"homepage_url": "https://github.com/python/importlib_metadata",
301-
"download_url": "https://files.pythonhosted.org/packages/f8/7d/e3adad613703c86d62aa991b45d6f090cf59975078a8c8100b50a0c86948/importlib_metadata-6.1.0-py3-none-any.whl",
302-
"size": 21918,
301+
"download_url": "https://files.pythonhosted.org/packages/af/15/544ee37359dd4d8e490d1846062015f9d7d59b0f11e2e8e629917608e592/importlib_metadata-6.3.0-py3-none-any.whl",
302+
"size": 22533,
303303
"sha1": null,
304-
"md5": "a952f41348b249647623b1f32c152c65",
305-
"sha256": "ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09",
304+
"md5": "fa927011905878792c54886f35e59bca",
305+
"sha256": "8f8bd2af397cf33bd344d35cfe7f489219b7d14fc79a3f854b75b8417e9226b0",
306306
"sha512": null,
307307
"bug_tracking_url": null,
308308
"code_view_url": null,
@@ -321,20 +321,20 @@
321321
"dependencies": [],
322322
"repository_homepage_url": null,
323323
"repository_download_url": null,
324-
"api_data_url": "https://pypi.org/pypi/importlib-metadata/6.1.0/json",
324+
"api_data_url": "https://pypi.org/pypi/importlib-metadata/6.3.0/json",
325325
"datasource_id": null,
326-
"purl": "pkg:pypi/importlib-metadata@6.1.0"
326+
"purl": "pkg:pypi/importlib-metadata@6.3.0"
327327
},
328328
{
329329
"type": "pypi",
330330
"namespace": null,
331331
"name": "importlib-metadata",
332-
"version": "6.1.0",
332+
"version": "6.3.0",
333333
"qualifiers": {},
334334
"subpath": null,
335335
"primary_language": "Python",
336336
"description": "Read metadata from Python packages\n.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg\n :target: https://pypi.org/project/importlib_metadata\n\n.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg\n\n.. image:: https://github.com/python/importlib_metadata/workflows/tests/badge.svg\n :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest\n :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata\n :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme\n\nLibrary to access the metadata for a Python package.\n\nThis package supplies third-party access to the functionality of\n`importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_\nincluding improvements added to subsequent Python versions.\n\n\nCompatibility\n=============\n\nNew features are introduced in this third-party library and later merged\ninto CPython. The following table indicates which versions of this library\nwere contributed to different versions in the standard library:\n\n.. list-table::\n :header-rows: 1\n\n * - importlib_metadata\n - stdlib\n * - 5.0\n - 3.12\n * - 4.13\n - 3.11\n * - 4.6\n - 3.10\n * - 1.4\n - 3.8\n\n\nUsage\n=====\n\nSee the `online documentation <https://importlib_metadata.readthedocs.io/>`_\nfor usage details.\n\n`Finder authors\n<https://docs.python.org/3/reference/import.html#finders-and-loaders>`_ can\nalso add support for custom package installers. See the above documentation\nfor details.\n\n\nCaveats\n=======\n\nThis project primarily supports third-party packages installed by PyPA\ntools (or other conforming packages). It does not support:\n\n- Packages in the stdlib.\n- Packages installed without metadata.\n\nProject details\n===============\n\n * Project home: https://github.com/python/importlib_metadata\n * Report bugs at: https://github.com/python/importlib_metadata/issues\n * Code hosting: https://github.com/python/importlib_metadata\n * Documentation: https://importlib_metadata.readthedocs.io/\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more <https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=referral&utm_campaign=github>`_.\n\nSecurity Contact\n================\n\nTo report a security vulnerability, please use the\n`Tidelift security contact <https://tidelift.com/security>`_.\nTidelift will coordinate the fix and disclosure.",
337-
"release_date": "2023-03-18T17:10:49",
337+
"release_date": "2023-04-10T02:27:42",
338338
"parties": [
339339
{
340340
"type": "person",
@@ -351,11 +351,11 @@
351351
"Programming Language :: Python :: 3 :: Only"
352352
],
353353
"homepage_url": "https://github.com/python/importlib_metadata",
354-
"download_url": "https://files.pythonhosted.org/packages/e2/d8/3d431bade4598ad9e33be9da41d15e6607b878008e922d122659ab01b077/importlib_metadata-6.1.0.tar.gz",
355-
"size": 50209,
354+
"download_url": "https://files.pythonhosted.org/packages/c2/84/ab374b7e05fbdeecf867294660ac0fdb23aa286aca68a31d587f67d181ad/importlib_metadata-6.3.0.tar.gz",
355+
"size": 52838,
356356
"sha1": null,
357-
"md5": "c92d5a03615c6ef97d283d71fb92cf1b",
358-
"sha256": "43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20",
357+
"md5": "f06a844f0917a1f4db1a1050f750c4fb",
358+
"sha256": "23c2bcae4762dfb0bbe072d358faec24957901d75b6c4ab11172c0c982532402",
359359
"sha512": null,
360360
"bug_tracking_url": null,
361361
"code_view_url": null,
@@ -374,9 +374,9 @@
374374
"dependencies": [],
375375
"repository_homepage_url": null,
376376
"repository_download_url": null,
377-
"api_data_url": "https://pypi.org/pypi/importlib-metadata/6.1.0/json",
377+
"api_data_url": "https://pypi.org/pypi/importlib-metadata/6.3.0/json",
378378
"datasource_id": null,
379-
"purl": "pkg:pypi/importlib-metadata@6.1.0"
379+
"purl": "pkg:pypi/importlib-metadata@6.3.0"
380380
},
381381
{
382382
"type": "pypi",
@@ -1006,14 +1006,14 @@
10061006
"package": "pkg:pypi/[email protected]",
10071007
"dependencies": [
10081008
"pkg:pypi/[email protected]",
1009-
"pkg:pypi/importlib-metadata@6.1.0",
1009+
"pkg:pypi/importlib-metadata@6.3.0",
10101010
"pkg:pypi/[email protected]",
10111011
"pkg:pypi/[email protected]",
10121012
"pkg:pypi/[email protected]"
10131013
]
10141014
},
10151015
{
1016-
"package": "pkg:pypi/importlib-metadata@6.1.0",
1016+
"package": "pkg:pypi/importlib-metadata@6.3.0",
10171017
"dependencies": [
10181018
"pkg:pypi/[email protected]"
10191019
]

0 commit comments

Comments
 (0)