1919from pathlib import Path
2020
2121import dparse2
22+ import packaging
2223import pip_requirements_parser
2324import pkginfo2
2425from commoncode import fileutils
@@ -684,10 +685,17 @@ def parse(cls, location):
684685
685686 metadata = {}
686687 parser = ConfigParser ()
688+ dependent_packages = []
687689 with open (location ) as f :
688690 parser .read_file (f )
689-
690691 for section in parser .values ():
692+ if section .name == 'options' :
693+ reqs = list (get_requirement_from_section (section = section , sub_section = "install_requires" ))
694+ dependent_packages .extend (cls .parse_reqs (reqs , "install" ))
695+ if section .name == "options.extras_require" :
696+ for sub_section in section :
697+ reqs = list (get_requirement_from_section (section = section , sub_section = sub_section ))
698+ dependent_packages .extend (cls .parse_reqs (reqs , sub_section ))
691699 if section .name == 'metadata' :
692700 options = (
693701 'name' ,
@@ -719,10 +727,6 @@ def parse(cls, location):
719727 if not dependency_type :
720728 return
721729
722- dependencies = parse_with_dparse2 (
723- location = location ,
724- file_name = dependency_type ,
725- )
726730 yield models .PackageData (
727731 datasource_id = cls .datasource_id ,
728732 type = cls .default_package_type ,
@@ -731,9 +735,33 @@ def parse(cls, location):
731735 parties = parties ,
732736 homepage_url = metadata .get ('url' ),
733737 primary_language = cls .default_primary_language ,
734- dependencies = dependencies ,
738+ dependencies = dependent_packages ,
735739 )
736740
741+ @classmethod
742+ def parse_reqs (cls , reqs , scope ):
743+ dependent_packages = []
744+ for req in reqs :
745+ is_resolved = False
746+ req_parsed = packaging .requirements .Requirement (str (req ))
747+ purl = PackageURL (type = "pypi" , name = req_parsed .name )
748+ specifiers = req_parsed .specifier ._specs
749+ if len (specifiers ) == 1 :
750+ specifier = list (specifiers )[0 ]
751+ if specifier .operator in ('==' , '===' ):
752+ is_resolved = True
753+ purl = purl ._replace (version = specifier .version )
754+ dependent_packages .append (
755+ models .DependentPackage (
756+ purl = purl ,
757+ scope = scope ,
758+ is_runtime = True ,
759+ is_optional = False ,
760+ is_resolved = is_resolved ,
761+ extracted_requirement = req
762+ )
763+ )
764+ return dependent_packages
737765
738766class PipfileHandler (BaseDependencyFileHandler ):
739767 datasource_id = 'pipfile'
@@ -1017,10 +1045,11 @@ def get_classifiers(metainfo):
10171045 license_classifiers = []
10181046 other_classifiers = []
10191047 for classifier in classifiers :
1020- if classifier .startswith ('License' ):
1021- license_classifiers .append (classifier )
1022- else :
1023- other_classifiers .append (classifier )
1048+ if classifier :
1049+ if classifier .startswith ('License' ):
1050+ license_classifiers .append (classifier )
1051+ else :
1052+ other_classifiers .append (classifier )
10241053 return license_classifiers , other_classifiers
10251054
10261055
@@ -1272,6 +1301,7 @@ def parse_with_dparse2(location, file_name=None):
12721301 dependent_packages = []
12731302
12741303 for dependency in dep_file .dependencies :
1304+ # print(dependency.serialize())
12751305 name = dependency .name
12761306 is_resolved = False
12771307 purl = PackageURL (type = 'pypi' , name = dependency .name )
@@ -1899,3 +1929,22 @@ def compute_normalized_license(declared_license):
18991929
19001930 if detected_licenses :
19011931 return combine_expressions (detected_licenses )
1932+
1933+
1934+ def get_requirement_from_section (section , sub_section ):
1935+ content = section .get (sub_section )
1936+ if content :
1937+ for req in content .splitlines ():
1938+ if req :
1939+ req = req .replace ("; \\ " , "" )
1940+ if "#" in req :
1941+ req , _ = req .rsplit ("#" )
1942+ req_split_by_semi_colon = req .split (";" )
1943+ req_split_by_semi_colon = [req .strip () for req in req_split_by_semi_colon ]
1944+ if len (req_split_by_semi_colon ) >= 2 and not (req_split_by_semi_colon [1 ].startswith ("python_version" )
1945+ or req_split_by_semi_colon [1 ].startswith ("sys_platform" )
1946+ or req_split_by_semi_colon [1 ].startswith ("platform_system" )):
1947+ for temp_req in req_split_by_semi_colon :
1948+ yield temp_req
1949+ else :
1950+ yield req
0 commit comments