spandx 0.4.1 → 0.5.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: bd43f4534fd78176bb372673b73a3fcd135872f4b784ed84a6b9d518fbb7001d
4
- data.tar.gz: a66deaed24189e97e130258647b4c10f00554514ae508510169ec5ff54dee30f
3
+ metadata.gz: 440933f7b4b8706a0a4da8ed5c84c5db80f93e40e7db258715bb73b11c5cbb31
4
+ data.tar.gz: 182e055dea23b17d3bb67fc16ce84ce245aa2dbfd247d9eead1b33162bf05472
5
5
  SHA512:
6
- metadata.gz: e25407370b0ec723f948f128a80e7030e969da7744740f3d49d9293b473c68370a59615bf8638da168b1bf47f5ecaa682f74a4689c77e1f15bc30bd3dcfebfcc
7
- data.tar.gz: 89151e50569afac8e15e8fb4e882e6241c083939d30a7ffd4b15151d5420b9dba3953c7aa774006d51d2fde1df8e4eb0da550c6c05584d9a8f7b841529cb912c
6
+ metadata.gz: 26f4bc7516adf9f96c3725b15acc6ead6a2bdad6deaaf718a145106dcbec9f7c95c0f2053163f3c913a7466d2a8c3af860d4903a78bcb6eec8329f05a0cdb17f
7
+ data.tar.gz: 441abbd1f3cd090514627386e6f175ff5e53ba2909a2722f7e34e0f9a5e514532c431ffdd54e23d501dd20c6626c382b0fba215939989b7e0d32ba477bf86aa9
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- Version 0.4.1
1
+ Version 0.5.0
2
2
 
3
3
  # Changelog
4
4
 
@@ -9,6 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.5.0] - 2020-02-13
13
+ ### Added
14
+ - Add jaro winkler string similarity support.
15
+ - Attempt to resolve rubygems dependencies via `spandx-rubygems` index.
16
+
17
+ ### Changed
18
+ - Make `text` and `jaro_winkler` gems a soft dependency.
19
+
12
20
  ## [0.4.1] - 2020-02-02
13
21
  ### Fixed
14
22
  - Save license expression as string instead of array.
@@ -65,7 +73,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
65
73
  ### Added
66
74
  - Provide ruby API to the latest SPDX catalogue.
67
75
 
68
- [Unreleased]: https://github.com/mokhan/spandx/compare/v0.4.1...HEAD
76
+ [Unreleased]: https://github.com/mokhan/spandx/compare/v0.5.0...HEAD
77
+ [0.5.0]: https://github.com/mokhan/spandx/compare/v0.4.1...v0.5.0
69
78
  [0.4.1]: https://github.com/mokhan/spandx/compare/v0.4.0...v0.4.1
70
79
  [0.4.0]: https://github.com/mokhan/spandx/compare/v0.3.0...v0.4.0
71
80
  [0.3.0]: https://github.com/mokhan/spandx/compare/v0.2.0...v0.3.0
@@ -36,7 +36,7 @@ module Spandx
36
36
  end
37
37
 
38
38
  def from_git
39
- from_json(Spandx.db.read('json/licenses.json'))
39
+ from_json(Spandx.spdx_db.read('json/licenses.json'))
40
40
  end
41
41
 
42
42
  def empty
@@ -2,10 +2,9 @@
2
2
 
3
3
  module Spandx
4
4
  class Content
5
- attr_reader :raw, :threshold
5
+ attr_reader :raw
6
6
 
7
- def initialize(raw, threshold: 89.0)
8
- @threshold = threshold
7
+ def initialize(raw)
9
8
  @raw = raw
10
9
  end
11
10
 
@@ -16,9 +15,11 @@ module Spandx
16
15
  def similar?(other, algorithm: :dice_coefficient)
17
16
  case algorithm
18
17
  when :dice_coefficient
19
- similarity_score(other) > threshold
18
+ similarity_score(other, algorithm: algorithm) > 89.0
20
19
  when :levenshtein
