spdx 3.1.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce3731b9fb9a2196aace855f2f9f23ed0932990b7a60b62c2ed5d3b7d023fb73
4
- data.tar.gz: d7d2344da8d844fdc11a2eed6cc56e6911a989eb276c655ce92a720857f397c7
3
+ metadata.gz: 57eb1d8fa593ee4d8502733dd5257f050a5a421e8e272036517f146a362f1eea
4
+ data.tar.gz: e6d33c4be673643a9e052df93fcac4d41a3c8c809fca6293482979f0ffb62fb1
5
5
  SHA512:
6
- metadata.gz: 5bc839f45793acbc7ae22e0230a801a8cec40e5b5935c4a289f0eb5eb1bea451071dc733bad9c4965a98cb073453e93d0ee971c20645c8acc279e6811322bd8c
7
- data.tar.gz: 98ced2d7c93929c544f68d150b9dde28d87f816c62df0d0b3b7fb438ef4a54d347606236a71ef33ec09fa0a2099e74bb00065a749ecf55634f089f067b440019
6
+ metadata.gz: 29d8dd9dd27711bc077d2a6828cfa58a8f378a5bcd2e6a0b3915fc070e2561b03b412f7683027985d50624a013310d6e4bdd4f053e3646c4fb659d4675553fd6
7
+ data.tar.gz: 03ea3f99549c654a817c53077f584feaacd4a85200f008e987a7aebac684435974269ab6edac88a22d253d78f4dd9171ab12f6713c9241a5cf153966ae8b7863
data/README.md CHANGED
@@ -20,25 +20,81 @@ Or install it yourself as:
20
20
  ## Usage
21
21
 
22
22
  ```ruby
23
- Spdx.valid_spdx?("(MIT OR AGPL-3.0+)")
23
+ Spdx.valid?("(MIT OR AGPL-3.0+)")
24
24
  => true
25
25
  ```
26
+
26
27
  ```ruby
27
- Spdx.parse_spdx("(MIT OR AGPL-3.0+)")
28
- => CompoundExpression+CompoundExpression0 offset=0, "((MIT OR AGPL-3.0+))" (body):
29
- Body offset=1, "(MIT OR AGPL-3.0+)":
30
- CompoundExpression+CompoundExpression0 offset=1, "(MIT OR AGPL-3.0+)" (body):
31
- Body offset=2, "MIT OR AGPL-3.0+":
32
- License+License0 offset=2, "MIT"
33
- LogicalOr+Or0 offset=5, " OR " (space1,space2)
34
- License+License0 offset=9, "AGPL-3.0+"
28
+ Spdx.parse("MIT OR AGPL-3.0+")
29
+ => LogicalOr+OrExpression4 offset=0, "MIT OR AGPL-3.0+":
30
+ License+LicenseId0 offset=0, "MIT" (idstring)
31
+ LicensePlus+SimpleExpression0 offset=7, "AGPL-3.0+" (license_id):
32
+ License+LicenseId0 offset=7, "AGPL-3.0" (idstring)
35
33
  ```
36
34
 
