Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PackageManifest Class #2748

Merged
merged 27 commits into from
Jan 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d5b09c3
Rename package attribute metafiles to file_patterns
AyanSinhaMahapatra Nov 2, 2021
1a4bd31
Add PackageManifest class to models
AyanSinhaMahapatra Nov 2, 2021
faa5f3a
Modify package classes to inherit PackageManifest mixin
AyanSinhaMahapatra Nov 2, 2021
a2dddba
Modify test expectations for recognize_package_manifests
AyanSinhaMahapatra Nov 3, 2021
1d561d5
Create PackageManifest classes for cocoapods
AyanSinhaMahapatra Nov 2, 2021
9466e0f
Create PackageManifest class fot aboutfiles
AyanSinhaMahapatra Nov 2, 2021
ab20f29
Create PackageManifest classes for NPM
AyanSinhaMahapatra Nov 3, 2021
a0d0010
Create PackageManifest classes for phpcomposer
AyanSinhaMahapatra Nov 3, 2021
9e5d3b7
Create PackageManifest class for Haxe
AyanSinhaMahapatra Nov 4, 2021
45553ae
Create PackageManifest classes for cargo
AyanSinhaMahapatra Nov 4, 2021
b72c03e
Add PackageManifest class for opam
AyanSinhaMahapatra Nov 4, 2021
83dee55
Add PackageManifest class for bower
AyanSinhaMahapatra Nov 4, 2021
e519e8e
Create PackageManifest class for freebsd
AyanSinhaMahapatra Nov 10, 2021
6270119
Add PackageManifest classes for ruby manifests
AyanSinhaMahapatra Nov 10, 2021
fd6d746
Add PackageManifest classes for pypi manifests
AyanSinhaMahapatra Nov 15, 2021
a368135
Create PackageManifest classes for golang manifests
AyanSinhaMahapatra Nov 15, 2021
2dbe916
Create PackageManifest class for nuspec manifest
AyanSinhaMahapatra Nov 15, 2021
f525e59
Add PackageManifest classes for chef manifests
AyanSinhaMahapatra Nov 15, 2021
54e3d20
Create PackageManifest classes for conda
AyanSinhaMahapatra Nov 15, 2021
a866432
Create PackageManifest class for readme manifests
AyanSinhaMahapatra Nov 16, 2021
1277580
Create PackageManifest classes for pubspec
AyanSinhaMahapatra Nov 16, 2021
8a30df3
Create PackageManifest classes for windows manifests
AyanSinhaMahapatra Nov 16, 2021
b014cd9
Modify PackageManifest classes in build
AyanSinhaMahapatra Nov 16, 2021
b8968e2
Create PackageManifest class for rpm
AyanSinhaMahapatra Nov 16, 2021
d2b37a1
Modify PackageManifest class names and attributes
AyanSinhaMahapatra Nov 30, 2021
b5196ff
Remove duplicate models and update docstrings
AyanSinhaMahapatra Nov 30, 2021
7b5cf8c
Remove recognize function from package class
AyanSinhaMahapatra Dec 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 58 additions & 31 deletions src/packagedcode/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from packagedcode import freebsd
from packagedcode import golang
from packagedcode import haxe
from packagedcode import jar_manifest
from packagedcode import maven
from packagedcode import models
from packagedcode import msi
Expand All @@ -38,73 +39,99 @@

# Note: the order matters: from the most to the least specific
# Package classes MUST be added to this list to be active
PACKAGE_TYPES = [
rpm.RpmPackage,
PACKAGE_MANIFEST_TYPES = [
rpm.RpmManifest,
debian.DebianPackage,

models.JavaJar,
jar_manifest.JavaManifest,
models.JavaEar,
models.JavaWar,
maven.MavenPomPackage,
models.IvyJar,
jar_manifest.IvyJar,
models.JBossSar,
models.Axis2Mar,

about.AboutPackage,
npm.NpmPackage,
phpcomposer.PHPComposerPackage,
haxe.HaxePackage,
cargo.RustCargoCrate,
cocoapods.CocoapodsPackage,
opam.OpamPackage,
about.Aboutfile,
npm.PackageJson,
npm.PackageLockJson,
npm.YarnLockJson,
phpcomposer.ComposerJson,
phpcomposer.ComposerLock,
haxe.HaxelibJson,
cargo.CargoToml,
cargo.CargoLock,
cocoapods.Podspec,
cocoapods.PodfileLock,
cocoapods.PodspecJson,
opam.OpamFile,
models.MeteorPackage,
bower.BowerPackage,
freebsd.FreeBSDPackage,
bower.BowerJson,
freebsd.CompactManifest,
models.CpanModule,
rubygems.RubyGem,
rubygems.GemArchive,
rubygems.GemArchiveExtracted,
rubygems.GemSpec,
rubygems.GemfileLock,
models.AndroidApp,
models.AndroidLibrary,
models.MozillaExtension,
models.ChromeExtension,
models.IOSApp,
pypi.PythonPackage,
golang.GolangPackage,
pypi.MetadataFile,
pypi.BinaryDistArchive,
pypi.SourceDistArchive,
pypi.SetupPy,
pypi.DependencyFile,
pypi.PipfileLock,
pypi.RequirementsFile,
golang.GoMod,
golang.GoSum,
models.CabPackage,
models.InstallShieldPackage,
models.NSISInstallerPackage,
nuget.NugetPackage,
nuget.Nuspec,
models.SharPackage,
models.AppleDmgPackage,
models.IsoImagePackage,
models.SquashfsPackage,
chef.ChefPackage,
chef.MetadataJson,
chef.Metadatarb,
build.BazelPackage,
build.BuckPackage,
build.AutotoolsPackage,
conda.CondaPackage,
win_pe.WindowsExecutable,
readme.ReadmePackage,
conda.Condayml,
win_pe.WindowsExecutableManifest,
readme.ReadmeManifest,
build.MetadataBzl,
msi.MsiInstallerPackage,
windows.MicrosoftUpdateManifestPackage,
pubspec.PubspecPackage,
windows.MicrosoftUpdateManifest,
pubspec.PubspecYaml,
pubspec.PubspecLock
]

PACKAGES_BY_TYPE = {cls.default_type: cls for cls in PACKAGE_TYPES}

PACKAGE_MANIFESTS_BY_TYPE = {
(
cls.package_manifest_type
if isinstance(cls, models.PackageManifest)
else cls.default_type
): cls
for cls in PACKAGE_MANIFEST_TYPES
}
# We cannot have two package classes with the same type
if len(PACKAGES_BY_TYPE) != len(PACKAGE_TYPES):
if len(PACKAGE_MANIFESTS_BY_TYPE) != len(PACKAGE_MANIFEST_TYPES):
AyanSinhaMahapatra marked this conversation as resolved.
Show resolved Hide resolved
seen_types = {}
for pt in PACKAGE_TYPES:
assert pt.default_type
seen = seen_types.get(pt.default_type)
for pmt in PACKAGE_MANIFEST_TYPES:
manifest = pmt()
assert manifest.package_manifest_type
seen = seen_types.get(manifest.package_manifest_type)
if seen:
msg = ('Invalid duplicated packagedcode.Package types: '
'"{}:{}" and "{}:{}" have the same type.'
.format(pt.default_type, pt.__name__, seen.default_type, seen.__name__,))
.format(manifest.package_manifest_type, manifest.__name__, seen.package_manifest_type, seen.__name__,))
raise Exception(msg)
else:
seen_types[pt.default_type] = pt
seen_types[manifest.package_manifest_type] = manifest