21
- similarity_score(other) < threshold
20
+ similarity_score(other, algorithm: algorithm) < 3
21
+ when :jaro_winkler
22
+ similarity_score(other, algorithm: algorithm) > 89.0
22
23
  end
23
24
  end
24
25
 
@@ -27,7 +28,13 @@ module Spandx
27
28
  when :dice_coefficient
28
29
  dice_coefficient(other)
29
30
  when :levenshtein
31
+ require 'text'
32
+
30
33
  Text::Levenshtein.distance(raw, other.raw, 100)
34
+ when :jaro_winkler
35
+ require 'jaro_winkler'
36
+
37
+ JaroWinkler.distance(raw, other.raw) * 100.0
31
38
  end
32
39
  end
33
40
 
@@ -16,13 +16,13 @@ module Spandx
16
16
  end
17
17
 
18
18
  def update!(index, limit: nil)
19
- counter = Concurrent::AtomicFixnum.new(0)
19
+ counter = 0
20
20
  each do |spec|
21
21
  upsert_into!(index, spec)
22
22
 
23
23
  if limit
24
- counter.increment
25
- break if counter.value > limit
24
+ counter += 1
25
+ break if counter > limit
26
26
  end
27
27
  end
28
28
  end
@@ -104,10 +104,9 @@ module Spandx
104
104
  key = [host, spec['id'], spec['version']]
105
105
  return if index.indexed?(key)
106
106
 
107
- if (license = spec['licenseExpression'])
108
- index.write(key, license)
109
- end
110
- puts [license, key].inspect
107
+ return unless spec['licenseExpression']
108
+
109
+ index.write(key, spec['licenseExpression'])
111
110
  end
112
111
  end
113
112
  end
@@ -9,13 +9,18 @@ module Spandx
9
9
  end
10
10
 
11
11
  def licenses_for(name, version)
12
- details_on(name, version)['licenses'] || []
12
+ found = index.licenses_for(name: name, version: version)
13
+ found.any? ? found : details_on(name, version)['licenses'] || []
13
14
  end
14
15
 
15
16
  private
16
17
 
17
18
  attr_reader :http
18
19
 
20
+ def index
21
+ @index ||= Spandx::Rubygems::Index.new
22
+ end
23
+
19
24
  def details_on(name, version)
20
25
  url = "https://rubygems.org/api/v2/rubygems/#{name}/versions/#{version}.json"
21
26
  response = http.get(url, default: {})
data/lib/spandx/guess.rb CHANGED
@@ -8,10 +8,18 @@ module Spandx
8
8
  attr_reader :score, :item
9
9
 
10
10
  def initialize(score, item)
11
+ update(score || 0.0, item)
12
+ end
13
+
14
+ def update(score, item)
11
15
  @score = score
12
16
  @item = item
13
17
  end
14
18
 
19
+ def empty?
20
+ score.nil? || item.nil?
21
+ end
22
+
15
23
  def <=>(other)
16
24
  score <=> other.score
17
25
  end
@@ -29,33 +37,40 @@ module Spandx
29
37
 
30
38
  def license_for(raw_content, algorithm: :dice_coefficient)
31
39
  content = Content.new(raw_content)
32
- score = nil
33
- catalogue.each do |license|
34
- next if license.deprecated_license_id?
40
+ score = Score.new(nil, nil)
41
+ threshold = threshold_for(algorithm)
42
+ direction = algorithm == :levenshtein ? method(:min) : method(:max)
35
43
 
36
- score = algorithm == :levenshtein ? levenshtein(content, license, score) : dice(content, license, score)
44
+ catalogue.each do |license|
45
+ direction.call(content, license, score, threshold, algorithm) unless license.deprecated_license_id?
37
46
  end
38
47
  score&.item&.id
39
48
  end
40
49
 
41
50
  private
42
51
 