35
+ ```ruby
36
+ Spdx.normalize("Mit OR agpl-3.0+ AND APACHE-2.0")
37
+ => "MIT OR (AGPL-3.0+ AND Apache-2.0)"
38
+
39
+ Spdx.normalize("Mit OR agpl-3.0+ AND APACHE-2.0", top_level_parens: true)
40
+ => "(MIT OR (AGPL-3.0+ AND Apache-2.0))"
41
+ ```
42
+
43
+ ### Nodes
44
+
45
+ Parsed SPDX license expressions can be a number of various nodes. Each of these nodes share a few methods, most notably `text_value` which contains the text that spans that node, and `licenses` which contains an array of individual licenses used in that portion of the expression. Below are the nodes in more detail, and their additional methods.
46
+
47
+ #### `License`
48
+
49
+ This node represents a single license, and is the result of the most simple form of expression, e.g. `Spdx.parse("MIT")`. It can also be found as a child node of other nodes.
50
+
51
+ #### `LicensePlus`
52
+
53
+ This node represents the current version of a license or any later version, e.g. `Spdx.parse("CDDL-1.0+")`. The inner license node can be found via the `child` method.
54
+
55
+ #### `LicenseRef`
56
+
57
+ This node represents a reference to a license not defined in the SPDX license list, e.g. `Spdx.parse("LicenseRef-23")`.
58
+
59
+ #### `DocumentRef`
60
+
61
+ Similar to `LicenseRef`, this node also represents a reference to a license not defined in the SPDX license list, e.g. `Spdx.parse("DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2")`.
62
+
63
+ #### `LicenseException`
64
+
65
+ This node represents an exception to a license. See `With`.
66
+
67
+ #### `With`
68
+
69
+ This node represents a license with an SPDX-defined license exception, e.g. `Spdx.parse("GPL-2.0-or-later WITH Bison-exception-2.2")`. This node has two extra methods, `license` and `exception`, which return the nodes for the license portion of the expression and the exception portion of the expression, respectively.
70
+
71
+ #### `LogicalAnd`
72
+
73
+ This node represents an "AND" expression, e.g. `Spdx.parse("LGPL-2.1-only AND MIT")`. This node has two extra methods, `left` and `right`, which return the node for the left side of the expression and the node for the right side of the expression, respectively. Any node can be the child of `LogicalAnd`, including `LogicalAnd`/`LogicalOr`.
74
+
75
+ `Spdx.parse("(MIT AND GPL-1.0) OR MPL-2.0 AND Apache-2.0")` would result in the following tree:
76
+
77
+ ```txt
78
+ LogicalOr
79
+ ├── LogicalAnd
80
+ │ ├── License (MIT)
81
+ │ └── License (GPL-1.0)
82
+ └── LogicalAnd
83
+ ├── License (MPL-2.0)
84
+ └── License Apache-2.0
85
+ ```
86
+
87
+ #### `LogicalOr`
88
+
89
+ The same as `LogicalAnd`, but for "OR" expressions.
90
+
37
91
  ## Testing
38
92
 
39
93
  Run the tests with:
40
94
 
41
- $ bundle exec rspec
95
+ ```sh
96
+ bundle exec rspec
97
+ ```
42
98
 
43
99
  ## Contributing
44
100
 
data/lib/spdx.rb CHANGED
@@ -61,7 +61,54 @@ module Spdx
61
61
  @exceptions_downcase
62
62
  end
63
63
 
64
- def self.valid_spdx?(spdx_string)
64
+ def self.normalize(spdx_string, top_level_parens: false)
65
+ normalize_tree(SpdxParser.parse(spdx_string), parens: top_level_parens)
66
+ end
67
+
68
+ private_class_method def self.normalize_tree(node, parens: true)
69
+ case node
70
+ when SpdxGrammar::LogicalAnd
71
+ left = normalize_tree(node.left)
72
+ right = normalize_tree(node.right)
73
+ if parens
74
+ "(#{left} AND #{right})"
75
+ else
76
+ "#{left} AND #{right}"
77
+ end
78
+ when SpdxGrammar::LogicalOr
79
+ left = normalize_tree(node.left)
80
+ right = normalize_tree(node.right)
81
+ if parens
82
+ "(#{left} OR #{right})"
83
+ else
84
+ "#{left} OR #{right}"
85
+ end
86
+ when SpdxGrammar::With
87
+ license = normalize_tree(node.license)
88
+ exception = normalize_tree(node.exception)
89
+ if parens
90
+ "(#{license} WITH #{exception})"
91
+ else
92
+ "#{license} WITH #{exception}"
93
+ end
94
+ when SpdxGrammar::None
95
+ "NONE"
96
+ when SpdxGrammar::NoAssertion
97
+ "NOASSERTION"
98
+ when SpdxGrammar::License
99
+ licenses_downcase[node.text_value.downcase]
100
+ when SpdxGrammar::LicensePlus
101
+ "#{normalize_tree(node.child)}+"
102
+ when SpdxGrammar::LicenseRef
103
+ node.text_value
104
+ when SpdxGrammar::DocumentRef
105
+ node.text_value
106
+ when SpdxGrammar::LicenseException
107
+ exceptions_downcase[node.text_value.downcase]
108
+ end
109
+ end
110
+
111
+ def self.valid?(spdx_string)
65
112
  return false unless spdx_string.is_a?(String)
