sinew 2.0.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +26 -0
  3. data/.rubocop.yml +9 -6
  4. data/.vscode/settings.json +0 -10
  5. data/Gemfile +9 -0
  6. data/README.md +13 -17
  7. data/Rakefile +33 -18
  8. data/bin/sinew +2 -0
  9. data/lib/sinew.rb +0 -1
  10. data/lib/sinew/connection.rb +52 -0
  11. data/lib/sinew/connection/log_formatter.rb +22 -0
  12. data/lib/sinew/connection/rate_limit.rb +29 -0
  13. data/lib/sinew/core_ext.rb +1 -1
  14. data/lib/sinew/dsl.rb +2 -1
  15. data/lib/sinew/main.rb +7 -55
  16. data/lib/sinew/output.rb +7 -23
  17. data/lib/sinew/request.rb +20 -71
  18. data/lib/sinew/response.rb +8 -57
  19. data/lib/sinew/runtime_options.rb +4 -4
  20. data/lib/sinew/version.rb +1 -1
  21. data/sample.sinew +2 -2
  22. data/sinew.gemspec +16 -17
  23. metadata +41 -99
  24. data/.travis.yml +0 -4
  25. data/lib/sinew/cache.rb +0 -79
  26. data/test/legacy/eu.httpbin.org/head/redirect,3 +0 -51
  27. data/test/legacy/eu.httpbin.org/head/status,500 +0 -1
  28. data/test/legacy/eu.httpbin.org/redirect,3 +0 -11
  29. data/test/legacy/eu.httpbin.org/status,500 +0 -1
  30. data/test/legacy/legacy.sinew +0 -2
  31. data/test/recipes/array_header.sinew +0 -6
  32. data/test/recipes/basic.sinew +0 -8
  33. data/test/recipes/dups.sinew +0 -7
  34. data/test/recipes/implicit_header.sinew +0 -5
  35. data/test/recipes/limit.sinew +0 -11
  36. data/test/recipes/noko.sinew +0 -9
  37. data/test/recipes/uri.sinew +0 -11
  38. data/test/recipes/xml.sinew +0 -8
  39. data/test/test.html +0 -45
  40. data/test/test_cache.rb +0 -69
  41. data/test/test_helper.rb +0 -126
  42. data/test/test_legacy.rb +0 -23
  43. data/test/test_main.rb +0 -34
  44. data/test/test_nokogiri_ext.rb +0 -18
  45. data/test/test_output.rb +0 -56
  46. data/test/test_recipes.rb +0 -60
  47. data/test/test_requests.rb +0 -164
  48. data/test/test_utf8.rb +0 -39
data/lib/sinew/output.rb CHANGED
@@ -1,13 +1,6 @@
1
1
  require 'csv'
2
2
  require 'set'
3
- require 'stringex'
4
-
5
- #
6
- # Stringex customizations
7
- #
8
-
9
- # turn '&' into '&', not 'and'
10
- Stringex::Localization::DefaultConversions::HTML_ENTITIES[:amp] = '&'
3
+ require 'sterile'
11
4
 
12
5
  #
13
6
  # CSV output.
@@ -52,6 +45,7 @@ module Sinew
52
45
 
53
46
  # don't allow duplicate urls
54
47
  return if dup_url?(row)
48
+
55
49
  rows << row.dup
56
50
 
57
51
  # map columns to row, and normalize along the way
@@ -108,24 +102,14 @@ module Sinew
108
102
  # strip html tags. Note that we replace tags with spaces
109
103
  s = s.gsub(/<[^>]+>/, ' ')
110
104
 
111
- #
112
- # Below uses stringex
113
- #
114
- # github.com/rsl/stringex/blob/master/lib/stringex/string_extensions.rb
115
- # github.com/rsl/stringex/blob/master/lib/stringex/localization/conversion_expressions.rb
116
- #
117
-
118
105
  # Converts MS Word 'smart punctuation' to ASCII
119
- s = s.convert_smart_punctuation
120
-
121
- # "&aacute;".convert_accented_html_entities # => "a"
122
- s = s.convert_accented_html_entities
106
+ s = Sterile.plain_format(s)
123
107
 
124
- # &amp, &frac, etc.
125
- s = s.convert_miscellaneous_html_entities
108
+ # &aacute; &amp; etc.
109
+ s = Sterile.decode_entities(s)
126
110
 