def get_package_class(scan_data, default=models.Package):
Expand All @@ -130,7 +157,7 @@ def get_package_class(scan_data, default=models.Package):
if not ptype:
# basic type for default package types
return default
ptype_class = PACKAGES_BY_TYPE.get(ptype)
ptype_class = PACKAGE_MANIFESTS_BY_TYPE.get(ptype)
return ptype_class or default


Expand Down
107 changes: 52 additions & 55 deletions src/packagedcode/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,8 @@

@attr.s()
class AboutPackage(models.Package):
metafiles = ('*.ABOUT',)
default_type = 'about'

@classmethod
def recognize(cls, location):
yield parse(location)
default_type = 'about'

def get_package_root(self, manifest_resource, codebase):
about_resource = self.extra_data.get('about_resource')
Expand All @@ -47,53 +43,54 @@ def get_package_root(self, manifest_resource, codebase):
return manifest_resource


def is_about_file(location):
return (filetype.is_file(location)
and location.lower().endswith(('.about',)))


def parse(location):
"""
Return a Package object from an ABOUT file or None.
"""
if not is_about_file(location):
return

with io.open(location, encoding='utf-8') as loc:
package_data = saneyaml.load(loc.read())

return build_package(package_data)


def build_package(package_data):
"""
Return a Package built from `package_data` obtained by an ABOUT file.
"""
name = package_data.get('name')
# FIXME: having no name may not be a problem See #1514
if not name:
return

version = package_data.get('version')
homepage_url = package_data.get('home_url') or package_data.get('homepage_url')
download_url = package_data.get('download_url')
declared_license = package_data.get('license_expression')
copyright_statement = package_data.get('copyright')

owner = package_data.get('owner')
if not isinstance(owner, str):
owner = repr(owner)
parties = [models.Party(type=models.party_person, name=owner, role='owner')]

about_package = AboutPackage(
type='about',
name=name,
version=version,
declared_license=declared_license,
copyright=copyright_statement,
parties=parties,
homepage_url=homepage_url,
download_url=download_url,
)
about_package.extra_data['about_resource'] = package_data.get('about_resource')
return about_package
@attr.s()
class Aboutfile(AboutPackage, models.PackageManifest):

file_patterns = ('*.ABOUT',)
extensions = ('.ABOUT',)

@classmethod
def is_manifest(cls, location):
"""
Return True if the file at ``location`` is likely a manifest of this type.
"""
return filetype.is_file(location) and location.lower().endswith(('.about',))

@classmethod
def recognize(cls, location):
"""
Yield one or more Package manifest objects given a file ``location`` pointing to a
package archive, manifest or similar.
"""
with io.open(location, encoding='utf-8') as loc:
package_data = saneyaml.load(loc.read())

name = package_data.get('name')
# FIXME: having no name may not be a problem See #1514
if not name:
return

version = package_data.get('version')
homepage_url = package_data.get('home_url') or package_data.get('homepage_url')
download_url = package_data.get('download_url')
declared_license = package_data.get('license_expression')
copyright_statement = package_data.get('copyright')

owner = package_data.get('owner')
if not isinstance(owner, str):
owner = repr(owner)
parties = [models.Party(type=models.party_person, name=owner, role='owner')]

about_package = cls(
type='about',
name=name,
version=version,
declared_license=declared_license,
copyright=copyright_statement,
parties=parties,
homepage_url=homepage_url,
download_url=download_url,
)

about_package.extra_data['about_resource'] = package_data.get('about_resource')
yield about_package
2 changes: 1 addition & 1 deletion src/packagedcode/alpine.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@


@attr.s()
class AlpinePackage(models.Package):
class AlpinePackage(models.Package, models.PackageManifest):
extensions = ('.apk', 'APKBUILD')
default_type = 'alpine'

Expand Down
Loading