Skip to content

Commit 609ca7b

Browse files
author
Li
committed
Add the declare_license new storage for phpcomposer #1403
Signed-off-by: Li <li@nexb.com>
1 parent 883746b commit 609ca7b

7 files changed

Lines changed: 249 additions & 19 deletions

File tree

src/packagedcode/phpcomposer.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
from commoncode import filetype
4040
from commoncode import fileutils
4141
from packagedcode import models
42+
from packagedcode.utils import combine_expressions
43+
4244

4345
"""
4446
Parse PHP composer package manifests, see https://getcomposer.org/ and
@@ -94,7 +96,39 @@ def compute_normalized_license(self):
9496
"""
9597
Per https://getcomposer.org/doc/04-schema.md#license this is an expression
9698
"""
97-
return models.Package.compute_normalized_license(self)
99+
return compute_normalized_license(self.declared_license)
100+
101+
102+
def compute_normalized_license(declared_license):
103+
"""
104+
Return a normalized license expression string detected from a list of
105+
declared license items or string type.
106+
"""
107+
if not declared_license:
108+
return
109+
110+
detected_licenses = []
111+
112+
if isinstance(declared_license, string_types):
113+
if declared_license == 'proprietary':
114+
return declared_license
115+
if '(' in declared_license and ')' in declared_license and ' or ' in declared_license:
116+
declared_license = declared_license.strip().rstrip(')').lstrip('(')
117+
declared_license = declared_license.split(' or ')
118+
else:
119+
return models.compute_normalized_license(declared_license)
120+
121+
if isinstance(declared_license, list):
122+
for declared in declared_license:
123+
detected_license = models.compute_normalized_license(declared)
124+
detected_licenses.append(detected_license)
125+
else:
126+
declared_license = repr(declared_license)
127+
detected_license = models.compute_normalized_license(declared_license)
128+
129+
if detected_licenses:
130+
# build a proper license expression: the defaultfor composer is OR
131+
return combine_expressions(detected_licenses, 'OR')
98132

99133

100134
def is_phpcomposer_json(location):
@@ -200,25 +234,11 @@ def licensing_mapper(licenses, package, is_private=False):
200234
license and the `is_private` Fkag is True, we return a "proprietary-license"
201235
license.
202236
"""
203-
if not licenses:
237+
if not licenses and is_private:
238+
package.declared_license = 'proprietary-license'
204239
return package
205240

206-
if isinstance(licenses, list):
207-
# For a package, when there is a choice between licenses
208-
# ("disjunctive license"), multiple can be specified as array.
209-
# build a proper license expression: the defaultfor composer is OR
210-
lics = [l.strip() for l in licenses if l and l.strip()]
211-
lics = ' OR '.join(lics)
212-
213-
elif not isinstance(licenses, string_types):
214-
lics = repr(licenses)
215-
else:
216-
lics = licenses
217-
218-
if not lics and is_private:
219-
lics ='proprietary-license'
220-
221-
package.declared_license = lics or None
241+
package.declared_license = licenses
222242
return package
223243

