tlaw 0.0.2 → 0.1.0.pre
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/.ruby-version +1 -0
- data/CHANGELOG.md +18 -2
- data/README.md +10 -7
- data/examples/demo_base.rb +2 -2
- data/examples/experimental/README.md +3 -0
- data/examples/experimental/afterthedeadline.rb +22 -0
- data/examples/experimental/airvisual.rb +14 -0
- data/examples/experimental/apixu.rb +32 -0
- data/examples/experimental/bing_maps.rb +18 -0
- data/examples/experimental/currencylayer.rb +25 -0
- data/examples/experimental/earthquake.rb +29 -0
- data/examples/experimental/freegeoip.rb +16 -0
- data/examples/experimental/geonames.rb +98 -0
- data/examples/experimental/isfdb.rb +17 -0
- data/examples/experimental/musicbrainz.rb +27 -0
- data/examples/experimental/nominatim.rb +52 -0
- data/examples/experimental/omdb.rb +68 -0
- data/examples/experimental/open_exchange_rates.rb +36 -0
- data/examples/experimental/open_route.rb +27 -0
- data/examples/experimental/open_street_map.rb +16 -0
- data/examples/experimental/quandl.rb +50 -0
- data/examples/experimental/reddit.rb +25 -0
- data/examples/experimental/swapi.rb +27 -0
- data/examples/experimental/tmdb.rb +53 -0
- data/examples/experimental/world_bank.rb +85 -0
- data/examples/experimental/world_bank_climate.rb +77 -0
- data/examples/experimental/wunderground.rb +66 -0
- data/examples/experimental/wunderground_demo.rb +7 -0
- data/examples/forecast_io.rb +16 -16
- data/examples/giphy.rb +4 -4
- data/examples/giphy_demo.rb +1 -1
- data/examples/open_weather_map.rb +64 -60
- data/examples/open_weather_map_demo.rb +4 -4
- data/examples/tmdb_demo.rb +1 -1
- data/examples/urbandictionary_demo.rb +2 -2
- data/lib/tlaw.rb +14 -15
- data/lib/tlaw/api.rb +108 -26
- data/lib/tlaw/api_path.rb +86 -87
- data/lib/tlaw/data_table.rb +15 -10
- data/lib/tlaw/dsl.rb +126 -224
- data/lib/tlaw/dsl/api_builder.rb +47 -0
- data/lib/tlaw/dsl/base_builder.rb +108 -0
- data/lib/tlaw/dsl/endpoint_builder.rb +26 -0
- data/lib/tlaw/dsl/namespace_builder.rb +86 -0
- data/lib/tlaw/endpoint.rb +63 -85
- data/lib/tlaw/formatting.rb +55 -0
- data/lib/tlaw/formatting/describe.rb +86 -0
- data/lib/tlaw/formatting/inspect.rb +52 -0
- data/lib/tlaw/namespace.rb +141 -98
- data/lib/tlaw/param.rb +45 -141
- data/lib/tlaw/param/type.rb +36 -49
- data/lib/tlaw/response_processors.rb +81 -0
- data/lib/tlaw/util.rb +16 -33
- data/lib/tlaw/version.rb +6 -3
- data/tlaw.gemspec +9 -9
- metadata +63 -13
- data/lib/tlaw/param_set.rb +0 -111
- data/lib/tlaw/response_processor.rb +0 -126
data/lib/tlaw/version.rb
CHANGED
data/tlaw.gemspec
CHANGED
@@ -3,14 +3,12 @@ require './lib/tlaw/version'
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'tlaw'
|
5
5
|
s.version = TLAW::VERSION
|
6
|
-
s.authors = ['Victor Shepelev']
|
7
|
-
s.email =
|
6
|
+
s.authors = ['Victor Shepelev', 'Joel Van Horn']
|
7
|
+
s.email = %w[zverok.offline@gmail.com joel@joelvanhorn.com]
|
8
8
|
s.homepage = 'https://github.com/molybdenum-99/tlaw'
|
9
9
|
|
10
|
-
s.summary = '
|
11
|
-
s.description =
|
12
|
-
And here would be description.
|
13
|
-
EOF
|
10
|
+
s.summary = 'The Last API Wrapper: Pragmatic API wrapper framework'
|
11
|
+
s.description = %q{TLAW is the last (and only) API wrapper framework you'll ever need for accessing GET-only APIs in a consistent way (think weather, search, economical indicators, geonames and so on).}
|
14
12
|
s.licenses = ['MIT']
|
15
13
|
|
16
14
|
s.files = `git ls-files`.split($RS).reject do |file|
|
@@ -24,10 +22,12 @@ Gem::Specification.new do |s|
|
|
24
22
|
|\.travis.yml
|
25
23
|
)$/x
|
26
24
|
end
|
27
|
-
s.require_paths = ["lib"]
|
28
25
|
|
29
|
-
s.
|
26
|
+
s.require_paths = ['lib']
|
30
27
|
|
28
|
+
s.required_ruby_version = '>= 2.3.0'
|
29
|
+
|
30
|
+
s.add_runtime_dependency 'backports'
|
31
31
|
s.add_runtime_dependency 'faraday'
|
32
32
|
s.add_runtime_dependency 'faraday_middleware'
|
33
33
|
s.add_runtime_dependency 'addressable'
|
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
|
|
38
38
|
s.add_development_dependency 'rubygems-tasks'
|
39
39
|
|
40
40
|
# Testing
|
41
|
-
s.add_development_dependency 'rubocop'
|
41
|
+
s.add_development_dependency 'rubocop'
|
42
42
|
s.add_development_dependency 'rubocop-rspec'
|
43
43
|
s.add_development_dependency 'rspec', '>= 3.5'
|
44
44
|
s.add_development_dependency 'rspec-its', '~> 1'
|
metadata
CHANGED
@@ -1,15 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tlaw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.1.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Shepelev
|
8
|
+
- Joel Van Horn
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2018-12-21 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: backports
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
13
28
|
- !ruby/object:Gem::Dependency
|
14
29
|
name: faraday
|
15
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +115,14 @@ dependencies:
|
|
100
115
|
requirements:
|
101
116
|
- - ">="
|
102
117
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0
|
118
|
+
version: '0'
|
104
119
|
type: :development
|
105
120
|
prerelease: false
|
106
121
|
version_requirements: !ruby/object:Gem::Requirement
|
107
122
|
requirements:
|
108
123
|
- - ">="
|
109
124
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0
|
125
|
+
version: '0'
|
111
126
|
- !ruby/object:Gem::Dependency
|
112
127
|
name: rubocop-rspec
|
113
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,19 +249,48 @@ dependencies:
|
|
234
249
|
- - ">="
|
235
250
|
- !ruby/object:Gem::Version
|
236
251
|
version: '0'
|
237
|
-
description:
|
238
|
-
|
252
|
+
description: TLAW is the last (and only) API wrapper framework you'll ever need for
|
253
|
+
accessing GET-only APIs in a consistent way (think weather, search, economical indicators,
|
254
|
+
geonames and so on).
|
255
|
+
email:
|
256
|
+
- zverok.offline@gmail.com
|
257
|
+
- joel@joelvanhorn.com
|
239
258
|
executables: []
|
240
259
|
extensions: []
|
241
260
|
extra_rdoc_files: []
|
242
261
|
files:
|
243
262
|
- ".codeclimate.yml"
|
244
263
|
- ".rubocop_todo.yml"
|
264
|
+
- ".ruby-version"
|
245
265
|
- ".yardopts"
|
246
266
|
- CHANGELOG.md
|
247
267
|
- LICENSE.txt
|
248
268
|
- README.md
|
249
269
|
- examples/demo_base.rb
|
270
|
+
- examples/experimental/README.md
|
271
|
+
- examples/experimental/afterthedeadline.rb
|
272
|
+
- examples/experimental/airvisual.rb
|
273
|
+
- examples/experimental/apixu.rb
|
274
|
+
- examples/experimental/bing_maps.rb
|
275
|
+
- examples/experimental/currencylayer.rb
|
276
|
+
- examples/experimental/earthquake.rb
|
277
|
+
- examples/experimental/freegeoip.rb
|
278
|
+
- examples/experimental/geonames.rb
|
279
|
+
- examples/experimental/isfdb.rb
|
280
|
+
- examples/experimental/musicbrainz.rb
|
281
|
+
- examples/experimental/nominatim.rb
|
282
|
+
- examples/experimental/omdb.rb
|
283
|
+
- examples/experimental/open_exchange_rates.rb
|
284
|
+
- examples/experimental/open_route.rb
|
285
|
+
- examples/experimental/open_street_map.rb
|
286
|
+
- examples/experimental/quandl.rb
|
287
|
+
- examples/experimental/reddit.rb
|
288
|
+
- examples/experimental/swapi.rb
|
289
|
+
- examples/experimental/tmdb.rb
|
290
|
+
- examples/experimental/world_bank.rb
|
291
|
+
- examples/experimental/world_bank_climate.rb
|
292
|
+
- examples/experimental/wunderground.rb
|
293
|
+
- examples/experimental/wunderground_demo.rb
|
250
294
|
- examples/forecast_io.rb
|
251
295
|
- examples/forecast_io_demo.rb
|
252
296
|
- examples/giphy.rb
|
@@ -260,12 +304,18 @@ files:
|
|
260
304
|
- lib/tlaw/api_path.rb
|
261
305
|
- lib/tlaw/data_table.rb
|
262
306
|
- lib/tlaw/dsl.rb
|
307
|
+
- lib/tlaw/dsl/api_builder.rb
|
308
|
+
- lib/tlaw/dsl/base_builder.rb
|
309
|
+
- lib/tlaw/dsl/endpoint_builder.rb
|
310
|
+
- lib/tlaw/dsl/namespace_builder.rb
|
263
311
|
- lib/tlaw/endpoint.rb
|
312
|
+
- lib/tlaw/formatting.rb
|
313
|
+
- lib/tlaw/formatting/describe.rb
|
314
|
+
- lib/tlaw/formatting/inspect.rb
|
264
315
|
- lib/tlaw/namespace.rb
|
265
316
|
- lib/tlaw/param.rb
|
266
317
|
- lib/tlaw/param/type.rb
|
267
|
-
- lib/tlaw/
|
268
|
-
- lib/tlaw/response_processor.rb
|
318
|
+
- lib/tlaw/response_processors.rb
|
269
319
|
- lib/tlaw/util.rb
|
270
320
|
- lib/tlaw/version.rb
|
271
321
|
- tlaw.gemspec
|
@@ -281,16 +331,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
281
331
|
requirements:
|
282
332
|
- - ">="
|
283
333
|
- !ruby/object:Gem::Version
|
284
|
-
version: 2.
|
334
|
+
version: 2.3.0
|
285
335
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
286
336
|
requirements:
|
287
|
-
- - "
|
337
|
+
- - ">"
|
288
338
|
- !ruby/object:Gem::Version
|
289
|
-
version:
|
339
|
+
version: 1.3.1
|
290
340
|
requirements: []
|
291
341
|
rubyforge_project:
|
292
|
-
rubygems_version: 2.6.
|
342
|
+
rubygems_version: 2.6.14
|
293
343
|
signing_key:
|
294
344
|
specification_version: 4
|
295
|
-
summary:
|
345
|
+
summary: 'The Last API Wrapper: Pragmatic API wrapper framework'
|
296
346
|
test_files: []
|
data/lib/tlaw/param_set.rb
DELETED
@@ -1,111 +0,0 @@
|
|
1
|
-
module TLAW
|
2
|
-
# Represents set of param current API endpoint or namespace have.
|
3
|
-
# You'll never instantiate it directly, just look at {DSL#param} for
|
4
|
-
# param creation. But probably you could make use of knowledge of this
|
5
|
-
# class' API when deep investigating what's going on, like:
|
6
|
-
#
|
7
|
-
# ```ruby
|
8
|
-
# params = api.namespaces[:my_namespace].endpoints[:my_endpoint].param_set
|
9
|
-
# p [params.count, params.names, params.describe]
|
10
|
-
# ```
|
11
|
-
class ParamSet
|
12
|
-
attr_accessor :parent
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@params = {}
|
16
|
-
end
|
17
|
-
|
18
|
-
def add(name, **opts)
|
19
|
-
# Not updating parent param, just make sure it exists
|
20
|
-
return if @parent && @parent.all_params[name]
|
21
|
-
|
22
|
-
@params[name] =
|
23
|
-
if @params[name]
|
24
|
-
@params[name].merge(**opts)
|
25
|
-
else
|
26
|
-
Param.make(name, **opts)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def [](name)
|
31
|
-
@params[name]
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_a
|
35
|
-
@params.values
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_h
|
39
|
-
@params
|
40
|
-
end
|
41
|
-
|
42
|
-
def names
|
43
|
-
@params.keys
|
44
|
-
end
|
45
|
-
|
46
|
-
def empty?
|
47
|
-
@params.empty? && (!@parent || @parent.empty?)
|
48
|
-
end
|
49
|
-
|
50
|
-
def to_code
|
51
|
-
ordered.map(&:to_code).join(', ')
|
52
|
-
end
|
53
|
-
|
54
|
-
def to_hash_code(values = nil)
|
55
|
-
if values
|
56
|
-
names.map { |n| "#{n}: #{values[n].inspect}" }.join(', ')
|
57
|
-
else
|
58
|
-
names.map { |n| "#{n}: #{n}" }.join(', ')
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def describe
|
63
|
-
Util::Description.new(ordered.map(&:describe).join("\n"))
|
64
|
-
end
|
65
|
-
|
66
|
-
def process(**input)
|
67
|
-
validate_unknown(input)
|
68
|
-
|
69
|
-
all_params
|
70
|
-
.map { |name, dfn| [name, dfn, input[name]] }
|
71
|
-
.tap(&method(:validate_required))
|
72
|
-
.reject { |*, val| val.nil? }
|
73
|
-
.map { |_name, dfn, val| [dfn.field, dfn.convert_and_format(val)] }
|
74
|
-
.to_h
|
75
|
-
end
|
76
|
-
|
77
|
-
def all_params
|
78
|
-
(@parent ? @parent.all_params : {}).merge(@params)
|
79
|
-
end
|
80
|
-
|
81
|
-
def inspect
|
82
|
-
"#<#{self.class.name} #{names.join(', ')}"\
|
83
|
-
"#{" (parent=#{parent.inspect})" if parent && !parent.empty?}>"
|
84
|
-
end
|
85
|
-
|
86
|
-
alias_method :to_s, :inspect
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
def validate_unknown(input)
|
91
|
-
(input.keys - all_params.keys).tap { |unknown|
|
92
|
-
unknown.empty? or
|
93
|
-
fail(ArgumentError, "Unknown parameters: #{unknown.join(', ')}")
|
94
|
-
}
|
95
|
-
end
|
96
|
-
|
97
|
-
def validate_required(definitions_and_params)
|
98
|
-
definitions_and_params.each do |name, dfn, val|
|
99
|
-
dfn.required? && val.nil? and
|
100
|
-
fail ArgumentError, "Required parameter #{name} is missing"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def ordered
|
105
|
-
@params.values
|
106
|
-
.partition(&:keyword?).reverse.map { |args|
|
107
|
-
args.partition(&:required?)
|
108
|
-
}.flatten
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
module TLAW
|
2
|
-
# @private
|
3
|
-
# FIXME: everything is awfully dirty here
|
4
|
-
class ResponseProcessor
|
5
|
-
class Base
|
6
|
-
def initialize(&block)
|
7
|
-
@block = block
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(hash)
|
11
|
-
hash.tap(&@block)
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_proc
|
15
|
-
method(:call).to_proc
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class Key < Base
|
20
|
-
def initialize(key, &block)
|
21
|
-
@key = key
|
22
|
-
super(&block)
|
23
|
-
end
|
24
|
-
|
25
|
-
def call(hash)
|
26
|
-
return hash unless hash.is_a?(Hash)
|
27
|
-
hash.keys.grep(@key).inject(hash) do |res, k|
|
28
|
-
res.merge(k => @block.call(hash[k]))
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class Replace < Base
|
34
|
-
def call(hash)
|
35
|
-
@block.call(hash)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class Items < Base
|
40
|
-
def initialize(key, subkey = nil, &block)
|
41
|
-
@key = key
|
42
|
-
@item_processor = subkey ? Key.new(subkey, &block) : Base.new(&block)
|
43
|
-
end
|
44
|
-
|
45
|
-
def call(hash)
|
46
|
-
return hash unless hash.is_a?(Hash)
|
47
|
-
hash.keys.grep(@key).inject(hash) do |res, k|
|
48
|
-
next res unless hash[k].is_a?(Array)
|
49
|
-
res.merge(k => hash[k].map(&@item_processor))
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
attr_reader :post_processors
|
55
|
-
attr_accessor :parent
|
56
|
-
|
57
|
-
def initialize(post_processors = [])
|
58
|
-
@post_processors = post_processors
|
59
|
-
end
|
60
|
-
|
61
|
-
def add_post_processor(key = nil, &block)
|
62
|
-
@post_processors << (key ? Key.new(key, &block) : Base.new(&block))
|
63
|
-
end
|
64
|
-
|
65
|
-
def add_replacer(&block)
|
66
|
-
@post_processors << Replace.new(&block)
|
67
|
-
end
|
68
|
-
|
69
|
-
def add_item_post_processor(key, subkey = nil, &block)
|
70
|
-
@post_processors << Items.new(key, subkey, &block)
|
71
|
-
end
|
72
|
-
|
73
|
-
def process(hash)
|
74
|
-
flatten(hash).derp(&method(:post_process)).derp(&method(:datablize))
|
75
|
-
end
|
76
|
-
|
77
|
-
def all_post_processors
|
78
|
-
[*(parent ? parent.all_post_processors : nil), *@post_processors]
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def flatten(value)
|
84
|
-
case value
|
85
|
-
when Hash
|
86
|
-
flatten_hash(value)
|
87
|
-
when Array
|
88
|
-
value.map(&method(:flatten))
|
89
|
-
else
|
90
|
-
value
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def flatten_hash(hash)
|
95
|
-
hash.flat_map { |k, v|
|
96
|
-
v = flatten(v)
|
97
|
-
if v.is_a?(Hash)
|
98
|
-
v.map { |k1, v1| ["#{k}.#{k1}", v1] }
|
99
|
-
else
|
100
|
-
[[k, v]]
|
101
|
-
end
|
102
|
-
}.reject { |_, v| v.nil? }.to_h
|
103
|
-
end
|
104
|
-
|
105
|
-
def post_process(hash)
|
106
|
-
all_post_processors.inject(hash) { |res, processor|
|
107
|
-
processor.call(res).derp(&method(:flatten))
|
108
|
-
}
|
109
|
-
end
|
110
|
-
|
111
|
-
def datablize(value)
|
112
|
-
case value
|
113
|
-
when Hash
|
114
|
-
value.map { |k, v| [k, datablize(v)] }.to_h
|
115
|
-
when Array
|
116
|
-
if !value.empty? && value.all? { |el| el.is_a?(Hash) }
|
117
|
-
DataTable.new(value)
|
118
|
-
else
|
119
|
-
value
|
120
|
-
end
|
121
|
-
else
|
122
|
-
value
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|