serrano 1.0.0 → 1.6
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 +4 -4
- data/.github/dependabot.yml +22 -0
- data/.github/workflows/ruby.yml +16 -16
- data/CHANGELOG.md +10 -0
- data/LICENSE +1 -1
- data/README.md +11 -10
- data/Rakefile +5 -0
- data/lib/serrano/cnrequest.rb +5 -19
- data/lib/serrano/faraday.rb +53 -51
- data/lib/serrano/filterhandler.rb +9 -4
- data/lib/serrano/request.rb +8 -12
- data/lib/serrano/request_cursor.rb +9 -14
- data/lib/serrano/styles.rb +2 -2
- data/lib/serrano/utils.rb +2 -2
- data/lib/serrano/version.rb +1 -1
- data/lib/serrano.rb +7 -18
- data/serrano.gemspec +15 -15
- metadata +67 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b5e125bb4a2745b6dbf520ad692df6817c0e2dc7d6db1ed307bdee243e9c501
|
4
|
+
data.tar.gz: 680c37e478abc9c5213ea7a6db288a3afa9e9f71140e796a7fc5cdb88ef27517
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82e9496fa1a0737ef3f491f199792c9b8e99a7c90d285a340108014e4a877ab8e38f79bde1d9a95f9999cef262e642a099f433a1ec2441537d677c6ec4ab1b58
|
7
|
+
data.tar.gz: 5ab1e3c2900d546894d0798014cd649b6b5d35e07c69b16565158fa7a4492c8dbdc13be81a7414517395be42b409875b309e232e95d80571398e7f0c0e597873
|
@@ -0,0 +1,22 @@
|
|
1
|
+
version: 2
|
2
|
+
updates:
|
3
|
+
- package-ecosystem: bundler
|
4
|
+
directory: "/"
|
5
|
+
schedule:
|
6
|
+
interval: weekly
|
7
|
+
time: "13:00"
|
8
|
+
open-pull-requests-limit: 10
|
9
|
+
ignore:
|
10
|
+
- dependency-name: codecov
|
11
|
+
versions:
|
12
|
+
- "> 0.1.17, < 0.2"
|
13
|
+
- dependency-name: codecov
|
14
|
+
versions:
|
15
|
+
- "> 0.2.1, < 0.3"
|
16
|
+
- dependency-name: codecov
|
17
|
+
versions:
|
18
|
+
- 0.4.2
|
19
|
+
- 0.4.3
|
20
|
+
- dependency-name: simplecov
|
21
|
+
versions:
|
22
|
+
- 0.20.0
|
data/.github/workflows/ruby.yml
CHANGED
@@ -2,29 +2,29 @@ name: Ruby
|
|
2
2
|
|
3
3
|
on:
|
4
4
|
push:
|
5
|
-
branches: [
|
5
|
+
branches: [main]
|
6
6
|
pull_request:
|
7
|
-
branches: [
|
7
|
+
branches: [main]
|
8
8
|
|
9
9
|
jobs:
|
10
10
|
test:
|
11
11
|
strategy:
|
12
12
|
fail-fast: false
|
13
13
|
matrix:
|
14
|
-
|
15
|
-
|
16
|
-
runs-on: ${{ matrix.os }}
|
14
|
+
ruby: [3.0, 3.1, 3.2, 3.3, 3.4]
|
15
|
+
runs-on: ubuntu-latest
|
17
16
|
env:
|
18
17
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
19
18
|
steps:
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
19
|
+
- uses: actions/checkout@v4
|
20
|
+
- name: Setup Ruby
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: ${{ matrix.ruby }}
|
24
|
+
bundler-cache: true
|
25
|
+
- name: Install dependencies
|
26
|
+
run: bundle install
|
27
|
+
- name: Run tests
|
28
|
+
run: |
|
29
|
+
bundle exec rake install
|
30
|
+
bundle exec rake test TESTOPTS="-v"
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 1.6 (2025-06-17)
|
2
|
+
|
3
|
+
* Fixed filter handling so that the same filter can be used multiple times (#176)
|
4
|
+
|
5
|
+
## 1.4 (2022-03-26)
|
6
|
+
|
7
|
+
* Moved to faraday > v2. There's no user facing changes here, but let me know if any issues arise (#172)
|
8
|
+
* PR by @LocoDelAssembly fixes `Serrano.content_negotiation(format: "citeproc-json")` by having it return `nil` instead of `Resource not found` when no DOI is found, so that the output is more compatible with flows that use serrano to create JSON (#169)
|
9
|
+
* PR by @xuanxu adds `REXML` as a runtime dependency (#159)
|
10
|
+
|
1
11
|
## 1.0.0 (2020-10-19)
|
2
12
|
|
3
13
|
* updated dependency versions
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (C)
|
1
|
+
Copyright (C) 2025 Scott Chamberlain
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
4
|
|
data/README.md
CHANGED
@@ -2,21 +2,21 @@ serrano
|
|
2
2
|
=========
|
3
3
|
|
4
4
|
[](https://rubygems.org/gems/serrano)
|
5
|
-
[](https://github.com/sckott/serrano/actions/workflows/ruby.yml)
|
6
|
+
[](https://codecov.io/github/sckott/serrano?branch=main)
|
7
|
+
[](https://zenodo.org/badge/latestdoi/2600/sckott/serrano)
|
8
8
|
[](https://github.com/testdouble/standard)
|
9
9
|
|
10
10
|
`serrano` is a low level client for Crossref APIs
|
11
11
|
|
12
|
-
Docs: https://www.rubydoc.info/gems/serrano
|
12
|
+
Docs: <https://www.rubydoc.info/gems/serrano>
|
13
13
|
|
14
14
|
Other Crossref API clients:
|
15
15
|
|
16
16
|
- Python: [habanero](https://github.com/sckott/habanero)
|
17
17
|
- R: [rcrossref](https://github.com/ropensci/rcrossref)
|
18
18
|
|
19
|
-
Crossref's API issue tracker: https://
|
19
|
+
Crossref's API issue tracker: <https://crossref.atlassian.net/jira/software/c/projects/CR/issues>
|
20
20
|
|
21
21
|
## Changes
|
22
22
|
|
@@ -47,7 +47,7 @@ Other methods:
|
|
47
47
|
|
48
48
|
Note about searching:
|
49
49
|
|
50
|
-
You are using the Crossref search API described at https://
|
50
|
+
You are using the Crossref search API described at https://api.crossref.org When you search with query terms, on Crossref servers they are not searching full text, or even abstracts of articles, but only what is available in the data that is returned to you. That is, they search article titles, authors, etc. For some discussion on this, see https://gitlab.com/crossref/issues/issues/101
|
51
51
|
|
52
52
|
Rate limits:
|
53
53
|
|
@@ -184,6 +184,8 @@ Commands:
|
|
184
184
|
|
185
185
|
# Many DOIs
|
186
186
|
~$ serrano works "10.1007/12080.1874-1746,10.1007/10452.1573-5125"
|
187
|
+
## if above two dois in a file called dois.txt
|
188
|
+
~$ cat dois.txt | xargs -I{} serrano works {}
|
187
189
|
|
188
190
|
# output JSON, then parse with e.g., jq
|
189
191
|
~$ serrano works --filter=has_orcid:true --json --limit=2 | jq '.message.items[].author[].ORCID | select(. != null)'
|
@@ -194,9 +196,8 @@ Commands:
|
|
194
196
|
* Please note that this project is released with a [Contributor Code of Conduct](CONDUCT.md). By participating in this project you agree to abide by its terms.
|
195
197
|
* License: MIT
|
196
198
|
|
197
|
-
[crapi]: https://
|
199
|
+
[crapi]: https://api.crossref.org/
|
198
200
|
[cn]: https://citation.crosscite.org/docs.html
|
199
|
-
[
|
200
|
-
[ccount]: https://labs.crossref.org/openurl/
|
201
|
+
[ccount]: https://www.crossref.org/documentation/retrieve-metadata/openurl/
|
201
202
|
[csl]: https://github.com/citation-style-language/styles
|
202
|
-
[changelog]: https://github.com/sckott/serrano/blob/
|
203
|
+
[changelog]: https://github.com/sckott/serrano/blob/main/CHANGELOG.md
|
data/Rakefile
CHANGED
data/lib/serrano/cnrequest.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "faraday"
|
4
|
-
require "
|
4
|
+
require "faraday/follow_redirects"
|
5
5
|
require "multi_json"
|
6
6
|
require "serrano/error"
|
7
7
|
require "serrano/utils"
|
@@ -23,7 +23,7 @@ CN_FORMAT_HEADERS = {"rdf-xml" => "application/rdf+xml",
|
|
23
23
|
#
|
24
24
|
# Class to perform HTTP requests to the Crossref API
|
25
25
|
module Serrano
|
26
|
-
class CNRequest
|
26
|
+
class CNRequest # :nodoc:
|
27
27
|
attr_accessor :ids
|
28
28
|
attr_accessor :format
|
29
29
|
attr_accessor :style
|
@@ -47,12 +47,12 @@ module Serrano
|
|
47
47
|
end
|
48
48
|
|
49
49
|
conn = Faraday.new "https://doi.org/" do |c|
|
50
|
-
c.use
|
50
|
+
c.use Faraday::FollowRedirects::Middleware
|
51
51
|
c.adapter :net_http
|
52
52
|
end
|
53
53
|
|
54
54
|
if ids.length == 1
|
55
|
-
self.ids = ids[0] if ids.
|
55
|
+
self.ids = ids[0] if ids.instance_of?(Array)
|
56
56
|
make_request(conn, ids, format, style, locale)
|
57
57
|
else
|
58
58
|
coll = []
|
@@ -87,19 +87,5 @@ def make_request(conn, ids, format, style, locale)
|
|
87
87
|
}
|
88
88
|
end
|
89
89
|
|
90
|
-
res.body
|
90
|
+
res.body if res.success?
|
91
91
|
end
|
92
|
-
|
93
|
-
# parser <- cn_types[[self.format]]
|
94
|
-
# if (raw) {
|
95
|
-
# content(response, "text")
|
96
|
-
# } else {
|
97
|
-
# out <- content(response, "parsed", parser, "UTF-8")
|
98
|
-
# if (format == "text") {
|
99
|
-
# out <- gsub("\n", "", out)
|
100
|
-
# }
|
101
|
-
# if (format == "bibentry") {
|
102
|
-
# out <- parse_bibtex(out)
|
103
|
-
# }
|
104
|
-
# out
|
105
|
-
# }
|
data/lib/serrano/faraday.rb
CHANGED
@@ -4,69 +4,71 @@ require "faraday"
|
|
4
4
|
require "multi_json"
|
5
5
|
|
6
6
|
# @private
|
7
|
-
module
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
7
|
+
module Faraday
|
8
|
+
module SerranoErrors
|
9
|
+
# @private
|
10
|
+
class Middleware < Faraday::Middleware
|
11
|
+
def call(env)
|
12
|
+
@app.call(env).on_complete do |response|
|
13
|
+
case response[:status].to_i
|
14
|
+
when 400
|
15
|
+
raise Serrano::BadRequest, error_message_400(response)
|
16
|
+
when 404
|
17
|
+
raise Serrano::NotFound, error_message_400(response)
|
18
|
+
when 500
|
19
|
+
raise Serrano::InternalServerError, error_message_500(response, "Something is technically wrong.")
|
20
|
+
when 502
|
21
|
+
raise Serrano::BadGateway, error_message_500(response, "The server returned an invalid or incomplete response.")
|
22
|
+
when 503
|
23
|
+
raise Serrano::ServiceUnavailable, error_message_500(response, "Crossref is rate limiting your requests.")
|
24
|
+
when 504
|
25
|
+
raise Serrano::GatewayTimeout, error_message_500(response, "504 Gateway Time-out")
|
26
|
+
end
|
25
27
|
end
|
26
28
|
end
|
27
|
-
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def initialize(app)
|
31
|
+
super
|
32
|
+
@parser = nil
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
+
private
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
def error_message_400(response)
|
38
|
+
"\n #{response[:method].to_s.upcase} #{response[:url]}\n Status #{response[:status]}#{error_body(response[:body])}"
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
def error_body(body)
|
42
|
+
if !body.nil? && !body.empty? && body.is_a?(String)
|
43
|
+
if json?(body)
|
44
|
+
body = ::MultiJson.load(body)
|
45
|
+
if body["message"].nil?
|
46
|
+
body = nil
|
47
|
+
elseif body["message"].length == 1
|
48
|
+
body = body["message"]
|
49
|
+
else
|
50
|
+
body = body["message"].collect { |x| x["message"] }.join("; ")
|
51
|
+
end
|
50
52
|
end
|
51
53
|
end
|
52
|
-
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
if body.nil?
|
56
|
+
nil
|
57
|
+
else
|
58
|
+
": #{body}"
|
59
|
+
end
|
58
60
|
end
|
59
|
-
end
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
def error_message_500(response, body = nil)
|
63
|
+
"#{response[:method].to_s.upcase} #{response[:url]}: #{[response[:status].to_s + ":", body].compact.join(" ")}"
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
def json?(string)
|
67
|
+
MultiJson.load(string)
|
68
|
+
true
|
69
|
+
rescue MultiJson::ParseError
|
70
|
+
false
|
71
|
+
end
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|
@@ -37,8 +37,13 @@ module Helpers
|
|
37
37
|
|
38
38
|
newnn = nn.collect { |m| m.tr("_", "-") }
|
39
39
|
x = rename_keys(x, newnn)
|
40
|
-
x.collect { |k, v|
|
41
|
-
|
40
|
+
x.collect { |k, v|
|
41
|
+
if v.is_a?(Array)
|
42
|
+
v.map { |val| [k, val].join(":") }
|
43
|
+
else
|
44
|
+
[k, v].join(":")
|
45
|
+
end
|
46
|
+
}.join(",")
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
@@ -52,11 +57,11 @@ module Helpers
|
|
52
57
|
end
|
53
58
|
|
54
59
|
module Serrano
|
55
|
-
class Request
|
60
|
+
class Request # :nodoc:
|
56
61
|
include Helpers
|
57
62
|
end
|
58
63
|
|
59
|
-
class RequestCursor
|
64
|
+
class RequestCursor # :nodoc:
|
60
65
|
include Helpers
|
61
66
|
end
|
62
67
|
end
|
data/lib/serrano/request.rb
CHANGED
@@ -12,7 +12,7 @@ require "serrano/helpers/configuration"
|
|
12
12
|
#
|
13
13
|
# Class to perform HTTP requests to the Crossref API
|
14
14
|
module Serrano
|
15
|
-
class Request
|
15
|
+
class Request # :nodoc:
|
16
16
|
attr_accessor :endpt
|
17
17
|
attr_accessor :id
|
18
18
|
attr_accessor :query
|
@@ -32,7 +32,6 @@ module Serrano
|
|
32
32
|
def initialize(endpt, id, query, filter, offset,
|
33
33
|
limit, sample, sort, order, facet, select,
|
34
34
|
works, agency, options, verbose)
|
35
|
-
|
36
35
|
self.endpt = endpt
|
37
36
|
self.id = id
|
38
37
|
self.query = query
|
@@ -53,24 +52,21 @@ module Serrano
|
|
53
52
|
def perform
|
54
53
|
filt = filter_handler(filter)
|
55
54
|
|
56
|
-
self.select = select.join(",")
|
55
|
+
self.select = select&.instance_of?(Array) ? select.join(",") : select
|
57
56
|
|
58
|
-
args = {query: query, filter: filt, offset: offset,
|
59
|
-
|
60
|
-
order: order, facet: facet,
|
57
|
+
args = {query: query, filter: filt, offset: offset, rows: limit,
|
58
|
+
sample: sample, sort: sort, order: order, facet: facet,
|
61
59
|
select: select}
|
62
60
|
opts = args.delete_if { |_k, v| v.nil? }
|
63
61
|
|
64
62
|
conn = if verbose
|
65
|
-
Faraday.new(url: Serrano.base_url, request: options ||
|
63
|
+
Faraday.new(url: Serrano.base_url, request: options || {}) do |f|
|
66
64
|
f.response :logger
|
67
|
-
f.use
|
68
|
-
f.adapter Faraday.default_adapter
|
65
|
+
f.use Faraday::SerranoErrors::Middleware
|
69
66
|
end
|
70
67
|
else
|
71
|
-
Faraday.new(url: Serrano.base_url, request: options ||
|
72
|
-
f.use
|
73
|
-
f.adapter Faraday.default_adapter
|
68
|
+
Faraday.new(url: Serrano.base_url, request: options || {}) do |f|
|
69
|
+
f.use Faraday::SerranoErrors::Middleware
|
74
70
|
end
|
75
71
|
end
|
76
72
|
|
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
require "erb"
|
4
4
|
require "faraday"
|
5
|
-
require "faraday_middleware"
|
6
5
|
require "multi_json"
|
7
6
|
require "serrano/error"
|
8
7
|
require "serrano/helpers/configuration"
|
9
8
|
require "serrano/filterhandler"
|
10
|
-
require "serrano/error"
|
11
9
|
require "serrano/faraday"
|
12
10
|
require "serrano/utils"
|
13
11
|
|
@@ -16,7 +14,7 @@ require "serrano/utils"
|
|
16
14
|
#
|
17
15
|
# Class to perform HTTP requests to the Crossref API
|
18
16
|
module Serrano
|
19
|
-
class RequestCursor
|
17
|
+
class RequestCursor # :nodoc:
|
20
18
|
attr_accessor :endpt
|
21
19
|
attr_accessor :id
|
22
20
|
attr_accessor :query
|
@@ -40,7 +38,6 @@ module Serrano
|
|
40
38
|
limit, sample, sort, order, facet, select,
|
41
39
|
works, agency, options, verbose, cursor,
|
42
40
|
cursor_max, args)
|
43
|
-
|
44
41
|
self.endpt = endpt
|
45
42
|
self.id = id
|
46
43
|
self.query = query
|
@@ -64,7 +61,7 @@ module Serrano
|
|
64
61
|
def perform
|
65
62
|
filt = filter_handler(filter)
|
66
63
|
fieldqueries = field_query_handler(args)
|
67
|
-
self.select = select.join(",")
|
64
|
+
self.select = select&.instance_of?(Array) ? select.join(",") : select
|
68
65
|
|
69
66
|
unless cursor_max.class.nil?
|
70
67
|
raise "cursor_max must be of class int" unless cursor_max.is_a?(Integer)
|
@@ -78,15 +75,13 @@ module Serrano
|
|
78
75
|
opts = arguments.delete_if { |_k, v| v.nil? }
|
79
76
|
|
80
77
|
conn = if verbose
|
81
|
-
Faraday.new(url: Serrano.base_url, request: options ||
|
78
|
+
Faraday.new(url: Serrano.base_url, request: options || {}) do |f|
|
82
79
|
f.response :logger
|
83
|
-
f.use
|
84
|
-
f.adapter Faraday.default_adapter
|
80
|
+
f.use Faraday::SerranoErrors::Middleware
|
85
81
|
end
|
86
82
|
else
|
87
|
-
Faraday.new(url: Serrano.base_url, request: options ||
|
88
|
-
f.use
|
89
|
-
f.adapter Faraday.default_adapter
|
83
|
+
Faraday.new(url: Serrano.base_url, request: options || {}) do |f|
|
84
|
+
f.use Faraday::SerranoErrors::Middleware
|
90
85
|
end
|
91
86
|
end
|
92
87
|
|
@@ -98,7 +93,7 @@ module Serrano
|
|
98
93
|
js = _req(conn, endpt, opts)
|
99
94
|
cu = js["message"]["next-cursor"]
|
100
95
|
max_avail = js["message"]["total-results"]
|
101
|
-
_redo_req(conn, js, opts, cu, max_avail)
|
96
|
+
_redo_req(conn, js, opts, cu, max_avail, endpt2)
|
102
97
|
|
103
98
|
else
|
104
99
|
self.id = Array(id)
|
@@ -119,13 +114,13 @@ module Serrano
|
|
119
114
|
js = _req(conn, endpt2, opts)
|
120
115
|
cu = js["message"]["next-cursor"]
|
121
116
|
max_avail = js["message"]["total-results"]
|
122
|
-
coll << _redo_req(conn, js, opts, cu, max_avail)
|
117
|
+
coll << _redo_req(conn, js, opts, cu, max_avail, endpt2)
|
123
118
|
end
|
124
119
|
coll
|
125
120
|
end
|
126
121
|
end
|
127
122
|
|
128
|
-
def _redo_req(conn, js, opts, cu, max_avail)
|
123
|
+
def _redo_req(conn, js, opts, cu, max_avail, endpt2)
|
129
124
|
if !cu.nil? && (cursor_max > js["message"]["items"].length)
|
130
125
|
res = [js]
|
131
126
|
total = js["message"]["items"].length
|
data/lib/serrano/styles.rb
CHANGED
@@ -6,8 +6,8 @@ require "multi_json"
|
|
6
6
|
def fetch_styles
|
7
7
|
base = "https://api.github.com/repos/citation-style-language/styles"
|
8
8
|
conn = Faraday.new(url: base) { |f|
|
9
|
-
f.use
|
10
|
-
f.adapter Faraday.default_adapter
|
9
|
+
f.use Faraday::Response::RaiseError
|
10
|
+
# f.adapter Faraday.default_adapter
|
11
11
|
}
|
12
12
|
args = {per_page: 1}
|
13
13
|
tt = conn.get "commits", args
|
data/lib/serrano/utils.rb
CHANGED
@@ -24,12 +24,12 @@ end
|
|
24
24
|
|
25
25
|
class Hash
|
26
26
|
def tostrings
|
27
|
-
|
27
|
+
map { |(k, v)| [k.to_s, v] }.to_h
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
class Hash
|
32
32
|
def tosymbols
|
33
|
-
|
33
|
+
map { |(k, v)| [k.to_sym, v] }.to_h
|
34
34
|
end
|
35
35
|
end
|
data/lib/serrano/version.rb
CHANGED
data/lib/serrano.rb
CHANGED
@@ -42,8 +42,7 @@ require "rexml/xpath"
|
|
42
42
|
# @param cursor [String] Cursor character string to do deep paging. Default is `nil`.
|
43
43
|
# Pass in '*' to start deep paging. Any combination of query, filters and facets may be
|
44
44
|
# used with deep paging cursors. While limit may be specified along with cursor, offset
|
45
|
-
# and sample cannot be used. See
|
46
|
-
# https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md#deep-paging-with-cursors
|
45
|
+
# and sample cannot be used. See https://api.crossref.org/
|
47
46
|
# @param cursor_max [Fixnum] Max records to retrieve. Only used when cursor
|
48
47
|
# param used. Because deep paging can result in continuous requests until all
|
49
48
|
# are retrieved, use this parameter to set a maximum number of records. Of course,
|
@@ -63,8 +62,7 @@ require "rexml/xpath"
|
|
63
62
|
# - oauth [Hash] A hash with OAuth details
|
64
63
|
|
65
64
|
# @!macro field_queries
|
66
|
-
# @param [Hash<Object>] args Field queries, as named parameters. See
|
67
|
-
# https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md#field-queries
|
65
|
+
# @param [Hash<Object>] args Field queries, as named parameters. See https://api.crossref.org/
|
68
66
|
# Field query parameters mut be named, and must start with `query_`. Any dashes or
|
69
67
|
# periods should be replaced with underscores. The options include:
|
70
68
|
# - query_container_title: Query container-title aka. publication name
|
@@ -99,18 +97,16 @@ require "rexml/xpath"
|
|
99
97
|
# For example, if you want to inspect headers returned from the HTTP request,
|
100
98
|
# and parse the raw result in any way you wish.
|
101
99
|
#
|
102
|
-
# @see https://
|
103
|
-
# detailed description of the Crossref API
|
100
|
+
# @see https://api.crossref.org for detailed description of the Crossref API
|
104
101
|
#
|
105
102
|
# What am I actually searching when using the Crossref search API?
|
106
103
|
#
|
107
|
-
# You are using the Crossref search API described at
|
108
|
-
# https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md.
|
104
|
+
# You are using the Crossref search API described at https://api.crossref.org
|
109
105
|
# When you search with query terms, on Crossref servers they are not
|
110
106
|
# searching full text, or even abstracts of articles, but only what is
|
111
107
|
# available in the data that is returned to you. That is, they search
|
112
108
|
# article titles, authors, etc. For some discussion on this, see
|
113
|
-
# https://gitlab.com/crossref/issues
|
109
|
+
# https://gitlab.com/crossref/issues/-/issues/101
|
114
110
|
#
|
115
111
|
#
|
116
112
|
# The Polite Pool
|
@@ -232,7 +228,6 @@ module Serrano
|
|
232
228
|
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
233
229
|
select: nil, options: nil, verbose: false, cursor: nil,
|
234
230
|
cursor_max: 5000, **args)
|
235
|
-
|
236
231
|
assert_valid_filters(filter) if filter
|
237
232
|
RequestCursor.new("works", ids, query, filter, offset,
|
238
233
|
limit, sample, sort, order, facet, select, nil, nil, options,
|
@@ -289,7 +284,6 @@ module Serrano
|
|
289
284
|
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
290
285
|
select: nil, works: false, options: nil, verbose: false,
|
291
286
|
cursor: nil, cursor_max: 5000, **args)
|
292
|
-
|
293
287
|
assert_valid_filters(filter) if filter
|
294
288
|
RequestCursor.new("members", ids, query, filter, offset,
|
295
289
|
limit, sample, sort, order, facet, select, works, nil,
|
@@ -337,7 +331,6 @@ module Serrano
|
|
337
331
|
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
338
332
|
select: nil, works: false, options: nil, verbose: false,
|
339
333
|
cursor: nil, cursor_max: 5000, **args)
|
340
|
-
|
341
334
|
assert_valid_filters(filter) if filter
|
342
335
|
RequestCursor.new("prefixes", ids, nil, filter, offset,
|
343
336
|
limit, sample, sort, order, facet, select, works, nil,
|
@@ -390,7 +383,6 @@ module Serrano
|
|
390
383
|
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
391
384
|
select: nil, works: false, options: nil, verbose: false,
|
392
385
|
cursor: nil, cursor_max: 5000, **args)
|
393
|
-
|
394
386
|
assert_valid_filters(filter) if filter
|
395
387
|
RequestCursor.new("funders", ids, query, filter, offset,
|
396
388
|
limit, sample, sort, order, facet, select, works, nil, options,
|
@@ -443,7 +435,6 @@ module Serrano
|
|
443
435
|
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
444
436
|
select: nil, works: false, options: nil, verbose: false,
|
445
437
|
cursor: nil, cursor_max: 5000, **args)
|
446
|
-
|
447
438
|
assert_valid_filters(filter) if filter
|
448
439
|
RequestCursor.new("journals", ids, query, filter, offset,
|
449
440
|
limit, sample, sort, order, facet, select, works, nil, options,
|
@@ -486,7 +477,6 @@ module Serrano
|
|
486
477
|
# Serrano.types(ids: "journal", works: true, select: ['DOI', 'title'], limit: 3)
|
487
478
|
def self.types(ids: nil, offset: nil, limit: nil, select: nil, works: false,
|
488
479
|
options: nil, verbose: false, cursor: nil, cursor_max: 5000, **args)
|
489
|
-
|
490
480
|
RequestCursor.new("types", ids, nil, nil, offset,
|
491
481
|
limit, nil, nil, nil, nil, select, works, nil, options,
|
492
482
|
verbose, cursor, cursor_max, args).perform
|
@@ -527,7 +517,6 @@ module Serrano
|
|
527
517
|
def self.licenses(query: nil, offset: nil,
|
528
518
|
limit: nil, sample: nil, sort: nil, order: nil,
|
529
519
|
facet: nil, options: nil, verbose: false)
|
530
|
-
|
531
520
|
Request.new("licenses", nil, query, nil, offset,
|
532
521
|
limit, sample, sort, order, facet, nil, nil, nil, options, verbose).perform
|
533
522
|
end
|
@@ -643,7 +632,8 @@ module Serrano
|
|
643
632
|
# @param url [String] the API url for the function (should be left to default)
|
644
633
|
# @param key [String] your API key
|
645
634
|
#
|
646
|
-
# @see
|
635
|
+
# @see https://www.crossref.org/documentation/retrieve-metadata/openurl/ for
|
636
|
+
# more info on this Crossref API service.
|
647
637
|
#
|
648
638
|
# @example
|
649
639
|
# require 'serrano'
|
@@ -653,7 +643,6 @@ module Serrano
|
|
653
643
|
# Serrano.citation_count(doi: "10.1016/j.fbr.2012")
|
654
644
|
def self.citation_count(doi:, url: "https://www.crossref.org/openurl/",
|
655
645
|
key: "cboettig@ropensci.org", options: nil)
|
656
|
-
|
657
646
|
args = {id: "doi:" + doi, pid: key, noredirect: true}
|
658
647
|
opts = args.delete_if { |_k, v| v.nil? }
|
659
648
|
conn = Faraday.new(url: url, request: options)
|
data/serrano.gemspec
CHANGED
@@ -8,8 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.name = "serrano"
|
9
9
|
s.version = Serrano::VERSION
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
|
-
s.required_ruby_version = ">=
|
12
|
-
s.date = "2020-10-19"
|
11
|
+
s.required_ruby_version = ">= 3.0"
|
13
12
|
s.summary = "Crossref Client"
|
14
13
|
s.description = "Low Level Ruby Client for the Crossref Search API"
|
15
14
|
s.authors = "Scott Chamberlain"
|
@@ -25,20 +24,21 @@ Gem::Specification.new do |s|
|
|
25
24
|
s.bindir = "bin"
|
26
25
|
s.executables = ["serrano"]
|
27
26
|
|
28
|
-
s.add_development_dependency "bundler",
|
29
|
-
s.add_development_dependency "codecov", "~> 0.
|
30
|
-
s.add_development_dependency "json",
|
31
|
-
s.add_development_dependency "rake",
|
32
|
-
s.add_development_dependency "standard", "~> 0
|
33
|
-
s.add_development_dependency "simplecov", "~> 0.
|
34
|
-
s.add_development_dependency "test-unit",
|
35
|
-
s.add_development_dependency "vcr", "~> 6.
|
36
|
-
s.add_development_dependency "webmock",
|
27
|
+
s.add_development_dependency "bundler", "~> 2.1", ">= 2.1.4"
|
28
|
+
s.add_development_dependency "codecov", "~> 0.5.0"
|
29
|
+
s.add_development_dependency "json", "~> 2.3", ">= 2.3.1"
|
30
|
+
s.add_development_dependency "rake", "~> 13.0", ">= 13.0.1"
|
31
|
+
s.add_development_dependency "standard", "~> 1.0"
|
32
|
+
s.add_development_dependency "simplecov", "~> 0.21.2"
|
33
|
+
s.add_development_dependency "test-unit", "~> 3.3", ">= 3.3.6"
|
34
|
+
s.add_development_dependency "vcr", "~> 6.3", ">= 6.3.1"
|
35
|
+
s.add_development_dependency "webmock", "~> 3.25", ">= 3.25.1"
|
37
36
|
|
38
|
-
s.add_runtime_dependency "faraday", "~>
|
39
|
-
s.add_runtime_dependency "
|
40
|
-
s.add_runtime_dependency "multi_json",
|
41
|
-
s.add_runtime_dependency
|
37
|
+
s.add_runtime_dependency "faraday", "~> 2.13", ">= 2.13.1"
|
38
|
+
s.add_runtime_dependency "faraday-follow_redirects", ">= 0.1", "< 0.4"
|
39
|
+
s.add_runtime_dependency "multi_json", "~> 1.15"
|
40
|
+
s.add_runtime_dependency "rexml", "~> 3.2", ">= 3.2.5"
|
41
|
+
s.add_runtime_dependency "thor", "~> 1.2", ">= 1.2.1"
|
42
42
|
|
43
43
|
s.metadata = {
|
44
44
|
"homepage_uri" => "https://github.com/sckott/serrano",
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.6'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Chamberlain
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: bundler
|
@@ -36,14 +35,14 @@ dependencies:
|
|
36
35
|
requirements:
|
37
36
|
- - "~>"
|
38
37
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.
|
38
|
+
version: 0.5.0
|
40
39
|
type: :development
|
41
40
|
prerelease: false
|
42
41
|
version_requirements: !ruby/object:Gem::Requirement
|
43
42
|
requirements:
|
44
43
|
- - "~>"
|
45
44
|
- !ruby/object:Gem::Version
|
46
|
-
version: 0.
|
45
|
+
version: 0.5.0
|
47
46
|
- !ruby/object:Gem::Dependency
|
48
47
|
name: json
|
49
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,28 +89,28 @@ dependencies:
|
|
90
89
|
requirements:
|
91
90
|
- - "~>"
|
92
91
|
- !ruby/object:Gem::Version
|
93
|
-
version: '0
|
92
|
+
version: '1.0'
|
94
93
|
type: :development
|
95
94
|
prerelease: false
|
96
95
|
version_requirements: !ruby/object:Gem::Requirement
|
97
96
|
requirements:
|
98
97
|
- - "~>"
|
99
98
|
- !ruby/object:Gem::Version
|
100
|
-
version: '0
|
99
|
+
version: '1.0'
|
101
100
|
- !ruby/object:Gem::Dependency
|
102
101
|
name: simplecov
|
103
102
|
requirement: !ruby/object:Gem::Requirement
|
104
103
|
requirements:
|
105
104
|
- - "~>"
|
106
105
|
- !ruby/object:Gem::Version
|
107
|
-
version: 0.
|
106
|
+
version: 0.21.2
|
108
107
|
type: :development
|
109
108
|
prerelease: false
|
110
109
|
version_requirements: !ruby/object:Gem::Requirement
|
111
110
|
requirements:
|
112
111
|
- - "~>"
|
113
112
|
- !ruby/object:Gem::Version
|
114
|
-
version: 0.
|
113
|
+
version: 0.21.2
|
115
114
|
- !ruby/object:Gem::Dependency
|
116
115
|
name: test-unit
|
117
116
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,62 +137,80 @@ dependencies:
|
|
138
137
|
requirements:
|
139
138
|
- - "~>"
|
140
139
|
- !ruby/object:Gem::Version
|
141
|
-
version: '6.
|
140
|
+
version: '6.3'
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: 6.3.1
|
142
144
|
type: :development
|
143
145
|
prerelease: false
|
144
146
|
version_requirements: !ruby/object:Gem::Requirement
|
145
147
|
requirements:
|
146
148
|
- - "~>"
|
147
149
|
- !ruby/object:Gem::Version
|
148
|
-
version: '6.
|
150
|
+
version: '6.3'
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 6.3.1
|
149
154
|
- !ruby/object:Gem::Dependency
|
150
155
|
name: webmock
|
151
156
|
requirement: !ruby/object:Gem::Requirement
|
152
157
|
requirements:
|
153
158
|
- - "~>"
|
154
159
|
- !ruby/object:Gem::Version
|
155
|
-
version: '3.
|
160
|
+
version: '3.25'
|
156
161
|
- - ">="
|
157
162
|
- !ruby/object:Gem::Version
|
158
|
-
version: 3.
|
163
|
+
version: 3.25.1
|
159
164
|
type: :development
|
160
165
|
prerelease: false
|
161
166
|
version_requirements: !ruby/object:Gem::Requirement
|
162
167
|
requirements:
|
163
168
|
- - "~>"
|
164
169
|
- !ruby/object:Gem::Version
|
165
|
-
version: '3.
|
170
|
+
version: '3.25'
|
166
171
|
- - ">="
|
167
172
|
- !ruby/object:Gem::Version
|
168
|
-
version: 3.
|
173
|
+
version: 3.25.1
|
169
174
|
- !ruby/object:Gem::Dependency
|
170
175
|
name: faraday
|
171
176
|
requirement: !ruby/object:Gem::Requirement
|
172
177
|
requirements:
|
173
178
|
- - "~>"
|
174
179
|
- !ruby/object:Gem::Version
|
175
|
-
version: '
|
180
|
+
version: '2.13'
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: 2.13.1
|
176
184
|
type: :runtime
|
177
185
|
prerelease: false
|
178
186
|
version_requirements: !ruby/object:Gem::Requirement
|
179
187
|
requirements:
|
180
188
|
- - "~>"
|
181
189
|
- !ruby/object:Gem::Version
|
182
|
-
version: '
|
190
|
+
version: '2.13'
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: 2.13.1
|
183
194
|
- !ruby/object:Gem::Dependency
|
184
|
-
name:
|
195
|
+
name: faraday-follow_redirects
|
185
196
|
requirement: !ruby/object:Gem::Requirement
|
186
197
|
requirements:
|
187
|
-
- - "
|
198
|
+
- - ">="
|
188
199
|
- !ruby/object:Gem::Version
|
189
|
-
version: '1
|
200
|
+
version: '0.1'
|
201
|
+
- - "<"
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0.4'
|
190
204
|
type: :runtime
|
191
205
|
prerelease: false
|
192
206
|
version_requirements: !ruby/object:Gem::Requirement
|
193
207
|
requirements:
|
194
|
-
- - "
|
208
|
+
- - ">="
|
195
209
|
- !ruby/object:Gem::Version
|
196
|
-
version: '1
|
210
|
+
version: '0.1'
|
211
|
+
- - "<"
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '0.4'
|
197
214
|
- !ruby/object:Gem::Dependency
|
198
215
|
name: multi_json
|
199
216
|
requirement: !ruby/object:Gem::Requirement
|
@@ -208,26 +225,46 @@ dependencies:
|
|
208
225
|
- - "~>"
|
209
226
|
- !ruby/object:Gem::Version
|
210
227
|
version: '1.15'
|
228
|
+
- !ruby/object:Gem::Dependency
|
229
|
+
name: rexml
|
230
|
+
requirement: !ruby/object:Gem::Requirement
|
231
|
+
requirements:
|
232
|
+
- - "~>"
|
233
|
+
- !ruby/object:Gem::Version
|
234
|
+
version: '3.2'
|
235
|
+
- - ">="
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: 3.2.5
|
238
|
+
type: :runtime
|
239
|
+
prerelease: false
|
240
|
+
version_requirements: !ruby/object:Gem::Requirement
|
241
|
+
requirements:
|
242
|
+
- - "~>"
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
version: '3.2'
|
245
|
+
- - ">="
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: 3.2.5
|
211
248
|
- !ruby/object:Gem::Dependency
|
212
249
|
name: thor
|
213
250
|
requirement: !ruby/object:Gem::Requirement
|
214
251
|
requirements:
|
215
252
|
- - "~>"
|
216
253
|
- !ruby/object:Gem::Version
|
217
|
-
version: '1.
|
254
|
+
version: '1.2'
|
218
255
|
- - ">="
|
219
256
|
- !ruby/object:Gem::Version
|
220
|
-
version: 1.
|
257
|
+
version: 1.2.1
|
221
258
|
type: :runtime
|
222
259
|
prerelease: false
|
223
260
|
version_requirements: !ruby/object:Gem::Requirement
|
224
261
|
requirements:
|
225
262
|
- - "~>"
|
226
263
|
- !ruby/object:Gem::Version
|
227
|
-
version: '1.
|
264
|
+
version: '1.2'
|
228
265
|
- - ">="
|
229
266
|
- !ruby/object:Gem::Version
|
230
|
-
version: 1.
|
267
|
+
version: 1.2.1
|
231
268
|
description: Low Level Ruby Client for the Crossref Search API
|
232
269
|
email: myrmecocystus@gmail.com
|
233
270
|
executables:
|
@@ -235,6 +272,7 @@ executables:
|
|
235
272
|
extensions: []
|
236
273
|
extra_rdoc_files: []
|
237
274
|
files:
|
275
|
+
- ".github/dependabot.yml"
|
238
276
|
- ".github/workflows/ruby.yml"
|
239
277
|
- ".gitignore"
|
240
278
|
- CHANGELOG.md
|
@@ -264,10 +302,9 @@ licenses:
|
|
264
302
|
metadata:
|
265
303
|
homepage_uri: https://github.com/sckott/serrano
|
266
304
|
documentation_uri: https://www.rubydoc.info/gems/serrano
|
267
|
-
changelog_uri: https://github.com/sckott/serrano/releases/tag/v1.
|
305
|
+
changelog_uri: https://github.com/sckott/serrano/releases/tag/v1.6
|
268
306
|
source_code_uri: https://github.com/sckott/serrano
|
269
307
|
bug_tracker_uri: https://github.com/sckott/serrano/issues
|
270
|
-
post_install_message:
|
271
308
|
rdoc_options: []
|
272
309
|
require_paths:
|
273
310
|
- lib
|
@@ -275,15 +312,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
275
312
|
requirements:
|
276
313
|
- - ">="
|
277
314
|
- !ruby/object:Gem::Version
|
278
|
-
version: '
|
315
|
+
version: '3.0'
|
279
316
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
317
|
requirements:
|
281
318
|
- - ">="
|
282
319
|
- !ruby/object:Gem::Version
|
283
320
|
version: '0'
|
284
321
|
requirements: []
|
285
|
-
rubygems_version: 3.
|
286
|
-
signing_key:
|
322
|
+
rubygems_version: 3.6.9
|
287
323
|
specification_version: 4
|
288
324
|
summary: Crossref Client
|
289
325
|
test_files: []
|