forked from aboutcode-org/scancode-toolkit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreadme.py
More file actions
111 lines (89 loc) · 3.13 KB
/
readme.py
File metadata and controls
111 lines (89 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/scancode-toolkit for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
from commoncode import fileutils
from packagedcode import models
"""
Handle README.*-style semi-structured package metadata.
These are seen in Android, Chromium and a few more places.
"""
# Common README field name mapped to known PackageData field name
PACKAGE_FIELD_BY_README_FIELD = {
'name': 'name',
'project': 'name',
'version': 'version',
'copyright': 'copyright',
'download link': 'download_url',
'downloaded from': 'download_url',
'homepage': 'homepage_url',
'website': 'homepage_url',
'repo': 'homepage_url',
'source': 'homepage_url',
'upstream': 'homepage_url',
'url': 'homepage_url',
'project url': 'homepage_url',
'licence': 'extracted_license_statement',
'license': 'extracted_license_statement',
# This also has License File sometimes
}
class ReadmeHandler(models.NonAssemblableDatafileHandler):
datasource_id = 'readme'
default_package_type = 'readme'
path_patterns = (
'*/README.android',
'*/README.chromium',
'*/README.facebook',
'*/README.google',
'*/README.thirdparty',
)
description = ''
documentation_url = ''
@classmethod
def parse(cls, location, package_only=False):
with open(location, encoding='utf-8') as loc:
readme_manifest = loc.read()
package_data = build_package(readme_manifest, package_only)
if not package_data.name:
# If no name was detected for the Package, then we use the basename
# of the parent directory as the Package name
parent_dir = fileutils.parent_directory(location)
parent_dir_basename = fileutils.file_base_name(parent_dir)
package_data.name = parent_dir_basename
yield package_data
def build_package(readme_manifest, package_only=False):
"""
Return a Package object from a readme_manifest mapping (from a
README.chromium file or similar) or None.
"""
package = models.PackageData(
datasource_id=ReadmeHandler.datasource_id,
type=ReadmeHandler.default_package_type,
)
for line in readme_manifest.splitlines():
line = line.strip()
if ':' in line:
key, _sep, value = line.partition(':')
elif '=' in line:
key, _sep, value = line.partition('=')
else:
key = None
value = None
if key:
key = key.lower().strip()
if value:
value = value.strip()
if not key or not value:
continue
package_key = PACKAGE_FIELD_BY_README_FIELD.get(key)
if not package_key:
continue
setattr(package, package_key, value)
if not package_only:
package.populate_license_fields()
package.populate_holder_field()
return package