66
113
 
67
114
  SpdxParser.parse(spdx_string)
@@ -70,7 +117,7 @@ module Spdx
70
117
  false
71
118
  end
72
119
 
73
- def self.parse_spdx(spdx_string)
120
+ def self.parse(spdx_string)
74
121
  SpdxParser.parse(spdx_string)
75
122
  end
76
123
  end
data/lib/spdx/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spdx
4
- VERSION = "3.1.0"
4
+ VERSION = "4.0.0"
5
5
  end
data/lib/spdx_grammar.rb CHANGED
@@ -1,19 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SpdxGrammar
4
- class CompoundExpression < Treetop::Runtime::SyntaxNode
4
+ class LogicalBinary < Treetop::Runtime::SyntaxNode
5
+ # Used internally
6
+
5
7
  def licenses
6
- elements[0].licenses
8
+ (left.licenses + right.licenses).uniq
9
+ end
10
+
11
+ def left
12
+ elements[0]
13
+ end
14
+
15
+ def right
16
+ elements[1]
7
17
  end
8
18
  end
9
19
 
10
- class LogicalOr < Treetop::Runtime::SyntaxNode
20
+ class LogicalAnd < LogicalBinary
11
21
  end
12
22
 
13
- class LogicalAnd < Treetop::Runtime::SyntaxNode
23
+ class LogicalOr < LogicalBinary
14
24
  end
15
25
 
16
26
  class With < Treetop::Runtime::SyntaxNode
27
+ def licenses
28
+ license.licenses
29
+ end
30
+
31
+ def license
32
+ elements[0]
33
+ end
34
+
35
+ def exception
36
+ elements[1]
37
+ end
17
38
  end
18
39
 
19
40
  class None < Treetop::Runtime::SyntaxNode
@@ -30,22 +51,29 @@ module SpdxGrammar
30
51
 
31
52
  class License < Treetop::Runtime::SyntaxNode
32
53
  def licenses
33
- text_value
54
+ [text_value]
34
55
  end
35
56
  end
36
57
 
37
- class UserDefinedLicense < Treetop::Runtime::SyntaxNode
58
+ class LicensePlus < Treetop::Runtime::SyntaxNode
59
+ def licenses
60
+ child.licenses
61
+ end
62
+
63
+ def child
64
+ elements[0]
65
+ end
38
66
  end
39
67
 
40
68
  class LicenseRef < Treetop::Runtime::SyntaxNode
41
69
  def licenses
42
- text_value
70
+ [text_value]
43
71
  end
44
72
  end
45
73
 
46
74
  class DocumentRef < Treetop::Runtime::SyntaxNode
47
75
  def licenses
48
- text_value
76
+ [text_value]
49
77
  end
50
78
  end
51
79
 
@@ -53,10 +81,12 @@ module SpdxGrammar
53
81
  # TODO: actually do license exceptions
54
82
  end
55
83
 
56
- class Body < Treetop::Runtime::SyntaxNode
57
- def licenses
58
- elements.map { |node| node.licenses if node.respond_to?(:licenses) }.flatten.uniq.compact
59
- end
84
+ class GroupedExpression < Treetop::Runtime::SyntaxNode
85
+ # Used internally
86
+ end
87
+
88
+ class Operand < Treetop::Runtime::SyntaxNode
89
+ # Used internally
60
90
  end
61
91
 
62
92
  class SpdxParseError < StandardError
data/lib/spdx_parser.rb CHANGED
@@ -21,20 +21,48 @@ class SpdxParser
21
21
 
22
22
  private_class_method def self.parse_tree(data)
23
23
  parser = SpdxGrammarParser.new # The generated grammar parser is not thread safe
24
- # Couldn't figure out treetop to make parens optional
25
- data = "(#{data})" unless SKIP_PARENS.include?(data)
26
24
 
