Skip to content

Commit 9af1547

Browse files
Add is_virtual attribute and update tests
Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com>
1 parent 448fc36 commit 9af1547

File tree

1,149 files changed

+33197
-802467
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,149 files changed

+33197
-802467
lines changed

src/packagedcode/models.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,14 @@ class PackageData(IdentifiablePackageData):
698698
'repository, and is a private package.'
699699
)
700700

701+
is_virtual = Boolean(
702+
default=False,
703+
label='is virtual flag',
704+
help='True if this package or any of its files are not present in '
705+
'the codebase, but this package was created from a resolved '
706+
'package, typically present in a lockfile.'
707+
)
708+
701709
extra_data = Mapping(
702710
label='extra data',
703711
help='A mapping of arbitrary extra package data.',
@@ -1042,6 +1050,9 @@ class DatafileHandler:
10421050
# Informational: Default primary language for this parser.
10431051
default_primary_language = None
10441052

1053+
# If the datafilehandler contains only resolved dependencies
1054+
is_lockfile = False
1055+
10451056
# Informational: Description of this parser
10461057
description = None
10471058

@@ -1080,17 +1091,6 @@ def is_datafile(cls, location, filetypes=tuple(), _bare_filename=False):
10801091
actual_type = T.filetype_file.lower()
10811092
return any(ft in actual_type for ft in filetypes)
10821093

1083-
@classmethod
1084-
def is_lockfile(cls):
1085-
"""
1086-
Return True if this is a lockfile, False otherwise.
1087-
1088-
This has to be implemented by datafile handlers classes
1089-
of lockfiles, to return True, in contrast to the default
1090-
value False.
1091-
"""
1092-
return False
1093-
10941094
@classmethod
10951095
def parse(cls, location, package_only=False):
10961096
"""

src/packagedcode/npm.py

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,24 @@ def update_dependencies_by_purl(
204204
cls,
205205
dependencies,
206206
scope,
207-
dependecies_by_purl,
207+
dependencies_by_purl,
208208
is_runtime=False,
209209
is_optional=False,
210210
is_resolved=False,
211211
is_direct=True,
212212
):
213-
213+
"""
214+
Update the `dependencies_by_purl` mapping (which contains the cumulative
215+
dependencies for a package metadata) from a list of `dependencies` which
216+
have new dependencies or metadata for already existing dependencies.
217+
"""
218+
# npm/pnpm Dependency scopes which contain metadata for dependencies
219+
# see documentation below for more details
220+
# https://docs.npmjs.com/cli/v10/configuring-npm/package-json#peerdependenciesmeta
221+
# https://pnpm.io/package_json#dependenciesmeta
214222
metadata_deps = ['peerDependenciesMeta', 'dependenciesMeta']
215-
if type(dependencies) == list:
223+
224+
if isinstance(dependencies, list):
216225
for subdep in dependencies:
217226
sdns, _ , sdname = subdep.rpartition('/')
218227
dep_purl = PackageURL(
@@ -228,9 +237,9 @@ def update_dependencies_by_purl(
228237
is_resolved=is_resolved,
229238
is_direct=is_direct,
230239
)
231-
dependecies_by_purl[dep_purl] = dep_package
240+
dependencies_by_purl[dep_purl] = dep_package
232241

233-
elif type(dependencies) == dict:
242+
elif isinstance(dependencies, dict):
234243
for subdep, metadata in dependencies.items():
235244
sdns, _ , sdname = subdep.rpartition('/')
236245
dep_purl = PackageURL(
@@ -240,7 +249,7 @@ def update_dependencies_by_purl(
240249
).to_string()
241250

242251
if scope in metadata_deps :
243-
dep_package = dependecies_by_purl.get(dep_purl)
252+
dep_package = dependencies_by_purl.get(dep_purl)
244253
if dep_package:
245254
dep_package.is_optional = metadata.get("optional")
246255
else:
@@ -252,7 +261,7 @@ def update_dependencies_by_purl(
252261
is_resolved=is_resolved,
253262
is_direct=is_direct,
254263
)
255-
dependecies_by_purl[dep_purl] = dep_package
264+
dependencies_by_purl[dep_purl] = dep_package
256265
continue
257266

258267
# pnpm has peer dependencies also sometimes in version?
@@ -273,7 +282,7 @@ def update_dependencies_by_purl(
273282
is_resolved=is_resolved,
274283
is_direct=is_direct,
275284
)
276-
dependecies_by_purl[dep_purl] = dep_package
285+
dependencies_by_purl[dep_purl] = dep_package
277286

278287
@classmethod
279288
def get_workspace_members(cls, workspaces, codebase, workspace_root_path):
@@ -328,6 +337,9 @@ def get_workspace_members(cls, workspaces, codebase, workspace_root_path):
328337
@classmethod
329338
def update_workspace_members(cls, workspace_members, codebase):
330339
"""
340+
Update all version requirements referencing workspace level
341+
package versions with data from all the `workspace_members`.
342+
Example: "ruru-components@workspace:^"
331343
"""
332344
# Collect info needed from all workspace member
333345
workspace_package_versions_by_base_purl = {}
@@ -484,10 +496,6 @@ def parse(cls, location, package_only=False):
484496

485497
class BaseNpmLockHandler(BaseNpmHandler):
486498

487-
@classmethod
488-
def is_lockfile(cls):
489-
return True
490-
491499
@classmethod
492500
def parse(cls, location, package_only=False):
493501

@@ -620,6 +628,7 @@ def parse(cls, location, package_only=False):
620628
name=name,
621629
version=version,
622630
**misc,
631+
is_virtual=True,
623632
)
624633
resolved_package = models.PackageData.from_data(resolved_package_mapping, package_only)
625634
# these are paths t the root of the installed package in v2
@@ -647,7 +656,7 @@ def parse(cls, location, package_only=False):
647656
cls.update_dependencies_by_purl(
648657
dependencies=subdeps_data,
649658
scope=scope,
650-
dependecies_by_purl=sub_deps_by_purl,
659+
dependencies_by_purl=sub_deps_by_purl,
651660
is_runtime=is_runtime,
652661
is_optional=is_optional,
653662
is_resolved=False,
@@ -677,6 +686,7 @@ class NpmPackageLockJsonHandler(BaseNpmLockHandler):
677686
)
678687
default_package_type = 'npm'
679688
default_primary_language = 'JavaScript'
689+
is_lockfile = True
680690
description = 'npm package-lock.json lockfile'
681691
documentation_url = 'https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json'
682692

@@ -686,6 +696,7 @@ class NpmShrinkwrapJsonHandler(BaseNpmLockHandler):
686696
path_patterns = ('*/npm-shrinkwrap.json',)
687697
default_package_type = 'npm'
688698
default_primary_language = 'JavaScript'
699+
is_lockfile = True
689700
description = 'npm shrinkwrap.json lockfile'
690701
documentation_url = 'https://docs.npmjs.com/cli/v8/configuring-npm/npm-shrinkwrap-json'
691702

@@ -730,17 +741,14 @@ class YarnLockV2Handler(BaseNpmHandler):
730741
path_patterns = ('*/yarn.lock',)
731742
default_package_type = 'npm'
732743
default_primary_language = 'JavaScript'
744+
is_lockfile = True
733745
description = 'yarn.lock lockfile v2 format'
734746
documentation_url = 'https://classic.yarnpkg.com/lang/en/docs/yarn-lock/'
735747

736748
@classmethod
737749
def is_datafile(cls, location, filetypes=tuple()):
738750
return super().is_datafile(location, filetypes=filetypes) and is_yarn_v2(location)
739751

740-
@classmethod
741-
def is_lockfile(cls):
742-
return True
743-
744752
@classmethod
745753
def parse(cls, location, package_only=False):
746754
"""
@@ -789,17 +797,17 @@ def parse(cls, location, package_only=False):
789797
cls.update_dependencies_by_purl(
790798
dependencies=dependencies,
791799
scope="dependencies",
792-
dependecies_by_purl=deps_for_resolved_by_purl,
800+
dependencies_by_purl=deps_for_resolved_by_purl,
793801
)
794802
cls.update_dependencies_by_purl(
795803
dependencies=peer_dependencies,
796804
scope="peerDependencies",
797-
dependecies_by_purl=deps_for_resolved_by_purl,
805+
dependencies_by_purl=deps_for_resolved_by_purl,
798806
)
799807
cls.update_dependencies_by_purl(
800808
dependencies=dependencies_meta,
801809
scope="dependenciesMeta",
802-
dependecies_by_purl=deps_for_resolved_by_purl,
810+
dependencies_by_purl=deps_for_resolved_by_purl,
803811
)
804812

805813
dependencies_for_resolved = [
@@ -815,7 +823,7 @@ def parse(cls, location, package_only=False):
815823
name=name,
816824
version=version,
817825
dependencies=dependencies_for_resolved,
818-
826+
is_virtual=True,
819827
)
820828
resolved_package = models.PackageData.from_data(resolved_package_mapping)
821829
dependency = models.DependentPackage(
@@ -848,13 +856,10 @@ class YarnLockV1Handler(BaseNpmHandler):
848856
path_patterns = ('*/yarn.lock',)
849857
default_package_type = 'npm'
850858
default_primary_language = 'JavaScript'
859+
is_lockfile = True
851860
description = 'yarn.lock lockfile v1 format'
852861
documentation_url = 'https://classic.yarnpkg.com/lang/en/docs/yarn-lock/'
853862

854-
@classmethod
855-
def is_lockfile(cls):
856-
return True
857-
858863
@classmethod
859864
def is_datafile(cls, location, filetypes=tuple()):
860865
return super().is_datafile(location, filetypes=filetypes) and not is_yarn_v2(location)
@@ -960,6 +965,7 @@ def parse(cls, location, package_only=False):
960965
name=name,
961966
version=version,
962967
primary_language=cls.default_primary_language,
968+
is_virtual=True,
963969
**misc,
964970
)
965971
resolved_package_data = models.PackageData.from_data(resolved_package_mapping, package_only)
@@ -1012,10 +1018,6 @@ def parse(cls, location, package_only=False):
10121018

10131019
class BasePnpmLockHandler(BaseNpmHandler):
10141020

1015-
@classmethod
1016-
def is_lockfile(cls):
1017-
return True
1018-
10191021
@classmethod
10201022
def parse(cls, location, package_only=False):
10211023
"""
@@ -1089,34 +1091,34 @@ def parse(cls, location, package_only=False):
10891091
cls.update_dependencies_by_purl(
10901092
dependencies=dependencies,
10911093
scope='dependencies',
1092-
dependecies_by_purl=deps_for_resolved_by_purl,
1094+
dependencies_by_purl=deps_for_resolved_by_purl,
10931095
is_resolved=True,
10941096
is_direct=False,
10951097
)
10961098
cls.update_dependencies_by_purl(
10971099
dependencies=peer_dependencies,
10981100
scope='peerDependencies',
1099-
dependecies_by_purl=deps_for_resolved_by_purl,
1101+
dependencies_by_purl=deps_for_resolved_by_purl,
11001102
is_optional=True,
11011103
is_direct=False,
11021104
)
11031105
cls.update_dependencies_by_purl(
11041106
dependencies=optional_dependencies,
11051107
scope='optionalDependencies',
1106-
dependecies_by_purl=deps_for_resolved_by_purl,
1108+
dependencies_by_purl=deps_for_resolved_by_purl,
11071109
is_resolved=True,
11081110
is_optional=True,
11091111
is_direct=False,
11101112
)
11111113
cls.update_dependencies_by_purl(
11121114
dependencies=peer_dependencies_meta,
11131115
scope='peerDependenciesMeta',
1114-
dependecies_by_purl=deps_for_resolved_by_purl,
1116+
dependencies_by_purl=deps_for_resolved_by_purl,
11151117
)
11161118
cls.update_dependencies_by_purl(
11171119
dependencies=transitive_peer_dependencies,
11181120
scope='transitivePeerDependencies',
1119-
dependecies_by_purl=deps_for_resolved_by_purl,
1121+
dependencies_by_purl=deps_for_resolved_by_purl,
11201122
)
11211123

11221124
dependencies_for_resolved = [
@@ -1132,6 +1134,7 @@ def parse(cls, location, package_only=False):
11321134
name=name,
11331135
version=version,
11341136
dependencies=dependencies_for_resolved,
1137+
is_virtual=True,
11351138
**misc,
11361139
)
11371140
resolved_package = models.PackageData.from_data(resolved_package_mapping)
@@ -1179,6 +1182,7 @@ class PnpmShrinkwrapYamlHandler(BasePnpmLockHandler):
11791182
path_patterns = ('*/shrinkwrap.yaml',)
11801183
default_package_type = 'npm'
11811184
default_primary_language = 'JavaScript'
1185+
is_lockfile = True
11821186
description = 'pnpm shrinkwrap.yaml lockfile'
11831187
documentation_url = 'https://github.com/pnpm/spec/blob/master/lockfile/4.md'
11841188

@@ -1188,6 +1192,7 @@ class PnpmLockYamlHandler(BasePnpmLockHandler):
11881192
path_patterns = ('*/pnpm-lock.yaml',)
11891193
default_package_type = 'npm'
11901194
default_primary_language = 'JavaScript'
1195+
is_lockfile = True
11911196
description = 'pnpm pnpm-lock.yaml lockfile'
11921197
documentation_url = 'https://github.com/pnpm/spec/blob/master/lockfile/6.0.md'
11931198

0 commit comments

Comments
 (0)