Skip to content

Commit 9f9e3a6

Browse files
Adds PackageManifest classes for cran
Creates PackageManifest classes for cran description manifests and overrides the methods for detection and PackageManifest creation. See #2748 Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com>
1 parent fa010e4 commit 9f9e3a6

4 files changed

Lines changed: 249 additions & 239 deletions

File tree

src/packagedcode/cran.py

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import attr
1414
import saneyaml
1515

16+
from commoncode import filetype
17+
from commoncode import fileutils
1618
from packagedcode import models
1719
from packageurl import PackageURL
1820

@@ -34,15 +36,11 @@
3436

3537

3638
@attr.s()
37-
class CranPackage(models.Package, models.PackageManifest):
39+
class CranPackage(models.Package):
3840
file_patterns = ('DESCRIPTION',)
3941
default_type = 'cran'
4042
default_web_baseurl = 'https://cran.r-project.org/package='
4143

42-
@classmethod
43-
def recognize(cls, location):
44-
yield parse(location)
45-
4644
@classmethod
4745
def get_package_root(cls, manifest_resource, codebase):
4846
return manifest_resource.parent(codebase)
@@ -51,79 +49,87 @@ def repository_homepage_url(self, baseurl=default_web_baseurl):
5149
return '{}{}'.format(baseurl, self.name)
5250

5351

54-
def parse(location):
55-
"""
56-
Return a Package object from a DESCRIPTION file or None.
57-
"""
58-
yaml_data = get_yaml_data(location)
59-
return build_package(yaml_data)
52+
@attr.s()
53+
class DescriptionFile(CranPackage, models.PackageManifest):
6054

55+
file_patterns = ('DESCRIPTION')
6156

