klient 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 05be7e8bf426e334012023a497e378cbede55ec3b6ea3f1f7c0f912798744f3c
4
+ data.tar.gz: 46406b31960577c079ea06bfcd4532e5f175a5a1330d68f26ecac50f999850ba
5
+ SHA512:
6
+ metadata.gz: 06c7b1ed4383baf74ab9ccd24e471671cc2cbb2f208ce14c56d42962b7e951594210e2a3c082c9478ce275ca7d3058f612933fc6ac748e9beb88b5b60e4bcc70
7
+ data.tar.gz: 411da5be1600da3008f9fb0b3d7bf4804292297984bb78fa8446fd1cb38f72499608ece66c899ac83915c4565f83dfb5b1be1e28843594c6d96df661b183e487
@@ -0,0 +1,12 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'addressable'
4
+ require 'nokogiri'
5
+ # require 'parsed_data'
6
+
7
+ require_relative "klient/hash_methods.rb"
8
+ require_relative "klient/klient.rb"
9
+ require_relative "klient/resource.rb"
10
+ require_relative "klient/response.rb"
11
+ require_relative "klient/response_data.rb"
12
+ require_relative "klient/version.rb"
@@ -0,0 +1,32 @@
1
+ class Hash
2
+ def deep_get(key, obj, found = nil)
3
+ if obj.respond_to?(:key?) && obj.key?(key)
4
+ return obj[key]
5
+ elsif obj.respond_to?(:each)
6
+ obj.find { |*a| found = deep_get(key, a.last) }
7
+ return found
8
+ end
9
+ end
10
+
11
+ def deep_set(key, obj, value, found = nil)
12
+ if obj.respond_to?(:key?) && obj.key?(key)
13
+ obj[key] = value
14
+ return value
15
+ elsif obj.respond_to?(:each)
16
+ obj.find { |*a| found = deep_set(key, a.last, value) }
17
+ return found
18
+ end
19
+ end
20
+
21
+ def method_missing(mth, *args, &block)
22
+ m = mth.to_s
23
+
24
+ if keys.include?(m)
25
+ self[m]
26
+ elsif m =~ /\S+=/
27
+ deep_set(m.gsub(/=/, ''), self, args[0])
28
+ else
29
+ deep_get(m, self)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,77 @@
1
+ require 'rest-client'
2
+ require_relative "resource"
3
+ require_relative "resource_methods"
4
+
5
+ module Klient
6
+ attr_reader :base_url, :header_proc, :collection_accessor, :headers, :collection_key, :url_template, :root
7
+
8
+ module KlientClassMethods
9
+ attr_reader :header_proc, :resource_map
10
+
11
+ include ResourceMethods
12
+ end
13
+
14
+ def self.included(klass)
15
+ klass.extend(KlientClassMethods)
16
+ klass.send(:attr_reader, :header_proc)
17
+ klass.send(:attr_reader, :resource_map)
18
+ klass.send(:attr_reader, :identifier_map)
19
+ klass.instance_variable_set(:@resource_map, {})
20
+ klass.instance_variable_set(:@identifier_map, {})
21
+ end
22
+
23
+ def initialize(base_url)
24
+ @root = self
25
+ @header_proc = self.class.header_proc
26
+ @collection_accessor = self.class.instance_variable_get(:@collection_accessor)
27
+ @base_url = base_url
28
+ @headers = headers
29
+ @url_template = Addressable::Template.new(base_url)
30
+
31
+ rmap = {}
32
+ self.class::Resource.descendants
33
+ .select { |x| x.name.split('::').length == 2 }
34
+ .sort { |x, y| x.name.demodulize <=> y.name.demodulize }
35
+ .each do |klass|
36
+ next unless klass.id
37
+ cname = klass.name.demodulize.underscore.singularize.to_sym
38
+ cname_plural = klass.name.demodulize.underscore.pluralize.to_sym
39
+
40
+ if rmap.include?(cname)
41
+ next
42
+ else
43
+ rmap[cname_plural] = klass
44
+ rmap[cname] = klass
45
+ end
46
+ end
47
+
48
+ imap = {}
49
+ rmap.values.each do |klass|
50
+ next unless klass.id
51
+ imap[klass.id] = klass
52
+ end
53
+
54
+ @resource_map = rmap
55
+ @identifier_map = imap
56
+
57
+ self.class::Resource.descendants.each do |rklass|
58
+ cname = rklass.name.demodulize.underscore.to_sym
59
+
60
+ if rklass && rklass.arguments && rklass.arguments[:type]
61
+ rklass.resource_type = @resource_map[rklass.arguments[:type]]
62
+ elsif @resource_map[rklass.arguments[:type]] && @identifier_map.key(rklass)
63
+ rklass.resource_type = @resource_map[@identifier_map.key(rklass)]
64
+ elsif @resource_map.values.include?(rklass)
65
+ rklass.resource_type = rklass
66
+ elsif @resource_map[cname]
67
+ rklass.resource_type = @resource_map[cname]
68
+ elsif @identifier_map[rklass.id]
69
+ rklass.resource_type = rklass.id
70
+ else
71
+ rklass.resource_type = rklass
72
+ end
73
+ end
74
+ end
75
+
76
+ alias url base_url
77
+ end
@@ -0,0 +1,203 @@
1
+ require_relative "resource_methods"
2
+ require_relative "resource_collection"
3
+ require 'pry'
4
+ module Klient
5
+ class Resource
6
+ attr_reader :collection_accessor, :header_proc, :headers, :id, :last_response, :parent, :status, :url, :url_arguments, :url_template,:root
7
+
8
+ class << self
9
+ attr_reader :collection_accessor, :id, :identifier, :mapping, :url_template
10
+ attr_accessor :arguments, :resource_type, :type
11
+ end
12
+
13
+ extend ResourceMethods
14
+
15
+ def initialize(parent)
16
+ @root = parent.root
17
+ @header_proc = parent.header_proc
18
+ @regexp = /#{self.class.name.demodulize.underscore.gsub(/(_|-|\s+)/, "(_|-|\s*)")}/i
19
+ @id = self.class.try(:id)
20
+ @collection_accessor = @identifier = self.class.try(:identifier)
21
+
22
+ if @id
23
+ @url_arguments = {@id => @identifier}
24
+ else
25
+ @url_arguments = {}
26
+ end
27
+
28
+ @parent = parent
29
+ @headers = {}
30
+
31
+ @url_template = Addressable::Template.new(
32
+ @parent.url + self.class.url_template.pattern
33
+ )
34
+ end
35
+
36
+ def inspect
37
+ "#<#{self.class.name}:#{object_id} @url=#{self.url.inspect} @status_code=#{self.last_response.try(:status) || 'nil'}>"
38
+ end
39
+
40
+ %i(delete get head).each do |mth|
41
+ define_method(mth) do |identifier = nil, **params|
42
+
43
+ if params.empty?
44
+ @headers = @header_proc.call
45
+ else
46
+ @headers = @header_proc.call.merge(params: params)
47
+ end
48
+
49
+ if identifier
50
+ out = process_response(
51
+ RestClient.send(
52
+ mth,
53
+ @url_template.expand(@id => identifier).to_s,
54
+ @headers
55
+ )
56
+ )
57
+ else
58
+ out = process_response(RestClient.send(mth, url, @headers))
59
+ end
60
+
61
+ if respond_to?(:last_response) && out.respond_to?(:last_response)
62
+ @last_response = out.last_response
63
+ end
64
+
65
+ out.instance_variable_set(:@identifier, identifier)
66
+ out
67
+ end
68
+ end
69
+
70
+ %i(post put).each do |mth|
71
+ define_method(mth) do |identifier = nil, doc, **params|
72
+ if params.empty?
73
+ @headers = @header_proc.call
74
+ else
75
+ @headers = @header_proc.call.merge(params: params)
76
+ end
77
+ out = process_response(
78
+ RestClient.send(mth, url, doc, @headers)
79
+ )
80
+
81
+ if respond_to?(:last_response) && out.respond_to?(:last_response)
82
+ @last_response = out.last_response
83
+ end
84
+
85
+ out.instance_variable_set(:@identifier, identifier)
86
+ out
87
+ end
88
+ end
89
+
90
+ def url
91
+ @url_template.expand(@url_arguments).to_s
92
+ end
93
+
94
+ private
95
+ # Assumes JSON for the moment.
96
+ def process_doc(doc)
97
+ if doc.is_a?(Hash)
98
+ doc.to_json
99
+ elsif doc.empty?
100
+ {}.to_json
101
+ else
102
+ doc
103
+ end
104
+ end
105
+
106
+ def method_missing(mth, *args, &block)
107
+ if @parsed_body.respond_to?(mth)
108
+ @parsed_body.send(mth, *args, &block)
109
+ else
110
+ @last_response.send(mth, *args, &block)
111
+ end
112
+ end
113
+
114
+ # EXPERIMENTAL (USING HASH MODS)
115
+ def process_response(resp)
116
+ parsed = JSON.parse(resp.body)#.to_data
117
+
118
+ klass_type = self.class.resource_type
119
+
120
+ if klass_type == self.class
121
+ klass = self.class.new(parent)
122
+ else
123
+ klass = self.class.resource_type.new(@root)
124
+ end
125
+
126
+ if klass_type != self.class
127
+ if match = klass.url_template.match(resp.request.args[:url])
128
+ klass.url_arguments[klass.id] = match.mapping.with_indifferent_access[klass.id]
129
+ end
130
+ else
131
+ if match = self.url_template.match(resp.request.args[:url])
132
+ klass.url_arguments[klass.id] = match.mapping.with_indifferent_access[klass.id]
133
+ end
134
+ end
135
+
136
+ if klass.url_arguments[klass.id]
137
+ klass.url_arguments[klass.id]= parsed[klass.id]
138
+ klass.instance_variable_set(:@last_response, Response.new(resp))
139
+ return klass
140
+ # elsif parsed.is_a?(Hash) && parsed.keys.any? { |k| k.to_sym == @root.collection_accessor }
141
+ # klass.url_arguments[klass.id]= parsed[klass.id]
142
+ # klass.instance_variable_set(:@last_response, Response.new(resp))
143
+ # return klass
144
+ elsif key = parsed.keys.find { |k| k.to_s =~ @regexp }
145
+ if parsed[key].is_a?(Array)
146
+ arr = parsed[key].map! do |res|
147
+ tmp = klass_type.new(@root)
148
+ # TODO: Ugly. Revisit after recursive lookup.
149
+ tmp.url_arguments[klass.id]= res.send(klass.id) || res.send(klass.collection_accessor).try(klass.id)
150
+
151
+ processed = Response.new(resp, res)
152
+ tmp.instance_variable_set(:@last_response, processed)
153
+
154
+ tmp.instance_variable_set(:@parsed_body, processed.parsed_body)
155
+ tmp.instance_variable_set(:@status, processed.status)
156
+ tmp
157
+ end
158
+ return Klient::ResourceCollection.new(arr)
159
+ else
160
+ klass.url_arguments[klass.id]= parsed.send(klass.id) if klass.id
161
+ klass.instance_variable_set(:@last_response, Response.new(resp))
162
+ return klass
163
+ end
164
+ elsif self.class.type == :resource
165
+ klass.url_arguments[klass.id]= parsed.send(klass.id) if klass.id
166
+ klass.instance_variable_set(:@last_response, Response.new(resp))
167
+ return klass
168
+ elsif klass.url_arguments[klass.id]
169
+ klass.url_arguments[klass.id]= parsed.send(klass.id)
170
+ klass.instance_variable_set(:@last_response, Response.new(resp))
171
+ return klass
172
+ else
173
+ if parsed.is_a?(Array)
174
+ arr = parsed
175
+ elsif parsed.keys.length == 1 && parsed[parsed.keys.first].is_a?(Array)
176
+ arr = parsed[parsed.keys.first]
177
+ else
178
+ parsed.keys.each do |k|
179
+ if parsed[k].is_a?(Array) && parsed[k].first && parsed[k].first.send(klass.id.to_sym)
180
+ arr = parsed[k]
181
+ break
182
+ end
183
+ end
184
+ end
185
+
186
+ arr.map! do |res|
187
+ tmp = klass_type.new(@root)
188
+ # TODO: Ugly. Revisit after recursive lookup.
189
+ tmp.url_arguments[klass.id]= res.send(klass.id) || res.send(klass.collection_accessor).try(klass.id)
190
+
191
+ processed = Response.new(resp, res)
192
+ tmp.instance_variable_set(:@last_response, processed)
193
+
194
+ tmp.instance_variable_set(:@parsed_body, processed.parsed_body)
195
+ tmp.instance_variable_set(:@status, processed.status)
196
+ tmp
197
+ end
198
+
199
+ return Klient::ResourceCollection.new(arr)
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,17 @@
1
+ module Klient
2
+ class ResourceCollection
3
+ attr_reader :members, :last_response
4
+
5
+ def initialize(arr)
6
+ @members = arr
7
+ end
8
+
9
+ def method_missing(mth, *args, &block)
10
+ @members.send(mth, *args, &block)
11
+ end
12
+
13
+ def respond_to?(mth, *args, &block)
14
+ super || @members.respond_to?(mth)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,82 @@
1
+ module ResourceMethods
2
+ def default_collection_accessor(sym)
3
+ @collection_accessor = sym
4
+ end
5
+
6
+ def headers(&block)
7
+ @header_proc = block
8
+ end
9
+
10
+ def collection(name, template = nil, **hash_args, &block)
11
+ klass_name = name.to_s.camelcase
12
+
13
+ klass = Class.new(Klient::Resource) do
14
+ @arguments = hash_args
15
+ @type = :collection
16
+
17
+ # Obtain the collection's resource identifier. Don't allow hash arg AND block
18
+ # param for same thing -- it has to be either one or the other.
19
+ if block_given? && block.arity > 0 && hash_args[:identifier]
20
+ raise ArgumentError, "Collection identifier for :#{name} can be specified as a " \
21
+ "hash argument OR a block parameter (You can't use both simultaneously.)"
22
+ elsif block_given? && block.arity > 0
23
+ @id = block.parameters[0][1]
24
+ elsif hash_args[:identifier]
25
+ @id = hash_args[:identifier]
26
+ else
27
+ # raise ArgumentError, "#{name} collection definition does not specify a resource identifier."
28
+ end
29
+
30
+ # Don't allow templates with variables.
31
+ if template && template =~ /[\{\}]/
32
+ raise ArgumentError, "URL template variables not supported."
33
+ end
34
+
35
+ # Build a URL template if the template arg was provided.
36
+ if template && id
37
+ @url_template = Addressable::Template.new(template.to_s + "{/#{id}}")
38
+ elsif id
39
+ @identifier = nil
40
+ @url_template = Addressable::Template.new("/#{name}{/#{id}}")
41
+ else
42
+ @identifier = nil
43
+ @url_template = Addressable::Template.new("/#{name}")
44
+ end
45
+
46
+ class_eval(&block) if block
47
+ end
48
+ const_set(klass_name, klass)
49
+
50
+ define_method(name) do
51
+ klass.new(self)
52
+ end
53
+ end
54
+
55
+ def resource(name, template = nil, **hash_args, &block)
56
+ klass_name = name.to_s.camelcase
57
+
58
+ klass = Class.new(Klient::Resource) do
59
+ @arguments = hash_args
60
+ @type = :resource
61
+
62
+ # TODO: Avoid identifier conflicts between hash and URL template.
63
+ if template
64
+ @url_template = Addressable::Template.new(template)
65
+ else
66
+ @identifier = nil
67
+ @url_template = Addressable::Template.new("/#{name}")
68
+ end
69
+
70
+ class_eval(&block) if block
71
+ end
72
+ const_set(klass_name, klass)
73
+
74
+ define_method(name) do
75
+ klass.new(self)
76
+ end
77
+ end
78
+
79
+ def resources(*resource_names)
80
+ resource_names.each { |rname| resource rname }
81
+ end
82
+ end
@@ -0,0 +1,59 @@
1
+ require 'json'
2
+ module Klient
3
+ class Response
4
+ attr_reader :original_response, :parsed_body, :parsed_headers, :status
5
+
6
+ def body
7
+ @original_response.body
8
+ end
9
+
10
+ def ok?
11
+ (200..299).include?(status_code)
12
+ end
13
+
14
+ def status_code
15
+ @original_response.code
16
+ end
17
+
18
+ def headers
19
+ @parsed_headers
20
+ end
21
+
22
+ def initialize(original_response, data = nil)
23
+ @status = original_response.code
24
+
25
+ # If data arg is provided then it's a collection resource and the original
26
+ # response is for the entire collection. We don't want that -- this is an
27
+ # individual resource FOR the collection -- so the data arg is used in place
28
+ # of the parsed body for the collection response.
29
+ if data
30
+ @original_response = nil
31
+ @parsed_body = data
32
+ @parsed_headers = nil
33
+ else
34
+ @original_response = original_response
35
+ @body = @original_response.body
36
+ @parsed_headers = @original_response.headers
37
+
38
+ if @original_response.body.blank?
39
+ @parsed_body = {}
40
+ else
41
+ @parsed_body = JSON.parse(@original_response.body)
42
+ end
43
+ end
44
+ end
45
+
46
+ # TODO: This is dangerously wrong. It's just a shortcut to get something working.
47
+ def method_missing(mth, *args, &block)
48
+ if mth.to_s =~ /http_(\d+)\?/
49
+ status_code == $1.to_i
50
+ else
51
+ @parsed_body.send(mth)
52
+ end
53
+ end
54
+
55
+ def respond_to_missing?(mth, *args)
56
+ mth.to_s =~ /http_(\d+)\?/ || @parsed_body.respond_to?(mth) || super
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,31 @@
1
+ module Klient
2
+ class ResponseData
3
+ attr_reader :original_response, :parsed_body, :parsed_headers, :status_code
4
+
5
+ def body
6
+ nil
7
+ end
8
+
9
+ def headers
10
+ nil
11
+ end
12
+
13
+ def initialize(status_code, parsed_body)
14
+ @status_code = status_code
15
+ @parsed_body = parsed_body.freeze
16
+ end
17
+
18
+ def ok?
19
+ (200..299).include?(status_code)
20
+ end
21
+
22
+ # TODO: Bandaid.
23
+ def method_missing(mth, *args, &block)
24
+ @parsed_body.send(mth, *args, &block)
25
+ end
26
+
27
+ def respond_to_missing?(mth, *args)
28
+ mth.to_s =~ /http_(\d+)\?/ || @parsed_body.respond_to?(mth) || super
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Klient
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: klient
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - John Fitisoff
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: addressable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.5.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.5.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.7.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.7.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 0.8.21
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.8.21
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 0.16.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 0.16.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 0.11.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.11.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 12.3.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 12.3.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 3.7.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: 3.7.0
139
+ description: Experimental REST API client library.
140
+ email: jfitisoff@yahoo.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - lib/klient.rb
146
+ - lib/klient/hash_methods.rb
147
+ - lib/klient/klient.rb
148
+ - lib/klient/resource.rb
149
+ - lib/klient/resource_collection.rb
150
+ - lib/klient/resource_methods.rb
151
+ - lib/klient/response.rb
152
+ - lib/klient/response_data.rb
153
+ - lib/klient/version.rb
154
+ homepage: https://github.com/jfitisoff/klient
155
+ licenses:
156
+ - MIT
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: 2.3.0
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 2.7.6
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: Experimental REST API client library.
178
+ test_files: []