127
- # convert unicode => regular characters
128
- s = s.to_ascii
111
+ # "šţɽĩɳģ" => "string"
112
+ s = Sterile.transliterate(s)
129
113
 
130
114
  # squish
131
115
  s = s.squish
data/lib/sinew/request.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  require 'digest/md5'
2
- require 'httparty'
3
2
  require 'htmlentities'
4
3
 
5
4
  #
6
- # Process a single HTTP request. Mostly a wrapper around HTTParty.
5
+ # Process a single HTTP request.
7
6
  #
8
7
 
9
8
  module Sinew
@@ -12,16 +11,19 @@ module Sinew
12
11
  class Request
13
12
  HTML_ENTITIES = HTMLEntities.new
14
13
  VALID_METHODS = %w[get post patch put delete head options].freeze
14
+ METHODS_WITH_BODY = %w[patch post put].freeze
15
15
 
16
- attr_reader :sinew, :method, :uri, :options, :cache_key
16
+ attr_reader :sinew, :method, :uri, :options
17
17
 
18
- # Options are largely compatible with HTTParty, except for :method.
18
+ # Supported options:
19
+ # body: Body of http post
20
+ # headers: Hash of HTTP headers (combined with runtime_options.headers)
21
+ # query: Hash of query parameters to add to url
19
22
  def initialize(sinew, method, url, options = {})
20
23
  @sinew = sinew
21
24
  @method = method
22
25
  @options = options.dup
23
26
  @uri = parse_url(url)
24
- @cache_key = calculate_cache_key
25
27
  end
26
28
 
27
29
  def proxy
@@ -33,28 +35,19 @@ module Sinew
33
35
  end
34
36
 
35
37
  # run the request, return the result
36
- def perform
38
+ def perform(connection)
37
39
  validate!
38
40
 
39
- party_options = options.dup
40
-
41
- # merge proxy
42
- if proxy = self.proxy
43
- addr, port = proxy.split(':')
44
- party_options[:http_proxyaddr] = addr
45
- party_options[:http_proxyport] = port || 80
46
- end
41
+ headers = sinew.runtime_options.headers
42
+ headers = headers.merge(options[:headers]) if options[:headers]
47
43
 
48
- # now merge runtime_options
49
- party_options = party_options.merge(sinew.runtime_options.httparty_options)
44
+ body = options.delete(:body)
50
45
 
51
- # merge headers
52
- headers = sinew.runtime_options.headers
53
- headers = headers.merge(party_options[:headers]) if party_options[:headers]
54
- party_options[:headers] = headers
46
+ fday_response = connection.send(method, uri, body, headers) do
47
+ _1.options[:proxy] = proxy
48
+ end
55
49
 
56
- party_response = HTTParty.send(method, uri, party_options)
57
- Response.from_network(self, party_response)
50
+ Response.from_network(self, fday_response)
58
51
  end
59
52
 
60
53
  # We accept sloppy urls and attempt to clean them up
@@ -68,11 +61,11 @@ module Sinew
68
61
  s = s.gsub(' ', '%20')
69
62
  s = s.gsub("'", '%27')
70
63
 
71
- # append query manually (instead of letting HTTParty handle it) so we can
72
- # include it in cache_key
64
+ # append query manually (instead of letting Faraday handle it) for consistent
65
+ # Request#uri and Response#uri
73
66
  query = options.delete(:query)
74
67
  if query.present?
75
- q = HTTParty::HashConversions.to_params(query)
68
+ q = Faraday::Utils.default_params_encoder.encode(query)
76
69
  separator = s.include?('?') ? '&' : '?'
77
70
  s = "#{s}#{separator}#{q}"
78
71
  end
@@ -81,54 +74,10 @@ module Sinew
81
74
  end
82
75
  protected :parse_url
83
76
 