62-
def build_package(package_data):
63-
"""
64-
Return a cran Package object from a dictionary yaml data.
65-
"""
66-
name = package_data.get('Package')
67-
if name:
68-
parties = []
69-
maintainers = package_data.get('Maintainer')
70-
if maintainers:
71-
for maintainer in maintainers.split(',\n'):
72-
maintainer_name, maintainer_email = get_party_info(maintainer)
73-
if maintainer_name or maintainer_email:
74-
parties.append(
75-
models.Party(
76-
name=maintainer_name,
77-
role='maintainer',
78-
email=maintainer_email,
57+
@classmethod
58+
def is_manifest(cls, location):
59+
"""
60+
Return True if `location` path is for a Cran DESCRIPTION file.
61+
"""
62+
return (filetype.is_file(location)
63+
and fileutils.file_name(location) == 'DESCRIPTION')
64+
65+
@classmethod
66+
def recognize(cls, location):
67+
"""
68+
Yield one or more Package manifest objects given a file ``location`` pointing to a
69+
package archive, manifest or similar.
70+
"""
71+
package_data = get_yaml_data(location)
72+
73+
name = package_data.get('Package')
74+
if name:
75+
parties = []
76+
maintainers = package_data.get('Maintainer')
77+
if maintainers:
78+
for maintainer in maintainers.split(',\n'):
79+
maintainer_name, maintainer_email = get_party_info(maintainer)
80+
if maintainer_name or maintainer_email:
81+
parties.append(
82+
models.Party(
83+
name=maintainer_name,
84+
role='maintainer',
85+
email=maintainer_email,
86+
)
7987
)
80-
)
81-
authors = package_data.get('Author')
82-
if authors:
83-
for author in authors.split(',\n'):
84-
author_name, author_email = get_party_info(author)
85-
if author_name or author_email:
86-
parties.append(
87-
models.Party(
88-
name=author_name,
89-
role='author',
90-
email=author_email,
88+
authors = package_data.get('Author')
89+
if authors:
90+
for author in authors.split(',\n'):
91+
author_name, author_email = get_party_info(author)
92+
if author_name or author_email:
93+
parties.append(
94+
models.Party(
95+
name=author_name,
96+
role='author',
97+
email=author_email,
98+
)
99+
)
100+
package_dependencies = []
101+
dependencies = package_data.get('Depends')
102+
if dependencies:
103+
for dependency in dependencies.split(',\n'):
104+
requirement = None
105+
for splitter in ('==', '>=', '<=', '>', '<'):
106+
if splitter in dependency:
107+
splits = dependency.split(splitter)
108+
# Replace the package name and keep the relationship and version
109+
# For example: R (>= 2.1)
110+
requirement = dependency.replace(splits[0], '').strip().strip(')').strip()
111+
dependency = splits[0].strip().strip('(').strip()
112+
break
113+
package_dependencies.append(
114+
models.DependentPackage(
115+
purl=PackageURL(
116+
type='cran', name=dependency).to_string(),
117+
requirement=requirement,
118+
scope='dependencies',
119+
is_runtime=True,
120+
is_optional=False,
91121
)
92122
)
93-
package_dependencies = []
94-
dependencies = package_data.get('Depends')
95-
if dependencies:
96-
for dependency in dependencies.split(',\n'):
97-
requirement = None
98-
for splitter in ('==', '>=', '<=', '>', '<'):
99-
if splitter in dependency:
100-
splits = dependency.split(splitter)
101-
# Replace the package name and keep the relationship and version
102-
# For example: R (>= 2.1)
103-
requirement = dependency.replace(splits[0], '').strip().strip(')').strip()
104-
dependency = splits[0].strip().strip('(').strip()
105-
break
106-
package_dependencies.append(
107-
models.DependentPackage(
108-
purl=PackageURL(
109-
type='cran', name=dependency).to_string(),
110-
requirement=requirement,
111-
scope='dependencies',
112-
is_runtime=True,
113-
is_optional=False,
114-
)
115-
)
116-
package = CranPackage(
117-
name=name,
118-
version=package_data.get('Version'),
119-
description=package_data.get('Description', '') or package_data.get('Title', ''),
120-
declared_license=package_data.get('License'),
121-
parties=parties,
122-
dependencies=package_dependencies,
123-
# TODO: Let's handle the release date as a Date type
124-
# release_date = package_data.get('Date/Publication'),
125-
)
126-
return package
123+
yield cls(
124+
name=name,
125+
version=package_data.get('Version'),
126+
description=package_data.get('Description', '') or package_data.get('Title', ''),
127+
declared_license=package_data.get('License'),
128+
parties=parties,
129+
dependencies=package_dependencies,
130+
# TODO: Let's handle the release date as a Date type
131+
# release_date = package_data.get('Date/Publication'),
132+
)
127133

128134

129135
def get_yaml_data(location):
Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,62 @@
1-
{
2-
"type": "cran",
3-
"namespace": null,
4-
"name": "codetools",
5-
"version": "0.2-16",
6-
"qualifiers": {},
7-
"subpath": null,
8-
"primary_language": null,
9-
"description": "Code analysis tools for R.",
10-
"release_date": null,
11-
"parties": [
12-
{
13-
"type": null,
14-
"role": "maintainer",
15-
"name": "Luke Tierney",
16-
"email": "luke-tierney@uiowa.edu",
17-
"url": null
18-
},
19-
{
20-
"type": null,
21-
"role": "author",
22-
"name": "Luke Tierney",
23-
"email": "luke-tierney@uiowa.edu",
24-
"url": null
25-
}
26-
],
27-
"keywords": [],
28-
"homepage_url": null,
29-
"download_url": null,
30-
"size": null,
31-
"sha1": null,
32-
"md5": null,
33-
"sha256": null,
34-
"sha512": null,
35-
"bug_tracking_url": null,
36-
"code_view_url": null,
37-
"vcs_url": null,
38-
"copyright": null,
39-
"license_expression": "gpl-1.0-plus",
40-
"declared_license": "GPL",
41-
"notice_text": null,
42-
"root_path": null,
43-
"dependencies": [
44-
{
45-
"purl": "pkg:cran/R",
46-
"requirement": ">= 2.1",
47-
"scope": "dependencies",
48-
"is_runtime": true,
49-
"is_optional": false,
50-
"is_resolved": false
51-
}
52-
],
53-
"contains_source_code": null,
54-
"source_packages": [],
55-
"extra_data": {},
56-
"purl": "pkg:cran/codetools@0.2-16",
57-
"repository_homepage_url": "https://cran.r-project.org/package=codetools",
58-
"repository_download_url": null,
59-
"api_data_url": null
60-
}
1+
[
2+
{
3+
"type": "cran",
4+
"namespace": null,
5+
"name": "codetools",
6+
"version": "0.2-16",
7+
"qualifiers": {},
8+
"subpath": null,
9+
"primary_language": null,
10+
"description": "Code analysis tools for R.",
11+
"release_date": null,
12+
"parties": [
13+
{
14+
"type": null,
15+
"role": "maintainer",
16+
"name": "Luke Tierney",
17+
"email": "luke-tierney@uiowa.edu",
18+
"url": null
19+
},
20+
{
21+
"type": null,
22+
"role": "author",
23+
"name": "Luke Tierney",
24+
"email": "luke-tierney@uiowa.edu",
25+
"url": null
26+
}
27+
],
28+
"keywords": [],
29+
"homepage_url": null,
30+
"download_url": null,
31+
"size": null,
32+
"sha1": null,
33+
"md5": null,
34+
"sha256": null,
35+
"sha512": null,
36+
"bug_tracking_url": null,
37+
"code_view_url": null,
38+
"vcs_url": null,
39+
"copyright": null,
40+
"license_expression": "gpl-1.0-plus",
41+
"declared_license": "GPL",
42+
"notice_text": null,
43+
"root_path": null,
44+
"dependencies": [
45+
{
46+
"purl": "pkg:cran/R",
47+
"requirement": ">= 2.1",
48+
"scope": "dependencies",
49+
"is_runtime": true,
50+
"is_optional": false,
51+
"is_resolved": false
52+
}
53+
],
54+
"contains_source_code": null,
55+
"source_packages": [],
56+
"extra_data": {},
57+
"purl": "pkg:cran/codetools@0.2-16",
58+
"repository_homepage_url": "https://cran.r-project.org/package=codetools",
59+
"repository_download_url": null,
60+
"api_data_url": null
61+
}
62+
]

0 commit comments

Comments
 (0)