224244

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "fake/fake",
3+
"type": "library",
4+
"description": "A fake library.",
5+
"keywords": ["fake"],
6+
"homepage": "http://github.com/fake/fake",
7+
"license": "(LGPL-2.1-only or GPL-3.0-or-later)",
8+
"authors": [
9+
{
10+
"name": "Hi"
11+
}
12+
],
13+
"require": {
14+
"php": ">=5.6.0"
15+
},
16+
"require-dev": {
17+
"phpunit/phpunit": "^5.6",
18+
"squizlabs/php_codesniffer": "^2.7"
19+
}
20+
21+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"type": "composer",
3+
"namespace": "fake",
4+
"name": "fake",
5+
"version": null,
6+
"qualifiers": null,
7+
"subpath": null,
8+
"primary_language": "PHP",
9+
"description": null,
10+
"release_date": null,
11+
"parties": [
12+
{
13+
"type": "person",
14+
"role": "author",
15+
"name": "Hi",
16+
"email": null,
17+
"url": null
18+
},
19+
{
20+
"type": "person",
21+
"role": "vendor",
22+
"name": "fake",
23+
"email": null,
24+
"url": null
25+
}
26+
],
27+
"keywords": [],
28+
"homepage_url": "http://github.com/fake/fake",
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": "lgpl-2.1 OR gpl-3.0-plus",
40+
"declared_license": "(LGPL-2.1-only or GPL-3.0-or-later)",
41+
"notice_text": null,
42+
"manifest_path": null,
43+
"dependencies": [
44+
{
45+
"purl": "pkg:composer/php",
46+
"requirement": ">=5.6.0",
47+
"scope": "require",
48+
"is_runtime": true,
49+
"is_optional": false,
50+
"is_resolved": false
51+
},
52+
{
53+
"purl": "pkg:composer/phpunit/phpunit",
54+
"requirement": "^5.6",
55+
"scope": "require-dev",
56+
"is_runtime": false,
57+
"is_optional": true,
58+
"is_resolved": false
59+
},
60+
{
61+
"purl": "pkg:composer/squizlabs/php_codesniffer",
62+
"requirement": "^2.7",
63+
"scope": "require-dev",
64+
"is_runtime": false,
65+
"is_optional": true,
66+
"is_resolved": false
67+
}
68+
],
69+
"contains_source_code": null,
70+
"source_packages": [],
71+
"purl": "pkg:composer/fake/fake",
72+
"repository_homepage_url": "https://packagist.org/packages/fake/fake",
73+
"repository_download_url": null,
74+
"api_data_url": "https://packagist.org/p/packages/fake/fake.json"
75+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "fake/fake",
3+
"type": "library",
4+
"description": "A fake library.",
5+
"keywords": ["fake"],
6+
"homepage": "http://github.com/fake/fake",
7+
"license": [
8+
"LGPL-2.1-only",
9+
"GPL-3.0-or-later"
10+
],
11+
"authors": [
12+
{
13+
"name": "Hi"
14+
}
15+
],
16+
"require": {
17+
"php": ">=5.6.0"
18+
},
19+
"require-dev": {
20+
"phpunit/phpunit": "^5.6",
21+
"squizlabs/php_codesniffer": "^2.7"
22+
}
23+
24+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"type": "composer",
3+
"namespace": "fake",
4+
"name": "fake",
5+
"version": null,
6+
"qualifiers": null,
7+
"subpath": null,
8+
"primary_language": "PHP",
9+
"description": null,
10+
"release_date": null,
11+
"parties": [
12+
{
13+
"type": "person",
14+
"role": "author",
15+
"name": "Hi",
16+
"email": null,
17+
"url": null
18+
},
19+
{
20+
"type": "person",
21+
"role": "vendor",
22+
"name": "fake",
23+
"email": null,
24+
"url": null
25+
}
26+
],
27+
"keywords": [],
28+
"homepage_url": "http://github.com/fake/fake",
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": "lgpl-2.1 OR gpl-3.0-plus",
40+
"declared_license": [
41+
"LGPL-2.1-only",
42+
"GPL-3.0-or-later"
43+
],
44+
"notice_text": null,
45+
"manifest_path": null,
46+
"dependencies": [
47+
{
48+
"purl": "pkg:composer/php",
49+
"requirement": ">=5.6.0",
50+
"scope": "require",
51+
"is_runtime": true,
52+
"is_optional": false,
53+
"is_resolved": false
54+
},
55+
{
56+
"purl": "pkg:composer/phpunit/phpunit",
57+
"requirement": "^5.6",
58+
"scope": "require-dev",
59+
"is_runtime": false,
60+
"is_optional": true,
61+
"is_resolved": false
62+
},
63+
{
64+
"purl": "pkg:composer/squizlabs/php_codesniffer",
65+
"requirement": "^2.7",
66+
"scope": "require-dev",
67+
"is_runtime": false,
68+
"is_optional": true,
69+
"is_resolved": false
70+
}
71+
],
72+
"contains_source_code": null,
73+
"source_packages": [],
74+
"purl": "pkg:composer/fake/fake",
75+
"repository_homepage_url": "https://packagist.org/packages/fake/fake",
76+
"repository_download_url": null,
77+
"api_data_url": "https://packagist.org/p/packages/fake/fake.json"
78+
}

tests/packagedcode/data/phpcomposer/modern/composer.json.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"code_view_url": null,
2222
"vcs_url": null,
2323
"copyright": null,
24-
"license_expression": "unknown",
24+
"license_expression": "proprietary",
2525
"declared_license": "proprietary",
2626
"notice_text": null,
2727
"manifest_path": null,

tests/packagedcode/test_phpcomposer.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,15 @@ def test_parse_modern(self):
7979
expected_loc = self.get_test_loc('phpcomposer/modern/composer.json.expected')
8080
package = phpcomposer.parse(test_file)
8181
self.check_package(package, expected_loc, regen=False)
82+
83+
def test_parse_fake_license1(self):
84+
test_file = self.get_test_loc('phpcomposer/fake/composer.json')
85+
expected_loc = self.get_test_loc('phpcomposer/fake/composer.json.expected')
86+
package = phpcomposer.parse(test_file)
87+
self.check_package(package, expected_loc, regen=False)
88+
89+
def test_parse_fake_license2(self):
90+
test_file = self.get_test_loc('phpcomposer/fake2/composer.json')
91+
expected_loc = self.get_test_loc('phpcomposer/fake2/composer.json.expected')
92+
package = phpcomposer.parse(test_file)
93+
self.check_package(package, expected_loc, regen=False)

0 commit comments

Comments
 (0)