Skip to content

Commit 2cd448c

Browse files
committed
Adopt new handler design for README files
We now have this data file handler: * ReadmeHandler Signed-off-by: Philippe Ombredanne <[email protected]>
1 parent adc0862 commit 2cd448c

File tree

16 files changed

+182
-186
lines changed

16 files changed

+182
-186
lines changed

src/packagedcode/readme.py

Lines changed: 60 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -7,119 +7,101 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10-
import logging
11-
12-
import attr
13-
from commoncode import filetype
1410
from commoncode import fileutils
1511

1612
from packagedcode import models
1713

1814
"""
19-
Handle README.* package metadata
15+
Handle README.*-style semi-structured package metadata.
16+
These are seen in Android, Chromium and a few more places.
2017
"""
2118

22-
TRACE = False
19+
# Common README field name mapped to known PackageData field name
20+
PACKAGE_FIELD_BY_README_FIELD = {
21+
'name': 'name',
22+
'project': 'name',
23+
'version': 'version',
2324

24-
logger = logging.getLogger(__name__)
25+
'copyright': 'copyright',
2526

26-
if TRACE:
27-
import sys
28-
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
29-
logger.setLevel(logging.DEBUG)
27+
'download link': 'download_url',
28+
'downloaded from': 'download_url',
3029

30+
'homepage': 'homepage_url',
31+
'website': 'homepage_url',
32+
'repo': 'homepage_url',
33+
'source': 'homepage_url',
34+
'upstream': 'homepage_url',
35+
'url': 'homepage_url',
36+
'project url': 'homepage_url',
3137

32-
README_MAPPING = {
33-
'name': ['name', 'project'],
34-
'version': ['version'],
35-
'homepage_url': ['project url', 'repo', 'source', 'upstream', 'url', 'website'],
36-
'download_url': ['download link', 'downloaded from'],
37-
'declared_license': ['license'],
38+
'licence': 'declared_license',
39+
'license': 'declared_license',
3840
}
3941

4042

41-
@attr.s()
42-
class ReadmePackageData(models.PackageData):
43-
default_type = 'readme'
44-
45-
@classmethod
46-
def get_package_root(cls, manifest_resource, codebase):
47-
return manifest_resource.parent(codebase)
48-
49-
def compute_normalized_license(self):
50-
return models.compute_normalized_license(self.declared_license)
51-
52-
@attr.s()
53-
class ReadmeManifest(ReadmePackageData, models.PackageDataFile):
54-
55-
file_patterns = (
56-
'README.android',
57-
'README.chromium',
58-
'README.facebook',
59-
'README.google',
60-
'README.thirdparty',
43+
class ReadmeHandler(models.NonAssemblableDatafileHandler):
44+
datasource_id = 'readme'
45+
default_package_type = 'readme'
46+
path_patterns = (
47+
'*/README.android',
48+
'*/README.chromium',
49+
'*/README.facebook',
50+
'*/README.google',
51+
'*/README.thirdparty',
6152
)
6253

6354
@classmethod
64-
def is_package_data_file(cls, location):
65-
"""
66-
Return True if the file at ``location`` is likely a manifest of this type.
67-
"""
68-
return (filetype.is_file(location)
69-
and fileutils.file_name(location).lower() in [
70-
'readme.android',
71-
'readme.chromium',
72-
'readme.facebook',
73-
'readme.google',
74-
'readme.thirdparty'
75-
]
76-
)
77-
78-
@classmethod
79-
def recognize(cls, location):
80-
"""
81-
Yield one or more Package manifest objects given a file ``location`` pointing to a
82-
package archive, manifest or similar.
83-
"""
55+
def parse(cls, location):
8456
with open(location, encoding='utf-8') as loc:
8557
readme_manifest = loc.read()
8658

87-
package = build_package(cls, readme_manifest)
59+
package_data = build_package(readme_manifest)
8860

89-
if not package.name:
90-
# If no name was detected for the Package, then we use the basename of
91-
# the parent directory as the Package name
61+
if not package_data.name:
62+
# If no name was detected for the Package, then we use the basename
63+
# of the parent directory as the Package name
9264
parent_dir = fileutils.parent_directory(location)
9365
parent_dir_basename = fileutils.file_base_name(parent_dir)
94-
package.name = parent_dir_basename
66+
package_data.name = parent_dir_basename
9567

96-
yield package
68+
yield package_data
9769

9870

99-
def build_package(cls, readme_manifest):
71+
def build_package(readme_manifest):
10072
"""
10173
Return a Package object from a readme_manifest mapping (from a
10274
README.chromium file or similar) or None.
10375
"""
104-
package = cls()
76+
package = models.PackageData(
77+
datasource_id=ReadmeHandler.datasource_id,
78+
type=ReadmeHandler.default_package_type,
79+
)
10580

10681
for line in readme_manifest.splitlines():
107-
key, sep, value = line.partition(':')
82+
line = line.strip()
83+
84+
if ':' in line:
85+
key, _sep, value = line.partition(':')
86+
elif '=' in line:
87+
key, _sep, value = line.partition('=')
88+
else:
89+
key = None
90+
value = None
91+
92+
if key:
93+
key = key.lower().strip()
94+
if value:
95+
value = value.strip()
10896

10997
if not key or not value:
11098
continue
99+
package_key = PACKAGE_FIELD_BY_README_FIELD.get(key)
100+
if not package_key:
101+
continue
102+
setattr(package, package_key, value)
111103

112-
# Map the key, value pairs to the Package
113-
key, value = key.lower(), value.strip()
114-
if key in README_MAPPING['name']:
115-
package.name = value
116-
if key in README_MAPPING['version']:
117-
package.version = value
118-
if key in README_MAPPING['homepage_url']:
119-
package.homepage_url = value
120-
if key in README_MAPPING['download_url']:
121-
package.download_url = value
122-
if key in README_MAPPING['declared_license']:
123-
package.declared_license = value
104+
if not package.license_expression and package.declared_license:
105+
package.license_expression = models.compute_normalized_license(package.declared_license)
124106

125107
return package

tests/packagedcode/data/readme/android/basic/README.android.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": "unknown",
2626
"declared_license": "BSD",
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/[email protected]",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/[email protected]"
3637
}
3738
]