27
25
  tree = parser.parse(data)
28
26
  raise SpdxGrammar::SpdxParseError, "Unable to parse expression '#{data}'. Parse error at offset: #{parser.index}" if tree.nil?
29
27
 
30
- clean_tree(tree)
31
- tree
28
+ prune(tree)
32
29
  end
33
30
 
34
- private_class_method def self.clean_tree(root_node)
35
- return if root_node.elements.nil?
31
+ private_class_method def self.clean(root_node)
32
+ root_node.elements&.delete_if { |node| node.instance_of?(Treetop::Runtime::SyntaxNode) }
33
+ end
34
+
35
+ private_class_method def self.prune(root_node)
36
+ clean(root_node)
37
+
38
+ root_node.elements&.each_with_index do |node, i|
39
+ case node
40
+ when SpdxGrammar::GroupedExpression, SpdxGrammar::Operand
41
+ clean(node)
42
+ child = node.elements[0]
43
+ child.parent = root_node
44
+ root_node.elements[i] = child
45
+
46
+ case child
47
+ when SpdxGrammar::GroupedExpression, SpdxGrammar::Operand
48
+ # re-prune if child's child is a GroupedExpression or Operand
49
+ prune(root_node)
50
+ else
51
+ prune(child)
52
+ end
53
+ else
54
+ prune(node)
55
+ end
56
+ end
57
+
58
+ case root_node
59
+ when SpdxGrammar::GroupedExpression
60
+ child = root_node.elements[0]
61
+ child.parent = root_node.parent
62
+
63
+ return child
64
+ end
36
65
 
37
- root_node.elements.delete_if { |node| node.class.name == "Treetop::Runtime::SyntaxNode" }
38
- root_node.elements.each { |node| clean_tree(node) }
66
+ root_node
39
67
  end
40
68
  end
@@ -1,47 +1,56 @@
1
1
  grammar SpdxGrammar
2
2
 
3
- rule spdx_expression
3
+ rule license_expression
4
4
  compound_expression / none / no_assertion
5
5
  end
6
6
 
7
7
  rule compound_expression
8
- '(' body ')' <CompoundExpression>
8
+ or_expression / and_expression / expression / grouped_expression
9
9
  end
10
10
 
11
- rule body
12
- ( compound_expression / and / or / with / license_ref / document_ref / license )* <Body>
11
+ rule and_expression
12
+ ( expression space <Operand> / grouped_expression space? <Operand> ) "AND" ( space ( and_expression / expression ) <Operand> / space? grouped_expression <Operand> ) <LogicalAnd>
13
13
  end
14
14
 
15
- rule and
16
- space "AND" space !reserve_words <LogicalAnd>
15
+ rule or_expression
16
+ ( ( and_expression / expression ) space <Operand> / grouped_expression space? <Operand> ) "OR" ( space compound_expression <Operand> / space? grouped_expression <Operand> ) <LogicalOr>
17
17
  end
18
18
 
19
- rule or
20
- space "OR" space !reserve_words <LogicalOr>
19
+ rule expression
20
+ simple_expression space "WITH" space license_exception_id <With> /
21
+ simple_expression
21
22
  end
22
23
 
23
- rule with
24
- space "WITH" space license_exception <With>
24
+ rule grouped_expression
25
+ '(' compound_expression ')' <GroupedExpression>
25
26
  end
26
27
 
27
- rule license
28
- [a-zA-Z0-9\-\.\+]+ &{|seq| Spdx.license_exists?(seq.first.text_value) || Spdx.license_exists?(seq.first.text_value.delete_suffix('+')) } <License>
28
+ rule simple_expression
29
+ license_id '+' <LicensePlus> / license_id / ref
30
+ end
31
+
32
+ rule ref
33
+ document_ref / license_ref
29
34
  end
30
35
 
31
36
  rule license_ref
32
- "LicenseRef-" [a-zA-Z0-9\-\.]+ <LicenseRef>
37
+ "LicenseRef-" idstring <LicenseRef>
33
38
  end
34
39
 
35
40
  rule document_ref
