serrano 0.3.6 → 0.6.2
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 +5 -5
- data/.github/workflows/ruby.yml +28 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +50 -0
- data/.rubocop_todo.yml +105 -0
- data/CHANGELOG.md +33 -0
- data/{CONDUCT.md → CODE_OF_CONDUCT.md} +2 -2
- data/Gemfile +2 -0
- data/Gemfile.lock +56 -38
- data/LICENSE +1 -1
- data/README.md +35 -7
- data/Rakefile +26 -18
- data/bin/serrano +96 -98
- data/lib/serrano.rb +194 -77
- data/lib/serrano/cn.rb +7 -9
- data/lib/serrano/cnrequest.rb +42 -28
- data/lib/serrano/error.rb +2 -0
- data/lib/serrano/faraday.rb +15 -14
- data/lib/serrano/filterhandler.rb +13 -15
- data/lib/serrano/filters.rb +91 -78
- data/lib/serrano/helpers/configuration.rb +2 -2
- data/lib/serrano/request.rb +46 -39
- data/lib/serrano/request_cursor.rb +66 -59
- data/lib/serrano/styles.rb +14 -9
- data/lib/serrano/utils.rb +21 -14
- data/lib/serrano/version.rb +3 -1
- data/serrano.gemspec +33 -20
- metadata +87 -69
- data/.travis.yml +0 -8
- data/lib/serrano/constants.rb +0 -36
- data/lib/serrano/cursor_testing.rb +0 -52
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# taken from: https://viget.com/extend/easy-gem-configuration-variables-with-defaults
|
2
4
|
module Configuration
|
3
|
-
|
4
5
|
def configuration
|
5
6
|
yield self
|
6
7
|
end
|
@@ -22,5 +23,4 @@ module Configuration
|
|
22
23
|
define_method name, &block
|
23
24
|
end
|
24
25
|
end
|
25
|
-
|
26
26
|
end
|
data/lib/serrano/request.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
require 'faraday'
|
5
|
+
require 'multi_json'
|
6
|
+
require 'serrano/error'
|
5
7
|
require 'serrano/utils'
|
6
8
|
require 'serrano/helpers/configuration'
|
7
9
|
|
@@ -11,7 +13,6 @@ require 'serrano/helpers/configuration'
|
|
11
13
|
# Class to perform HTTP requests to the Crossref API
|
12
14
|
module Serrano
|
13
15
|
class Request #:nodoc:
|
14
|
-
|
15
16
|
attr_accessor :endpt
|
16
17
|
attr_accessor :id
|
17
18
|
attr_accessor :query
|
@@ -22,14 +23,15 @@ module Serrano
|
|
22
23
|
attr_accessor :sort
|
23
24
|
attr_accessor :order
|
24
25
|
attr_accessor :facet
|
26
|
+
attr_accessor :select
|
25
27
|
attr_accessor :works
|
26
28
|
attr_accessor :agency
|
27
29
|
attr_accessor :options
|
28
30
|
attr_accessor :verbose
|
29
31
|
|
30
32
|
def initialize(endpt, id, query, filter, offset,
|
31
|
-
|
32
|
-
|
33
|
+
limit, sample, sort, order, facet, select,
|
34
|
+
works, agency, options, verbose)
|
33
35
|
|
34
36
|
self.endpt = endpt
|
35
37
|
self.id = id
|
@@ -41,6 +43,7 @@ module Serrano
|
|
41
43
|
self.sort = sort
|
42
44
|
self.order = order
|
43
45
|
self.facet = facet
|
46
|
+
self.select = select
|
44
47
|
self.works = works
|
45
48
|
self.agency = agency
|
46
49
|
self.options = options
|
@@ -48,49 +51,53 @@ module Serrano
|
|
48
51
|
end
|
49
52
|
|
50
53
|
def perform
|
51
|
-
filt = filter_handler(
|
54
|
+
filt = filter_handler(filter)
|
52
55
|
|
53
|
-
|
54
|
-
rows: self.limit, sample: self.sample, sort: self.sort,
|
55
|
-
order: self.order, facet: self.facet }
|
56
|
-
opts = args.delete_if { |k, v| v.nil? }
|
56
|
+
self.select = select.join(',') if select && select.class == Array
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
58
|
+
args = { query: query, filter: filt, offset: offset,
|
59
|
+
rows: limit, sample: sample, sort: sort,
|
60
|
+
order: order, facet: facet,
|
61
|
+
select: select }
|
62
|
+
opts = args.delete_if { |_k, v| v.nil? }
|
63
|
+
|
64
|
+
conn = if verbose
|
65
|
+
Faraday.new(url: Serrano.base_url, request: options || []) do |f|
|
66
|
+
f.response :logger
|
67
|
+
f.use FaradayMiddleware::RaiseHttpException
|
68
|
+
f.adapter Faraday.default_adapter
|
69
|
+
end
|
70
|
+
else
|
71
|
+
Faraday.new(url: Serrano.base_url, request: options || []) do |f|
|
72
|
+
f.use FaradayMiddleware::RaiseHttpException
|
73
|
+
f.adapter Faraday.default_adapter
|
74
|
+
end
|
75
|
+
end
|
70
76
|
|
71
77
|
conn.headers[:user_agent] = make_ua
|
72
|
-
conn.headers[
|
78
|
+
conn.headers['X-USER-AGENT'] = make_ua
|
73
79
|
|
74
|
-
if
|
75
|
-
res = conn.get
|
76
|
-
|
80
|
+
if id.nil?
|
81
|
+
res = conn.get endpt, opts
|
82
|
+
MultiJson.load(res.body)
|
77
83
|
else
|
84
|
+
self.id = Array(id)
|
85
|
+
# url encoding
|
86
|
+
self.id = id.map { |x| ERB::Util.url_encode(x) }
|
78
87
|
coll = []
|
79
|
-
|
80
|
-
if
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
end
|
88
|
+
id.each do |x|
|
89
|
+
endpt = if works
|
90
|
+
self.endpt + '/' + x.to_s + '/works'
|
91
|
+
elsif agency
|
92
|
+
self.endpt + '/' + x.to_s + '/agency'
|
93
|
+
else
|
94
|
+
self.endpt + '/' + x.to_s
|
95
|
+
end
|
89
96
|
|
90
97
|
res = conn.get endpt, opts
|
91
98
|
coll << MultiJson.load(res.body)
|
92
99
|
end
|
93
|
-
|
100
|
+
coll
|
94
101
|
end
|
95
102
|
end
|
96
103
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
require 'faraday'
|
2
5
|
require 'faraday_middleware'
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require "serrano/constants"
|
6
|
+
require 'multi_json'
|
7
|
+
require 'serrano/error'
|
6
8
|
require 'serrano/helpers/configuration'
|
7
9
|
require 'serrano/filterhandler'
|
8
10
|
require 'serrano/error'
|
@@ -15,7 +17,6 @@ require 'serrano/utils'
|
|
15
17
|
# Class to perform HTTP requests to the Crossref API
|
16
18
|
module Serrano
|
17
19
|
class RequestCursor #:nodoc:
|
18
|
-
|
19
20
|
attr_accessor :endpt
|
20
21
|
attr_accessor :id
|
21
22
|
attr_accessor :query
|
@@ -26,6 +27,7 @@ module Serrano
|
|
26
27
|
attr_accessor :sort
|
27
28
|
attr_accessor :order
|
28
29
|
attr_accessor :facet
|
30
|
+
attr_accessor :select
|
29
31
|
attr_accessor :works
|
30
32
|
attr_accessor :agency
|
31
33
|
attr_accessor :options
|
@@ -35,8 +37,9 @@ module Serrano
|
|
35
37
|
attr_accessor :args
|
36
38
|
|
37
39
|
def initialize(endpt, id, query, filter, offset,
|
38
|
-
|
39
|
-
|
40
|
+
limit, sample, sort, order, facet, select,
|
41
|
+
works, agency, options, verbose, cursor,
|
42
|
+
cursor_max, args)
|
40
43
|
|
41
44
|
self.endpt = endpt
|
42
45
|
self.id = id
|
@@ -48,6 +51,7 @@ module Serrano
|
|
48
51
|
self.sort = sort
|
49
52
|
self.order = order
|
50
53
|
self.facet = facet
|
54
|
+
self.select = select
|
51
55
|
self.works = works
|
52
56
|
self.agency = agency
|
53
57
|
self.options = options
|
@@ -58,86 +62,89 @@ module Serrano
|
|
58
62
|
end
|
59
63
|
|
60
64
|
def perform
|
61
|
-
filt = filter_handler(
|
62
|
-
fieldqueries = field_query_handler(
|
65
|
+
filt = filter_handler(filter)
|
66
|
+
fieldqueries = field_query_handler(args)
|
67
|
+
self.select = select.join(',') if select && select.class == Array
|
63
68
|
|
64
|
-
|
65
|
-
|
66
|
-
raise "cursor_max must be of class int"
|
67
|
-
end
|
69
|
+
unless cursor_max.class.nil?
|
70
|
+
raise 'cursor_max must be of class int' unless cursor_max.is_a?(Integer)
|
68
71
|
end
|
69
72
|
|
70
|
-
arguments = { query:
|
71
|
-
|
72
|
-
|
73
|
+
arguments = { query: query, filter: filt, offset: offset,
|
74
|
+
rows: limit, sample: sample, sort: sort,
|
75
|
+
order: order, facet: facet, select: select,
|
76
|
+
cursor: cursor }.tostrings
|
73
77
|
arguments = arguments.merge(fieldqueries)
|
74
|
-
opts = arguments.delete_if { |
|
78
|
+
opts = arguments.delete_if { |_k, v| v.nil? }
|
75
79
|
|
76
|
-
if verbose
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
80
|
+
conn = if verbose
|
81
|
+
Faraday.new(url: Serrano.base_url, request: options || []) do |f|
|
82
|
+
f.response :logger
|
83
|
+
f.use FaradayMiddleware::RaiseHttpException
|
84
|
+
f.adapter Faraday.default_adapter
|
85
|
+
end
|
86
|
+
else
|
87
|
+
Faraday.new(url: Serrano.base_url, request: options || []) do |f|
|
88
|
+
f.use FaradayMiddleware::RaiseHttpException
|
89
|
+
f.adapter Faraday.default_adapter
|
90
|
+
end
|
91
|
+
end
|
88
92
|
|
89
|
-
|
90
|
-
|
93
|
+
conn.headers[:user_agent] = make_ua
|
94
|
+
conn.headers['X-USER-AGENT'] = make_ua
|
91
95
|
|
92
|
-
if
|
93
|
-
|
96
|
+
if id.nil?
|
97
|
+
endpt2 = endpt
|
98
|
+
js = _req(conn, endpt, opts)
|
94
99
|
cu = js['message']['next-cursor']
|
95
100
|
max_avail = js['message']['total-results']
|
96
|
-
res =
|
97
|
-
|
101
|
+
res = _redo_req(conn, js, opts, cu, max_avail)
|
102
|
+
res
|
98
103
|
else
|
104
|
+
self.id = Array(id)
|
105
|
+
# url encoding
|
106
|
+
self.id = id.map { |x| ERB::Util.url_encode(x) }
|
99
107
|
coll = []
|
100
|
-
|
101
|
-
if
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
108
|
+
id.each do |x|
|
109
|
+
endpt2 = if works
|
110
|
+
endpt + '/' + x.to_s + '/works'
|
111
|
+
else
|
112
|
+
endpt2 = if agency
|
113
|
+
endpt + '/' + x.to_s + '/agency'
|
114
|
+
else
|
115
|
+
endpt + '/' + x.to_s
|
116
|
+
end
|
117
|
+
end
|
110
118
|
|
111
|
-
js =
|
119
|
+
js = _req(conn, endpt2, opts)
|
112
120
|
cu = js['message']['next-cursor']
|
113
121
|
max_avail = js['message']['total-results']
|
114
|
-
coll <<
|
122
|
+
coll << _redo_req(conn, js, opts, cu, max_avail)
|
115
123
|
end
|
116
|
-
|
124
|
+
coll
|
117
125
|
end
|
118
126
|
end
|
119
127
|
|
120
|
-
def _redo_req(js, opts, cu, max_avail)
|
121
|
-
if !cu.nil?
|
128
|
+
def _redo_req(conn, js, opts, cu, max_avail)
|
129
|
+
if !cu.nil? && (cursor_max > js['message']['items'].length)
|
122
130
|
res = [js]
|
123
131
|
total = js['message']['items'].length
|
124
|
-
while !cu.nil?
|
132
|
+
while !cu.nil? && (cursor_max > total) && (total < max_avail)
|
125
133
|
opts[:cursor] = cu
|
126
|
-
out =
|
134
|
+
out = _req(conn, endpt2, opts)
|
127
135
|
cu = out['message']['next-cursor']
|
128
136
|
res << out
|
129
|
-
total = res.collect {|x| x['message']['items'].length}.reduce(0, :+)
|
137
|
+
total = res.collect { |x| x['message']['items'].length }.reduce(0, :+)
|
130
138
|
end
|
131
|
-
|
139
|
+
res
|
132
140
|
else
|
133
|
-
|
141
|
+
js
|
134
142
|
end
|
135
143
|
end
|
136
144
|
|
137
|
-
def _req(path, opts)
|
138
|
-
res =
|
139
|
-
|
145
|
+
def _req(conn, path, opts)
|
146
|
+
res = conn.get path, opts
|
147
|
+
MultiJson.load(res.body)
|
140
148
|
end
|
141
|
-
|
142
149
|
end
|
143
150
|
end
|
data/lib/serrano/styles.rb
CHANGED
@@ -1,23 +1,28 @@
|
|
1
|
-
|
2
|
-
require "multi_json"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
require 'faraday'
|
4
|
+
require 'multi_json'
|
5
|
+
|
6
|
+
def fetch_styles
|
7
|
+
base = 'https://api.github.com/repos/citation-style-language/styles'
|
8
|
+
conn = Faraday.new(url: base) do |f|
|
9
|
+
f.use FaradayMiddleware::RaiseHttpException
|
10
|
+
f.adapter Faraday.default_adapter
|
11
|
+
end
|
7
12
|
args = { per_page: 1 }
|
8
13
|
tt = conn.get 'commits', args
|
9
14
|
commres = MultiJson.load(tt.body)
|
10
15
|
sha = commres[0]['sha']
|
11
|
-
sty = conn.get
|
16
|
+
sty = conn.get 'git/trees/' + sha
|
12
17
|
res = MultiJson.load(sty.body)
|
13
18
|
files = res['tree'].collect { |x| x['path'] }
|
14
|
-
matches = files.collect
|
19
|
+
matches = files.collect do |x|
|
15
20
|
if x.match('csl').nil?
|
16
21
|
nil
|
17
22
|
else
|
18
23
|
x.match('csl').string
|
19
24
|
end
|
20
|
-
|
25
|
+
end
|
21
26
|
csls = matches.compact
|
22
|
-
|
27
|
+
csls.collect { |z| z.gsub('.csl', '') }
|
23
28
|
end
|
data/lib/serrano/utils.rb
CHANGED
@@ -1,29 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
def make_ua
|
2
|
-
|
4
|
+
requa = 'Faraday/v' + Faraday::VERSION
|
3
5
|
habua = 'Serrano/v' + Serrano::VERSION
|
4
|
-
|
6
|
+
ua = requa + ' ' + habua
|
7
|
+
if Serrano.mailto
|
8
|
+
ua = ua + " (mailto:%s)" % Serrano.mailto
|
9
|
+
end
|
10
|
+
# ua += format(' (mailto:%s)', Serrano.mailto) if Serrano.mailto
|
11
|
+
ua
|
5
12
|
end
|
6
13
|
|
7
14
|
def field_query_handler(x)
|
8
|
-
|
9
|
-
|
15
|
+
tmp = x.keep_if { |z| z.match(/query_/) }
|
16
|
+
rename_query_filters(tmp)
|
10
17
|
end
|
11
18
|
|
12
19
|
def rename_query_filters(foo)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
20
|
+
foo = foo.tostrings
|
21
|
+
foo = foo.map { |x, y| [x.to_s.sub('container_title', 'container-title'), y] }.to_h
|
22
|
+
foo = foo.map { |x, y| [x.to_s.sub('query_', 'query.'), y] }.to_h
|
23
|
+
foo
|
17
24
|
end
|
18
25
|
|
19
26
|
class Hash
|
20
|
-
|
21
|
-
|
22
|
-
|
27
|
+
def tostrings
|
28
|
+
Hash[map { |(k, v)| [k.to_s, v] }]
|
29
|
+
end
|
23
30
|
end
|
24
31
|
|
25
32
|
class Hash
|
26
|
-
|
27
|
-
|
28
|
-
|
33
|
+
def tosymbols
|
34
|
+
Hash[map { |(k, v)| [k.to_sym, v] }]
|
35
|
+
end
|
29
36
|
end
|
data/lib/serrano/version.rb
CHANGED
data/serrano.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'serrano/version'
|
5
6
|
|
@@ -7,32 +8,44 @@ Gem::Specification.new do |s|
|
|
7
8
|
s.name = 'serrano'
|
8
9
|
s.version = Serrano::VERSION
|
9
10
|
s.platform = Gem::Platform::RUBY
|
10
|
-
s.required_ruby_version = '>= 2.
|
11
|
-
s.date = '
|
12
|
-
s.summary =
|
13
|
-
s.description =
|
14
|
-
s.authors =
|
11
|
+
s.required_ruby_version = '>= 2.1'
|
12
|
+
s.date = '2020-05-29'
|
13
|
+
s.summary = 'Crossref Client'
|
14
|
+
s.description = 'Low Level Ruby Client for the Crossref Search API'
|
15
|
+
s.authors = 'Scott Chamberlain'
|
15
16
|
s.email = 'myrmecocystus@gmail.com'
|
16
17
|
s.homepage = 'https://github.com/sckott/serrano'
|
17
18
|
s.licenses = 'MIT'
|
18
19
|
|
19
|
-
s.files = `git ls-files -z`.split("\x0").reject
|
20
|
-
|
20
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
21
|
+
f.match(%r{^(test|spec|features)/})
|
22
|
+
end
|
23
|
+
s.require_paths = ['lib']
|
21
24
|
|
22
25
|
s.bindir = 'bin'
|
23
26
|
s.executables = ['serrano']
|
24
27
|
|
25
|
-
s.add_development_dependency 'bundler', '~>
|
26
|
-
s.add_development_dependency 'rake', '~> 12.0', '>= 12.0.0'
|
27
|
-
s.add_development_dependency 'test-unit', '~> 3.2', '>= 3.2.1'
|
28
|
-
s.add_development_dependency 'simplecov', '~> 0.14.1'
|
28
|
+
s.add_development_dependency 'bundler', '~> 2.0', '>= 2.0.2'
|
29
29
|
s.add_development_dependency 'codecov', '~> 0.1.10'
|
30
|
-
s.add_development_dependency 'json', '~> 2.
|
31
|
-
s.add_development_dependency '
|
32
|
-
s.add_development_dependency '
|
30
|
+
s.add_development_dependency 'json', '~> 2.1'
|
31
|
+
s.add_development_dependency 'rake', '>= 12.3.1', '~> 13.0'
|
32
|
+
s.add_development_dependency 'rubocop', '~> 0.84.0'
|
33
|
+
s.add_development_dependency 'simplecov', '~> 0.18.5'
|
34
|
+
s.add_development_dependency 'test-unit', '~> 3.2', '>= 3.2.7'
|
35
|
+
s.add_development_dependency 'vcr', '~> 6.0'
|
36
|
+
s.add_development_dependency 'webmock', '~> 3.4', '>= 3.4.1'
|
37
|
+
|
38
|
+
s.add_runtime_dependency 'faraday', '~> 1.0', '>= 1.0.1'
|
39
|
+
s.add_runtime_dependency 'faraday_middleware', '~> 1.0'
|
40
|
+
s.add_runtime_dependency 'multi_json', '~> 1.13', '>= 1.13.1'
|
41
|
+
s.add_runtime_dependency 'thor', '>= 0.20', '< 1.1'
|
33
42
|
|
34
|
-
s.
|
35
|
-
|
36
|
-
|
37
|
-
|
43
|
+
s.metadata = {
|
44
|
+
'homepage_uri' => 'https://github.com/sckott/serrano',
|
45
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/serrano',
|
46
|
+
'changelog_uri' =>
|
47
|
+
"https://github.com/sckott/serrano/releases/tag/v#{s.version}",
|
48
|
+
'source_code_uri' => 'https://github.com/sckott/serrano',
|
49
|
+
'bug_tracker_uri' => 'https://github.com/sckott/serrano/issues'
|
50
|
+
}
|
38
51
|
end
|