tests/packagedcode/data/readme/chromium/basic/README.chromium.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": "unknown",
2626
"declared_license": "Apache",
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/tsproxy@a2f578febcd79b751d948f615bbde8f6189fbeed%20%28commit%20hash%29",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/tsproxy@a2f578febcd79b751d948f615bbde8f6189fbeed%20%28commit%20hash%29"
3637
}
3738
]

tests/packagedcode/data/readme/facebook/basic/README.facebook.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": "unknown",
2626
"declared_license": "PSF or ZPL",
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/[email protected]",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/[email protected]"
3637
}
3738
]

tests/packagedcode/data/readme/facebook/capital-filename/README.FACEBOOK.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": "unknown",
2626
"declared_license": "PSF or ZPL",
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/[email protected]",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/[email protected]"
3637
}
3738
]

tests/packagedcode/data/readme/facebook/download-link-as-download_url/README.facebook.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": "apache-2.0",
2626
"declared_license": "Apache 2.0",
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/mbed%[email protected]",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/mbed%[email protected]"
3637
}
3738
]

tests/packagedcode/data/readme/facebook/downloaded-from-as-download_url/README.facebook.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": "apache-2.0",
2626
"declared_license": "Apache 2.0",
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/mbed%[email protected]",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/mbed%[email protected]"
3637
}
3738
]

tests/packagedcode/data/readme/facebook/missing-type/README.facebook.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": null,
2626
"declared_license": null,
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/missing-type",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/missing-type"
3637
}
3738
]

tests/packagedcode/data/readme/facebook/project-as-name/README.facebook.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"license_expression": "apache-2.0",
2626
"declared_license": "Apache 2.0",
2727
"notice_text": null,
28-
"contains_source_code": null,
2928
"source_packages": [],
29+
"file_references": [],
3030
"extra_data": {},
3131
"dependencies": [],
32-
"purl": "pkg:readme/mbed%[email protected]",
3332
"repository_homepage_url": null,
3433
"repository_download_url": null,
35-
"api_data_url": null
34+
"api_data_url": null,
35+
"datasource_id": "readme",
36+
"purl": "pkg:readme/mbed%[email protected]"
3637
}
3738
]

0 commit comments

Comments
 (0)