43
- def levenshtein(target, other, score)
44
- percentage = target.similarity_score(other.content, algorithm: :levenshtein)
45
- if score.nil? || percentage < score.score
46
- return Score.new(percentage, other)
47
- end
52
+ def threshold_for(algorithm)
53
+ {
54
+ dice_coefficient: 89.0,
55
+ jaro_winkler: 80.0,
56
+ levenshtein: 80.0,
57
+ }[algorithm.to_sym]
58
+ end
48
59
 
49
- score
60
+ def min(target, other, score, threshold, algorithm)
61
+ percentage = target.similarity_score(other.content, algorithm: algorithm)
62
+ return if percentage > threshold
63
+ return if score.score > 0.0 && score.score < percentage
64
+
65
+ score.update(percentage, other)
50
66
  end
51
67
 
52
- def dice(target, other, score)
53
- percentage = target.similarity_score(other.content, algorithm: :dice_coefficient)
54
- if (percentage > 89.0) && (score.nil? || percentage > score.score)
55
- return Score.new(percentage, other)
56
- end
68
+ def max(target, other, score, threshold, algorithm)
69
+ percentage = target.similarity_score(other.content, algorithm: algorithm)
70
+ return if percentage < threshold
71
+ return if score.score >= percentage
57
72
 
58
- score
73
+ score.update(percentage, other)
59
74
  end
60
75
  end
61
76
  end
@@ -65,7 +65,7 @@ module Spandx
65
65
  end
66
66
 
67
67
  def raw_content
68
- @raw_content ||= (Spandx.db.read("text/#{id}.txt") || '')
68
+ @raw_content ||= (Spandx.spdx_db.read("text/#{id}.txt") || '')
69
69
  end
70
70
 
71
71
  def <=>(other)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spandx
4
- VERSION = '0.4.1'
4
+ VERSION = '0.5.0'
5
5
  end
data/lib/spandx.rb CHANGED
@@ -2,13 +2,11 @@
2
2
 
3
3
  require 'addressable/uri'
4
4
  require 'bundler'
5
- require 'concurrent'
6
5
  require 'forwardable'
7
6
  require 'json'
8
7
  require 'net/hippie'
9
8
  require 'nokogiri'
10
9
  require 'pathname'
11
- require 'text'
12
10
 
13
11
  require 'spandx/catalogue'
14
12
  require 'spandx/content'
@@ -24,6 +22,7 @@ require 'spandx/index'
24
22
  require 'spandx/license'
25
23
  require 'spandx/parsers'
26
24
  require 'spandx/report'
25
+ require 'spandx/rubygems'
27
26
  require 'spandx/version'
28
27
 
29
28
  module Spandx
@@ -38,8 +37,8 @@ module Spandx
38
37
  @http ||= Spandx::Gateways::Http.new
39
38
  end
40
39
 
41
- def db
42
- @db ||= Spandx::Database.new(url: 'https://github.com/spdx/license-list-data.git').tap(&:update!)
40
+ def spdx_db
41
+ @spdx_db ||= Spandx::Database.new(url: 'https://github.com/spdx/license-list-data.git').tap(&:update!)
43
42
  end
44
43
  end
45
44
  end
data/spandx.gemspec CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.description = 'A ruby interface to the SPDX catalogue.'
15
15
  spec.homepage = 'https://github.com/mokhan/spandx'
16
16
  spec.license = 'MIT'
17
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
17
18
 
18
19
  spec.metadata['homepage_uri'] = spec.homepage
19
20
  spec.metadata['source_code_uri'] = 'https://github.com/mokhan/spandx'
@@ -29,20 +30,21 @@ Gem::Specification.new do |spec|
29
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
31
  spec.require_paths = ['lib']
31
32
 
32
- spec.required_ruby_version = '>= 2.4.0'
33
33
  spec.add_dependency 'addressable', '~> 2.7'
34
34
  spec.add_dependency 'bundler', '>= 1.16', '< 3.0.0'
35
- spec.add_dependency 'concurrent-ruby-ext', '~> 1.1'
36
35
  spec.add_dependency 'net-hippie', '~> 0.3'
37
36
  spec.add_dependency 'nokogiri', '~> 1.10'
