spdx 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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