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.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37f3ec860edbe2fac8ea3e85b3e0d2d75392ee15
4
- data.tar.gz: b11a83253074b9dfb89c650bd46b155359f4b3f9
3
+ metadata.gz: '009cee34cd6c91e7fdb5a24914d1b8ffcb7c0639'
4
+ data.tar.gz: ab895dc56817673f6222f930a59fc525ff72fff3
5
5
  SHA512:
6
- metadata.gz: e2ad59fcbebd0f0302dbda95365c6c46f15baf8b9333a0bd78c7720540f62785909d6fb3baa07581dd1a504a70527ec047713150c79239ffdcc7566bfa2ba2a1
7
- data.tar.gz: e4cddec1d3e1074001a71dfd6a3858c7afdc57e11f5129ce35fd99d91d8635102b381c4f33b56edd53a974393c792bbbe1f357cd992b484877c0a84c39348039
6
+ metadata.gz: f5e188083216814e176d0c0161a424f9d124272411c8c15ca54b3ed3f7367d1f62e689c61ec80cc8feb22c2231178638dc1c7f066cac199dd383ab4861bbe754
7
+ data.tar.gz: 78c2c75ba92efde05fdb927198fe4a565da0a5ce53d94dd1142b2592f980edeaca11a9018fe5d2e6ef4bc759a9ee49ffd5f3257b5326ab1b44a3b146744e131f
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.0
data/CHANGELOG.md CHANGED
@@ -1,11 +1,27 @@
1
1
  # The Last API Wrapper Changelog
2
2
 
3
- # 0.0.2 (2017-07-31)
3
+ ## 0.1.0.pre (2018-12-21)
4
+
5
+ * `Namespace#children` is an `Array` now, with `Namespace#child_index` being a `Hash` (@marcandre);
6
+ * DSL now can accept strings as a Namespace/Endpoint name (@marcandre);
7
+ * Classes' `.inspect` fixed to match Ruby's conventions (@marcandre);
8
+ * Improved object tree navigation (@marcandre):
9
+ * `APIPath#parent`, `APIPath.parent` (immediate parent class/object);
10
+ * `APIPath#parents`, `APIPath.parents` (parent classes/objects all the way up);
11
+ * `Namespace#traverse` (depth-first children tree enumeration).
12
+ * Lots of refactoring (better call it "rewrite", honestly), internal structure was simplified and
13
+ decoupled, API and DSL was kept the same (I hope).
14
+ * I am really thankful to @marcandre and @joelvh for cleaning up job they've done. Sorry, guys,
15
+ eventually I've rewrote the thing completely :)
16
+ * Added `shared_def`/`use_def` to reuse some common parts of definitions (thanks @marcandre for
17
+ discussion).
18
+
19
+ ## 0.0.2 (2017-07-31)
4
20
 
5
21
  * Codebase modernized and rubocopped;
6
22
  * Support for redirects;
7
23
  * Support for pattern-based (regexp) postprocessors.
8
24
 
9
- # 0.0.1 (2016-09-19)
25
+ ## 0.0.1 (2016-09-19)
10
26
 
11
27
  Initial release.
