arxiv-dl 0.3.0 → 0.3.1
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/CHANGELOG.md +5 -0
- data/lib/arxiv/downloader/author.rb +1 -7
- data/lib/arxiv/downloader/cli.rb +11 -93
- data/lib/arxiv/downloader/client.rb +6 -79
- data/lib/arxiv/downloader/error.rb +1 -1
- data/lib/arxiv/downloader/http_error.rb +1 -10
- data/lib/arxiv/downloader/metadata/json.rb +1 -27
- data/lib/arxiv/downloader/metadata/markdown.rb +2 -24
- data/lib/arxiv/downloader/metadata/yaml.rb +1 -26
- data/lib/arxiv/downloader/slug.rb +1 -40
- data/lib/arxiv/downloader/version.rb +1 -1
- data/lib/arxiv/downloader.rb +6 -3
- metadata +7 -35
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 14d23483457b1dbb20c8aa9fa1384e52caf7144cab5ed357450f235dbcd29b80
|
|
4
|
+
data.tar.gz: 4d7255130c208f959bb0bb7249a33b3a076a362da7894dc370e480f2511109b7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0572297cdb2a74bb5cb46cdcd8449e2e41611a9649493e8ba5bc22b2fcb84d264e5982f114d2cff640cfd76e1761de592c8a472815ee6a8116b70f35807a11a0'
|
|
7
|
+
data.tar.gz: 8fd1844b84d8fc2044b8d92078ad2dae136713c93768269b64fe9a83b169a9da37466661dbaf61bb12f81d2ba827276f9c56e00291b978e8bdf7524de4a858ad
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## [0.3.1]
|
|
2
|
+
|
|
3
|
+
- Built on [dl-core](https://github.com/xoengineering/dl-core) 0.1: the HTTP client, errors, `Author`, `Slug`, sidecar writers, and CLI now come from it instead of copies. No change in behavior or output. `Arxiv::Downloader::Client`, `HTTPError`, `Author`, `Slug`, and `Metadata::YAML`/`JSON` still work; they are now `dl-core`'s classes. `Arxiv::Downloader::Error` now subclasses `DL::Core::Error`.
|
|
4
|
+
- Direct dependencies on `http`, `stringex`, and `ostruct` replaced by `dl-core`.
|
|
5
|
+
|
|
1
6
|
## [0.3.0]
|
|
2
7
|
|
|
3
8
|
Less folder nesting for the common case: most papers only ever have one version.
|
data/lib/arxiv/downloader/cli.rb
CHANGED
|
@@ -1,106 +1,24 @@
|
|
|
1
|
-
require 'optparse'
|
|
2
|
-
|
|
3
1
|
module Arxiv
|
|
4
2
|
module Downloader
|
|
5
|
-
class CLI
|
|
6
|
-
|
|
7
|
-
USAGE = 'Usage: arxiv-dl [options] <ARXIV_ID_OR_URL> [<ARXIV_ID_OR_URL>...]'.freeze
|
|
8
|
-
|
|
9
|
-
def initialize argv, stderr: $stderr, stdin: $stdin, stdout: $stdout
|
|
10
|
-
@argv = argv
|
|
11
|
-
@stderr = stderr
|
|
12
|
-
@stdin = stdin
|
|
13
|
-
@stdout = stdout
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def run
|
|
17
|
-
options = parse
|
|
18
|
-
return options.fetch(:exit_status) if options.key? :exit_status
|
|
19
|
-
|
|
20
|
-
return error_with USAGE if options[:targets].empty?
|
|
21
|
-
return error_with conflict if options[:verbose] && options[:quiet]
|
|
22
|
-
|
|
23
|
-
failures = download_each options
|
|
24
|
-
failures.zero? ? 0 : 1
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
def conflict
|
|
30
|
-
'-v and -q are mutually exclusive'
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def parse
|
|
34
|
-
options = { targets: [], verbose: false, quiet: false }
|
|
35
|
-
parser = build_parser options
|
|
36
|
-
|
|
37
|
-
begin
|
|
38
|
-
parser.parse! @argv
|
|
39
|
-
options[:targets] = @argv + input_targets(options[:input])
|
|
40
|
-
rescue OptionParser::ParseError, SystemCallError => e
|
|
41
|
-
@stderr.puts e.message
|
|
42
|
-
return { exit_status: 1 }
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
options[:path] ||= ENV['ARXIV_DOWNLOAD_PATH'] || DEFAULT_DOWNLOAD_PATH
|
|
46
|
-
options[:rate_limit] ||= (ENV['ARXIV_RATE_LIMIT'] || Client::DEFAULT_RATE_LIMIT).to_i
|
|
47
|
-
options
|
|
48
|
-
end
|
|
3
|
+
class CLI < DL::Core::CLI
|
|
4
|
+
def program = 'arxiv-dl'
|
|
49
5
|
|
|
50
|
-
def
|
|
51
|
-
OptionParser.new do |parser|
|
|
52
|
-
parser.banner = USAGE
|
|
53
|
-
parser.on('-i FILE', '--input FILE') { |value| options[:input] = value }
|
|
54
|
-
parser.on('-p PATH', '--path PATH') { |value| options[:path] = value }
|
|
55
|
-
parser.on('--rate-limit SECONDS', Integer) { |value| options[:rate_limit] = value }
|
|
56
|
-
parser.on('-v', '--verbose') { options[:verbose] = true }
|
|
57
|
-
parser.on('-q', '--quiet') { options[:quiet] = true }
|
|
58
|
-
parser.on('--version') do
|
|
59
|
-
@stdout.puts VERSION
|
|
60
|
-
options[:exit_status] = 0
|
|
61
|
-
end
|
|
62
|
-
parser.on('-h', '--help') do
|
|
63
|
-
@stdout.puts parser.help
|
|
64
|
-
options[:exit_status] = 0
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
6
|
+
def target_name = 'ARXIV_ID_OR_URL'
|
|
68
7
|
|
|
69
|
-
#
|
|
70
|
-
def
|
|
71
|
-
return [] if input.nil?
|
|
8
|
+
# ARXIV_DOWNLOAD_PATH, ARXIV_RATE_LIMIT
|
|
9
|
+
def env_prefix = 'ARXIV'
|
|
72
10
|
|
|
73
|
-
|
|
74
|
-
text.lines.map(&:strip).reject { it.empty? || it.start_with?('#') }
|
|
75
|
-
end
|
|
11
|
+
def default_path = File.join(Dir.home, 'Downloads', 'ArXiv_Papers')
|
|
76
12
|
|
|
77
|
-
def
|
|
78
|
-
@stderr.puts message
|
|
79
|
-
1
|
|
80
|
-
end
|
|
13
|
+
def version = VERSION
|
|
81
14
|
|
|
82
|
-
def
|
|
83
|
-
client = Client.new rate_limit: options[:rate_limit], log: (options[:verbose] ? @stdout : nil)
|
|
15
|
+
def user_agent = Client::USER_AGENT
|
|
84
16
|
|
|
85
|
-
|
|
86
|
-
options[:targets].each do |target|
|
|
87
|
-
failures += 1 unless download_one(target, client:, options:)
|
|
88
|
-
end
|
|
89
|
-
failures
|
|
90
|
-
end
|
|
17
|
+
def client_for(rate_limit:, log:) = Client.new(rate_limit:, log:)
|
|
91
18
|
|
|
92
|
-
|
|
93
|
-
def download_one target, client:, options:
|
|
94
|
-
identifier = Identifier.new target
|
|
95
|
-
@stdout.puts "==> Downloading #{identifier.id}" if options[:verbose]
|
|
19
|
+
def identifier_for(target) = Identifier.new(target)
|
|
96
20
|
|
|
97
|
-
|
|
98
|
-
@stdout.puts path unless options[:quiet]
|
|
99
|
-
true
|
|
100
|
-
rescue Error, HTTP::Error => e
|
|
101
|
-
@stderr.puts "#{target}: #{e.message}"
|
|
102
|
-
false
|
|
103
|
-
end
|
|
21
|
+
def archive_for(identifier, root:, client:) = Archive.new(identifier, root:, client:)
|
|
104
22
|
end
|
|
105
23
|
end
|
|
106
24
|
end
|
|
@@ -1,85 +1,12 @@
|
|
|
1
|
-
require 'http'
|
|
2
|
-
|
|
3
1
|
module Arxiv
|
|
4
2
|
module Downloader
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
MAX_RETRIES = 3
|
|
10
|
-
RETRY_BACKOFF = 10 # seconds before the first retry. doubles on each retry.
|
|
11
|
-
RETRYABLE_STATUSES = [429, 503].freeze
|
|
12
|
-
|
|
13
|
-
attr_reader :rate_limit
|
|
14
|
-
|
|
15
|
-
def initialize rate_limit: DEFAULT_RATE_LIMIT, log: nil
|
|
16
|
-
@rate_limit = rate_limit
|
|
17
|
-
@log = log
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def user_agent
|
|
21
|
-
"arxiv-dl/#{VERSION} (+#{SOURCE_URL})"
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def get url
|
|
25
|
-
retries = 0
|
|
26
|
-
|
|
27
|
-
loop do
|
|
28
|
-
response = request url
|
|
29
|
-
return response if response.status.success?
|
|
30
|
-
raise http_error(url, response) unless retryable? response, retries
|
|
31
|
-
|
|
32
|
-
retries += 1
|
|
33
|
-
wait_before_retry response, retries
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def request url
|
|
40
|
-
throttle
|
|
41
|
-
response = HTTP.timeout(TIMEOUTS).headers('User-Agent' => user_agent).follow.get(url)
|
|
42
|
-
@last_request_at = Time.now
|
|
43
|
-
log_request url, response
|
|
44
|
-
response
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def http_error url, response
|
|
48
|
-
HTTPError.new status: response.status.code, url: url, reason: response.status.reason
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def retryable? response, retries
|
|
52
|
-
RETRYABLE_STATUSES.include?(response.status.code) && retries < MAX_RETRIES
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def wait_before_retry response, retries
|
|
56
|
-
seconds = retry_after(response) || (RETRY_BACKOFF * (2**(retries - 1)))
|
|
57
|
-
@log&.puts "==> #{response.status}. Retrying in #{seconds}s"
|
|
58
|
-
sleep seconds
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Retry-After in delay-seconds form. The HTTP-date form falls back to backoff.
|
|
62
|
-
def retry_after response
|
|
63
|
-
value = response.headers['Retry-After']
|
|
64
|
-
return if value.nil?
|
|
65
|
-
|
|
66
|
-
Integer(value, exception: false)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def log_request url, response
|
|
70
|
-
return if @log.nil?
|
|
71
|
-
|
|
72
|
-
@log.puts "==> GET #{url} (#{response.body.to_s.bytesize} bytes)"
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def throttle
|
|
76
|
-
return if @rate_limit.zero?
|
|
77
|
-
return if @last_request_at.nil?
|
|
78
|
-
|
|
79
|
-
elapsed = Time.now - @last_request_at
|
|
80
|
-
return if elapsed >= @rate_limit
|
|
3
|
+
# DL::Core::Client with arxiv-dl's User-Agent filled in
|
|
4
|
+
class Client < DL::Core::Client
|
|
5
|
+
SOURCE_URL = 'https://github.com/xoengineering/arxiv-dl'.freeze
|
|
6
|
+
USER_AGENT = "arxiv-dl/#{VERSION} (+#{SOURCE_URL})".freeze
|
|
81
7
|
|
|
82
|
-
|
|
8
|
+
def initialize log: nil, rate_limit: DEFAULT_RATE_LIMIT
|
|
9
|
+
super(user_agent: USER_AGENT, log:, rate_limit:)
|
|
83
10
|
end
|
|
84
11
|
end
|
|
85
12
|
end
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
module Arxiv
|
|
2
2
|
module Downloader
|
|
3
|
-
|
|
4
|
-
attr_reader :status, :url
|
|
5
|
-
|
|
6
|
-
def initialize status:, url:, reason: nil
|
|
7
|
-
@status = status
|
|
8
|
-
@url = url
|
|
9
|
-
|
|
10
|
-
super("GET #{url} failed: #{[status, reason].compact.join ' '}")
|
|
11
|
-
end
|
|
12
|
-
end
|
|
3
|
+
HTTPError = DL::Core::HTTPError
|
|
13
4
|
end
|
|
14
5
|
end
|
|
@@ -1,33 +1,7 @@
|
|
|
1
|
-
require 'fileutils'
|
|
2
|
-
require 'json'
|
|
3
|
-
|
|
4
1
|
module Arxiv
|
|
5
2
|
module Downloader
|
|
6
3
|
class Metadata
|
|
7
|
-
|
|
8
|
-
FILENAME = 'metadata.json'.freeze
|
|
9
|
-
|
|
10
|
-
def initialize metadata
|
|
11
|
-
@metadata = metadata
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def write to:
|
|
15
|
-
FileUtils.mkdir_p to
|
|
16
|
-
File.write File.join(to, FILENAME), "#{::JSON.pretty_generate(serialize(@metadata.to_h))}\n"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def serialize object
|
|
22
|
-
case object
|
|
23
|
-
when Hash then object.to_h { |key, value| [key.to_s, serialize(value)] }
|
|
24
|
-
when Array then object.map { |item| serialize item }
|
|
25
|
-
when Data then serialize object.to_h
|
|
26
|
-
when Date, Time then object.iso8601
|
|
27
|
-
else object
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
4
|
+
JSON = DL::Core::Sidecar::JSON
|
|
31
5
|
end
|
|
32
6
|
end
|
|
33
7
|
end
|
|
@@ -1,44 +1,22 @@
|
|
|
1
|
-
require 'fileutils'
|
|
2
|
-
require 'yaml'
|
|
3
|
-
|
|
4
1
|
module Arxiv
|
|
5
2
|
module Downloader
|
|
6
3
|
class Metadata
|
|
4
|
+
# metadata.md: dl-core writes the frontmatter; the body is arxiv-specific
|
|
7
5
|
class Markdown
|
|
8
|
-
FILENAME = 'metadata.md'.freeze
|
|
9
|
-
|
|
10
6
|
def initialize metadata
|
|
11
7
|
@metadata = metadata
|
|
12
8
|
end
|
|
13
9
|
|
|
14
10
|
def write to:
|
|
15
|
-
|
|
16
|
-
File.write File.join(to, FILENAME), "#{frontmatter}\n#{body}"
|
|
11
|
+
DL::Core::Sidecar::Markdown.new(@metadata, body:, extras: { bibtex_key: }).write to:
|
|
17
12
|
end
|
|
18
13
|
|
|
19
14
|
private
|
|
20
15
|
|
|
21
|
-
def frontmatter
|
|
22
|
-
"---\n#{::YAML.dump(stringify(frontmatter_hash)).delete_prefix("---\n")}---"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def frontmatter_hash
|
|
26
|
-
@metadata.to_h.merge bibtex_key: bibtex_key
|
|
27
|
-
end
|
|
28
|
-
|
|
29
16
|
def bibtex_key
|
|
30
17
|
Downloader::Bibtex.new(@metadata).key
|
|
31
18
|
end
|
|
32
19
|
|
|
33
|
-
def stringify object
|
|
34
|
-
case object
|
|
35
|
-
when Hash then object.to_h { |key, value| [key.to_s, stringify(value)] }
|
|
36
|
-
when Array then object.map { |item| stringify item }
|
|
37
|
-
when Data then stringify object.to_h
|
|
38
|
-
else object
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
20
|
def body
|
|
43
21
|
<<~MARKDOWN
|
|
44
22
|
|
|
@@ -1,32 +1,7 @@
|
|
|
1
|
-
require 'fileutils'
|
|
2
|
-
require 'yaml'
|
|
3
|
-
|
|
4
1
|
module Arxiv
|
|
5
2
|
module Downloader
|
|
6
3
|
class Metadata
|
|
7
|
-
|
|
8
|
-
FILENAME = 'metadata.yaml'.freeze
|
|
9
|
-
|
|
10
|
-
def initialize metadata
|
|
11
|
-
@metadata = metadata
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def write to:
|
|
15
|
-
FileUtils.mkdir_p to
|
|
16
|
-
File.write File.join(to, FILENAME), ::YAML.dump(stringify(@metadata.to_h))
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def stringify object
|
|
22
|
-
case object
|
|
23
|
-
when Hash then object.to_h { |key, value| [key.to_s, stringify(value)] }
|
|
24
|
-
when Array then object.map { |item| stringify item }
|
|
25
|
-
when Data then stringify object.to_h
|
|
26
|
-
else object
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
4
|
+
YAML = DL::Core::Sidecar::YAML
|
|
30
5
|
end
|
|
31
6
|
end
|
|
32
7
|
end
|
|
@@ -1,44 +1,5 @@
|
|
|
1
|
-
require 'stringex'
|
|
2
|
-
|
|
3
1
|
module Arxiv
|
|
4
2
|
module Downloader
|
|
5
|
-
|
|
6
|
-
MAX_LENGTH = 80
|
|
7
|
-
|
|
8
|
-
TEX_INLINE_MATH = /\$[^$]*\$/ # $...$
|
|
9
|
-
TEX_DISPLAY_MATH = /\\\(.*?\\\)|\\\[.*?\\\]/m # \(...\) or \[...\]
|
|
10
|
-
TEX_COMMAND = /\\[a-zA-Z]+\*?/ # \emph, \alpha, etc.
|
|
11
|
-
|
|
12
|
-
def initialize title
|
|
13
|
-
@title = title
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def to_s
|
|
17
|
-
truncate strip_tex(@title).to_url
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
def strip_tex string
|
|
23
|
-
string
|
|
24
|
-
.gsub(TEX_INLINE_MATH, ' ')
|
|
25
|
-
.gsub(TEX_DISPLAY_MATH, ' ')
|
|
26
|
-
.gsub(TEX_COMMAND, ' ')
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def truncate slug
|
|
30
|
-
return slug if slug.length <= MAX_LENGTH
|
|
31
|
-
|
|
32
|
-
words = slug.split '-'
|
|
33
|
-
result = +''
|
|
34
|
-
words.each do |word|
|
|
35
|
-
break if result.length + 1 + word.length > MAX_LENGTH
|
|
36
|
-
|
|
37
|
-
result << '-' unless result.empty?
|
|
38
|
-
result << word
|
|
39
|
-
end
|
|
40
|
-
result
|
|
41
|
-
end
|
|
42
|
-
end
|
|
3
|
+
Slug = DL::Core::Slug
|
|
43
4
|
end
|
|
44
5
|
end
|
data/lib/arxiv/downloader.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
require 'dl/core'
|
|
2
|
+
|
|
3
|
+
require_relative 'downloader/version' # before client: Client::USER_AGENT uses VERSION
|
|
4
|
+
|
|
1
5
|
require_relative 'downloader/abstract_page'
|
|
2
6
|
require_relative 'downloader/archive'
|
|
3
7
|
require_relative 'downloader/assets_cache'
|
|
@@ -5,11 +9,11 @@ require_relative 'downloader/author'
|
|
|
5
9
|
require_relative 'downloader/bibtex'
|
|
6
10
|
require_relative 'downloader/categories'
|
|
7
11
|
require_relative 'downloader/cli'
|
|
8
|
-
require_relative 'downloader/client'
|
|
12
|
+
require_relative 'downloader/client' # after version
|
|
9
13
|
require_relative 'downloader/error' # before errors below that subclass Error
|
|
10
14
|
require_relative 'downloader/feed_parser'
|
|
11
15
|
require_relative 'downloader/html_archive'
|
|
12
|
-
require_relative 'downloader/http_error'
|
|
16
|
+
require_relative 'downloader/http_error'
|
|
13
17
|
require_relative 'downloader/identifier' # after error
|
|
14
18
|
require_relative 'downloader/metadata' # before metadata/*: they reopen class Metadata
|
|
15
19
|
require_relative 'downloader/metadata/bibtex' # after metadata
|
|
@@ -22,7 +26,6 @@ require_relative 'downloader/path'
|
|
|
22
26
|
require_relative 'downloader/pdf'
|
|
23
27
|
require_relative 'downloader/slug'
|
|
24
28
|
require_relative 'downloader/source_archive'
|
|
25
|
-
require_relative 'downloader/version'
|
|
26
29
|
|
|
27
30
|
module Arxiv
|
|
28
31
|
module Downloader
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: arxiv-dl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shane Becker
|
|
@@ -10,33 +10,33 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: dl-core
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '0.1'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '
|
|
25
|
+
version: '0.1'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: feedjira
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '4.0'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '4.0'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: nokogiri
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -51,34 +51,6 @@ dependencies:
|
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '1.19'
|
|
54
|
-
- !ruby/object:Gem::Dependency
|
|
55
|
-
name: ostruct
|
|
56
|
-
requirement: !ruby/object:Gem::Requirement
|
|
57
|
-
requirements:
|
|
58
|
-
- - "~>"
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: '0.6'
|
|
61
|
-
type: :runtime
|
|
62
|
-
prerelease: false
|
|
63
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
-
requirements:
|
|
65
|
-
- - "~>"
|
|
66
|
-
- !ruby/object:Gem::Version
|
|
67
|
-
version: '0.6'
|
|
68
|
-
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: stringex
|
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - "~>"
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '2.8'
|
|
75
|
-
type: :runtime
|
|
76
|
-
prerelease: false
|
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - "~>"
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: '2.8'
|
|
82
54
|
description: Command line tool and Ruby library for archiving arxiv.org papers as
|
|
83
55
|
PDFs with sidecar metadata.
|
|
84
56
|
email:
|