tlaw 0.0.2 → 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +18 -2
  4. data/README.md +10 -7
  5. data/examples/demo_base.rb +2 -2
  6. data/examples/experimental/README.md +3 -0
  7. data/examples/experimental/afterthedeadline.rb +22 -0
  8. data/examples/experimental/airvisual.rb +14 -0
  9. data/examples/experimental/apixu.rb +32 -0
  10. data/examples/experimental/bing_maps.rb +18 -0
  11. data/examples/experimental/currencylayer.rb +25 -0
  12. data/examples/experimental/earthquake.rb +29 -0
  13. data/examples/experimental/freegeoip.rb +16 -0
  14. data/examples/experimental/geonames.rb +98 -0
  15. data/examples/experimental/isfdb.rb +17 -0
  16. data/examples/experimental/musicbrainz.rb +27 -0
  17. data/examples/experimental/nominatim.rb +52 -0
  18. data/examples/experimental/omdb.rb +68 -0
  19. data/examples/experimental/open_exchange_rates.rb +36 -0
  20. data/examples/experimental/open_route.rb +27 -0
  21. data/examples/experimental/open_street_map.rb +16 -0
  22. data/examples/experimental/quandl.rb +50 -0
  23. data/examples/experimental/reddit.rb +25 -0
  24. data/examples/experimental/swapi.rb +27 -0
  25. data/examples/experimental/tmdb.rb +53 -0
  26. data/examples/experimental/world_bank.rb +85 -0
  27. data/examples/experimental/world_bank_climate.rb +77 -0
  28. data/examples/experimental/wunderground.rb +66 -0
  29. data/examples/experimental/wunderground_demo.rb +7 -0
  30. data/examples/forecast_io.rb +16 -16
  31. data/examples/giphy.rb +4 -4
  32. data/examples/giphy_demo.rb +1 -1
  33. data/examples/open_weather_map.rb +64 -60
  34. data/examples/open_weather_map_demo.rb +4 -4
  35. data/examples/tmdb_demo.rb +1 -1
  36. data/examples/urbandictionary_demo.rb +2 -2
  37. data/lib/tlaw.rb +14 -15
  38. data/lib/tlaw/api.rb +108 -26
  39. data/lib/tlaw/api_path.rb +86 -87
  40. data/lib/tlaw/data_table.rb +15 -10
  41. data/lib/tlaw/dsl.rb +126 -224
  42. data/lib/tlaw/dsl/api_builder.rb +47 -0
  43. data/lib/tlaw/dsl/base_builder.rb +108 -0
  44. data/lib/tlaw/dsl/endpoint_builder.rb +26 -0
  45. data/lib/tlaw/dsl/namespace_builder.rb +86 -0
  46. data/lib/tlaw/endpoint.rb +63 -85
  47. data/lib/tlaw/formatting.rb +55 -0
  48. data/lib/tlaw/formatting/describe.rb +86 -0
  49. data/lib/tlaw/formatting/inspect.rb +52 -0
  50. data/lib/tlaw/namespace.rb +141 -98
  51. data/lib/tlaw/param.rb +45 -141
  52. data/lib/tlaw/param/type.rb +36 -49
  53. data/lib/tlaw/response_processors.rb +81 -0
  54. data/lib/tlaw/util.rb +16 -33
  55. data/lib/tlaw/version.rb +6 -3
  56. data/tlaw.gemspec +9 -9
  57. metadata +63 -13
  58. data/lib/tlaw/param_set.rb +0 -111
  59. data/lib/tlaw/response_processor.rb +0 -126
data/lib/tlaw/version.rb CHANGED
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TLAW
2
4
  MAJOR = 0
3
- MINOR = 0
4
- PATCH = 2
5
+ MINOR = 1
6
+ PATCH = 0
7
+ PRE = 'pre'
5
8
 
6
- VERSION = [MAJOR, MINOR, PATCH].join('.')
9
+ VERSION = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
7
10
  end
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 = 'zverok.offline@gmail.com'
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 = 'Here would be summary'
11
- s.description = <<-EOF
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.required_ruby_version = '>= 2.1.0'
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', '>= 0.40'
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.2
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: 2017-07-31 00:00:00.000000000 Z
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.40'
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.40'
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: " And here would be description.\n"
238
- email: zverok.offline@gmail.com
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/param_set.rb
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.1.0
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: '0'
339
+ version: 1.3.1
290
340
  requirements: []
291
341
  rubyforge_project:
292
- rubygems_version: 2.6.10
342
+ rubygems_version: 2.6.14
293
343
  signing_key:
294
344
  specification_version: 4
295
- summary: Here would be summary
345
+ summary: 'The Last API Wrapper: Pragmatic API wrapper framework'
296
346
  test_files: []
@@ -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