@@ -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
568656META_DIR_SUFFIXES = '.dist-info' , '.egg-info' , 'EGG-INFO' ,
0 commit comments