Skip to content

Commit 12cd136

Browse files
Add support for pip-inspect.deplock files
Add parser for pip-inspect.deplock files generated by deplock which has all the package metadata, i.e. the resolved versions and the dependency relationships. Reference: aboutcode-org/scancode.io#1262 Signed-off-by: Ayan Sinha Mahapatra <[email protected]>
1 parent c8046f1 commit 12cd136

File tree

5 files changed

+2120
-0
lines changed

5 files changed

+2120
-0
lines changed

src/packagedcode/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@
207207
windows.MicrosoftUpdateManifestHandler,
208208

209209
win_pe.WindowsExecutableHandler,
210+
211+
# These are handlers for deplock generated files
212+
pypi.PipInspectDeplockHandler,
210213
]
211214

212215
if on_linux:

src/packagedcode/pypi.py

+88
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,94 @@ def parse(cls, location, package_only=False):
563563
yield models.PackageData.from_data(package_data, package_only)
564564

565565

566+
class PipInspectDeplockHandler(models.DatafileHandler):
567+
datasource_id = 'pypi_inspect_deplock'
568+
path_patterns = ('*pip-inspect.deplock',)
569+
default_package_type = 'pypi'
570+
default_primary_language = 'Python'
571+
description = 'Python poetry pyproject.toml'
572+
# These are files generated by deplock, see https://github.com/nexB/dependency-inspector
573+
documentation_url = 'https://pip.pypa.io/en/stable/cli/pip_inspect/'
574+
575+
@classmethod
576+
def get_resolved_package_from_metadata(cls, metadata, package_only=False):
577+
578+
requires_dist = metadata.get('requires_dist')
579+
dependencies_for_resolved = get_requires_dependencies(
580+
requires=requires_dist,
581+
)
582+
package_data = dict(
583+
datasource_id=cls.datasource_id,
584+
type=cls.default_package_type,
585+
primary_language='Python',
586+
name=metadata.get('name'),
587+
version=metadata.get('version'),
588+
extracted_license_statement=metadata.get('license'),
589+
description=metadata.get('description'),
590+
keywords=metadata.get('keywords'),
591+
is_virtual=True,
592+
dependencies=[
593+
dep.to_dict()
594+
for dep in dependencies_for_resolved
595+
],
596+
)
597+
return models.PackageData.from_data(package_data, package_only)
598+
599+
@classmethod
600+
def parse(cls, location, package_only=False):
601+
602+
with open(location) as f:
603+
content = f.read()
604+
605+
data = json.loads(content)
606+
installed_packages = data.get('installed')
607+
if not installed_packages:
608+
return
609+
610+
main_package_metadata = {}
611+
dependencies = []
612+
613+
for package_metadata in installed_packages:
614+
package_metadata_dep = package_metadata.get('metadata')
615+
616+
# `direct_url` is only present for root package
617+
# `requested` is true for root package and direct dependencies only
618+
if package_metadata.get('requested') and 'direct_url' in package_metadata:
619+
main_package_metadata = package_metadata_dep
620+
continue
621+
622+
package_data_dep = cls.get_resolved_package_from_metadata(
623+
metadata=package_metadata_dep,
624+
package_only=package_only,
625+
)
626+
dep_purl = package_data_dep.purl
627+
628+
dependency = models.DependentPackage(
629+
purl=dep_purl,
630+
extracted_requirement=None,
631+
scope=None,
632+
is_runtime=True,
633+
is_optional=False,
634+
is_direct=False,
635+
is_resolved=True,
636+
resolved_package=package_data_dep.to_dict()
637+
)
638+
dependencies.append(dependency.to_dict())
639+
640+
pip_version = data.get('pip_version')
641+
inspect_version = data.get('version')
642+
extra_data = {
643+
"pip_version": pip_version,
644+
"inspect_version": inspect_version,
645+
}
646+
647+
package_data_main = cls.get_resolved_package_from_metadata(
648+
metadata=main_package_metadata,
649+
package_only=package_only,
650+
)
651+
package_data_main.dependencies = dependencies
652+
package_data_main.extra_data = extra_data
653+
yield package_data_main
566654

567655

568656
META_DIR_SUFFIXES = '.dist-info', '.egg-info', 'EGG-INFO',

tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock

+519
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)