serrano
Advanced tools
| version: 2 | ||
| updates: | ||
| - package-ecosystem: bundler | ||
| directory: "/" | ||
| schedule: | ||
| interval: daily | ||
| time: "13:00" | ||
| open-pull-requests-limit: 10 | ||
| ignore: | ||
| - dependency-name: codecov | ||
| versions: | ||
| - "> 0.1.17, < 0.2" | ||
| - dependency-name: codecov | ||
| versions: | ||
| - "> 0.2.1, < 0.3" | ||
| - dependency-name: codecov | ||
| versions: | ||
| - 0.4.2 | ||
| - 0.4.3 | ||
| - dependency-name: simplecov | ||
| versions: | ||
| - 0.20.0 |
@@ -5,5 +5,5 @@ name: Ruby | ||
| push: | ||
| branches: [ master ] | ||
| branches: [ main ] | ||
| pull_request: | ||
| branches: [ master ] | ||
| branches: [ main ] | ||
@@ -15,4 +15,4 @@ jobs: | ||
| matrix: | ||
| os: [ ubuntu-latest, macos-latest ] | ||
| ruby: [ 2.5, 2.6, 2.7 ] | ||
| os: [ ubuntu-latest, macos-11 ] | ||
| ruby: [ 2.6, 2.7, 3.0, 3.1 ] | ||
| runs-on: ${{ matrix.os }} | ||
@@ -19,0 +19,0 @@ env: |
+6
-0
@@ -0,1 +1,7 @@ | ||
| ## 1.4 (2022-03-26) | ||
| * Moved to faraday > v2. There's no user facing changes here, but let me know if any issues arise (#172) | ||
| * 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) | ||
| * PR by @xuanxu adds `REXML` as a runtime dependency (#159) | ||
| ## 1.0.0 (2020-10-19) | ||
@@ -2,0 +8,0 @@ |
+7
-10
@@ -45,4 +45,3 @@ # frozen_string_literal: true | ||
| # used with deep paging cursors. While limit may be specified along with cursor, offset | ||
| # and sample cannot be used. See | ||
| # https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md#deep-paging-with-cursors | ||
| # and sample cannot be used. See https://api.crossref.org/ | ||
| # @param cursor_max [Fixnum] Max records to retrieve. Only used when cursor | ||
@@ -67,4 +66,3 @@ # param used. Because deep paging can result in continuous requests until all | ||
| # @!macro field_queries | ||
| # @param [Hash<Object>] args Field queries, as named parameters. See | ||
| # https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md#field-queries | ||
| # @param [Hash<Object>] args Field queries, as named parameters. See https://api.crossref.org/ | ||
| # Field query parameters mut be named, and must start with `query_`. Any dashes or | ||
@@ -104,9 +102,7 @@ # periods should be replaced with underscores. The options include: | ||
| # | ||
| # @see https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md for | ||
| # detailed description of the Crossref API | ||
| # @see https://api.crossref.org for detailed description of the Crossref API | ||
| # | ||
| # What am I actually searching when using the Crossref search API? | ||
| # | ||
| # You are using the Crossref search API described at | ||
| # https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md. | ||
| # 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 | ||
@@ -116,3 +112,3 @@ # searching full text, or even abstracts of articles, but only what is | ||
| # article titles, authors, etc. For some discussion on this, see | ||
| # https://gitlab.com/crossref/issues/issues/101 | ||
| # https://gitlab.com/crossref/issues/-/issues/101 | ||
| # | ||
@@ -650,3 +646,4 @@ # | ||
| # | ||
| # @see http://labs.crossref.org/openurl/ for more info on this Crossref API service. | ||
| # @see https://www.crossref.org/documentation/retrieve-metadata/openurl/ for | ||
| # more info on this Crossref API service. | ||
| # | ||
@@ -653,0 +650,0 @@ # @example |
| # frozen_string_literal: true | ||
| require "faraday" | ||
| require "faraday_middleware" | ||
| require "faraday/follow_redirects" | ||
| require "multi_json" | ||
@@ -26,3 +26,3 @@ require "serrano/error" | ||
| module Serrano | ||
| class CNRequest #:nodoc: | ||
| class CNRequest # :nodoc: | ||
| attr_accessor :ids | ||
@@ -51,3 +51,3 @@ attr_accessor :format | ||
| conn = Faraday.new "https://doi.org/" do |c| | ||
| c.use FaradayMiddleware::FollowRedirects | ||
| c.use Faraday::FollowRedirects::Middleware | ||
| c.adapter :net_http | ||
@@ -57,3 +57,3 @@ end | ||
| if ids.length == 1 | ||
| self.ids = ids[0] if ids.class == Array | ||
| self.ids = ids[0] if ids.instance_of?(Array) | ||
| make_request(conn, ids, format, style, locale) | ||
@@ -93,17 +93,3 @@ else | ||
| res.body | ||
| res.body if res.success? | ||
| end | ||
| # parser <- cn_types[[self.format]] | ||
| # if (raw) { | ||
| # content(response, "text") | ||
| # } else { | ||
| # out <- content(response, "parsed", parser, "UTF-8") | ||
| # if (format == "text") { | ||
| # out <- gsub("\n", "", out) | ||
| # } | ||
| # if (format == "bibentry") { | ||
| # out <- parse_bibtex(out) | ||
| # } | ||
| # out | ||
| # } |
+53
-51
@@ -7,67 +7,69 @@ # frozen_string_literal: true | ||
| # @private | ||
| module FaradayMiddleware | ||
| # @private | ||
| class RaiseHttpException < Faraday::Middleware | ||
| def call(env) | ||
| @app.call(env).on_complete do |response| | ||
| case response[:status].to_i | ||
| when 400 | ||
| raise Serrano::BadRequest, error_message_400(response) | ||
| when 404 | ||
| raise Serrano::NotFound, error_message_400(response) | ||
| when 500 | ||
| raise Serrano::InternalServerError, error_message_500(response, "Something is technically wrong.") | ||
| when 502 | ||
| raise Serrano::BadGateway, error_message_500(response, "The server returned an invalid or incomplete response.") | ||
| when 503 | ||
| raise Serrano::ServiceUnavailable, error_message_500(response, "Crossref is rate limiting your requests.") | ||
| when 504 | ||
| raise Serrano::GatewayTimeout, error_message_500(response, "504 Gateway Time-out") | ||
| module Faraday | ||
| module SerranoErrors | ||
| # @private | ||
| class Middleware < Faraday::Middleware | ||
| def call(env) | ||
| @app.call(env).on_complete do |response| | ||
| case response[:status].to_i | ||
| when 400 | ||
| raise Serrano::BadRequest, error_message_400(response) | ||
| when 404 | ||
| raise Serrano::NotFound, error_message_400(response) | ||
| when 500 | ||
| raise Serrano::InternalServerError, error_message_500(response, "Something is technically wrong.") | ||
| when 502 | ||
| raise Serrano::BadGateway, error_message_500(response, "The server returned an invalid or incomplete response.") | ||
| when 503 | ||
| raise Serrano::ServiceUnavailable, error_message_500(response, "Crossref is rate limiting your requests.") | ||
| when 504 | ||
| raise Serrano::GatewayTimeout, error_message_500(response, "504 Gateway Time-out") | ||
| end | ||
| end | ||
| end | ||
| end | ||
| def initialize(app) | ||
| super app | ||
| @parser = nil | ||
| end | ||
| def initialize(app) | ||
| super app | ||
| @parser = nil | ||
| end | ||
| private | ||
| private | ||
| def error_message_400(response) | ||
| "\n #{response[:method].to_s.upcase} #{response[:url]}\n Status #{response[:status]}#{error_body(response[:body])}" | ||
| end | ||
| def error_message_400(response) | ||
| "\n #{response[:method].to_s.upcase} #{response[:url]}\n Status #{response[:status]}#{error_body(response[:body])}" | ||
| end | ||
| def error_body(body) | ||
| if !body.nil? && !body.empty? && body.is_a?(String) | ||
| if json?(body) | ||
| body = ::MultiJson.load(body) | ||
| if body["message"].nil? | ||
| body = nil | ||
| elseif body["message"].length == 1 | ||
| body = body["message"] | ||
| else | ||
| body = body["message"].collect { |x| x["message"] }.join("; ") | ||
| def error_body(body) | ||
| if !body.nil? && !body.empty? && body.is_a?(String) | ||
| if json?(body) | ||
| body = ::MultiJson.load(body) | ||
| if body["message"].nil? | ||
| body = nil | ||
| elseif body["message"].length == 1 | ||
| body = body["message"] | ||
| else | ||
| body = body["message"].collect { |x| x["message"] }.join("; ") | ||
| end | ||
| end | ||
| end | ||
| if body.nil? | ||
| nil | ||
| else | ||
| ": #{body}" | ||
| end | ||
| end | ||
| if body.nil? | ||
| nil | ||
| else | ||
| ": #{body}" | ||
| def error_message_500(response, body = nil) | ||
| "#{response[:method].to_s.upcase} #{response[:url]}: #{[response[:status].to_s + ":", body].compact.join(" ")}" | ||
| end | ||
| end | ||
| def error_message_500(response, body = nil) | ||
| "#{response[:method].to_s.upcase} #{response[:url]}: #{[response[:status].to_s + ":", body].compact.join(" ")}" | ||
| def json?(string) | ||
| MultiJson.load(string) | ||
| true | ||
| rescue MultiJson::ParseError | ||
| false | ||
| end | ||
| end | ||
| def json?(string) | ||
| MultiJson.load(string) | ||
| true | ||
| rescue MultiJson::ParseError | ||
| false | ||
| end | ||
| end | ||
| end |
@@ -55,9 +55,9 @@ # frozen_string_literal: true | ||
| module Serrano | ||
| class Request #:nodoc: | ||
| class Request # :nodoc: | ||
| include Helpers | ||
| end | ||
| class RequestCursor #:nodoc: | ||
| class RequestCursor # :nodoc: | ||
| include Helpers | ||
| end | ||
| end |
@@ -5,3 +5,2 @@ # frozen_string_literal: true | ||
| require "faraday" | ||
| require "faraday_middleware" | ||
| require "multi_json" | ||
@@ -11,3 +10,2 @@ require "serrano/error" | ||
| require "serrano/filterhandler" | ||
| require "serrano/error" | ||
| require "serrano/faraday" | ||
@@ -21,3 +19,3 @@ require "serrano/utils" | ||
| module Serrano | ||
| class RequestCursor #:nodoc: | ||
| class RequestCursor # :nodoc: | ||
| attr_accessor :endpt | ||
@@ -70,3 +68,3 @@ attr_accessor :id | ||
| fieldqueries = field_query_handler(args) | ||
| self.select = select.join(",") if select && select.class == Array | ||
| self.select = select&.instance_of?(Array) ? select.join(",") : select | ||
@@ -85,11 +83,9 @@ unless cursor_max.class.nil? | ||
| conn = if verbose | ||
| Faraday.new(url: Serrano.base_url, request: options || []) do |f| | ||
| Faraday.new(url: Serrano.base_url, request: options || {}) do |f| | ||
| f.response :logger | ||
| f.use FaradayMiddleware::RaiseHttpException | ||
| f.adapter Faraday.default_adapter | ||
| f.use Faraday::SerranoErrors::Middleware | ||
| end | ||
| else | ||
| Faraday.new(url: Serrano.base_url, request: options || []) do |f| | ||
| f.use FaradayMiddleware::RaiseHttpException | ||
| f.adapter Faraday.default_adapter | ||
| Faraday.new(url: Serrano.base_url, request: options || {}) do |f| | ||
| f.use Faraday::SerranoErrors::Middleware | ||
| end | ||
@@ -106,3 +102,3 @@ end | ||
| max_avail = js["message"]["total-results"] | ||
| _redo_req(conn, js, opts, cu, max_avail) | ||
| _redo_req(conn, js, opts, cu, max_avail, endpt2) | ||
@@ -128,3 +124,3 @@ else | ||
| max_avail = js["message"]["total-results"] | ||
| coll << _redo_req(conn, js, opts, cu, max_avail) | ||
| coll << _redo_req(conn, js, opts, cu, max_avail, endpt2) | ||
| end | ||
@@ -135,3 +131,3 @@ coll | ||
| def _redo_req(conn, js, opts, cu, max_avail) | ||
| def _redo_req(conn, js, opts, cu, max_avail, endpt2) | ||
| if !cu.nil? && (cursor_max > js["message"]["items"].length) | ||
@@ -138,0 +134,0 @@ res = [js] |
@@ -15,3 +15,3 @@ # frozen_string_literal: true | ||
| module Serrano | ||
| class Request #:nodoc: | ||
| class Request # :nodoc: | ||
| attr_accessor :endpt | ||
@@ -57,7 +57,6 @@ attr_accessor :id | ||
| self.select = select.join(",") if select && select.class == Array | ||
| self.select = select&.instance_of?(Array) ? select.join(",") : select | ||
| args = {query: query, filter: filt, offset: offset, | ||
| rows: limit, sample: sample, sort: sort, | ||
| order: order, facet: facet, | ||
| args = {query: query, filter: filt, offset: offset, rows: limit, | ||
| sample: sample, sort: sort, order: order, facet: facet, | ||
| select: select} | ||
@@ -67,11 +66,9 @@ opts = args.delete_if { |_k, v| v.nil? } | ||
| conn = if verbose | ||
| Faraday.new(url: Serrano.base_url, request: options || []) do |f| | ||
| Faraday.new(url: Serrano.base_url, request: options || {}) do |f| | ||
| f.response :logger | ||
| f.use FaradayMiddleware::RaiseHttpException | ||
| f.adapter Faraday.default_adapter | ||
| f.use Faraday::SerranoErrors::Middleware | ||
| end | ||
| else | ||
| Faraday.new(url: Serrano.base_url, request: options || []) do |f| | ||
| f.use FaradayMiddleware::RaiseHttpException | ||
| f.adapter Faraday.default_adapter | ||
| Faraday.new(url: Serrano.base_url, request: options || {}) do |f| | ||
| f.use Faraday::SerranoErrors::Middleware | ||
| end | ||
@@ -78,0 +75,0 @@ end |
@@ -9,4 +9,4 @@ # frozen_string_literal: true | ||
| conn = Faraday.new(url: base) { |f| | ||
| f.use FaradayMiddleware::RaiseHttpException | ||
| f.adapter Faraday.default_adapter | ||
| f.use Faraday::Response::RaiseError | ||
| # f.adapter Faraday.default_adapter | ||
| } | ||
@@ -13,0 +13,0 @@ args = {per_page: 1} |
@@ -27,3 +27,3 @@ # frozen_string_literal: true | ||
| def tostrings | ||
| Hash[map { |(k, v)| [k.to_s, v] }] | ||
| map { |(k, v)| [k.to_s, v] }.to_h | ||
| end | ||
@@ -34,4 +34,4 @@ end | ||
| def tosymbols | ||
| Hash[map { |(k, v)| [k.to_sym, v] }] | ||
| map { |(k, v)| [k.to_sym, v] }.to_h | ||
| end | ||
| end |
| # frozen_string_literal: true | ||
| module Serrano | ||
| VERSION = "1.0.0" | ||
| VERSION = "1.4" | ||
| end |
+1
-1
@@ -1,2 +0,2 @@ | ||
| Copyright (C) 2020 Scott Chamberlain | ||
| Copyright (C) 2022 Scott Chamberlain | ||
@@ -3,0 +3,0 @@ 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: |
+5
-0
@@ -47,1 +47,6 @@ # frozen_string_literal: true | ||
| end | ||
| desc "open an irb session preloaded with this gem" | ||
| task :console do | ||
| sh "irb -r pp -r ./lib/serrano.rb" | ||
| end |
+7
-6
@@ -6,3 +6,3 @@ serrano | ||
| [](https://github.com/sckott/serrano/actions) | ||
| [](https://codecov.io/github/sckott/serrano?branch=master) | ||
| [](https://codecov.io/github/sckott/serrano?branch=main) | ||
| [](https://zenodo.org/badge/latestdoi/2600/sckott/serrano) | ||
@@ -51,3 +51,3 @@ [](https://github.com/testdouble/standard) | ||
| You are using the Crossref search API described at https://github.com/CrossRef/rest-api-doc 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 | ||
| 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 | ||
@@ -189,2 +189,4 @@ Rate limits: | ||
| ~$ serrano works "10.1007/12080.1874-1746,10.1007/10452.1573-5125" | ||
| ## if above two dois in a file called dois.txt | ||
| ~$ cat dois.txt | xargs -I{} serrano works {} | ||
@@ -200,7 +202,6 @@ # output JSON, then parse with e.g., jq | ||
| [crapi]: https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md | ||
| [crapi]: https://api.crossref.org/ | ||
| [cn]: https://citation.crosscite.org/docs.html | ||
| [tdm]: https://www.crossref.org/education/retrieve-metadata/rest-api/text-and-data-mining/ | ||
| [ccount]: https://labs.crossref.org/openurl/ | ||
| [ccount]: https://www.crossref.org/documentation/retrieve-metadata/openurl/ | ||
| [csl]: https://github.com/citation-style-language/styles | ||
| [changelog]: https://github.com/sckott/serrano/blob/master/CHANGELOG.md | ||
| [changelog]: https://github.com/sckott/serrano/blob/main/CHANGELOG.md |
+14
-14
@@ -12,3 +12,2 @@ # frozen_string_literal: true | ||
| s.required_ruby_version = ">= 2.1" | ||
| s.date = "2020-10-19" | ||
| s.summary = "Crossref Client" | ||
@@ -29,16 +28,17 @@ s.description = "Low Level Ruby Client for the Crossref Search API" | ||
| s.add_development_dependency "bundler", '~> 2.1', '>= 2.1.4' | ||
| s.add_development_dependency "codecov", "~> 0.2.0" | ||
| s.add_development_dependency "json", '~> 2.3', '>= 2.3.1' | ||
| s.add_development_dependency "rake", '~> 13.0', '>= 13.0.1' | ||
| s.add_development_dependency "standard", "~> 0.7" | ||
| s.add_development_dependency "simplecov", "~> 0.19.0" | ||
| s.add_development_dependency "test-unit", '~> 3.3', '>= 3.3.6' | ||
| s.add_development_dependency "vcr", "~> 6.0" | ||
| s.add_development_dependency "webmock", '~> 3.9', '>= 3.9.3' | ||
| s.add_development_dependency "bundler", "~> 2.1", ">= 2.1.4" | ||
| s.add_development_dependency "codecov", "~> 0.5.0" | ||
| s.add_development_dependency "json", "~> 2.3", ">= 2.3.1" | ||
| s.add_development_dependency "rake", "~> 13.0", ">= 13.0.1" | ||
| s.add_development_dependency "standard", "~> 1.0" | ||
| s.add_development_dependency "simplecov", "~> 0.21.2" | ||
| s.add_development_dependency "test-unit", "~> 3.3", ">= 3.3.6" | ||
| s.add_development_dependency "vcr", "~> 6.1" | ||
| s.add_development_dependency "webmock", "~> 3.14" | ||
| s.add_runtime_dependency "faraday", "~> 1.1" | ||
| s.add_runtime_dependency "faraday_middleware", "~> 1.0" | ||
| s.add_runtime_dependency "multi_json", '~> 1.15' | ||
| s.add_runtime_dependency 'thor', '~> 1.0', '>= 1.0.1' | ||
| s.add_runtime_dependency "faraday", "~> 2.2" | ||
| s.add_runtime_dependency "faraday-follow_redirects", "~> 0.1.0" | ||
| s.add_runtime_dependency "multi_json", "~> 1.15" | ||
| s.add_runtime_dependency "rexml", "~> 3.2", ">= 3.2.5" | ||
| s.add_runtime_dependency "thor", "~> 1.2", ">= 1.2.1" | ||
@@ -45,0 +45,0 @@ s.metadata = { |