36
- "DocumentRef-" [a-zA-Z0-9\-\.]+ ":" license_ref <DocumentRef>
41
+ "DocumentRef-" idstring ':' license_ref <DocumentRef>
42
+ end
43
+
44
+ rule license_id
45
+ idstring &{|seq| Spdx.license_exists?(seq.first.text_value) } <License>
37
46
  end
38
47
 
39
- rule license_exception
40
- [a-zA-Z0-9\-\.]+ &{|seq| Spdx.exception_exists?(seq.first.text_value) } <LicenseException>
48
+ rule license_exception_id
49
+ idstring &{|seq| Spdx.exception_exists?(seq.first.text_value) } <LicenseException>
41
50
  end
42
51
 
43
- rule reserve_words
44
- "AND" / "OR" / "WITH"
52
+ rule idstring
53
+ [a-zA-Z0-9\-\.]+
45
54
  end
46
55
 
47
56
  rule none
data/spec/spdx_spec.rb CHANGED
@@ -4,67 +4,121 @@ require "spec_helper"
4
4
 
5
5
  describe Spdx do
6
6
  context "spdx parsing" do
7
- context "valid_spdx?" do
7
+ context "valid?" do
8
8
  it "returns false for invalid spdx" do
9
- expect(Spdx.valid_spdx?("AND AND")).to be false
10
- expect(Spdx.valid_spdx?("MIT OR MIT AND OR")).to be false
11
- expect(Spdx.valid_spdx?("MIT OR FAKEYLICENSE")).to be false
12
- expect(Spdx.valid_spdx?(nil)).to be false
13
- expect(Spdx.valid_spdx?("")).to be false
14
- expect(Spdx.valid_spdx?("MIT (MIT)")).to be false
9
+ expect(Spdx.valid?("AND AND")).to be false
10
+ expect(Spdx.valid?(" AND ")).to be false
11
+ expect(Spdx.valid?(" WITH ")).to be false
12
+ expect(Spdx.valid?("MIT AND ")).to be false
13
+ expect(Spdx.valid?("MIT OR MIT AND OR")).to be false
14
+ expect(Spdx.valid?("MIT OR FAKEYLICENSE")).to be false
15
+ expect(Spdx.valid?(nil)).to be false
16
+ expect(Spdx.valid?("")).to be false
17
+ expect(Spdx.valid?("MIT (MIT)")).to be false
15
18
  end
16
19
  it "returns true for valid spdx" do
17
- expect(Spdx.valid_spdx?("(MIT OR MPL-2.0)")).to be true
18
- expect(Spdx.valid_spdx?("MIT")).to be true
19
- expect(Spdx.valid_spdx?("((MIT OR AGPL-1.0) AND (MIT OR MPL-2.0))")).to be true
20
- expect(Spdx.valid_spdx?("MIT OR (MIT)")).to be true
20
+ expect(Spdx.valid?("(MIT OR MPL-2.0)")).to be true
21
+ expect(Spdx.valid?("MIT")).to be true
22
+ expect(Spdx.valid?("MIT OR MPL-2.0 AND AGPL-1.0")).to be true
23
+ expect(Spdx.valid?("MIT OR (GPL-1.0 OR MPL-2.0) AND AGPL-1.0")).to be true
24
+ expect(Spdx.valid?("MIT AND MPL-2.0 OR AGPL-1.0")).to be true
25
+ expect(Spdx.valid?("MIT AND (GPL-1.0 OR MPL-2.0) OR AGPL-1.0")).to be true
26
+ expect(Spdx.valid?("MIT OR (DocumentRef-something-1:LicenseRef-MIT-style-1 OR MPL-2.0) AND AGPL-1.0")).to be true
27
+ expect(Spdx.valid?("((MIT OR AGPL-1.0) AND (MIT OR MPL-2.0))")).to be true
28
+ expect(Spdx.valid?("MIT OR (MIT)")).to be true
21
29
  end
22
30
  it "returns true for NONE and NOASSERTION" do
