spdx 3.0.0 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +71 -5
- data/exceptions.json +2 -2
- data/lib/spdx.rb +49 -4
- data/lib/spdx/version.rb +1 -1
- data/lib/spdx_grammar.rb +46 -10
- data/lib/spdx_parser.rb +37 -8
- data/lib/spdx_parser.treetop +27 -18
- data/licenses.json +472 -447
- data/spdx.gemspec +1 -2
- data/spec/spdx_spec.rb +112 -27
- metadata +4 -18
data/spdx.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.version = Spdx::VERSION
|
10
10
|
spec.authors = ["Tidelift, Inc."]
|
11
11
|
spec.email = ["support@tidelift.com"]
|
12
|
-
spec.summary = "A SPDX license
|
12
|
+
spec.summary = "A SPDX license parser"
|
13
13
|
spec.homepage = "https://github.com/librariesio/spdx"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -18,7 +18,6 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "fuzzy_match", "~> 2.1"
|
22
21
|
spec.add_dependency "treetop", "~> 1.6"
|
23
22
|
spec.add_development_dependency "bundler"
|
24
23
|
spec.add_development_dependency "pry"
|
data/spec/spdx_spec.rb
CHANGED
@@ -4,61 +4,146 @@ require "spec_helper"
|
|
4
4
|
|
5
5
|
describe Spdx do
|
6
6
|
context "spdx parsing" do
|
7
|
-
context "
|
7
|
+
context "parse" do
|
8
|
+
it "handles bad input" do
|
9
|
+
expect { Spdx.parse(nil) }.to raise_error(SpdxGrammar::SpdxParseError)
|
10
|
+
expect { Spdx.parse("") }.to raise_error(SpdxGrammar::SpdxParseError)
|
11
|
+
end
|
12
|
+
it "parses into respective classes" do
|
13
|
+
expect(Spdx.parse("MIT")).to be_an_instance_of(SpdxGrammar::License)
|
14
|
+
expect(Spdx.parse("MIT AND Apache-2.0")).to be_an_instance_of(SpdxGrammar::LogicalAnd)
|
15
|
+
expect(Spdx.parse("(MIT AND Apache-2.0)")).to be_an_instance_of(SpdxGrammar::LogicalAnd)
|
16
|
+
expect(Spdx.parse("MIT OR Apache-2.0")).to be_an_instance_of(SpdxGrammar::LogicalOr)
|
17
|
+
expect(Spdx.parse("MIT AND Apache-2.0").left).to be_an_instance_of(SpdxGrammar::License)
|
18
|
+
expect(Spdx.parse("MIT AND Apache-2.0").right).to be_an_instance_of(SpdxGrammar::License)
|
19
|
+
expect(Spdx.parse("MIT+")).to be_an_instance_of(SpdxGrammar::LicensePlus)
|
20
|
+
expect(Spdx.parse("LicenseRef-MIT-style-1")).to be_an_instance_of(SpdxGrammar::LicenseRef)
|
21
|
+
expect(Spdx.parse("DocumentRef-something-1:LicenseRef-MIT-style-1")).to be_an_instance_of(SpdxGrammar::DocumentRef)
|
22
|
+
expect(Spdx.parse("GPL-2.0-only WITH Classpath-exception-2.0")).to be_an_instance_of(SpdxGrammar::With)
|
23
|
+
expect(Spdx.parse("GPL-2.0-only WITH Classpath-exception-2.0").license).to be_an_instance_of(SpdxGrammar::License)
|
24
|
+
expect(Spdx.parse("GPL-2.0-only WITH Classpath-exception-2.0").exception).to be_an_instance_of(SpdxGrammar::LicenseException)
|
25
|
+
expect(Spdx.parse("NONE")).to be_an_instance_of(SpdxGrammar::None)
|
26
|
+
expect(Spdx.parse("NOASSERTION")).to be_an_instance_of(SpdxGrammar::NoAssertion)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
context "valid?" do
|
8
30
|
it "returns false for invalid spdx" do
|
9
|
-
expect(Spdx.
|
10
|
-
expect(Spdx.
|
11
|
-
expect(Spdx.
|
12
|
-
expect(Spdx.
|
13
|
-
expect(Spdx.
|
14
|
-
expect(Spdx.
|
31
|
+
expect(Spdx.valid?("AND AND")).to be false
|
32
|
+
expect(Spdx.valid?(" AND ")).to be false
|
33
|
+
expect(Spdx.valid?(" WITH ")).to be false
|
34
|
+
expect(Spdx.valid?("MIT AND ")).to be false
|
35
|
+
expect(Spdx.valid?("MIT OR MIT AND OR")).to be false
|
36
|
+
expect(Spdx.valid?("MIT OR FAKEYLICENSE")).to be false
|
37
|
+
expect(Spdx.valid?(nil)).to be false
|
38
|
+
expect(Spdx.valid?("")).to be false
|
39
|
+
expect(Spdx.valid?("MIT (MIT)")).to be false
|
15
40
|
end
|
16
41
|
it "returns true for valid spdx" do
|
17
|
-
expect(Spdx.
|
18
|
-
expect(Spdx.
|
19
|
-
expect(Spdx.
|
20
|
-
expect(Spdx.
|
42
|
+
expect(Spdx.valid?("(MIT OR MPL-2.0)")).to be true
|
43
|
+
expect(Spdx.valid?("MIT")).to be true
|
44
|
+
expect(Spdx.valid?("MIT OR MPL-2.0 AND AGPL-1.0")).to be true
|
45
|
+
expect(Spdx.valid?("MIT OR (GPL-1.0 OR MPL-2.0) AND AGPL-1.0")).to be true
|
46
|
+
expect(Spdx.valid?("MIT AND MPL-2.0 OR AGPL-1.0")).to be true
|
47
|
+
expect(Spdx.valid?("MIT AND (GPL-1.0 OR MPL-2.0) OR AGPL-1.0")).to be true
|
48
|
+
expect(Spdx.valid?("MIT OR (DocumentRef-something-1:LicenseRef-MIT-style-1 OR MPL-2.0) AND AGPL-1.0")).to be true
|
49
|
+
expect(Spdx.valid?("((MIT OR AGPL-1.0) AND (MIT OR MPL-2.0))")).to be true
|
50
|
+
expect(Spdx.valid?("MIT OR (MIT)")).to be true
|
21
51
|
end
|
22
52
|
it "returns true for NONE and NOASSERTION" do
|
23
|
-
expect(Spdx.
|
24
|
-
expect(Spdx.
|
25
|
-
expect(Spdx.
|
26
|
-
expect(Spdx.
|
53
|
+
expect(Spdx.valid?("NONE")).to be true
|
54
|
+
expect(Spdx.valid?("(NONE)")).to be false
|
55
|
+
expect(Spdx.valid?("NOASSERTION")).to be true
|
56
|
+
expect(Spdx.valid?("MIT OR NONE")).to be false
|
27
57
|
end
|
28
58
|
it "returns true for + expression" do
|
29
|
-
expect(Spdx.
|
59
|
+
expect(Spdx.valid?("AGPL-3.0+")).to be true
|
30
60
|
end
|
31
61
|
it "is case insentive for license ids" do
|
32
|
-
expect(Spdx.
|
62
|
+
expect(Spdx.valid?("mit OR agpl-3.0+")).to be true
|
33
63
|
end
|
34
64
|
it "handles LicenseRef" do
|
35
|
-
expect(Spdx.
|
65
|
+
expect(Spdx.valid?("MIT OR LicenseRef-MIT-style-1")).to be true
|
36
66
|
end
|
37
67
|
it "handles DocumentRef" do
|
38
|
-
expect(Spdx.
|
39
|
-
expect(Spdx.
|
68
|
+
expect(Spdx.valid?("MIT OR DocumentRef-something-1:LicenseRef-MIT-style-1")).to be true
|
69
|
+
expect(Spdx.valid?("MIT OR DocumentRef-something-1")).to be false
|
40
70
|
end
|
41
71
|
end
|
42
72
|
end
|
73
|
+
context "normalize" do
|
74
|
+
it "normalizes simple licenses" do
|
75
|
+
expect(Spdx.normalize("MIT")).to eq "MIT"
|
76
|
+
expect(Spdx.normalize("mit")).to eq "MIT"
|
77
|
+
expect(Spdx.normalize("MiT")).to eq "MIT"
|
78
|
+
expect(Spdx.normalize("(MiT)")).to eq "MIT"
|
79
|
+
expect(Spdx.normalize("(((MiT)))")).to eq "MIT"
|
80
|
+
expect(Spdx.normalize("LicenseRef-MIT-style-1")).to eq "LicenseRef-MIT-style-1"
|
81
|
+
expect(Spdx.normalize("DocumentRef-something-1:LicenseRef-MIT-style-1")).to eq "DocumentRef-something-1:LicenseRef-MIT-style-1"
|
82
|
+
expect(Spdx.normalize("Apache-2.0+")).to eq "Apache-2.0+"
|
83
|
+
expect(Spdx.normalize("apache-2.0+")).to eq "Apache-2.0+"
|
84
|
+
end
|
85
|
+
it "normalizes NONE/NOASSERTION" do
|
86
|
+
expect(Spdx.normalize("NONE")).to eq "NONE"
|
87
|
+
expect(Spdx.normalize("NOASSERTION")).to eq "NOASSERTION"
|
88
|
+
end
|
89
|
+
it "normalizes boolean expressions" do
|
90
|
+
expect(Spdx.normalize("mit AND gPL-2.0")).to eq "MIT AND GPL-2.0"
|
91
|
+
expect(Spdx.normalize("mit OR gPL-2.0")).to eq "MIT OR GPL-2.0"
|
92
|
+
expect(Spdx.normalize("mit OR gPL-2.0")).to eq "MIT OR GPL-2.0"
|
93
|
+
|
94
|
+
# With top level parens
|
95
|
+
expect(Spdx.normalize("mit AND gPL-2.0", top_level_parens: true)).to eq "(MIT AND GPL-2.0)"
|
96
|
+
expect(Spdx.normalize("mit OR gPL-2.0", top_level_parens: true)).to eq "(MIT OR GPL-2.0)"
|
97
|
+
expect(Spdx.normalize("mit OR gPL-2.0", top_level_parens: true)).to eq "(MIT OR GPL-2.0)"
|
98
|
+
|
99
|
+
# Does semantic grouping
|
100
|
+
expect(Spdx.normalize("mit OR gPL-2.0 AND apAcHe-2.0+")).to eq "MIT OR (GPL-2.0 AND Apache-2.0+)"
|
101
|
+
|
102
|
+
# But also preserves original groups
|
103
|
+
expect(Spdx.normalize("(mit OR gPL-2.0) AND apAcHe-2.0+")).to eq "(MIT OR GPL-2.0) AND Apache-2.0+"
|
104
|
+
end
|
105
|
+
it "normalizes WITH expressions" do
|
106
|
+
expect(Spdx.normalize("GPL-2.0-only WITH Classpath-exception-2.0")).to eq "GPL-2.0-only WITH Classpath-exception-2.0"
|
107
|
+
expect(Spdx.normalize("Gpl-2.0-ONLY WITH ClassPath-exception-2.0")).to eq "GPL-2.0-only WITH Classpath-exception-2.0"
|
108
|
+
|
109
|
+
# With top level parens
|
110
|
+
expect(Spdx.normalize("GPL-2.0-only WITH Classpath-exception-2.0", top_level_parens: true)).to eq "(GPL-2.0-only WITH Classpath-exception-2.0)"
|
111
|
+
expect(Spdx.normalize("Gpl-2.0-ONLY WITH ClassPath-exception-2.0", top_level_parens: true)).to eq "(GPL-2.0-only WITH Classpath-exception-2.0)"
|
112
|
+
|
113
|
+
expect(Spdx.normalize("EPL-2.0 OR (GPL-2.0-only WITH Classpath-exception-2.0)")).to eq "EPL-2.0 OR (GPL-2.0-only WITH Classpath-exception-2.0)"
|
114
|
+
expect(Spdx.normalize("epl-2.0 OR (gpl-2.0-only WITH classpath-exception-2.0)")).to eq "EPL-2.0 OR (GPL-2.0-only WITH Classpath-exception-2.0)"
|
115
|
+
expect(Spdx.normalize("epl-2.0 OR gpl-2.0-only WITH classpath-exception-2.0")).to eq "EPL-2.0 OR (GPL-2.0-only WITH Classpath-exception-2.0)"
|
116
|
+
expect(Spdx.normalize("epl-2.0 OR gpl-2.0-only WITH classpath-exception-2.0 AND mpl-2.0+")).to eq "EPL-2.0 OR ((GPL-2.0-only WITH Classpath-exception-2.0) AND MPL-2.0+)"
|
117
|
+
end
|
118
|
+
end
|
43
119
|
context "licenses" do
|
44
120
|
it "returns a list of possible licenses" do
|
45
|
-
expect(Spdx.
|
121
|
+
expect(Spdx.parse("MIT").licenses).to eq ["MIT"]
|
122
|
+
expect(Spdx.parse("MIT OR MPL-2.0").licenses).to eq ["MIT", "MPL-2.0"]
|
123
|
+
expect(Spdx.parse("MIT OR MPL-2.0+").licenses).to eq ["MIT", "MPL-2.0+"]
|
124
|
+
expect(Spdx.parse("GPL-2.0-only WITH Classpath-exception-2.0").licenses).to eq ["GPL-2.0-only"]
|
46
125
|
end
|
47
126
|
it "returns empty array for NONE or NOASSERTION" do
|
48
|
-
expect(Spdx.
|
49
|
-
expect(Spdx.
|
127
|
+
expect(Spdx.parse("NONE").licenses).to eq []
|
128
|
+
expect(Spdx.parse("NOASSERTION").licenses).to eq []
|
129
|
+
end
|
130
|
+
it "returns LicenseRefs" do
|
131
|
+
expect(Spdx.parse("MIT OR LicenseRef-MIT-style-1").licenses).to eq %w[MIT LicenseRef-MIT-style-1]
|
132
|
+
end
|
133
|
+
it "returns DocumentRefs" do
|
134
|
+
expect(Spdx.parse("MIT OR DocumentRef-something-1:LicenseRef-MIT-style-1").licenses).to eq %w[MIT DocumentRef-something-1:LicenseRef-MIT-style-1]
|
50
135
|
end
|
51
136
|
end
|
52
137
|
|
53
138
|
context "exceptions" do
|
54
|
-
it "parses a valid spdx
|
55
|
-
expect(Spdx.
|
139
|
+
it "parses a valid spdx WITH expression" do
|
140
|
+
expect(Spdx.valid?("EPL-2.0 OR (GPL-2.0-only WITH Classpath-exception-2.0)")).to be true
|
56
141
|
end
|
57
142
|
it "returns false for a license in the exception spot" do
|
58
|
-
expect(Spdx.
|
143
|
+
expect(Spdx.valid?("EPL-2.0 OR (GPL-2.0-only WITH AGPL-3.0)")).to be false
|
59
144
|
end
|
60
145
|
it "provides full details for a parse error" do
|
61
|
-
expect { Spdx.
|
146
|
+
expect { Spdx.parse("MIT OR ((WHAT)") }.to raise_error(SpdxGrammar::SpdxParseError, "Unable to parse expression 'MIT OR ((WHAT)'. Parse error at offset: 3")
|
62
147
|
end
|
63
148
|
end
|
64
149
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spdx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tidelift, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: fuzzy_match
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.1'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '2.1'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: treetop
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -161,10 +147,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
147
|
- !ruby/object:Gem::Version
|
162
148
|
version: '0'
|
163
149
|
requirements: []
|
164
|
-
rubygems_version: 3.
|
150
|
+
rubygems_version: 3.1.2
|
165
151
|
signing_key:
|
166
152
|
specification_version: 4
|
167
|
-
summary: A SPDX license
|
153
|
+
summary: A SPDX license parser
|
168
154
|
test_files:
|
169
155
|
- spec/spdx_spec.rb
|
170
156
|
- spec/spec_helper.rb
|