38
- spec.add_dependency 'text', '~> 1.3'
39
- spec.add_dependency 'thor', '~> 0.1'
37
+ spec.add_dependency 'spandx-rubygems', '~> 0.1'
38
+ spec.add_dependency 'thor'
39
+
40
40
  spec.add_development_dependency 'bundler-audit', '~> 0.6'
41
+ spec.add_development_dependency 'jaro_winkler', '~> 1.5'
41
42
  spec.add_development_dependency 'rake', '~> 13.0'
42
43
  spec.add_development_dependency 'rspec', '~> 3.0'
43
44
  spec.add_development_dependency 'rspec-benchmark', '~> 0.5'
44
45
  spec.add_development_dependency 'rubocop', '~> 0.52'
45
46
  spec.add_development_dependency 'rubocop-rspec', '~> 1.22'
47
+ spec.add_development_dependency 'text', '~> 1.3'
46
48
  spec.add_development_dependency 'vcr', '~> 5.0'
47
49
  spec.add_development_dependency 'webmock', '~> 3.7'
48
50
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spandx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mo khan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-02 00:00:00.000000000 Z
11
+ date: 2020-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -44,20 +44,6 @@ dependencies:
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
46
  version: 3.0.0
47
- - !ruby/object:Gem::Dependency
48
- name: concurrent-ruby-ext
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '1.1'
54
- type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '1.1'
61
47
  - !ruby/object:Gem::Dependency
62
48
  name: net-hippie
63
49
  requirement: !ruby/object:Gem::Requirement
@@ -87,33 +73,33 @@ dependencies:
87
73
  - !ruby/object:Gem::Version
88
74
  version: '1.10'
89
75
  - !ruby/object:Gem::Dependency
90
- name: text
76
+ name: spandx-rubygems
91
77
  requirement: !ruby/object:Gem::Requirement
92
78
  requirements:
93
79
  - - "~>"
94
80
  - !ruby/object:Gem::Version
95
- version: '1.3'
81
+ version: '0.1'
96
82
  type: :runtime
97
83
  prerelease: false
98
84
  version_requirements: !ruby/object:Gem::Requirement
99
85
  requirements:
100
86
  - - "~>"
101
87
  - !ruby/object:Gem::Version
102
- version: '1.3'
88
+ version: '0.1'
103
89
  - !ruby/object:Gem::Dependency
104
90
  name: thor
105
91
  requirement: !ruby/object:Gem::Requirement
106
92
  requirements:
107
- - - "~>"
93
+ - - ">="
108
94
  - !ruby/object:Gem::Version
109
- version: '0.1'
95
+ version: '0'
110
96
  type: :runtime
111
97
  prerelease: false
112
98
  version_requirements: !ruby/object:Gem::Requirement
113
99
  requirements:
114
- - - "~>"
100
+ - - ">="
115
101
  - !ruby/object:Gem::Version
116
- version: '0.1'
102
+ version: '0'
117
103
  - !ruby/object:Gem::Dependency
118
104
  name: bundler-audit
119
105
  requirement: !ruby/object:Gem::Requirement
@@ -128,6 +114,20 @@ dependencies:
128
114
  - - "~>"
129
115
  - !ruby/object:Gem::Version
130
116
  version: '0.6'
117
+ - !ruby/object:Gem::Dependency
118
+ name: jaro_winkler
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '1.5'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '1.5'
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: rake
133
133
  requirement: !ruby/object:Gem::Requirement
@@ -198,6 +198,20 @@ dependencies:
198
198
  - - "~>"
199
199
  - !ruby/object:Gem::Version
200
200
  version: '1.22'
201
+ - !ruby/object:Gem::Dependency
202
+ name: text
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: '1.3'
208
+ type: :development
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - "~>"
213
+ - !ruby/object:Gem::Version
214
+ version: '1.3'
201
215
  - !ruby/object:Gem::Dependency
202
216
  name: vcr
203
217
  requirement: !ruby/object:Gem::Requirement