84
- def calculate_cache_key
85
- dir = pathify(uri.host)
86
-
87
- body_key = if body.is_a?(Hash)
88
- HTTParty::HashConversions.to_params(body)
89
- else
90
- body&.dup
91
- end
92
-
93
- # Build key, as a hash for before_generate_cache_key. Note that :scheme is
94
- # just a placeholder in case someone wants to add it for real, so that
95
- # it'll appear in the correct order. We remove the placerholder after we
96
- # call the proc.
97
- key = {
98
- method: method.dup,
99
- scheme: 'placeholder',
100
- path: uri.path,
101
- query: uri.query,
102
- body: body_key,
103
- }
104
-
105
- args = [ key ]
106
- if sinew.runtime_options.before_generate_cache_key.arity == 2
107
- args << uri
108
- end
109
- key = sinew.runtime_options.before_generate_cache_key.call(*args)
110
-
111
- # strip defaults
112
- key.delete(:scheme) if key[:scheme] == 'placeholder'
113
- key.delete(:method) if key[:method] == 'get'
114
-
115
- # pull out the values, join and pathify
116
- path = key.values.select(&:present?).join(',')
117
- path = pathify(path)
118
-
119
- # shorten long paths
120
- if path.length > 250
121
- path = Digest::MD5.hexdigest(path)
122
- end
123
-
124
- "#{dir}/#{path}"
125
- end
126
- protected :calculate_cache_key
127
-
128
77
  def validate!
129
78
  raise "invalid method #{method}" if !VALID_METHODS.include?(method)
130
79
  raise "invalid url #{uri}" if uri.scheme !~ /^http/
131
- raise "can't get with a body" if method == 'get' && body
80
+ raise "can't #{method} with a body" if body && !METHODS_WITH_BODY.include?(method)
132
81
  raise "Content-Type doesn't make sense without a body" if content_type && !body
133
82
  end
134
83
  protected :validate!
@@ -164,7 +113,7 @@ module Sinew
164
113
  s = s.gsub(',,', ',')
165
114
  # encode invalid path chars
166
115
  s = s.gsub(/[^A-Za-z0-9_.,=-]/) do |i|
167
- hex = i.unpack('H2').first
116
+ hex = i.unpack1('H2')
168
117
  "%#{hex}"
169
118
  end
170
119
  # handle empty case
@@ -2,7 +2,7 @@ require 'stringio'
2
2
  require 'zlib'
3
3
 
4
4
  #
5
- # An HTTP response. Mostly a wrapper around HTTParty.
5
+ # An HTTP response.
6
6
  #
7
7
 
8
8
  module Sinew
@@ -13,62 +13,13 @@ module Sinew
13
13
  # factory methods
14
14
  #
15
15
 