23
- expect(Spdx.valid_spdx?("NONE")).to be true
24
- expect(Spdx.valid_spdx?("(NONE)")).to be false
25
- expect(Spdx.valid_spdx?("NOASSERTION")).to be true
26
- expect(Spdx.valid_spdx?("MIT OR NONE")).to be false
31
+ expect(Spdx.valid?("NONE")).to be true
32
+ expect(Spdx.valid?("(NONE)")).to be false
33
+ expect(Spdx.valid?("NOASSERTION")).to be true
34
+ expect(Spdx.valid?("MIT OR NONE")).to be false
27
35
  end
28
36
  it "returns true for + expression" do
29
- expect(Spdx.valid_spdx?("AGPL-3.0+")).to be true
37
+ expect(Spdx.valid?("AGPL-3.0+")).to be true
30
38
  end
31
39
  it "is case insentive for license ids" do
32
- expect(Spdx.valid_spdx?("mit OR agpl-3.0+")).to be true
40
+ expect(Spdx.valid?("mit OR agpl-3.0+")).to be true
33
41
  end
34
42
  it "handles LicenseRef" do
35
- expect(Spdx.valid_spdx?("MIT OR LicenseRef-MIT-style-1")).to be true
43
+ expect(Spdx.valid?("MIT OR LicenseRef-MIT-style-1")).to be true
36
44
  end
37
45
  it "handles DocumentRef" do
38
- expect(Spdx.valid_spdx?("MIT OR DocumentRef-something-1:LicenseRef-MIT-style-1")).to be true
39
- expect(Spdx.valid_spdx?("MIT OR DocumentRef-something-1")).to be false
46
+ expect(Spdx.valid?("MIT OR DocumentRef-something-1:LicenseRef-MIT-style-1")).to be true
47
+ expect(Spdx.valid?("MIT OR DocumentRef-something-1")).to be false
40
48
  end
41
49
  end
42
50
  end
51
+ context "normalize" do
52
+ it "normalizes simple licenses" do
53
+ expect(Spdx.normalize("MIT")).to eq "MIT"
54
+ expect(Spdx.normalize("mit")).to eq "MIT"
55
+ expect(Spdx.normalize("MiT")).to eq "MIT"
56
+ expect(Spdx.normalize("(MiT)")).to eq "MIT"
57
+ expect(Spdx.normalize("(((MiT)))")).to eq "MIT"
58
+ expect(Spdx.normalize("LicenseRef-MIT-style-1")).to eq "LicenseRef-MIT-style-1"
59
+ expect(Spdx.normalize("DocumentRef-something-1:LicenseRef-MIT-style-1")).to eq "DocumentRef-something-1:LicenseRef-MIT-style-1"
60
+ expect(Spdx.normalize("Apache-2.0+")).to eq "Apache-2.0+"
61
+ expect(Spdx.normalize("apache-2.0+")).to eq "Apache-2.0+"
62
+ end
63
+ it "normalizes NONE/NOASSERTION" do
64
+ expect(Spdx.normalize("NONE")).to eq "NONE"
65
+ expect(Spdx.normalize("NOASSERTION")).to eq "NOASSERTION"
66
+ end
67
+ it "normalizes boolean expressions" do
68
+ expect(Spdx.normalize("mit AND gPL-2.0")).to eq "MIT AND GPL-2.0"
69
+ expect(Spdx.normalize("mit OR gPL-2.0")).to eq "MIT OR GPL-2.0"
70
+ expect(Spdx.normalize("mit OR gPL-2.0")).to eq "MIT OR GPL-2.0"
71
+
72
+ # With top level parens
73
+ expect(Spdx.normalize("mit AND gPL-2.0", top_level_parens: true)).to eq "(MIT AND GPL-2.0)"
74
+ expect(Spdx.normalize("mit OR gPL-2.0", top_level_parens: true)).to eq "(MIT OR GPL-2.0)"
75
+ expect(Spdx.normalize("mit OR gPL-2.0", top_level_parens: true)).to eq "(MIT OR GPL-2.0)"
76
+
77
+ # Does semantic grouping
78
+ expect(Spdx.normalize("mit OR gPL-2.0 AND apAcHe-2.0+")).to eq "MIT OR (GPL-2.0 AND Apache-2.0+)"
79
+
80
+ # But also preserves original groups
81
+ expect(Spdx.normalize("(mit OR gPL-2.0) AND apAcHe-2.0+")).to eq "(MIT OR GPL-2.0) AND Apache-2.0+"
82
+ end
83
+ it "normalizes WITH expressions" do
84
+ expect(Spdx.normalize("GPL-2.0-only WITH Classpath-exception-2.0")).to eq "GPL-2.0-only WITH Classpath-exception-2.0"
85
+ expect(Spdx.normalize("Gpl-2.0-ONLY WITH ClassPath-exception-2.0")).to eq "GPL-2.0-only WITH Classpath-exception-2.0"
86
+
87
+ # With top level parens
88
+ 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)"
89
+ 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)"
90
+
91
+ 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)"
92
+ 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)"
93
+ 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)"
94
+ 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+)"
95
+ end
96
+ end
43
97
  context "licenses" do