data/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
  [![Build Status](https://travis-ci.org/molybdenum-99/tlaw.svg?branch=master)](https://travis-ci.org/molybdenum-99/tlaw)
5
5
  [![Coverage Status](https://coveralls.io/repos/molybdenum-99/tlaw/badge.svg?branch=master)](https://coveralls.io/r/molybdenum-99/tlaw?branch=master)
6
6
 
7
- **TLAW** (pronounce it like "tea+love"... or whatever) is the last (and
8
- only) API wrapper framework for _get-only APIes_<sup>[*](#get-only-api)</sup>
9
- (think weather, search, economical indicators, geonames and so on).
7
+ **TLAW** (pronounce it like "tea+love"... or whatever) is the last (and only)
8
+ API wrapper framework you'll ever need for accessing _GET-only APIs_<sup>[*](#get-only-api)</sup>
9
+ in a consistent way (think weather, search, economical indicators, geonames and so on).
10
10
 
11
11
  ## Table Of Contents
12
12
 
@@ -68,6 +68,9 @@ options:
68
68
  TLAW tries to close this gap: provide a base for _breath-easy_ API description
69
69
  which produces solid, fast and reliable wrappers.
70
70
 
71
+ See also a [showcase blog post](http://zverok.github.io/blog/2017-07-31-giphy-tlaw.html) with on-the-fly
72
+ API wrapper building for GIPHY.
73
+
71
74
  ## Usage
72
75
 
73
76
  ### URLs and params description
@@ -88,7 +91,7 @@ class Example < TLAW::API
88
91
  # Method is still e.bar, though.
89
92
 
90
93
  # Now, for params definition:
91
- endpont :movie do
94
+ endpoint :movie do
92
95
  param :id
93
96
  end
94
97
  # Method call would be movie(id: '123')
@@ -299,7 +302,7 @@ post_process_items('foo') {
299
302
 
300
303
  # More realistic examples:
301
304
  post_process('meta.count', &:to_i)
302
- post_process('daily') {
305
+ post_process_items('daily') {
303
306
  post_process('date', &Date.method(:parse))
304
307
  }
305
308
  post_process('auxiliary_value') { nil } # Nil's will be thrown away completely
@@ -311,9 +314,9 @@ See full post-processing features descriptions in
311
314
  #### All at once
312
315
 
313
316
  All described response processing steps are performed in this order:
317
+
314
318
  * parsing and initial flattening of JSON (or XML) hash;
315
- * applying post-processors (and flatten the response after _each_ of
316
- them);
319
+ * applying post-processors (and flatten the response after _each_ of them);
317
320
  * make `DataTable`s from arrays of hashes.
318
321
 
319
322
  ### Documentability
@@ -1,7 +1,7 @@
1
- require 'pp'
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
2
 
3
- $:.unshift 'lib'
4
3
  require 'tlaw'
4
+ require 'pp'
5
5
 
6
6
  begin
7
7
  require 'dotenv'
@@ -0,0 +1,3 @@
1
+ This folder contains examples of TLAW usage that may or may not be working.
2
+
3
+ Most of them are semi-ready, some are outdated. The main target of it is having a lot of "real" cases to guide further TLAW design.
@@ -0,0 +1,22 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ #http://docs.themoviedb.apiary.io/#reference/movies/movielatest
7
+
8
+ class AfterTheDeadline < TLAW::API
9
+ define do
10
+ base 'http://service.afterthedeadline.com'
11
+
12
+ param :key, required: true
13
+
14
+ endpoint :document, '/checkDocument', xml: true do
15
+ param :data, keyword: false
16
+ end
17
+ end
18
+ end
19
+
20
+ atd = AfterTheDeadline.new(key: 'test-tlaw')
21
+
22
+ pp atd.document("Isn't it cool and cute and awesme? Yepx it is.")['results.error'].to_a
@@ -0,0 +1,14 @@
1
+ require_relative '../demo_base'
2
+
3
+ class AirVisual < TLAW::API
4
+ define do
5
+ base 'http://api.airvisual.com/v1'
6
+ param :key, required: true
7
+
8
+ endpoint :nearest, '/nearest?lat={latitude}&lon={longitude}' do
9
+ end
10
+ end
11
+ end
12
+
13
+ av = AirVisual.new(key: ENV['AIRVISUAL'])
14
+ pp av.nearest(50.004444, 36.231389)
@@ -0,0 +1,32 @@
1
+ require_relative '../demo_base'
2
+
3
+ class APIXU < TLAW::API
4
+ define do
5
+ docs 'https://www.apixu.com/doc/'
6
+
7
+ base 'http://api.apixu.com/v1'
8
+
9
+ param :key, required: true
10
+ param :lang
11
+
12
+ namespace :current, '/current.json' do
13
+ endpoint :city, '?q={city}' do
14
+ param :city, :to_s, required: true
15
+ end
16
+ end
17
+
18
+ namespace :forecast, '/forecast.json' do
19
+ endpoint :city, '?q={city}' do
20
+ param :city, :to_s, required: true
21
+ param :days, :to_i
22
+ param :dt, Date, format: ->(dt) { dt.strftime('%Y-%m-%d') }
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ apixu = APIXU.new(key: ENV['APIXU'], lang: 'uk')
29
+ pp apixu.current.city('Kharkiv')
30
+ #res = apixu.forecast.city('Odesa', days: 10, dt: Date.parse('2017-07-03'))
31
+ #pp res['forecast.forecastday']['day.mintemp_c']
32
+ #pp res['forecast.forecastday']['day.maxtemp_c']
@@ -0,0 +1,18 @@
1
+ require_relative '../demo_base'
2
+
3
+ #http://docs.themoviedb.apiary.io/#reference/movies/movielatest
4
+
5
+ class BingMaps < TLAW::API
6
+ define do
7
+ base 'http://dev.virtualearth.net/REST/v1'
8
+ param :key, required: true
9
+
10
+ namespace :locations, '/Locations' do
11
+ endpoint :query, '?q={q}'
12
+ end
13
+ end
14
+ end
15
+
16
+ maps = BingMaps.new(key: ENV['BING_MAPS'])
17
+
18
+ pp maps.locations.query('Харків, Олексіівська 33а')['resourceSets'].first
@@ -0,0 +1,25 @@
1
+ require_relative '../demo_base'
2
+
3
+ class CurrencyLayer < TLAW::API
4
+ define do
5
+ base 'http://apilayer.net/api/'
6
+
7
+ param :access_key, required: true
8
+
9
+ endpoint :live do
10
+ param :currencies, Array
11
+ end
12
+
13
+ endpoint :historical do
14
+ param :date, :to_date, required: :true, keyword: false, format: ->(d) { d.strftime('%Y-%m-%d') }
15
+ param :currencies, Array
16
+
17
+ post_process 'date', &Date.method(:parse)
18
+ post_process 'timestamp', &Time.method(:at)
19
+ end
20
+ end
21
+ end
22
+
23
+ cur = CurrencyLayer.new(access_key: ENV['CURRENCYLAYER'])
24
+
25
+ pp cur.historical(Date.parse('2016-01-01'), currencies: %w[UAH])
@@ -0,0 +1,29 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class Earthquake < TLAW::API
7
+ define do
8
+ base 'http://earthquake.usgs.gov/fdsnws/event/1'
9
+
10
+ endpoint :count, '/count?format=geojson' do
11
+ param :starttime, Date, format: ->(d) { d.strftime('%Y-%m-%d') }
12
+ param :endtime, Date, format: ->(d) { d.strftime('%Y-%m-%d') }
13
+ end
14
+
15
+ endpoint :query, '/query?format=geojson' do
16
+ param :starttime, Date, format: ->(d) { d.strftime('%Y-%m-%d') }
17
+ param :endtime, Date, format: ->(d) { d.strftime('%Y-%m-%d') }
18
+ param :minmagnitude, :to_i
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ #/query?format=geojson&starttime=2001-01-01&endtime=2014-01-02
25
+
26
+ e = Earthquake.new
27
+ res = e.query(starttime: Date.parse('2000-01-01'), endtime: Date.parse('2017-01-02'), minmagnitude: 9)
28
+ pp res['features'].count
29
+ pp res['features'].first
@@ -0,0 +1,16 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class FreeGeoIP < TLAW::API
7
+ define do
8
+ base 'http://freegeoip.net/json/'
9
+
10
+ endpoint :here, ''
11
+ endpoint :at, '/{ip}'
12
+ end
13
+ end
14
+
15
+ fgi = FreeGeoIP.new
16
+ pp fgi.here
@@ -0,0 +1,98 @@
1
+ require_relative '../demo_base'
2
+ require 'geo/coord'
3
+
4
+ #http://www.geonames.org/export/web-services.html
5
+ #http://www.geonames.org/export/credits.html
6
+ #http://www.geonames.org/export/ws-overview.html
7
+
8
+ class GeoNames < TLAW::API
9
+ define do
10
+ base 'http://api.geonames.org'
11
+
12
+ param :username, required: true
13
+ param :lang
14
+
15
+ ERROR_CODES = {
16
+ 10 => 'Authorization Exception',
17
+ 11 => 'record does not exist',
18
+ 12 => 'other error',
19
+ 13 => 'database timeout',
20
+ 14 => 'invalid parameter',
21
+ 15 => 'no result found',
22
+ 16 => 'duplicate exception',
23
+ 17 => 'postal code not found',
24
+ 18 => 'daily limit of credits exceeded',
25
+ 19 => 'hourly limit of credits exceeded',
26
+ 20 => 'weekly limit of credits exceeded',
27
+ 21 => 'invalid input',
28
+ 22 => 'server overloaded exception',
29
+ 23 => 'service not implemented',
30
+ }
31
+
32
+ post_process do |response|
33
+ if response['status.value']
34
+ fail "#{ERROR_CODES[response['status.value']]}: #{response['status.message']}"
35
+ end
36
+ end
37
+
38
+ namespace :search, path: '/searchJSON' do
39
+ endpoint :query, path: '?q={q}' do
40
+ param :q, required: true
41
+ param :country #TODO: country=FR&country=GP
42
+ end
43
+
44
+ endpoint :name, path: '?name={name}' do
45
+ param :name, required: true
46
+ end
47
+
48
+ endpoint :name_equals, path: '?name_equals={name}' do
49
+ param :name, required: true
50
+ end
51
+ end
52
+
53
+ namespace :postal_codes, path: '' do
54
+ endpoint :countries, path: '/postalCodeCountryInfoJSON'
55
+ end
56
+
57
+ namespace :near, path: '' do
58
+ param :lat, keyword: false
59
+ param :lng, keyword: false
60
+
61
+ endpoint :ocean, path: '/oceanJSON'
62
+ endpoint :country, path: '/countryCodeJSON'
63
+ endpoint :weather, path: '/findNearByWeatherJSON'
64
+ endpoint :extended, path: '/extendedFindNearby', xml: true do
65
+ post_process_replace { |res| res['geonames.geoname'] }
66
+ end
67
+ end
68
+
69
+ namespace :weather, path: '' do
70
+ endpoint :near, path: '/findNearByWeatherJSON?lat={lat}&lng={lng}'
71
+ end
72
+
73
+ endpoint :earthquakes, path: '/earthquakesJSON' do
74
+ param :north
75
+ param :south
76
+ param :east
77
+ param :west
78
+
79
+ post_process_items 'earthquakes' do
80
+ post_process 'datetime', &Time.method(:parse)
81
+ post_process { |h| h['coord'] = Geo::Coord.new(h['lat'], h['lng']) }
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ gn = GeoNames.new(username: ENV.fetch('GEONAMES'))
88
+
89
+ #pp gn.search.name_equals('Kharkiv')['geonames'].to_a
90
+ #pp gn.postal_codes.countries['geonames'].detect { |r| r['countryName'].include?('Thai') }
91
+ #pp gn.near(50.004444, 36.231389).country
92
+ #pp gn.near(50.004444, 36.231389).ocean
93
+ pp gn.near(50.004444, 36.231389).extended.to_a
94
+ #pp gn.near(50.004444, 36.231389).weather
95
+ #pp gn.weather.near(50.004444, 36.231389)
96
+
97
+ #pp gn.earthquakes(north: 44.1, south: -9.9, east: -22.4, west: 55.2)['earthquakes'].to_a
98
+ # => to worldize!
@@ -0,0 +1,17 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class ISFDB < TLAW::API
7
+ define do
8
+ base 'http://www.isfdb.org/cgi-bin/rest'
9
+
10
+ endpoint :isbn, '/getpub.cgi?{isbn}', xml: true
11
+ end
12
+ end
13
+
14
+ i = ISFDB.new
15
+
16
+ #pp i.isbn('0399137378')["ISFDB.Publications.Publication"].last
17
+ pp i.isbn('038533348X')["ISFDB.Publications.Publication"].to_a
@@ -0,0 +1,27 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class MusicBrainz < TLAW::API
7
+ define do
8
+ base 'http://musicbrainz.org/ws/2'
9
+
10
+ endpoint :area, '/area/{id}?fmt=json'
11
+
12
+ namespace :artist do
13
+ endpoint :area, '?area={area_id}&fmt=json'
14
+ endpoint :get, '/{id}?fmt=json' do
15
+ param :inc, :to_a, format: ->(a) { a.join('+') }
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ mb = MusicBrainz.new
22
+
23
+ #pp mb.area '37572420-4b2c-47e5-bf2b-536c9a50a362'
24
+ #pp mb.artist.area('904768d0-61ca-3c40-93ac-93adc36fef4b')['artists'].first
25
+ res = mb.artist.get('00496bc8-93bf-4284-a3ea-cfd97eb99b2f', inc: %w[recordings releases release-groups works])
26
+ pp res['recordings'].first
27
+ pp res['releases'].first
@@ -0,0 +1,52 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class Nominatim < TLAW::API
7
+ define do
8
+ base 'http://nominatim.openstreetmap.org'
9
+
10
+ param :lang, field: 'accept%2Dlanguage'
11
+
12
+ namespace :search, '/search?format=json' do
13
+ endpoint :query, '' do
14
+ param :query, field: :q, keyword: false
15
+
16
+ param :details, field: :addressdetails, enum: {false => 0, true => 1}
17
+ param :geojson, field: :polygon_geojson, enum: {false => 0, true => 1}
18
+ param :tags, field: :extratags, enum: {false => 0, true => 1}
19
+ param :limit
20
+ end
21
+
22
+ endpoint :address, '' do
23
+ param :city
24
+ param :country
25
+ param :street
26
+ param :postalcode
27
+ param :details, field: :addressdetails, enum: {false => 0, true => 1}
28
+ param :geojson, field: :polygon_geojson, enum: {false => 0, true => 1}
29
+ param :tags, field: :extratags, enum: {false => 0, true => 1}
30
+ end
31
+ end
32
+
33
+ endpoint :geocode, '/reverse?format=json' do
34
+ param :lat, :to_f, keyword: false
35
+ param :lng, :to_f, field: :lon, keyword: false
36
+ end
37
+
38
+ endpoint :lookup, '/lookup?format=json&osm_ids={ids}' do
39
+ param :ids # , splat: true -- TODO
40
+ end
41
+ end
42
+ end
43
+
44
+ n = Nominatim.new(lang: 'en')
45
+
46
+ #pp n.search.address(country: 'Ukraine', city: 'Kharkiv', street: '33a Oleksiivska', details: true, geojson: true, tags: true).first
47
+ # pp n.search.query('New York, Times Square', details: true, tags: true, limit: 1).to_a
48
+ #pp n.geocode(50.0403843, 36.203339684)
49
+ #pp n.search.query('Pharmacy, Kharkiv', details: true, tags: true, limit: 100)['address.pharmacy'].compact
50
+ #pp n.geocode(49.9808, 36.2527)
51
+ # pp n.search.address(country: 'Thailand', city: 'Bangkok', details: true, tags: true).to_a
52
+ pp n.search.query('Oleksiivska 33a, Kharkiv, Ukraine').to_a