eclaircir 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +21 -0
  6. data/README.md +70 -0
  7. data/Rakefile +12 -0
  8. data/TODO.md +75 -0
  9. data/bin/console +10 -0
  10. data/bin/test.rb +17 -0
  11. data/eclaircir.gemspec +20 -0
  12. data/lib/eclaircir/api_models/attributes/nullable_date_time.rb +15 -0
  13. data/lib/eclaircir/api_models/attributes.rb +8 -0
  14. data/lib/eclaircir/api_models/base_model.rb +11 -0
  15. data/lib/eclaircir/api_models/concept.rb +12 -0
  16. data/lib/eclaircir/api_models/data.rb +17 -0
  17. data/lib/eclaircir/api_models/input.rb +22 -0
  18. data/lib/eclaircir/api_models/media.rb +9 -0
  19. data/lib/eclaircir/api_models/model.rb +29 -0
  20. data/lib/eclaircir/api_models/output.rb +14 -0
  21. data/lib/eclaircir/api_models/response.rb +16 -0
  22. data/lib/eclaircir/api_models/status.rb +46 -0
  23. data/lib/eclaircir/api_models.rb +16 -0
  24. data/lib/eclaircir/client/status_validator.rb +30 -0
  25. data/lib/eclaircir/client.rb +85 -0
  26. data/lib/eclaircir/configuration.rb +16 -0
  27. data/lib/eclaircir/constants.rb +5 -0
  28. data/lib/eclaircir/error.rb +27 -0
  29. data/lib/eclaircir/version.rb +5 -0
  30. data/lib/eclaircir.rb +32 -0
  31. data/spec/eclaircir/api_models/concept_spec.rb +32 -0
  32. data/spec/eclaircir/api_models/data_spec.rb +104 -0
  33. data/spec/eclaircir/api_models/input_spec.rb +70 -0
  34. data/spec/eclaircir/api_models/media_spec.rb +15 -0
  35. data/spec/eclaircir/api_models/model_spec.rb +109 -0
  36. data/spec/eclaircir/api_models/output_spec.rb +42 -0
  37. data/spec/eclaircir/api_models/response_spec.rb +63 -0
  38. data/spec/eclaircir/api_models/status_spec.rb +67 -0
  39. data/spec/eclaircir/client/status_validator_spec.rb +77 -0
  40. data/spec/eclaircir/client_spec.rb +123 -0
  41. data/spec/eclaircir/configuration_spec.rb +64 -0
  42. data/spec/eclaircir_spec.rb +55 -0
  43. data/spec/etc/fixtures/predict_outputs/invalid_request.json +7 -0
  44. data/spec/etc/fixtures/predict_outputs/success.json +58 -0
  45. data/spec/factories/concept.rb +8 -0
  46. data/spec/factories/data.rb +13 -0
  47. data/spec/factories/input.rb +7 -0
  48. data/spec/factories/media.rb +6 -0
  49. data/spec/factories/model.rb +9 -0
  50. data/spec/factories/response.rb +7 -0
  51. data/spec/factories/status.rb +7 -0
  52. data/spec/spec_helper.rb +53 -0
  53. metadata +122 -0
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe Eclaircir::Client do
4
+ subject do
5
+ described_class.new(api_key)
6
+ end
7
+
8
+ let(:api_key) do
9
+ 'xxx'
10
+ end
11
+
12
+ describe '#models' do
13
+ before do
14
+ stub_request(:get, 'https://api.clarifai.com/v2/models')
15
+ .with(headers: {
16
+ 'Content-Type' => 'application/json',
17
+ 'Authorization' => 'Key xxx',
18
+ })
19
+ end
20
+
21
+ it 'uses the right authorization header' do
22
+ expect do
23
+ subject.models
24
+ end.not_to raise_error
25
+ end
26
+ end
27
+
28
+ describe '#predict_outputs' do
29
+ before do
30
+ stub_request(:post, 'https://api.clarifai.com/v2/models/blah/outputs')
31
+ .with(
32
+ headers: {
33
+ 'Content-Type' => 'application/json',
34
+ 'Authorization' => 'Key xxx',
35
+ },
36
+ body: {
37
+ 'inputs' => [
38
+ {
39
+ 'data' => {
40
+ 'image' => {
41
+ 'url' => 'http://example.com/lol.jpg'
42
+ },
43
+ 'concepts' => []
44
+ }
45
+ }
46
+ ]
47
+ }.to_json)
48
+ .to_return(status: status, body: body)
49
+ end
50
+
51
+ let(:predicted_outputs) do
52
+ subject.predict_outputs(model, input)
53
+ end
54
+
55
+ let(:model) do
56
+ build(:model, id: 'blah')
57
+ end
58
+
59
+ let(:input) do
60
+ Eclaircir::Input.new(
61
+ data: Eclaircir::Data.new(
62
+ image: Eclaircir::Media.new(
63
+ url: 'http://example.com/lol.jpg')))
64
+ end
65
+
66
+ context 'when the status code is 2xx' do
67
+ let(:status) do
68
+ 201
69
+ end
70
+
71
+ let(:body) do
72
+ load_fixture('predict_outputs/success.json')
73
+ end
74
+
75
+ before do
76
+ allow(Eclaircir::Response)
77
+ .to receive(:parse)
78
+ .with(JSON.parse(body))
79
+ .and_return(fake_response)
80
+
81
+ allow(Eclaircir::Client::StatusValidator)
82
+ .to receive(:new)
83
+ .with(fake_response)
84
+ .and_return(status_validator)
85
+ end
86
+
87
+ let(:fake_response) do
88
+ instance_double(Eclaircir::Response)
89
+ end
90
+
91
+ let(:status_validator) do
92
+ instance_double(Eclaircir::Client::StatusValidator,
93
+ validate!: true)
94
+ end
95
+
96
+ it 'returns a parsed response' do
97
+ expect(predicted_outputs).to be fake_response
98
+ end
99
+
100
+ it 'delegates the response to the status validator' do
101
+ expect(status_validator).to receive(:validate!)
102
+
103
+ predicted_outputs
104
+ end
105
+ end
106
+
107
+ context 'when the status code is not 2xx' do
108
+ let(:status) do
109
+ 400
110
+ end
111
+
112
+ let(:body) do
113
+ load_fixture('predict_outputs/invalid_request.json')
114
+ end
115
+
116
+ it 'raises a Eclaircir::APIError with the status message' do
117
+ expect do
118
+ predicted_outputs
119
+ end.to raise_error(Eclaircir::APIError, /Invalid request/)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Eclaircir::Configuration do
4
+ subject do
5
+ described_class.new(params)
6
+ end
7
+
8
+ let(:params) do
9
+ {
10
+ env: env,
11
+ api_key: api_key,
12
+ }
13
+ end
14
+
15
+ let(:env) do
16
+ {}
17
+ end
18
+
19
+ let(:api_key) do
20
+ 'xyzzy'
21
+ end
22
+
23
+ describe '#api_key' do
24
+ context 'when the api_key is provided explicitely' do
25
+ it 'returns provided api_key' do
26
+ expect(subject.api_key).to eq 'xyzzy'
27
+ end
28
+ end
29
+
30
+ context 'when the api_key is not provided explicitely' do
31
+ let(:api_key) do
32
+ nil
33
+ end
34
+
35
+ context 'when the CLARIFIER_API_KEY env var is provided' do
36
+ let(:env) do
37
+ {
38
+ 'CLARIFIER_API_KEY' => 'xxx'
39
+ }
40
+ end
41
+
42
+ it 'returns the CLARIFIER_API_KEY env var value' do
43
+ expect(subject.api_key).to eq 'xxx'
44
+ end
45
+ end
46
+
47
+ context 'when the CLARIFIER_API_KEY env var is not provided' do
48
+ its(:api_key) { is_expected.to be_nil }
49
+ end
50
+ end
51
+ end
52
+
53
+ describe '#api_key=' do
54
+ it 'changes the api_key' do
55
+ expect { subject.api_key = 'yoloswag' }.to change { subject.api_key }
56
+ end
57
+
58
+ it 'sets the right value' do
59
+ subject.api_key = 'yoloswag'
60
+
61
+ expect(subject.api_key).to eq 'yoloswag'
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Eclaircir do
4
+ describe '.configuration' do
5
+ it 'returns a new configuration' do
6
+ expect(described_class.configuration).to be_a Eclaircir::Configuration
7
+ end
8
+ end
9
+
10
+ describe '.configure' do
11
+ before do
12
+ allow(described_class)
13
+ .to receive(:configuration)
14
+ .and_return(fake_configuration)
15
+ end
16
+
17
+ let(:fake_configuration) do
18
+ instance_double(Eclaircir::Configuration)
19
+ end
20
+
21
+ it 'yields the configuration' do
22
+ expect do |b|
23
+ described_class.configure(&b)
24
+ end.to yield_with_args(fake_configuration)
25
+ end
26
+ end
27
+
28
+ describe '.new_client' do
29
+ before do
30
+ allow(described_class)
31
+ .to receive(:configuration)
32
+ .and_return(fake_configuration)
33
+ end
34
+
35
+ let(:fake_configuration) do
36
+ instance_double(Eclaircir::Configuration,
37
+ api_key: 'xxx')
38
+ end
39
+
40
+ before do
41
+ expect(Eclaircir::Client)
42
+ .to receive(:new)
43
+ .with('xxx')
44
+ .and_return(fake_client)
45
+ end
46
+
47
+ let(:fake_client) do
48
+ instance_double(Eclaircir::Client)
49
+ end
50
+
51
+ it 'builds and returns the client correctly' do
52
+ expect(described_class.new_client).to be fake_client
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ {
2
+ "status": {
3
+ "code": 11102,
4
+ "description": "Invalid request",
5
+ "details": "Malformed or invalid request"
6
+ }
7
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "status": {
3
+ "code": 10000,
4
+ "description": "Ok"
5
+ },
6
+ "outputs": [
7
+ {
8
+ "id": "ea68cac87c304b28a8046557062f34a0",
9
+ "status": {
10
+ "code": 10000,
11
+ "description": "Ok"
12
+ },
13
+ "created_at": "2016-11-22T16:50:25Z",
14
+ "model": {
15
+ "name": "general-v1.3",
16
+ "id": "aaa03c23b3724a16a56b629203edc62c",
17
+ "created_at": "2016-03-09T17:11:39Z",
18
+ "app_id": null,
19
+ "output_info": {
20
+ "message": "Show output_info with: GET /models/{model_id}/output_info",
21
+ "type": "concept"
22
+ },
23
+ "model_version": {
24
+ "id": "aa9ca48295b37401f8af92ad1af0d91d",
25
+ "created_at": "2016-07-13T01:19:12Z",
26
+ "status": {
27
+ "code": 21100,
28
+ "description": "Model trained successfully"
29
+ }
30
+ }
31
+ },
32
+ "input": {
33
+ "id": "ea68cac87c304b28a8046557062f34a0",
34
+ "data": {
35
+ "image": {
36
+ "url": "https://samples.clarifai.com/metro-north.jpg"
37
+ }
38
+ }
39
+ },
40
+ "data": {
41
+ "concepts": [
42
+ {
43
+ "id": "ai_HLmqFqBf",
44
+ "name": "train",
45
+ "app_id": null,
46
+ "value": 0.9989112
47
+ },
48
+ {
49
+ "id": "ai_fvlBqXZR",
50
+ "name": "railway",
51
+ "app_id": null,
52
+ "value": 0.9975532
53
+ }
54
+ ]
55
+ }
56
+ }
57
+ ]
58
+ }
@@ -0,0 +1,8 @@
1
+ FactoryBot.define do
2
+ factory :concept, class: Eclaircir::Concept do
3
+ id { Faker::Base.regexify(%r/ai_[A-z0-9]{8}/) }
4
+ name { Faker::Food.ingredient }
5
+ value { rand(0.4..1.0).round(7) }
6
+ initialize_with { Eclaircir::Concept.new(attributes) }
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ FactoryBot.define do
2
+ factory :data, class: Eclaircir::Data do
3
+ trait :image do
4
+ image { build(:media) }
5
+ end
6
+
7
+ trait :with_concepts do
8
+ concepts { build_list(:concept, 3) }
9
+ end
10
+
11
+ initialize_with { Eclaircir::Data.new(attributes) }
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :input, class: Eclaircir::Input do
3
+ id { Faker::Base.regexify(%r/[a-f0-9]{32}/) }
4
+ data { build(:data, :image) }
5
+ initialize_with { Eclaircir::Input.new(attributes) }
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :media, class: Eclaircir::Media do
3
+ url { Faker::Internet.url }
4
+ initialize_with { Eclaircir::Media.new(attributes) }
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ FactoryBot.define do
2
+ factory :model, class: Eclaircir::Model do
3
+ id { Faker::Base.regexify(%r/[a-f0-9]{32}/) }
4
+ name { Faker::Food.ingredient }
5
+ created_at { DateTime.now }
6
+ app_id nil
7
+ initialize_with { Eclaircir::Model.new(attributes) }
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :response, class: Eclaircir::Response do
3
+ status { build(:status) }
4
+ outputs { build_list(:output, 1) }
5
+ initialize_with { Eclaircir::Response.new(attributes) }
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :status, class: Eclaircir::Status do
3
+ code { rand(10_000..20_000) }
4
+ description { Faker::Lorem.sentence }
5
+ initialize_with { Eclaircir::Status.new(attributes) }
6
+ end
7
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ require 'dotenv'
6
+ Dotenv.load
7
+
8
+ require 'simplecov'
9
+ require 'coveralls'
10
+
11
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
12
+ SimpleCov::Formatter::HTMLFormatter,
13
+ Coveralls::SimpleCov::Formatter
14
+ ]
15
+
16
+ SimpleCov.start do
17
+ add_filter ENV['GEM_HOME'] if ENV.fetch('GEM_HOME', '').include?('bundle')
18
+ add_filter 'spec/support'
19
+ add_filter '.bundle'
20
+ add_group 'Library', 'lib'
21
+ add_group 'Specs', 'spec'
22
+ end
23
+
24
+ require 'eclaircir'
25
+ require 'pp'
26
+ require 'byebug'
27
+ require 'rspec'
28
+ require 'rspec/its'
29
+ require 'webmock/rspec'
30
+ require 'factory_bot'
31
+ require 'faker'
32
+
33
+ Dir["./spec/factories/**/*.rb"].sort.each do |factory|
34
+ require factory
35
+ end
36
+
37
+ RSpec.configure do |config|
38
+ config.expect_with :rspec do |c|
39
+ c.syntax = :expect
40
+ end
41
+
42
+ config.include FactoryBot::Syntax::Methods
43
+ end
44
+
45
+ def load_fixture(fixture_path)
46
+ complete_path = File.join(
47
+ File.dirname(__FILE__),
48
+ 'etc',
49
+ 'fixtures',
50
+ fixture_path)
51
+
52
+ File.read(complete_path)
53
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eclaircir
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Karim Bogtob
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.14.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: virtus
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ description: Ruby Clarifai API wrapper that aims to be complete, tested and covered
42
+ email: kabogtob@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - ".gitignore"
48
+ - ".travis.yml"
49
+ - Gemfile
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - TODO.md
54
+ - bin/console
55
+ - bin/test.rb
56
+ - eclaircir.gemspec
57
+ - lib/eclaircir.rb
58
+ - lib/eclaircir/api_models.rb
59
+ - lib/eclaircir/api_models/attributes.rb
60
+ - lib/eclaircir/api_models/attributes/nullable_date_time.rb
61
+ - lib/eclaircir/api_models/base_model.rb
62
+ - lib/eclaircir/api_models/concept.rb
63
+ - lib/eclaircir/api_models/data.rb
64
+ - lib/eclaircir/api_models/input.rb
65
+ - lib/eclaircir/api_models/media.rb
66
+ - lib/eclaircir/api_models/model.rb
67
+ - lib/eclaircir/api_models/output.rb
68
+ - lib/eclaircir/api_models/response.rb
69
+ - lib/eclaircir/api_models/status.rb
70
+ - lib/eclaircir/client.rb
71
+ - lib/eclaircir/client/status_validator.rb
72
+ - lib/eclaircir/configuration.rb
73
+ - lib/eclaircir/constants.rb
74
+ - lib/eclaircir/error.rb
75
+ - lib/eclaircir/version.rb
76
+ - spec/eclaircir/api_models/concept_spec.rb
77
+ - spec/eclaircir/api_models/data_spec.rb
78
+ - spec/eclaircir/api_models/input_spec.rb
79
+ - spec/eclaircir/api_models/media_spec.rb
80
+ - spec/eclaircir/api_models/model_spec.rb
81
+ - spec/eclaircir/api_models/output_spec.rb
82
+ - spec/eclaircir/api_models/response_spec.rb
83
+ - spec/eclaircir/api_models/status_spec.rb
84
+ - spec/eclaircir/client/status_validator_spec.rb
85
+ - spec/eclaircir/client_spec.rb
86
+ - spec/eclaircir/configuration_spec.rb
87
+ - spec/eclaircir_spec.rb
88
+ - spec/etc/fixtures/predict_outputs/invalid_request.json
89
+ - spec/etc/fixtures/predict_outputs/success.json
90
+ - spec/factories/concept.rb
91
+ - spec/factories/data.rb
92
+ - spec/factories/input.rb
93
+ - spec/factories/media.rb
94
+ - spec/factories/model.rb
95
+ - spec/factories/response.rb
96
+ - spec/factories/status.rb
97
+ - spec/spec_helper.rb
98
+ homepage: https://github.com/kbogtob/eclaircir
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.4.5.3
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Clarifai APIv2 Client
122
+ test_files: []