44
98
  it "returns a list of possible licenses" do
45
- expect(Spdx.parse_spdx("MIT OR MPL-2.0").licenses).to eq ["MIT", "MPL-2.0"]
99
+ expect(Spdx.parse("MIT OR MPL-2.0").licenses).to eq ["MIT", "MPL-2.0"]
46
100
  end
47
101
  it "returns empty array for NONE or NOASSERTION" do
48
- expect(Spdx.parse_spdx("NONE").licenses).to eq []
49
- expect(Spdx.parse_spdx("NOASSERTION").licenses).to eq []
102
+ expect(Spdx.parse("NONE").licenses).to eq []
103
+ expect(Spdx.parse("NOASSERTION").licenses).to eq []
50
104
  end
51
105
  it "returns LicenseRefs" do
52
- expect(Spdx.parse_spdx("MIT OR LicenseRef-MIT-style-1").licenses).to eq %w[MIT LicenseRef-MIT-style-1]
106
+ expect(Spdx.parse("MIT OR LicenseRef-MIT-style-1").licenses).to eq %w[MIT LicenseRef-MIT-style-1]
53
107
  end
54
108
  it "returns DocumentRefs" do
55
- expect(Spdx.parse_spdx("MIT OR DocumentRef-something-1:LicenseRef-MIT-style-1").licenses).to eq %w[MIT DocumentRef-something-1:LicenseRef-MIT-style-1]
109
+ expect(Spdx.parse("MIT OR DocumentRef-something-1:LicenseRef-MIT-style-1").licenses).to eq %w[MIT DocumentRef-something-1:LicenseRef-MIT-style-1]
56
110
  end
57
111
  end
58
112
 
59
113
  context "exceptions" do
60
- it "parses a valid spdx with expression" do
61
- expect(Spdx.valid_spdx?("EPL-2.0 OR (GPL-2.0-only WITH Classpath-exception-2.0)")).to be true
114
+ it "parses a valid spdx WITH expression" do
115
+ expect(Spdx.valid?("EPL-2.0 OR (GPL-2.0-only WITH Classpath-exception-2.0)")).to be true
62
116
  end
63
117
  it "returns false for a license in the exception spot" do
64
- expect(Spdx.valid_spdx?("EPL-2.0 OR (GPL-2.0-only WITH AGPL-3.0)")).to be false
118
+ expect(Spdx.valid?("EPL-2.0 OR (GPL-2.0-only WITH AGPL-3.0)")).to be false
65
119
  end
66
120
  it "provides full details for a parse error" do
67
- expect { Spdx.parse_spdx("MIT OR ((WHAT)") }.to raise_error(SpdxGrammar::SpdxParseError, "Unable to parse expression '(MIT OR ((WHAT))'. Parse error at offset: 0")
121
+ expect { Spdx.parse("MIT OR ((WHAT)") }.to raise_error(SpdxGrammar::SpdxParseError, "Unable to parse expression 'MIT OR ((WHAT)'. Parse error at offset: 3")
68
122
  end
69
123
  end
70
124
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spdx
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tidelift, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-11 00:00:00.000000000 Z
11
+ date: 2021-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: treetop