16
- def self.from_network(request, party_response)
17
- Response.new.tap do |response|
18
- response.request = request
19
- response.uri = party_response.request.last_uri
20
- response.code = party_response.code
21
- response.headers = party_response.headers.to_h
22
- response.body = process_body(party_response)
23
- end
24
- end
25
-
26
- def self.from_cache(request, body, head)
27
- Response.new.tap do |response|
28
- response.request = request
29
- response.body = body
30
-
31
- # defaults
32
- response.uri = request.uri
33
- response.code = 200
34
- response.headers = {}
35
-
36
- # overwrite with cached response headers
37
- if head
38
- if head !~ /^{/
39
- return from_legacy_head(response, head)
40
- end
41
- head = JSON.parse(head, symbolize_names: true)
42
- response.uri = URI.parse(head[:uri])
43
- response.code = head[:code]
44
- response.headers = head[:headers]
45
- end
46
- end
47
- end
48
-
49
- def self.from_error(request, error)
50
- Response.new.tap do |response|
51
- response.request = request
52
- response.uri = request.uri
53
- response.body = error.to_s
54
- response.code = 999
55
- response.headers = {}
56
- end
57
- end
58
-
59
- def self.from_legacy_head(response, head)
60
- response.tap do |r|
61
- case head
62
- when /\ACURLER_ERROR/
63
- # error
64
- r.code = 999
65
- when /\AHTTP/
66
- # redirect
67
- location = head.scan(/Location: ([^\r\n]+)/).flatten.last
68
- r.uri += location
69
- else
70
- $stderr.puts "unknown cached /head for #{r.uri}"
71
- end
16
+ def self.from_network(request, fday_response)
17
+ Response.new.tap do
18
+ _1.request = request
19
+ _1.uri = fday_response.env.url
20
+ _1.code = fday_response.status
21
+ _1.headers = fday_response.headers.to_h
22
+ _1.body = process_body(fday_response)
72
23
  end
73
24
  end
74
25
 
@@ -7,8 +7,8 @@ module Sinew
7
7
  attr_accessor :retries
8
8
  attr_accessor :rate_limit
9
9
  attr_accessor :headers
10
- attr_accessor :httparty_options
11
- attr_accessor :before_generate_cache_key
10
+ attr_accessor :httpdisk_options
11
+ attr_accessor :insecure
12
12
 
13
13
  def initialize
14
14
  self.retries = 3
@@ -16,8 +16,8 @@ module Sinew
16
16
  self.headers = {
17
17
  'User-Agent' => "sinew/#{VERSION}",
18
18
  }
19
- self.httparty_options = {}
20
- self.before_generate_cache_key = ->(i) { i }
19
+ self.httpdisk_options = {}
20
+ self.insecure = false
21
21
 
22
22
  # for testing
23
23
  if ENV['SINEW_TEST']
data/lib/sinew/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Sinew
2
2
  # Gem version
3
- VERSION = '2.0.5'.freeze
3
+ VERSION = '3.0.0'.freeze
4
4
  end
data/sample.sinew CHANGED
@@ -1,4 +1,4 @@
1
- get 'http://httpbin.org'
1
+ get 'http://httpbingo.org'
2
2
  noko.css('ul li a').each do |a|
3
3
  row = {}
4
4
  row[:url] = a[:href]
@@ -6,4 +6,4 @@ noko.css('ul li a').each do |a|
6
6
  csv_emit(row)
7
7
  end
8
8
 
9
- get 'http://httpbin.org/redirect/2'
9
+ get 'http://httpbingo.org/redirect/2'
data/sinew.gemspec CHANGED
@@ -5,30 +5,29 @@ require 'sinew/version'
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'sinew'
7
7
  s.version = Sinew::VERSION
8
- s.platform = Gem::Platform::RUBY
9
8
  s.license = 'MIT'
10
- s.authors = [ 'Adam Doppelt' ]
9
+ s.authors = [ 'Adam Doppelt', 'Nathan Kriege' ]
11
10
  s.email = [ 'amd@gurge.com' ]
12
11
  s.homepage = 'http://github.com/gurgeous/sinew'
13
12
  s.summary = 'Sinew - structured web crawling using recipes.'
14
13
  s.description = 'Crawl web sites easily using ruby recipes, with caching and nokogiri.'
15
- s.required_ruby_version = '~> 2.3'
14
+ s.required_ruby_version = '>= 2.7'
16
15
 
17
- s.rubyforge_project = 'sinew'
16
+ # what's in the gem?
17
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
18
+ `git ls-files -z`.split("\x0").reject { _1.match(%r{^test/}) }
19
+ end
20
+ s.bindir = 'bin'
21
+ s.executables = s.files.grep(%r{^#{s.bindir}/}) { File.basename(_1) }
22
+ s.require_paths = [ 'lib' ]
18
23
 
19
- s.add_runtime_dependency 'awesome_print', '~> 1.8'
24
+ s.add_runtime_dependency 'amazing_print', '~> 1.3'
25
+ s.add_runtime_dependency 'faraday', '~> 1.4'
26
+ s.add_runtime_dependency 'faraday-encoding', '~> 0'
20
27
  s.add_runtime_dependency 'htmlentities', '~> 4.3'
21
- s.add_runtime_dependency 'httparty', '~> 0.16'
22
- s.add_runtime_dependency 'nokogiri', '~> 1.8'
28
+ s.add_runtime_dependency 'httpdisk', '~> 0'
29
+ s.add_runtime_dependency 'nokogiri', '~> 1.11'
23
30
  s.add_runtime_dependency 'scripto', '~> 0'
24
- s.add_runtime_dependency 'slop', '~> 4.6'
25
- s.add_runtime_dependency 'stringex', '~> 2.8'
26
- s.add_development_dependency 'minitest', '~> 5.11'
27
- s.add_development_dependency 'rake', '~> 12.3'
28
- s.add_development_dependency 'webmock', '~> 3.4'
29
-
30
- s.files = `git ls-files`.split("\n")
31
- s.test_files = `git ls-files -- test/*`.split("\n")
32
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
33
- s.require_paths = [ 'lib' ]
31
+ s.add_runtime_dependency 'slop', '~> 4.8'
32
+ s.add_runtime_dependency 'sterile', '~> 1.0'
34
33
  end
metadata CHANGED
@@ -1,73 +1,74 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinew
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.5
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Doppelt
8
- autorequire:
8
+ - Nathan Kriege
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2019-03-22 00:00:00.000000000 Z
12
+ date: 2021-05-11 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: awesome_print
15
+ name: amazing_print
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
18
  - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: '1.8'
20
+ version: '1.3'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: '1.8'
27
+ version: '1.3'
27
28
  - !ruby/object:Gem::Dependency
28
- name: htmlentities
29
+ name: faraday
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
32
  - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: '4.3'
34
+ version: '1.4'
34
35
  type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: '4.3'
41
+ version: '1.4'
41
42
  - !ruby/object:Gem::Dependency
42
- name: httparty
43
+ name: faraday-encoding
43
44
  requirement: !ruby/object:Gem::Requirement
44
45
  requirements:
45
46
  - - "~>"
46
47
  - !ruby/object:Gem::Version
47
- version: '0.16'
48
+ version: '0'
48
49
  type: :runtime
49
50
  prerelease: false
50
51
  version_requirements: !ruby/object:Gem::Requirement
51
52
  requirements:
52
53
  - - "~>"
53
54
  - !ruby/object:Gem::Version
54
- version: '0.16'
55
+ version: '0'
55
56
  - !ruby/object:Gem::Dependency
56
- name: nokogiri
57
+ name: htmlentities
57
58
  requirement: !ruby/object:Gem::Requirement
58
59
  requirements:
59
60
  - - "~>"
60
61
  - !ruby/object:Gem::Version
61
- version: '1.8'
62
+ version: '4.3'
62
63
  type: :runtime
63
64
  prerelease: false
64
65
  version_requirements: !ruby/object:Gem::Requirement
65
66
  requirements:
66
67
  - - "~>"
67
68
  - !ruby/object:Gem::Version
68
- version: '1.8'
69
+ version: '4.3'
69
70
  - !ruby/object:Gem::Dependency
70
- name: scripto
71
+ name: httpdisk
71
72
  requirement: !ruby/object:Gem::Requirement
72
73
  requirements:
73
74
  - - "~>"
@@ -81,75 +82,61 @@ dependencies:
81
82
  - !ruby/object:Gem::Version
82
83
  version: '0'
83
84
  - !ruby/object:Gem::Dependency
84
- name: slop
85
+ name: nokogiri
85
86
  requirement: !ruby/object:Gem::Requirement
86
87
  requirements:
87
88
  - - "~>"
88
89
  - !ruby/object:Gem::Version
89
- version: '4.6'
90
+ version: '1.11'
90
91
  type: :runtime
91
92
  prerelease: false
92
93
  version_requirements: !ruby/object:Gem::Requirement
93
94
  requirements:
94
95
  - - "~>"
95
96
  - !ruby/object:Gem::Version
96
- version: '4.6'
97
+ version: '1.11'
97
98
  - !ruby/object:Gem::Dependency
98
- name: stringex
99
+ name: scripto
99
100
  requirement: !ruby/object:Gem::Requirement
100
101
  requirements:
101
102
  - - "~>"
102
103
  - !ruby/object:Gem::Version
103
- version: '2.8'
104
+ version: '0'
104
105
  type: :runtime
105
106
  prerelease: false
106
107
  version_requirements: !ruby/object:Gem::Requirement
107
108
  requirements:
108
109
  - - "~>"
109
110
  - !ruby/object:Gem::Version
110
- version: '2.8'
111
- - !ruby/object:Gem::Dependency
112
- name: minitest
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '5.11'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '5.11'
111
+ version: '0'
125
112
  - !ruby/object:Gem::Dependency
126
- name: rake
113
+ name: slop
127
114
  requirement: !ruby/object:Gem::Requirement
128
115
  requirements:
129
116
  - - "~>"
130
117
  - !ruby/object:Gem::Version
131
- version: '12.3'
132
- type: :development
118
+ version: '4.8'
119
+ type: :runtime
133
120
  prerelease: false
134
121
  version_requirements: !ruby/object:Gem::Requirement
135
122
  requirements:
136
123
  - - "~>"
137
124
  - !ruby/object:Gem::Version
138
- version: '12.3'
125
+ version: '4.8'
139
126
  - !ruby/object:Gem::Dependency
140
- name: webmock
127
+ name: sterile
141
128
  requirement: !ruby/object:Gem::Requirement
142
129
  requirements:
143
130
  - - "~>"
144
131
  - !ruby/object:Gem::Version
145
- version: '3.4'
146
- type: :development
132
+ version: '1.0'
133
+ type: :runtime
147
134
  prerelease: false
148
135
  version_requirements: !ruby/object:Gem::Requirement
149
136
  requirements:
150
137
  - - "~>"
151
138
  - !ruby/object:Gem::Version
152
- version: '3.4'
139
+ version: '1.0'
153
140
  description: Crawl web sites easily using ruby recipes, with caching and nokogiri.
154
141
  email:
155
142
  - amd@gurge.com
@@ -158,9 +145,9 @@ executables:
158
145
  extensions: []
159
146
  extra_rdoc_files: []
160
147
  files:
148
+ - ".github/workflows/test.yml"
161
149
  - ".gitignore"
162
150
  - ".rubocop.yml"
163
- - ".travis.yml"
164
151
  - ".vscode/extensions.json"
165
152
  - ".vscode/settings.json"
166
153
  - Gemfile
@@ -169,7 +156,9 @@ files:
169
156
  - Rakefile
170
157
  - bin/sinew
171
158
  - lib/sinew.rb
172
- - lib/sinew/cache.rb
159
+ - lib/sinew/connection.rb
160
+ - lib/sinew/connection/log_formatter.rb
161
+ - lib/sinew/connection/rate_limit.rb
173
162
  - lib/sinew/core_ext.rb
174
163
  - lib/sinew/dsl.rb
175
164
  - lib/sinew/main.rb
@@ -181,74 +170,27 @@ files:
181
170
  - lib/sinew/version.rb
182
171
  - sample.sinew
183
172
  - sinew.gemspec
184
- - test/legacy/eu.httpbin.org/head/redirect,3
185
- - test/legacy/eu.httpbin.org/head/status,500
186
- - test/legacy/eu.httpbin.org/redirect,3
187
- - test/legacy/eu.httpbin.org/status,500
188
- - test/legacy/legacy.sinew
189
- - test/recipes/array_header.sinew
190
- - test/recipes/basic.sinew
191
- - test/recipes/dups.sinew
192
- - test/recipes/implicit_header.sinew
193
- - test/recipes/limit.sinew
194
- - test/recipes/noko.sinew
195
- - test/recipes/uri.sinew
196
- - test/recipes/xml.sinew
197
- - test/test.html
198
- - test/test_cache.rb
199
- - test/test_helper.rb
200
- - test/test_legacy.rb
201
- - test/test_main.rb
202
- - test/test_nokogiri_ext.rb
203
- - test/test_output.rb
204
- - test/test_recipes.rb
205
- - test/test_requests.rb
206
- - test/test_utf8.rb
207
173
  homepage: http://github.com/gurgeous/sinew
208
174
  licenses:
209
175
  - MIT
210
176
  metadata: {}
211
- post_install_message:
177
+ post_install_message:
212
178
  rdoc_options: []
213
179
  require_paths:
214
180
  - lib
215
181
  required_ruby_version: !ruby/object:Gem::Requirement
216
182
  requirements:
217
- - - "~>"
183
+ - - ">="
218
184
  - !ruby/object:Gem::Version
219
- version: '2.3'
185
+ version: '2.7'
220
186
  required_rubygems_version: !ruby/object:Gem::Requirement
221
187
  requirements:
222
188
  - - ">="
223
189
  - !ruby/object:Gem::Version
224
190
  version: '0'
225
191
  requirements: []
226
- rubyforge_project: sinew
227
- rubygems_version: 2.7.6
228
- signing_key:
192
+ rubygems_version: 3.1.4
193
+ signing_key:
229
194
  specification_version: 4
230
195
  summary: Sinew - structured web crawling using recipes.
231
- test_files:
232
- - test/legacy/eu.httpbin.org/head/redirect,3
233
- - test/legacy/eu.httpbin.org/head/status,500
234
- - test/legacy/eu.httpbin.org/redirect,3
235
- - test/legacy/eu.httpbin.org/status,500
236
- - test/legacy/legacy.sinew
237
- - test/recipes/array_header.sinew
238
- - test/recipes/basic.sinew
239
- - test/recipes/dups.sinew
240
- - test/recipes/implicit_header.sinew
241
- - test/recipes/limit.sinew
242
- - test/recipes/noko.sinew
243
- - test/recipes/uri.sinew
244
- - test/recipes/xml.sinew
245
- - test/test.html
246
- - test/test_cache.rb
247
- - test/test_helper.rb
248
- - test/test_legacy.rb
249
- - test/test_main.rb
250
- - test/test_nokogiri_ext.rb
251
- - test/test_output.rb
252
- - test/test_recipes.rb
253
- - test/test_requests.rb
254
- - test/test_utf8.rb
196
+ test_files: []