From e18b9bb580b01f557c86ed463e37778da768a677 Mon Sep 17 00:00:00 2001 From: danielstanojevic Date: Tue, 24 Apr 2018 14:05:46 -0400 Subject: [PATCH 1/5] Fixed Typo on Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bacb613..2f2acb4 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ For every type of task, you can pass in the following options when creating: - `urgency`: a string indicating how long the task should take, options are `immediate`, `day`, or `week`. The default is `day`. - `metadata`: a `Hash` that contains anything you want in it. Use it for storing data relevant to that task, such as an internal ID for your application to associate the task with. Note that the keys of the `Hash` will be returned as `String` rather than `Symbol`. -### Categoriation Tasks +### Categorization Tasks To create a [categorization task](https://docs.scaleapi.com/#create-categorization-task), run the following: ```ruby From 531d4dc2ad2e2ab27d17a748b834030ded197bab Mon Sep 17 00:00:00 2001 From: LiRen Tu Date: Thu, 4 Apr 2019 14:44:54 -0700 Subject: [PATCH 2/5] Add unit tests (#12) * Activate travis ci * Set up rspec files * Add more tests for scale.rb * Fix example labels in readme * Depend on webmock and vcr for testing * Add tests for create-task methods * Use let and test all alias methods * Allow selection of test server * Split each task to its own spec * Unify task specs * Add specs for remaining tasks * Add spec for task list * Update cassettes * Test tasks and task list * Update readme * Use custom serializer to remove headers from cassette * Fix spec for cancellation of valid task * Update task list spec * Use downcase for comments * Add rake task spec:production to test against production server * Add notes about unit tests in readme * Revise comment for custom serializer * Revise readme about test --- .rspec | 2 + .travis.yml | 6 ++ README.md | 16 +++-- Rakefile | 7 +- lib/scale/api/task_list.rb | 3 +- scaleapi-ruby.gemspec | 4 ++ spec/cassettes/audio_transcription.yml | 20 ++++++ spec/cassettes/categorization.yml | 20 ++++++ spec/cassettes/comparison.yml | 20 ++++++ spec/cassettes/cuboid_annotation.yml | 20 ++++++ spec/cassettes/custom_serializer.rb | 17 +++++ spec/cassettes/data_collection.yml | 23 +++++++ spec/cassettes/image_recognition.yml | 27 ++++++++ spec/cassettes/line_annotation.yml | 23 +++++++ spec/cassettes/point_annotation.yml | 20 ++++++ spec/cassettes/polygon_annotation.yml | 23 +++++++ spec/cassettes/segment_annotation.yml | 23 +++++++ spec/cassettes/task_cancel_invalid.yml | 18 ++++++ spec/cassettes/task_cancel_valid.yml | 19 ++++++ spec/cassettes/task_find_invalid.yml | 18 ++++++ spec/cassettes/task_find_valid.yml | 19 ++++++ spec/cassettes/task_list_1.yml | 23 +++++++ spec/cassettes/task_list_2.yml | 19 ++++++ spec/cassettes/transcription.yml | 23 +++++++ spec/lib/api/task_list_spec.rb | 45 +++++++++++++ .../tasks/audio_transcription_task_spec.rb | 16 +++++ .../lib/api/tasks/categorization_task_spec.rb | 17 +++++ spec/lib/api/tasks/comparison_task_spec.rb | 20 ++++++ .../api/tasks/cuboid_annotation_task_spec.rb | 19 ++++++ .../api/tasks/data_collection_task_spec.rb | 19 ++++++ .../api/tasks/image_recognition_task_spec.rb | 32 ++++++++++ .../api/tasks/line_annotation_task_spec.rb | 20 ++++++ .../api/tasks/point_annotation_task_spec.rb | 17 +++++ .../api/tasks/polygon_annotation_task_spec.rb | 20 ++++++ .../api/tasks/segment_annotation_task_spec.rb | 22 +++++++ spec/lib/api/tasks/transcription_task_spec.rb | 20 ++++++ spec/lib/api/tasks_spec.rb | 64 +++++++++++++++++++ spec/lib/scale_spec.rb | 52 +++++++++++++++ spec/spec_helper.rb | 26 ++++++++ tasks/spec_production.rake | 10 +++ 40 files changed, 823 insertions(+), 9 deletions(-) create mode 100644 .rspec create mode 100644 .travis.yml create mode 100644 spec/cassettes/audio_transcription.yml create mode 100644 spec/cassettes/categorization.yml create mode 100644 spec/cassettes/comparison.yml create mode 100644 spec/cassettes/cuboid_annotation.yml create mode 100644 spec/cassettes/custom_serializer.rb create mode 100644 spec/cassettes/data_collection.yml create mode 100644 spec/cassettes/image_recognition.yml create mode 100644 spec/cassettes/line_annotation.yml create mode 100644 spec/cassettes/point_annotation.yml create mode 100644 spec/cassettes/polygon_annotation.yml create mode 100644 spec/cassettes/segment_annotation.yml create mode 100644 spec/cassettes/task_cancel_invalid.yml create mode 100644 spec/cassettes/task_cancel_valid.yml create mode 100644 spec/cassettes/task_find_invalid.yml create mode 100644 spec/cassettes/task_find_valid.yml create mode 100644 spec/cassettes/task_list_1.yml create mode 100644 spec/cassettes/task_list_2.yml create mode 100644 spec/cassettes/transcription.yml create mode 100644 spec/lib/api/task_list_spec.rb create mode 100644 spec/lib/api/tasks/audio_transcription_task_spec.rb create mode 100644 spec/lib/api/tasks/categorization_task_spec.rb create mode 100644 spec/lib/api/tasks/comparison_task_spec.rb create mode 100644 spec/lib/api/tasks/cuboid_annotation_task_spec.rb create mode 100644 spec/lib/api/tasks/data_collection_task_spec.rb create mode 100644 spec/lib/api/tasks/image_recognition_task_spec.rb create mode 100644 spec/lib/api/tasks/line_annotation_task_spec.rb create mode 100644 spec/lib/api/tasks/point_annotation_task_spec.rb create mode 100644 spec/lib/api/tasks/polygon_annotation_task_spec.rb create mode 100644 spec/lib/api/tasks/segment_annotation_task_spec.rb create mode 100644 spec/lib/api/tasks/transcription_task_spec.rb create mode 100644 spec/lib/api/tasks_spec.rb create mode 100644 spec/lib/scale_spec.rb create mode 100644 spec/spec_helper.rb create mode 100644 tasks/spec_production.rake diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..83e16f8 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--require spec_helper diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..308b1c7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: ruby +rvm: + - 2.3.0 + - 2.5.0 +notifications: + email: false diff --git a/README.md b/README.md index 8e2d1c6..5b7cb2d 100644 --- a/README.md +++ b/README.md @@ -189,12 +189,12 @@ scale.create_annotation_task({ with_labels: true, examples: [ { - correct: false, + correct: true, image: 'http://i.imgur.com/lj6e98s.jpg', explanation: 'The boxes are tight and accurate' }, { - correct: true, + correct: false, image: 'http://i.imgur.com/HIrvIDq.jpg', explanation: 'The boxes are neither accurate nor complete' } @@ -221,12 +221,12 @@ scale.tasks.create({ with_labels: true, examples: [ { - correct: false, + correct: true, image: 'http://i.imgur.com/lj6e98s.jpg', explanation: 'The boxes are tight and accurate' }, { - correct: true, + correct: false, image: 'http://i.imgur.com/HIrvIDq.jpg', explanation: 'The boxes are neither accurate nor complete' } @@ -510,13 +510,17 @@ After checking out the repo, run `bin/setup` to install dependencies. You can al To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `scaleapi-ruby.gemspec`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). +To test locally, run `bundle exec rspec`. By default, client - server communication is mocked by [vcr](https://github.com/vcr/vcr), which uses local [casettes](spec/cassettes) recorded from production server. +To test against production server, set a test api key as `SCALE_TEST_API_KEY` and run `bundle exec rake spec:production`, which sets environment variable `SCALE_TEST_SERVER` to `production`. It will also update new client - server communication in the cassette. +Please note that changes in the cassettes will break existing specs. This is because 1) the server may return random results for test api key, and 2) some of the cassettes have been modified specifically for the specs. + ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/scaleapi/scaleapi-ruby. -Currently, this repository has no tests - and adding tests using RSpec would make a for a great PR :) -Thanks to [wikiti](https://github.com/wikiti/) for creating the first unofficial Scale Ruby Client! +Thanks to [wikiti](https://github.com/wikiti/) for creating the first unofficial Scale API Ruby Client! + ## License diff --git a/Rakefile b/Rakefile index 43022f7..ad5cea5 100644 --- a/Rakefile +++ b/Rakefile @@ -1,2 +1,7 @@ require "bundler/gem_tasks" -task :default => :spec +require 'rspec/core/rake_task' + +import './tasks/spec_production.rake' + +RSpec::Core::RakeTask.new(:spec) +task default: :spec diff --git a/lib/scale/api/task_list.rb b/lib/scale/api/task_list.rb index 14ee5f3..f2e85f9 100644 --- a/lib/scale/api/task_list.rb +++ b/lib/scale/api/task_list.rb @@ -25,11 +25,10 @@ def has_more? end def page - (offset + (limit * 1)) / limit + (offset + limit) / limit end def next_page - next_page_params = params.dup params[:offset] = params[:limit] + params[:offset] Scale::Api::Tasks.new(client).list(params) end diff --git a/scaleapi-ruby.gemspec b/scaleapi-ruby.gemspec index 8b766d0..2de9c82 100644 --- a/scaleapi-ruby.gemspec +++ b/scaleapi-ruby.gemspec @@ -23,5 +23,9 @@ Gem::Specification.new do |spec| spec.add_development_dependency "bundler", "~> 1.11" spec.add_development_dependency "rake", "~> 10.0" + spec.add_development_dependency "rspec", "~> 3.8" + spec.add_development_dependency "webmock", "~> 3.5" + spec.add_development_dependency "vcr", "~> 4.0" + spec.add_dependency "faraday", "~> 0.11.0" end diff --git a/spec/cassettes/audio_transcription.yml b/spec/cassettes/audio_transcription.yml new file mode 100644 index 0000000..bca6824 --- /dev/null +++ b/spec/cassettes/audio_transcription.yml @@ -0,0 +1,20 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/audiotranscription + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","attachment_type":"audio","attachment":"https://storage.googleapis.com/deepmind-media/pixie/knowing-what-to-say/second-list/speaker-3.wav","verbatim":false}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0efc4fd4f0075d11f8c","created_at":"2019-03-10T08:55:12.058Z","completed_at":"2019-03-10T08:55:12.111Z","callback_url":"http://www.example.com/callback","type":"audiotranscription","status":"completed","instruction":"Please + transcribe the attached audio file.","params":{"attachment":"https://storage.googleapis.com/deepmind-media/pixie/knowing-what-to-say/second-list/speaker-3.wav","attachment_type":"audio","verbatim":false,"skip_human_transcription":false},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"transcript":"This + is an example transcript using your Scale test key.","duration":5,"alignment":[{"word":"This","start":0.3,"end":0.37,"confidence":0.9},{"word":"is","start":0.37,"end":0.79,"confidence":0.9},{"word":"an","start":0.79,"end":0.94,"confidence":0.9},{"word":"example","start":0.94,"end":1,"confidence":0.9},{"word":"transcript","start":1,"end":1.3,"confidence":0.3},{"word":"using","start":1.3,"end":1.59,"confidence":0.3},{"word":"your","start":1.59,"end":1.8,"confidence":0.9},{"word":"Scale","start":1.81,"end":2.01,"confidence":0.9},{"word":"API","start":2.01,"end":2.37,"confidence":0.9},{"word":"test","start":2.37,"end":2.82,"confidence":0.9},{"word":"key","start":2.85,"end":3.11,"confidence":0.9}]}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:12 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/categorization.yml b/spec/cassettes/categorization.yml new file mode 100644 index 0000000..5e67a73 --- /dev/null +++ b/spec/cassettes/categorization.yml @@ -0,0 +1,20 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/categorization + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Is + this company public or private?","attachment_type":"website","attachment":"https://www.google.com","categories":["public","private"]}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0fe958593004f13e5ba","created_at":"2019-03-10T08:55:26.624Z","completed_at":"2019-03-10T08:55:26.669Z","callback_url":"http://www.example.com/callback","type":"categorization","status":"completed","instruction":"Is + this company public or private?","params":{"attachment_type":"website","attachment":"https://www.google.com","categories":["public","private"],"allow_multiple":false},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"category":"public"}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:26 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/comparison.yml b/spec/cassettes/comparison.yml new file mode 100644 index 0000000..f794b17 --- /dev/null +++ b/spec/cassettes/comparison.yml @@ -0,0 +1,20 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/comparison + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Do + the objects in these images have the same pattern?","attachments":["http://i.ebayimg.com/00/$T2eC16dHJGwFFZKjy5ZjBRfNyMC4Ig~~_32.JPG","http://images.wisegeek.com/checkered-tablecloth.jpg"],"attachment_type":"image","choices":["yes","no"]}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f367764e00561a72eb","created_at":"2019-03-10T08:55:15.129Z","completed_at":"2019-03-10T08:55:15.174Z","callback_url":"http://www.example.com/callback","type":"comparison","status":"completed","instruction":"Do + the objects in these images have the same pattern?","params":{"attachments":["http://i.ebayimg.com/00/$T2eC16dHJGwFFZKjy5ZjBRfNyMC4Ig~~_32.JPG","http://images.wisegeek.com/checkered-tablecloth.jpg"],"attachment_type":"image","choices":["yes","no"]},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"choice":"yes"}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:15 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/cuboid_annotation.yml b/spec/cassettes/cuboid_annotation.yml new file mode 100644 index 0000000..ff56f0b --- /dev/null +++ b/spec/cassettes/cuboid_annotation.yml @@ -0,0 +1,20 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/cuboidannotation + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw + a cuboid around each car or truck.","attachment_type":"image","attachment":"http://i.imgur.com/v4cBreD.jpg","objects_to_annotate":["car","truck"]}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f32e5be1004a45c510","created_at":"2019-03-10T08:55:16.082Z","completed_at":"2019-03-10T08:55:16.128Z","callback_url":"http://www.example.com/callback","type":"cuboidannotation","status":"completed","instruction":"Draw + a cuboid around each car or truck.","params":{"attachment":"http://i.imgur.com/v4cBreD.jpg","attachment_type":"image","objects_to_annotate":["car","truck"],"with_labels":true,"min_annotations":0,"max_annotations":0},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"annotations":[{"vertices":[{"description":"face-topleft","y":70,"x":100,"type":"vertex"},{"description":"face-bottomleft","y":296,"x":100,"type":"vertex"},{"description":"face-topright","y":70,"x":320,"type":"vertex"},{"description":"face-bottomright","y":296,"x":320,"type":"vertex"},{"description":"side-topcorner","y":82,"x":441,"type":"vertex"},{"description":"side-bottomcorner","y":198,"x":441,"type":"vertex"}],"label":"car"}]}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:16 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/custom_serializer.rb b/spec/cassettes/custom_serializer.rb new file mode 100644 index 0000000..d69d6e0 --- /dev/null +++ b/spec/cassettes/custom_serializer.rb @@ -0,0 +1,17 @@ +require 'yaml' +require 'vcr/cassette/serializers/yaml' + +# Remove request.headers and response.headers from the cassette, +# which contain sensitive information (e.g. authentication hash). +module Cassettes + class CustomSerializer + extend VCR::Cassette::EncodingErrorHandling + extend VCR::Cassette::Serializers::YAML + + def self.serialize(hash) + hash['http_interactions'][0]['request'].delete('headers') + hash['http_interactions'][0]['response'].delete('headers') + VCR::Cassette::Serializers::YAML.serialize(hash) + end + end +end diff --git a/spec/cassettes/data_collection.yml b/spec/cassettes/data_collection.yml new file mode 100644 index 0000000..8a3754f --- /dev/null +++ b/spec/cassettes/data_collection.yml @@ -0,0 +1,23 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/datacollection + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Find + the URL for the hiring page for the company with attached website.","attachment":"https://www.scaleapi.com/","attachment_type":"website","fields":{"hiring_page":"Hiring + Page URL"}}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f562e7490079ffae3b","created_at":"2019-03-10T08:55:17.126Z","completed_at":"2019-03-10T08:55:17.173Z","callback_url":"http://www.example.com/callback","type":"datacollection","status":"completed","instruction":"Find + the URL for the hiring page for the company with attached website.","params":{"attachment_type":"website","attachment":"https://www.scaleapi.com/","fields":{"hiring_page":"Hiring + Page URL"}},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"fields":{"hiring_page":"test + response"},"time_spent_in_seconds":15}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:17 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/image_recognition.yml b/spec/cassettes/image_recognition.yml new file mode 100644 index 0000000..4274ed2 --- /dev/null +++ b/spec/cassettes/image_recognition.yml @@ -0,0 +1,27 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/annotation + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw + a box around each **baby cow** and **big cow**","attachment_type":"image","attachment":"http://i.imgur.com/v4cBreD.jpg","objects_to_annotate":["baby + cow","big cow"],"with_labels":true,"examples":[{"correct":true,"image":"http://i.imgur.com/lj6e98s.jpg","explanation":"The + boxes are tight and accurate"},{"correct":false,"image":"http://i.imgur.com/HIrvIDq.jpg","explanation":"The + boxes are neither accurate nor complete"}]}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f50413320064109f34","created_at":"2019-03-10T08:55:18.054Z","completed_at":"2019-03-10T08:55:18.100Z","callback_url":"http://www.example.com/callback","type":"annotation","status":"completed","instruction":"Draw + a box around each **baby cow** and **big cow**","params":{"attachment":"http://i.imgur.com/v4cBreD.jpg","attachment_type":"image","objects_to_annotate":["baby + cow","big cow"],"with_labels":true,"min_width":0,"min_height":0,"examples":[{"correct":true,"image":"http://i.imgur.com/lj6e98s.jpg","explanation":"The + boxes are tight and accurate"},{"correct":false,"image":"http://i.imgur.com/HIrvIDq.jpg","explanation":"The + boxes are neither accurate nor complete"}]},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"annotations":[{"left":0,"top":0,"width":100,"height":100,"label":"big + cow"}]}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:18 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/line_annotation.yml b/spec/cassettes/line_annotation.yml new file mode 100644 index 0000000..65c4226 --- /dev/null +++ b/spec/cassettes/line_annotation.yml @@ -0,0 +1,23 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/lineannotation + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw + a tight shape around the big cow","attachment_type":"image","attachment":"http://i.imgur.com/v4cBreD.jpg","objects_to_annotate":["big + cow"],"with_labels":true}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f61fd428005d20e8dc","created_at":"2019-03-10T08:55:18.928Z","completed_at":"2019-03-10T08:55:18.978Z","callback_url":"http://www.example.com/callback","type":"lineannotation","status":"completed","instruction":"Draw + a tight shape around the big cow","params":{"attachment":"http://i.imgur.com/v4cBreD.jpg","attachment_type":"image","objects_to_annotate":["big + cow"],"with_labels":true,"splines":false},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"annotations":[{"vertices":[{"x":10,"y":10},{"x":110,"y":110},{"x":10,"y":110}],"label":"big + cow"}]}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:19 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/point_annotation.yml b/spec/cassettes/point_annotation.yml new file mode 100644 index 0000000..44da588 --- /dev/null +++ b/spec/cassettes/point_annotation.yml @@ -0,0 +1,20 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/pointannotation + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw + a point on every **headlight** and **brakelight** of a car in the image.","attachment_type":"image","attachment":"http://i.imgur.com/XOJbalC.jpg","objects_to_annotate":["headlight","brakelight"],"with_labels":true}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f74d286e0056a9c39a","created_at":"2019-03-10T08:55:19.964Z","completed_at":"2019-03-10T08:55:20.009Z","callback_url":"http://www.example.com/callback","type":"pointannotation","status":"completed","instruction":"Draw + a point on every **headlight** and **brakelight** of a car in the image.","params":{"attachment":"http://i.imgur.com/XOJbalC.jpg","attachment_type":"image","objects_to_annotate":["headlight","brakelight"],"with_labels":true},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[]}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:20 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/polygon_annotation.yml b/spec/cassettes/polygon_annotation.yml new file mode 100644 index 0000000..4472aec --- /dev/null +++ b/spec/cassettes/polygon_annotation.yml @@ -0,0 +1,23 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/polygonannotation + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw + a tight shape around the big cow","attachment_type":"image","attachment":"http://i.imgur.com/v4cBreD.jpg","objects_to_annotate":["big + cow"],"with_labels":true}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f862e7490079ffae3e","created_at":"2019-03-10T08:55:20.968Z","completed_at":"2019-03-10T08:55:21.015Z","callback_url":"http://www.example.com/callback","type":"polygonannotation","status":"completed","instruction":"Draw + a tight shape around the big cow","params":{"attachment":"http://i.imgur.com/v4cBreD.jpg","attachment_type":"image","objects_to_annotate":["big + cow"],"with_labels":true},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"annotations":[{"vertices":[{"x":10,"y":10},{"x":110,"y":110},{"x":10,"y":110}],"label":"big + cow"}]}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:21 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/segment_annotation.yml b/spec/cassettes/segment_annotation.yml new file mode 100644 index 0000000..9f5bf68 --- /dev/null +++ b/spec/cassettes/segment_annotation.yml @@ -0,0 +1,23 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/segmentannotation + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Please + segment the image using the given labels.","attachment_type":"image","attachment":"http://i.imgur.com/XOJbalC.jpg","labels":["background","road","vegetation","lane + marking"],"instance_labels":["vehicle","pedestrian"],"allow_unlabeled":false}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0f9e95619006b073a90","created_at":"2019-03-10T08:55:21.714Z","completed_at":"2019-03-10T08:55:23.259Z","callback_url":"http://www.example.com/callback","type":"segmentannotation","status":"completed","instruction":"Please + segment the image using the given labels.","params":{"attachment":"http://i.imgur.com/XOJbalC.jpg","attachment_type":"image","labels":["background","road","vegetation","lane + marking"],"instance_labels":["vehicle","pedestrian"],"allow_unlabeled":false,"allow_parent_labels":false},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"annotations":{"unlabeled":"https://scaleapi-results.s3.us-west-1.amazonaws.com/7d7cfc4e-68e2-4a11-9e68-79795bd2d0eb","labeled":{"background":"https://scaleapi-results.s3.us-west-1.amazonaws.com/6587eb57-65a5-4a9b-9b89-67d16fafc425"},"combined":{"image":"https://scaleapi-results.s3.us-west-1.amazonaws.com/48dbfee9-e849-4aa6-b060-803c433676fc","indexedImage":"https://scaleapi-results.s3.us-west-1.amazonaws.com/dc9cd6c3-a4d2-4030-9fca-618aceb996ab"}},"labelMapping":{"background":{"index":1,"color":"#ff0000"},"road":{"index":2,"color":"#ffff00"},"vegetation":{"index":3,"color":"#00ff00"},"lane + marking":{"index":4,"color":"#00ffff"}}}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:23 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/task_cancel_invalid.yml b/spec/cassettes/task_cancel_invalid.yml new file mode 100644 index 0000000..2dbcb3a --- /dev/null +++ b/spec/cassettes/task_cancel_invalid.yml @@ -0,0 +1,18 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/invalid_task_id/cancel + body: + encoding: UTF-8 + string: '{"callback_url":null}' + response: + status: + code: 404 + message: Not Found + body: + encoding: ASCII-8BIT + string: '{"status_code":404,"error":"Task with that ID not found."}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:27 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/task_cancel_valid.yml b/spec/cassettes/task_cancel_valid.yml new file mode 100644 index 0000000..80f6b95 --- /dev/null +++ b/spec/cassettes/task_cancel_valid.yml @@ -0,0 +1,19 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/5c84d0fe958593004f13e5ba/cancel + body: + encoding: US-ASCII + string: '{"callback_url":null}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0fe958593004f13e5ba","created_at":"2019-03-10T08:55:26.624Z","completed_at":"2019-03-10T08:55:26.669Z","callback_url":"http://www.example.com/callback","type":"categorization","status":"canceled","instruction":"Is + this company public or private?","params":{"attachment_type":"website","attachment":"https://www.google.com","categories":["public","private"],"allow_multiple":false},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"category":"private","category_id":null}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:58:56 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/task_find_invalid.yml b/spec/cassettes/task_find_invalid.yml new file mode 100644 index 0000000..81c65d0 --- /dev/null +++ b/spec/cassettes/task_find_invalid.yml @@ -0,0 +1,18 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.scaleapi.com/v1/task/invalid_task_id?callback_url + body: + encoding: US-ASCII + string: '' + response: + status: + code: 404 + message: Not Found + body: + encoding: ASCII-8BIT + string: '{"status_code":404,"error":"Task with that ID not found."}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:26 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/task_find_valid.yml b/spec/cassettes/task_find_valid.yml new file mode 100644 index 0000000..999ee95 --- /dev/null +++ b/spec/cassettes/task_find_valid.yml @@ -0,0 +1,19 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.scaleapi.com/v1/task/5c84d0fe958593004f13e5ba?callback_url + body: + encoding: US-ASCII + string: '' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0fe958593004f13e5ba","created_at":"2019-03-10T08:55:26.624Z","completed_at":"2019-03-10T08:55:26.669Z","callback_url":"http://www.example.com/callback","type":"categorization","status":"completed","instruction":"Is + this company public or private?","params":{"attachment_type":"website","attachment":"https://www.google.com","categories":["public","private"],"allow_multiple":false},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"category":"private","category_id":null}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:58:56 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/task_list_1.yml b/spec/cassettes/task_list_1.yml new file mode 100644 index 0000000..680330c --- /dev/null +++ b/spec/cassettes/task_list_1.yml @@ -0,0 +1,23 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.scaleapi.com/v1/tasks?callback_url&end_time&limit=2&offset=0&start_time&status&type + body: + encoding: US-ASCII + string: '' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"docs":[{"task_id":"5c849c3fe95619006b071dd4","created_at":"2019-03-10T05:10:23.260Z","completed_at":"2019-03-10T05:10:25.224Z","callback_url":"http://www.example.com/callback","type":"segmentannotation","status":"completed","instruction":"Please + segment the image using the given labels.","params":{"attachment":"http://i.imgur.com/XOJbalC.jpg","attachment_type":"image","labels":["background","road","vegetation","lane + marking"],"instance_labels":["vehicle","pedestrian"],"allow_unlabeled":false,"allow_parent_labels":false},"is_test":true,"urgency":"day","metadata":{},"processed_attachments":[],"response":{"annotations":{"unlabeled":"https://scaleapi-results.s3.amazonaws.com/0704357e-de4f-4247-b4fe-3347039624bb","labeled":{"background":"https://scaleapi-results.s3.amazonaws.com/e405b86f-3f47-41ab-9ea3-aaedd6f34c53","road":null,"vegetation":null,"lane + marking":null},"combined":{"image":"https://scaleapi-results.s3.amazonaws.com/dae72038-eb78-4e89-b994-1ca249ad888a","indexedImage":"https://scaleapi-results.s3.amazonaws.com/8d57af40-a7d5-4514-aff0-f033ab90b55f"}},"labelMapping":{"background":{"index":1,"color":"#ff0000","attributes":null},"road":{"index":2,"color":"#ffff00","attributes":null},"vegetation":{"index":3,"color":"#00ff00","attributes":null},"lane + marking":{"index":4,"color":"#00ffff","attributes":null}}}},{"task_id":"5c849b4fe95619006b071d5d","created_at":"2019-03-10T05:06:23.993Z","completed_at":"2019-03-10T05:06:24.039Z","callback_url":"http://www.example.com/callback","type":"cuboidannotation","status":"completed","instruction":"Draw + a cuboid around each car or truck.","params":{"attachment":"http://i.imgur.com/v4cBreD.jpg","attachment_type":"image","objects_to_annotate":["car","truck"],"with_labels":true,"min_annotations":0,"max_annotations":0},"is_test":true,"urgency":"day","metadata":{},"processed_attachments":[],"response":{"annotations":[{"vertices":[{"description":"face-topleft","y":70,"x":100,"type":"vertex"},{"description":"face-bottomleft","y":296,"x":100,"type":"vertex"},{"description":"face-topright","y":70,"x":320,"type":"vertex"},{"description":"face-bottomright","y":296,"x":320,"type":"vertex"},{"description":"side-topcorner","y":82,"x":441,"type":"vertex"},{"description":"side-bottomcorner","y":198,"x":441,"type":"vertex"}],"label":"car"}]}}],"total":3,"limit":2,"offset":0,"has_more":true}' + http_version: + recorded_at: Sun, 10 Mar 2019 06:00:56 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/task_list_2.yml b/spec/cassettes/task_list_2.yml new file mode 100644 index 0000000..2a2b4d3 --- /dev/null +++ b/spec/cassettes/task_list_2.yml @@ -0,0 +1,19 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.scaleapi.com/v1/tasks?callback_url&end_time&limit=2&offset=2&start_time&status&type + body: + encoding: US-ASCII + string: '' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"docs":[{"task_id":"5c8498e23beb09005d953d51","created_at":"2019-03-10T04:56:02.086Z","completed_at":"2019-03-10T04:56:02.133Z","callback_url":"http://www.example.com/callback","type":"pointannotation","status":"completed","instruction":"Draw + a point on every **headlight** and **brakelight** of a car in the image.","params":{"attachment":"http://i.imgur.com/XOJbalC.jpg","attachment_type":"image","objects_to_annotate":["headlight","brakelight"],"with_labels":true},"is_test":true,"urgency":"day","metadata":{},"processed_attachments":[]}],"total":3,"limit":2,"offset":2,"has_more":false}' + http_version: + recorded_at: Sun, 10 Mar 2019 06:00:57 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/transcription.yml b/spec/cassettes/transcription.yml new file mode 100644 index 0000000..d175cfe --- /dev/null +++ b/spec/cassettes/transcription.yml @@ -0,0 +1,23 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.scaleapi.com/v1/task/transcription + body: + encoding: UTF-8 + string: '{"callback_url":"http://www.example.com/callback","instruction":"Transcribe + the given fields.","attachment_type":"website","attachment":"http://news.ycombinator.com/","fields":{"title":"Title + of Webpage","top_result":"Title of the top result"}}' + response: + status: + code: 200 + message: OK + body: + encoding: ASCII-8BIT + string: '{"task_id":"5c84d0fb26eb2700706a9069","created_at":"2019-03-10T08:55:24.068Z","completed_at":"2019-03-10T08:55:24.114Z","callback_url":"http://www.example.com/callback","type":"transcription","status":"completed","instruction":"Transcribe + the given fields.","params":{"attachment_type":"website","attachment":"http://news.ycombinator.com/","fields":{"title":"Title + of Webpage","top_result":"Title of the top result"}},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"fields":{"title":"test + response","top_result":"test response"},"repeatable_fields":[null,null]}}' + http_version: + recorded_at: Sun, 10 Mar 2019 08:55:24 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/lib/api/task_list_spec.rb b/spec/lib/api/task_list_spec.rb new file mode 100644 index 0000000..ded6bf8 --- /dev/null +++ b/spec/lib/api/task_list_spec.rb @@ -0,0 +1,45 @@ +RSpec.describe Scale::Api::TaskList do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + # the cassette assumes there are totally 3 tasks + # page 1 retrieves 2 tasks + let(:page_1) { VCR.use_cassette('task_list_1') { scale.tasks.list(limit: 2) } } + # page 2 retrieves the remaining 1 task. + let(:page_2) { VCR.use_cassette('task_list_2') { page_1.next_page } } + + it 'returns a task list' do + expect(page_1).to be_an_instance_of Scale::Api::TaskList + expect(page_2).to be_an_instance_of Scale::Api::TaskList + + expect(page_1.length).to eq 2 + expect(page_2.length).to eq 1 + end + + it 'is an enumerable of task' do + types = page_1.map(&:class).uniq + expect(types.size).to eq 1 + expect(types.first).to eq Scale::Api::Tasks::BaseTask + + types = page_2.map(&:class).uniq + expect(types.size).to eq 1 + expect(types.first).to eq Scale::Api::Tasks::BaseTask + end + + describe '#has_more?' do + it { expect(page_1.has_more?).to be true } + it { expect(page_2.has_more?).to be false } + end + + describe '#page' do + it { expect(page_1.page).to eq 1 } + it { expect(page_2.page).to eq 2 } + end + + describe '#next_page' do + it 'does not change limit' do + # page 2 inherits 2 as its limit from page 1 + expect(page_1.limit).to eq 2 + expect(page_2.limit).to eq 2 + end + end +end diff --git a/spec/lib/api/tasks/audio_transcription_task_spec.rb b/spec/lib/api/tasks/audio_transcription_task_spec.rb new file mode 100644 index 0000000..273d0c2 --- /dev/null +++ b/spec/lib/api/tasks/audio_transcription_task_spec.rb @@ -0,0 +1,16 @@ +RSpec.describe Scale::Api::Tasks, 'audio transcription' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns transcription for audio transcription task' do + response = VCR.use_cassette('audio_transcription') do + scale.create_audiotranscription_task( + callback_url: 'http://www.example.com/callback', + attachment_type: 'audio', + attachment: 'https://storage.googleapis.com/deepmind-media/pixie/knowing-what-to-say/second-list/speaker-3.wav', + verbatim: false) + end + + expect(response.type).to eq 'audiotranscription' + expect(response.response.keys).to contain_exactly('transcript', 'duration', 'alignment') + end +end diff --git a/spec/lib/api/tasks/categorization_task_spec.rb b/spec/lib/api/tasks/categorization_task_spec.rb new file mode 100644 index 0000000..80da6da --- /dev/null +++ b/spec/lib/api/tasks/categorization_task_spec.rb @@ -0,0 +1,17 @@ +RSpec.describe Scale::Api::Tasks, 'categorization' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns category for categorization task' do + response = VCR.use_cassette('categorization') do + scale.create_categorization_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Is this company public or private?', + attachment_type: 'website', + attachment: 'https://www.google.com', + categories: %w(public private)) + end + + expect(response.type).to eq 'categorization' + expect(response.response['category']).to eq 'public' + end +end diff --git a/spec/lib/api/tasks/comparison_task_spec.rb b/spec/lib/api/tasks/comparison_task_spec.rb new file mode 100644 index 0000000..5b165a8 --- /dev/null +++ b/spec/lib/api/tasks/comparison_task_spec.rb @@ -0,0 +1,20 @@ +RSpec.describe Scale::Api::Tasks, 'comparison' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns choice for comparison task' do + response = VCR.use_cassette('comparison') do + scale.create_comparison_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Do the objects in these images have the same pattern?', + attachments: [ + 'http://i.ebayimg.com/00/$T2eC16dHJGwFFZKjy5ZjBRfNyMC4Ig~~_32.JPG', + 'http://images.wisegeek.com/checkered-tablecloth.jpg' + ], + attachment_type: 'image', + choices: %w(yes no)) + end + + expect(response.type).to eq 'comparison' + expect(response.response['choice']).to eq 'yes' + end +end diff --git a/spec/lib/api/tasks/cuboid_annotation_task_spec.rb b/spec/lib/api/tasks/cuboid_annotation_task_spec.rb new file mode 100644 index 0000000..3117368 --- /dev/null +++ b/spec/lib/api/tasks/cuboid_annotation_task_spec.rb @@ -0,0 +1,19 @@ +RSpec.describe Scale::Api::Tasks, 'cuboid annotation' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns annotations for line cuboid annotation task' do + response = VCR.use_cassette('cuboid_annotation') do + scale.create_cuboidannotation_task({ + callback_url: 'http://www.example.com/callback', + instruction: 'Draw a cuboid around each car or truck.', + attachment_type: 'image', + attachment: 'http://i.imgur.com/v4cBreD.jpg', + objects_to_annotate: ['car', 'truck']}) + end + + expect(response.type).to eq 'cuboidannotation' + response.response['annotations'].each do |annotation| + expect(annotation.keys).to contain_exactly('vertices', "label") + end + end +end diff --git a/spec/lib/api/tasks/data_collection_task_spec.rb b/spec/lib/api/tasks/data_collection_task_spec.rb new file mode 100644 index 0000000..a65593d --- /dev/null +++ b/spec/lib/api/tasks/data_collection_task_spec.rb @@ -0,0 +1,19 @@ +RSpec.describe Scale::Api::Tasks, 'data collection' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns fields for data collection task' do + response = VCR.use_cassette('data_collection') do + scale.create_datacollection_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Find the URL for the hiring page for the company with attached website.', + attachment: 'https://www.scaleapi.com/', + attachment_type: 'website', + fields: { + hiring_page: 'Hiring Page URL' + }) + end + + expect(response.type).to eq 'datacollection' + expect(response.response['fields']['hiring_page']).to eq 'test response' + end +end diff --git a/spec/lib/api/tasks/image_recognition_task_spec.rb b/spec/lib/api/tasks/image_recognition_task_spec.rb new file mode 100644 index 0000000..5967072 --- /dev/null +++ b/spec/lib/api/tasks/image_recognition_task_spec.rb @@ -0,0 +1,32 @@ +RSpec.describe Scale::Api::Tasks, 'image recognition' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns annotations for image recognition task' do + response = VCR.use_cassette('image_recognition') do + scale.create_annotation_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Draw a box around each **baby cow** and **big cow**', + attachment_type: 'image', + attachment: 'http://i.imgur.com/v4cBreD.jpg', + objects_to_annotate: ['baby cow', 'big cow'], + with_labels: true, + examples: [ + { + correct: true, + image: 'http://i.imgur.com/lj6e98s.jpg', + explanation: 'The boxes are tight and accurate' + }, + { + correct: false, + image: 'http://i.imgur.com/HIrvIDq.jpg', + explanation: 'The boxes are neither accurate nor complete' + } + ]) + end + + expect(response.type).to eq 'annotation' + response.response['annotations'].each do |annotation| + expect(annotation.keys).to contain_exactly('left', 'top', 'width', 'height', 'label') + end + end +end diff --git a/spec/lib/api/tasks/line_annotation_task_spec.rb b/spec/lib/api/tasks/line_annotation_task_spec.rb new file mode 100644 index 0000000..8d07494 --- /dev/null +++ b/spec/lib/api/tasks/line_annotation_task_spec.rb @@ -0,0 +1,20 @@ +RSpec.describe Scale::Api::Tasks, 'line annotation' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns annotations for line lineannotation task' do + response = VCR.use_cassette('line_annotation') do + scale.create_lineannotation_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Draw a tight shape around the big cow', + attachment_type: 'image', + attachment: 'http://i.imgur.com/v4cBreD.jpg', + objects_to_annotate: ['big cow'], + with_labels: true) + end + + expect(response.type).to eq 'lineannotation' + response.response['annotations'].each do |annotation| + expect(annotation.keys).to contain_exactly('vertices', "label") + end + end +end diff --git a/spec/lib/api/tasks/point_annotation_task_spec.rb b/spec/lib/api/tasks/point_annotation_task_spec.rb new file mode 100644 index 0000000..57c3ea4 --- /dev/null +++ b/spec/lib/api/tasks/point_annotation_task_spec.rb @@ -0,0 +1,17 @@ +RSpec.describe Scale::Api::Tasks, 'point annotation' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns annotations for point annotation task' do + response = VCR.use_cassette('point_annotation') do + scale.create_pointannotation_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Draw a point on every **headlight** and **brakelight** of a car in the image.', + attachment_type: 'image', + attachment: 'http://i.imgur.com/XOJbalC.jpg', + objects_to_annotate: ['headlight', 'brakelight'], + with_labels: true) + end + + expect(response.type).to eq 'pointannotation' + end +end diff --git a/spec/lib/api/tasks/polygon_annotation_task_spec.rb b/spec/lib/api/tasks/polygon_annotation_task_spec.rb new file mode 100644 index 0000000..f51b131 --- /dev/null +++ b/spec/lib/api/tasks/polygon_annotation_task_spec.rb @@ -0,0 +1,20 @@ +RSpec.describe Scale::Api::Tasks, 'polygon annotation' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns annotations for polygon annotation task' do + response = VCR.use_cassette('polygon_annotation') do + scale.create_polygonannotation_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Draw a tight shape around the big cow', + attachment_type: 'image', + attachment: 'http://i.imgur.com/v4cBreD.jpg', + objects_to_annotate: ['big cow'], + with_labels: true) + end + + expect(response.type).to eq 'polygonannotation' + response.response['annotations'].each do |annotation| + expect(annotation.keys).to contain_exactly('vertices', "label") + end + end +end diff --git a/spec/lib/api/tasks/segment_annotation_task_spec.rb b/spec/lib/api/tasks/segment_annotation_task_spec.rb new file mode 100644 index 0000000..ac5267e --- /dev/null +++ b/spec/lib/api/tasks/segment_annotation_task_spec.rb @@ -0,0 +1,22 @@ +RSpec.describe Scale::Api::Tasks, 'segment annotation' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns annotations for segment annotation task' do + response = VCR.use_cassette('segment_annotation') do + scale.create_segmentannotation_task({ + callback_url: 'http://www.example.com/callback', + instruction: 'Please segment the image using the given labels.', + attachment_type: 'image', + attachment: 'http://i.imgur.com/XOJbalC.jpg', + labels: ['background', 'road', 'vegetation', 'lane marking'], + instance_labels: ['vehicle', 'pedestrian'], + allow_unlabeled: false}) + end + + expect(response.type).to eq 'segmentannotation' + expect(response.response['annotations'].keys) + .to contain_exactly('unlabeled', 'labeled', 'combined') + expect(response.response['labelMapping'].keys) + .to contain_exactly('background', 'road', 'vegetation', 'lane marking') + end +end diff --git a/spec/lib/api/tasks/transcription_task_spec.rb b/spec/lib/api/tasks/transcription_task_spec.rb new file mode 100644 index 0000000..8112303 --- /dev/null +++ b/spec/lib/api/tasks/transcription_task_spec.rb @@ -0,0 +1,20 @@ +RSpec.describe Scale::Api::Tasks, 'transcription' do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + + it 'returns transcription for transcription task' do + response = VCR.use_cassette('transcription') do + scale.create_transcription_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Transcribe the given fields.', + attachment_type: 'website', + attachment: 'http://news.ycombinator.com/', + fields: { + title: 'Title of Webpage', + top_result: 'Title of the top result' + }) + end + + expect(response.type).to eq 'transcription' + expect(response.response['fields'].keys).to contain_exactly('title', 'top_result') + end +end diff --git a/spec/lib/api/tasks_spec.rb b/spec/lib/api/tasks_spec.rb new file mode 100644 index 0000000..c14a326 --- /dev/null +++ b/spec/lib/api/tasks_spec.rb @@ -0,0 +1,64 @@ +RSpec.describe Scale::Api::Tasks do + let(:scale) { Scale.new(api_key: SCALE_TEST_API_KEY) } + let(:original_task) do + # reuse cassette from categorization_task_spec + VCR.use_cassette('categorization') do + scale.create_categorization_task( + callback_url: 'http://www.example.com/callback', + instruction: 'Is this company public or private?', + attachment_type: 'website', + attachment: 'https://www.google.com', + categories: %w(public private)) + end + end + + describe '#find' do + context 'with valid task id' do + it 'fetches the same task' do + retrieved_task = VCR.use_cassette('task_find_valid') do + scale.tasks.find(original_task.id) + end + + expect(retrieved_task.id).to eq original_task.id + expect(retrieved_task.type).to eq original_task.type + expect(retrieved_task.callback_url).to eq original_task.callback_url + expect(retrieved_task.instruction).to eq original_task.instruction + expect(retrieved_task.params).to eq original_task.params + expect(retrieved_task.metadata).to eq original_task.metadata + expect(retrieved_task.created_at).to eq original_task.created_at + end + end + + context 'with invalid task id' do + it 'raises error' do + expect { + VCR.use_cassette('task_find_invalid') do + scale.tasks.find('invalid_task_id') + end + }.to raise_error Scale::Api::NotFound + end + end + end + + describe '#cancel' do + context 'with valid task id' do + it 'cancels the task' do + canceled_task = VCR.use_cassette('task_cancel_valid') do + scale.tasks.cancel(original_task.id) + end + + expect(canceled_task.canceled?).to be true + end + end + + context 'with invalid task id' do + it 'raises error' do + expect { + VCR.use_cassette('task_cancel_invalid') do + scale.tasks.cancel('invalid_task_id') + end + }.to raise_error Scale::Api::NotFound + end + end + end +end diff --git a/spec/lib/scale_spec.rb b/spec/lib/scale_spec.rb new file mode 100644 index 0000000..cc6c24e --- /dev/null +++ b/spec/lib/scale_spec.rb @@ -0,0 +1,52 @@ +require 'securerandom' +require 'scale/api' +require 'scale/api/errors' + +RSpec.describe Scale do + describe '.validate_api_key' do + it 'rejects short api key' do + expect{ + Scale.validate_api_key(SecureRandom.base64(4)) + }.to raise_error Scale::Api::APIKeyInvalid + end + + it 'accepts test key' do + expect{ + Scale.validate_api_key("test_#{SecureRandom.base64(4)}") + }.to_not raise_error + end + + it 'accepts live key' do + expect{ + Scale.validate_api_key("live_#{SecureRandom.base64(4)}") + }.to_not raise_error + end + end + + let(:test_client) { Scale.new(api_key: "test_#{SecureRandom.base64(10)}") } + let(:live_client) { Scale.new(api_key: "live_#{SecureRandom.base64(10)}") } + + describe '#test?' do + it 'recognizes test api' do + expect(test_client.test?).to be true + expect(test_client.test).to be true + expect(test_client.test_mode?).to be true + + expect(live_client.test?).to be false + expect(live_client.test).to be false + expect(live_client.test_mode?).to be false + end + end + + describe '#live?' do + it 'recognizes live api' do + expect(test_client.live?).to be false + expect(test_client.live).to be false + expect(test_client.live_mode?).to be false + + expect(live_client.live?).to be true + expect(live_client.live).to be true + expect(live_client.live_mode?).to be true + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..230ef1c --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,26 @@ +require 'rspec' +require 'webmock/rspec' +require 'vcr' +require 'scale' +require 'cassettes/custom_serializer' + +# by default, rspec use local vcr cassettes to mock client - server +# communication; to run tests against production server (or update +# cassettes), set SCALE_TEST_API_KEY, and run rspec with +# SCALE_TEST_SERVER=production, which is encapsulated in rake task +# spec:production +SCALE_TEST_API_KEY = ENV['SCALE_TEST_API_KEY'] || 'test_api_key' +SCALE_TEST_SERVER = ENV['SCALE_TEST_SERVER'] || 'local' + +RSpec.configure do |config| + config.include WebMock::API +end + +VCR.configure do |c| + c.cassette_library_dir = 'spec/cassettes' + c.hook_into :webmock + c.cassette_serializers[:yaml] = Cassettes::CustomSerializer + c.default_cassette_options = { + record: SCALE_TEST_SERVER == 'production' ? :all : :once + } +end diff --git a/tasks/spec_production.rake b/tasks/spec_production.rake new file mode 100644 index 0000000..07bffbc --- /dev/null +++ b/tasks/spec_production.rake @@ -0,0 +1,10 @@ +namespace :spec do + desc 'Run rspec against production server instead of local cassettes' + task :production do + if ENV['SCALE_TEST_API_KEY'].nil? + raise 'Please specify SCALE_TEST_API_KEY to run against production server' + end + ENV['SCALE_TEST_SERVER'] = 'production' + Rake::Task['spec'].invoke + end +end From 8eebac553252962f86bdf25331766b4c1312b95b Mon Sep 17 00:00:00 2001 From: LiRen Tu Date: Tue, 4 Jun 2019 20:18:50 -0700 Subject: [PATCH 3/5] Update url in cassettes (#13) --- spec/cassettes/audio_transcription.yml | 2 +- spec/cassettes/categorization.yml | 2 +- spec/cassettes/comparison.yml | 2 +- spec/cassettes/cuboid_annotation.yml | 2 +- spec/cassettes/data_collection.yml | 2 +- spec/cassettes/image_recognition.yml | 2 +- spec/cassettes/line_annotation.yml | 2 +- spec/cassettes/point_annotation.yml | 2 +- spec/cassettes/polygon_annotation.yml | 2 +- spec/cassettes/segment_annotation.yml | 2 +- spec/cassettes/task_cancel_invalid.yml | 2 +- spec/cassettes/task_cancel_valid.yml | 2 +- spec/cassettes/task_find_invalid.yml | 2 +- spec/cassettes/task_find_valid.yml | 2 +- spec/cassettes/task_list_1.yml | 2 +- spec/cassettes/task_list_2.yml | 2 +- spec/cassettes/transcription.yml | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/spec/cassettes/audio_transcription.yml b/spec/cassettes/audio_transcription.yml index bca6824..c576b3e 100644 --- a/spec/cassettes/audio_transcription.yml +++ b/spec/cassettes/audio_transcription.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/audiotranscription + uri: https://api.scale.ai/v1/task/audiotranscription body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","attachment_type":"audio","attachment":"https://storage.googleapis.com/deepmind-media/pixie/knowing-what-to-say/second-list/speaker-3.wav","verbatim":false}' diff --git a/spec/cassettes/categorization.yml b/spec/cassettes/categorization.yml index 5e67a73..02eca51 100644 --- a/spec/cassettes/categorization.yml +++ b/spec/cassettes/categorization.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/categorization + uri: https://api.scale.ai/v1/task/categorization body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Is diff --git a/spec/cassettes/comparison.yml b/spec/cassettes/comparison.yml index f794b17..4691109 100644 --- a/spec/cassettes/comparison.yml +++ b/spec/cassettes/comparison.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/comparison + uri: https://api.scale.ai/v1/task/comparison body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Do diff --git a/spec/cassettes/cuboid_annotation.yml b/spec/cassettes/cuboid_annotation.yml index ff56f0b..7997664 100644 --- a/spec/cassettes/cuboid_annotation.yml +++ b/spec/cassettes/cuboid_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/cuboidannotation + uri: https://api.scale.ai/v1/task/cuboidannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/data_collection.yml b/spec/cassettes/data_collection.yml index 8a3754f..539edd1 100644 --- a/spec/cassettes/data_collection.yml +++ b/spec/cassettes/data_collection.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/datacollection + uri: https://api.scale.ai/v1/task/datacollection body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Find diff --git a/spec/cassettes/image_recognition.yml b/spec/cassettes/image_recognition.yml index 4274ed2..9e236f1 100644 --- a/spec/cassettes/image_recognition.yml +++ b/spec/cassettes/image_recognition.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/annotation + uri: https://api.scale.ai/v1/task/annotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/line_annotation.yml b/spec/cassettes/line_annotation.yml index 65c4226..20a75a9 100644 --- a/spec/cassettes/line_annotation.yml +++ b/spec/cassettes/line_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/lineannotation + uri: https://api.scale.ai/v1/task/lineannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/point_annotation.yml b/spec/cassettes/point_annotation.yml index 44da588..63f5e81 100644 --- a/spec/cassettes/point_annotation.yml +++ b/spec/cassettes/point_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/pointannotation + uri: https://api.scale.ai/v1/task/pointannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/polygon_annotation.yml b/spec/cassettes/polygon_annotation.yml index 4472aec..def3f23 100644 --- a/spec/cassettes/polygon_annotation.yml +++ b/spec/cassettes/polygon_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/polygonannotation + uri: https://api.scale.ai/v1/task/polygonannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/segment_annotation.yml b/spec/cassettes/segment_annotation.yml index 9f5bf68..4286318 100644 --- a/spec/cassettes/segment_annotation.yml +++ b/spec/cassettes/segment_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/segmentannotation + uri: https://api.scale.ai/v1/task/segmentannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Please diff --git a/spec/cassettes/task_cancel_invalid.yml b/spec/cassettes/task_cancel_invalid.yml index 2dbcb3a..06fc939 100644 --- a/spec/cassettes/task_cancel_invalid.yml +++ b/spec/cassettes/task_cancel_invalid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/invalid_task_id/cancel + uri: https://api.scale.ai/v1/task/invalid_task_id/cancel body: encoding: UTF-8 string: '{"callback_url":null}' diff --git a/spec/cassettes/task_cancel_valid.yml b/spec/cassettes/task_cancel_valid.yml index 80f6b95..f57f041 100644 --- a/spec/cassettes/task_cancel_valid.yml +++ b/spec/cassettes/task_cancel_valid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/5c84d0fe958593004f13e5ba/cancel + uri: https://api.scale.ai/v1/task/5c84d0fe958593004f13e5ba/cancel body: encoding: US-ASCII string: '{"callback_url":null}' diff --git a/spec/cassettes/task_find_invalid.yml b/spec/cassettes/task_find_invalid.yml index 81c65d0..04f7c53 100644 --- a/spec/cassettes/task_find_invalid.yml +++ b/spec/cassettes/task_find_invalid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scaleapi.com/v1/task/invalid_task_id?callback_url + uri: https://api.scale.ai/v1/task/invalid_task_id?callback_url body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/task_find_valid.yml b/spec/cassettes/task_find_valid.yml index 999ee95..506e136 100644 --- a/spec/cassettes/task_find_valid.yml +++ b/spec/cassettes/task_find_valid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scaleapi.com/v1/task/5c84d0fe958593004f13e5ba?callback_url + uri: https://api.scale.ai/v1/task/5c84d0fe958593004f13e5ba?callback_url body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/task_list_1.yml b/spec/cassettes/task_list_1.yml index 680330c..4c6d57c 100644 --- a/spec/cassettes/task_list_1.yml +++ b/spec/cassettes/task_list_1.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scaleapi.com/v1/tasks?callback_url&end_time&limit=2&offset=0&start_time&status&type + uri: https://api.scale.ai/v1/tasks?callback_url&end_time&limit=2&offset=0&start_time&status&type body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/task_list_2.yml b/spec/cassettes/task_list_2.yml index 2a2b4d3..80875ab 100644 --- a/spec/cassettes/task_list_2.yml +++ b/spec/cassettes/task_list_2.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scaleapi.com/v1/tasks?callback_url&end_time&limit=2&offset=2&start_time&status&type + uri: https://api.scale.ai/v1/tasks?callback_url&end_time&limit=2&offset=2&start_time&status&type body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/transcription.yml b/spec/cassettes/transcription.yml index d175cfe..51c7125 100644 --- a/spec/cassettes/transcription.yml +++ b/spec/cassettes/transcription.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scaleapi.com/v1/task/transcription + uri: https://api.scale.ai/v1/task/transcription body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Transcribe From 6fad60b7e8dcddbf9905d153e01759d7da22bafc Mon Sep 17 00:00:00 2001 From: Ramiro Silveyra d'Avila Date: Mon, 29 Jul 2019 20:07:57 -0300 Subject: [PATCH 4/5] fix: rename to new domain (#15) --- README.md | 38 +++++++++---------- lib/scale/api.rb | 2 +- scaleapi-ruby.gemspec | 2 +- spec/cassettes/audio_transcription.yml | 2 +- spec/cassettes/categorization.yml | 2 +- spec/cassettes/comparison.yml | 2 +- spec/cassettes/cuboid_annotation.yml | 2 +- spec/cassettes/data_collection.yml | 6 +-- spec/cassettes/image_recognition.yml | 2 +- spec/cassettes/line_annotation.yml | 2 +- spec/cassettes/point_annotation.yml | 2 +- spec/cassettes/polygon_annotation.yml | 2 +- spec/cassettes/segment_annotation.yml | 2 +- spec/cassettes/task_cancel_invalid.yml | 2 +- spec/cassettes/task_cancel_valid.yml | 2 +- spec/cassettes/task_find_invalid.yml | 2 +- spec/cassettes/task_find_valid.yml | 2 +- spec/cassettes/task_list_1.yml | 2 +- spec/cassettes/task_list_2.yml | 2 +- spec/cassettes/transcription.yml | 2 +- .../api/tasks/data_collection_task_spec.rb | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 5b7cb2d..b50b644 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ # Scale -![Scale Logo](https://scale.ai/static/global/facebook-card.png) +![Scale Logo](https://scale.com/static/global/facebook-card.png) This is the official Scale RubyGem (`scaleapi`). -[Scale](https://scale.ai) is an API for Human Intelligence. Businesses like Alphabet (Google), Uber, Proctor & Gamble, Houzz, and many more use us to power tasks such as: +[Scale](https://scale.com) is an API for Human Intelligence. Businesses like Alphabet (Google), Uber, Proctor & Gamble, Houzz, and many more use us to power tasks such as: - Draw bounding boxes and label parts of images (to train ML algorithms for self-driving cars) - Transcribe documents, images, and webpages - Scrape websites - Triage support tickets - Categorize and compare images, documents, and webpages -Scale is actively hiring software engineers - [apply here](https://scale.ai/about#jobs). +Scale is actively hiring software engineers - [apply here](https://scale.com/about#jobs). ## Installation @@ -40,7 +40,7 @@ scale = Scale.new(api_key: 'SCALE_API_KEY') Note that you can optionally provide a `callback_auth_key` and `callback_url` when initializing the Scale client. You can also set `default_request_params` which is a `Hash` that will be included in every request sent to Scale (either as a query string param or part of the request body). -If you're having trouble finding your API Key or Callback Auth Key, then go to the [Scale Dashboard](https://scale.ai/dashboard). If you set a default `callback_url` in your account settings, you won't need to pass it in everytime. +If you're having trouble finding your API Key or Callback Auth Key, then go to the [Scale Dashboard](https://scale.com/dashboard). If you set a default `callback_url` in your account settings, you won't need to pass it in everytime. ## Creating Tasks @@ -53,7 +53,7 @@ For every type of task, you can pass in the following options when creating: ### Categorization Tasks -To create a [categorization task](https://docs.scale.ai/#create-categorization-task), run the following: +To create a [categorization task](https://docs.scale.com/#create-categorization-task), run the following: ```ruby require 'scale' scale = Scale.new(api_key: 'SCALE_API_KEY') @@ -86,11 +86,11 @@ scale.tasks.create({ This will also return a `Scale::Api::Tasks::Categorization` object. -[Read more about creating categorization tasks](https://docs.scale.ai/#create-categorization-task) +[Read more about creating categorization tasks](https://docs.scale.com/#create-categorization-task) ### Comparison Tasks -To create a [comparison task](https://docs.scale.ai/#create-comparison-task), run the following: +To create a [comparison task](https://docs.scale.com/#create-comparison-task), run the following: ```ruby require 'scale' scale = Scale.new(api_key: 'SCALE_API_KEY') @@ -129,11 +129,11 @@ scale.tasks.create({ This will also return a `Scale::Api::Tasks::Comparison` object. -[Read more about creating comparison tasks](https://docs.scale.ai/#create-comparison-task) +[Read more about creating comparison tasks](https://docs.scale.com/#create-comparison-task) ### Datacollection Tasks -To create a [datacollection task](https://docs.scale.ai/#create-datacollection-task), run the following: +To create a [datacollection task](https://docs.scale.com/#create-datacollection-task), run the following: ```ruby require 'scale' scale = Scale.new(api_key: 'SCALE_API_KEY') @@ -141,7 +141,7 @@ scale = Scale.new(api_key: 'SCALE_API_KEY') scale.create_datacollection_task({ callback_url: 'http://www.example.com/callback', instruction: 'Find the URL for the hiring page for the company with attached website.', - attachment: 'https://scale.ai/', + attachment: 'https://scale.com/', attachment_type: 'website', fields: { hiring_page: 'Hiring Page URL' @@ -160,7 +160,7 @@ scale.tasks.create({ type: 'datacollection', callback_url: 'http://www.example.com/callback', instruction: 'Find the URL for the hiring page for the company with attached website.', - attachment: 'https://scale.ai/', + attachment: 'https://scale.com/', attachment_type: 'website', fields: { hiring_page: 'Hiring Page URL' @@ -170,12 +170,12 @@ scale.tasks.create({ This will also return a `Scale::Api::Tasks::Datacollection` object. -[Read more about creating datacollection tasks](https://docs.scale.ai/#create-data-collection-task) +[Read more about creating datacollection tasks](https://docs.scale.com/#create-data-collection-task) ### Image Recognition Tasks -To create an [image recognition task](https://docs.scale.ai/#create-image-recognition-task), run the following: +To create an [image recognition task](https://docs.scale.com/#create-image-recognition-task), run the following: ```ruby require 'scale' scale = Scale.new(api_key: 'SCALE_API_KEY') @@ -236,11 +236,11 @@ scale.tasks.create({ This will also return a `Scale::Api::Tasks::ImageRecognition` object. -[Read more about creating image recognition tasks](https://docs.scale.ai/#create-image-recognition-task) +[Read more about creating image recognition tasks](https://docs.scale.com/#create-image-recognition-task) ### Transcription Tasks -To create a [transcription task](https://docs.scale.ai/#create-transcription-task), run the following: +To create a [transcription task](https://docs.scale.com/#create-transcription-task), run the following: ```ruby require 'scale' scale = Scale.new(api_key: 'SCALE_API_KEY') @@ -278,12 +278,12 @@ scale.tasks.create({ This will also return a `Scale::Api::Tasks::Transcription` object. -[Read more about creating transcription tasks](https://docs.scale.ai/#create-transcription-task) +[Read more about creating transcription tasks](https://docs.scale.com/#create-transcription-task) ### Audio Transcription Tasks -To create an [audio transcription task](https://docs.scale.ai/#create-audio-transcription-task), run the following: +To create an [audio transcription task](https://docs.scale.com/#create-audio-transcription-task), run the following: ```ruby require 'scale' scale = Scale.new(api_key: 'SCALE_API_KEY') @@ -314,7 +314,7 @@ scale.tasks.create({ This will also return a `Scale::Api::Tasks::AudioTranscription` object. -[Read more about creating audio transcription tasks](https://docs.scale.ai/#create-audio-transcription-task) +[Read more about creating audio transcription tasks](https://docs.scale.com/#create-audio-transcription-task) ## Listing Tasks @@ -383,7 +383,7 @@ second_page = first_page.next_page `scale.tasks.list` is aliased to `scale.tasks.where` and `scale.tasks.all`. -For more information, [read our documentation](https://docs.scale.ai/#list-all-tasks) +For more information, [read our documentation](https://docs.scale.com/#list-all-tasks) ## Finding tasks by ID diff --git a/lib/scale/api.rb b/lib/scale/api.rb index f25748d..06ea484 100644 --- a/lib/scale/api.rb +++ b/lib/scale/api.rb @@ -4,7 +4,7 @@ class Scale class Api < Struct.new(:api_key, :callback_auth_key, :default_request_params, :logging) - SCALE_API_URL = 'https://api.scale.ai/v1/' + SCALE_API_URL = 'https://api.scale.com/v1/' SCALEAPI_GEM_INFO = Gem.loaded_specs["scaleapi"] SCALE_RUBY_CLIENT_VERSION = SCALEAPI_GEM_INFO ? SCALEAPI_GEM_INFO.version.to_s : '0.1.1'.freeze diff --git a/scaleapi-ruby.gemspec b/scaleapi-ruby.gemspec index 2de9c82..a7d3f49 100644 --- a/scaleapi-ruby.gemspec +++ b/scaleapi-ruby.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |spec| spec.summary = %q{Official Ruby Client for Scale API} spec.description = %q{Scale is an API For Human Intelligence. Get high quality results for all sorts of tasks within minutes. This is the official Ruby client.} - spec.homepage = "https://scale.ai" + spec.homepage = "https://scale.com" spec.license = "MIT" diff --git a/spec/cassettes/audio_transcription.yml b/spec/cassettes/audio_transcription.yml index c576b3e..abafdd2 100644 --- a/spec/cassettes/audio_transcription.yml +++ b/spec/cassettes/audio_transcription.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/audiotranscription + uri: https://api.scale.com/v1/task/audiotranscription body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","attachment_type":"audio","attachment":"https://storage.googleapis.com/deepmind-media/pixie/knowing-what-to-say/second-list/speaker-3.wav","verbatim":false}' diff --git a/spec/cassettes/categorization.yml b/spec/cassettes/categorization.yml index 02eca51..f5d559a 100644 --- a/spec/cassettes/categorization.yml +++ b/spec/cassettes/categorization.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/categorization + uri: https://api.scale.com/v1/task/categorization body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Is diff --git a/spec/cassettes/comparison.yml b/spec/cassettes/comparison.yml index 4691109..10644fc 100644 --- a/spec/cassettes/comparison.yml +++ b/spec/cassettes/comparison.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/comparison + uri: https://api.scale.com/v1/task/comparison body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Do diff --git a/spec/cassettes/cuboid_annotation.yml b/spec/cassettes/cuboid_annotation.yml index 7997664..6cf0f31 100644 --- a/spec/cassettes/cuboid_annotation.yml +++ b/spec/cassettes/cuboid_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/cuboidannotation + uri: https://api.scale.com/v1/task/cuboidannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/data_collection.yml b/spec/cassettes/data_collection.yml index 539edd1..7173daf 100644 --- a/spec/cassettes/data_collection.yml +++ b/spec/cassettes/data_collection.yml @@ -2,11 +2,11 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/datacollection + uri: https://api.scale.com/v1/task/datacollection body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Find - the URL for the hiring page for the company with attached website.","attachment":"https://www.scaleapi.com/","attachment_type":"website","fields":{"hiring_page":"Hiring + the URL for the hiring page for the company with attached website.","attachment":"https://scale.com/","attachment_type":"website","fields":{"hiring_page":"Hiring Page URL"}}' response: status: @@ -15,7 +15,7 @@ http_interactions: body: encoding: ASCII-8BIT string: '{"task_id":"5c84d0f562e7490079ffae3b","created_at":"2019-03-10T08:55:17.126Z","completed_at":"2019-03-10T08:55:17.173Z","callback_url":"http://www.example.com/callback","type":"datacollection","status":"completed","instruction":"Find - the URL for the hiring page for the company with attached website.","params":{"attachment_type":"website","attachment":"https://www.scaleapi.com/","fields":{"hiring_page":"Hiring + the URL for the hiring page for the company with attached website.","params":{"attachment_type":"website","attachment":"https://scale.com/","fields":{"hiring_page":"Hiring Page URL"}},"is_test":true,"urgency":"standard","metadata":{},"callback_succeeded":true,"processed_attachments":[],"response":{"fields":{"hiring_page":"test response"},"time_spent_in_seconds":15}}' http_version: diff --git a/spec/cassettes/image_recognition.yml b/spec/cassettes/image_recognition.yml index 9e236f1..5258dd9 100644 --- a/spec/cassettes/image_recognition.yml +++ b/spec/cassettes/image_recognition.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/annotation + uri: https://api.scale.com/v1/task/annotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/line_annotation.yml b/spec/cassettes/line_annotation.yml index 20a75a9..2f4ead5 100644 --- a/spec/cassettes/line_annotation.yml +++ b/spec/cassettes/line_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/lineannotation + uri: https://api.scale.com/v1/task/lineannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/point_annotation.yml b/spec/cassettes/point_annotation.yml index 63f5e81..c513a6b 100644 --- a/spec/cassettes/point_annotation.yml +++ b/spec/cassettes/point_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/pointannotation + uri: https://api.scale.com/v1/task/pointannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/polygon_annotation.yml b/spec/cassettes/polygon_annotation.yml index def3f23..baa3b74 100644 --- a/spec/cassettes/polygon_annotation.yml +++ b/spec/cassettes/polygon_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/polygonannotation + uri: https://api.scale.com/v1/task/polygonannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Draw diff --git a/spec/cassettes/segment_annotation.yml b/spec/cassettes/segment_annotation.yml index 4286318..8b64904 100644 --- a/spec/cassettes/segment_annotation.yml +++ b/spec/cassettes/segment_annotation.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/segmentannotation + uri: https://api.scale.com/v1/task/segmentannotation body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Please diff --git a/spec/cassettes/task_cancel_invalid.yml b/spec/cassettes/task_cancel_invalid.yml index 06fc939..ad4db58 100644 --- a/spec/cassettes/task_cancel_invalid.yml +++ b/spec/cassettes/task_cancel_invalid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/invalid_task_id/cancel + uri: https://api.scale.com/v1/task/invalid_task_id/cancel body: encoding: UTF-8 string: '{"callback_url":null}' diff --git a/spec/cassettes/task_cancel_valid.yml b/spec/cassettes/task_cancel_valid.yml index f57f041..9214f9e 100644 --- a/spec/cassettes/task_cancel_valid.yml +++ b/spec/cassettes/task_cancel_valid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/5c84d0fe958593004f13e5ba/cancel + uri: https://api.scale.com/v1/task/5c84d0fe958593004f13e5ba/cancel body: encoding: US-ASCII string: '{"callback_url":null}' diff --git a/spec/cassettes/task_find_invalid.yml b/spec/cassettes/task_find_invalid.yml index 04f7c53..5090513 100644 --- a/spec/cassettes/task_find_invalid.yml +++ b/spec/cassettes/task_find_invalid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scale.ai/v1/task/invalid_task_id?callback_url + uri: https://api.scale.com/v1/task/invalid_task_id?callback_url body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/task_find_valid.yml b/spec/cassettes/task_find_valid.yml index 506e136..3f95ed6 100644 --- a/spec/cassettes/task_find_valid.yml +++ b/spec/cassettes/task_find_valid.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scale.ai/v1/task/5c84d0fe958593004f13e5ba?callback_url + uri: https://api.scale.com/v1/task/5c84d0fe958593004f13e5ba?callback_url body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/task_list_1.yml b/spec/cassettes/task_list_1.yml index 4c6d57c..bd6803c 100644 --- a/spec/cassettes/task_list_1.yml +++ b/spec/cassettes/task_list_1.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scale.ai/v1/tasks?callback_url&end_time&limit=2&offset=0&start_time&status&type + uri: https://api.scale.com/v1/tasks?callback_url&end_time&limit=2&offset=0&start_time&status&type body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/task_list_2.yml b/spec/cassettes/task_list_2.yml index 80875ab..3f05017 100644 --- a/spec/cassettes/task_list_2.yml +++ b/spec/cassettes/task_list_2.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://api.scale.ai/v1/tasks?callback_url&end_time&limit=2&offset=2&start_time&status&type + uri: https://api.scale.com/v1/tasks?callback_url&end_time&limit=2&offset=2&start_time&status&type body: encoding: US-ASCII string: '' diff --git a/spec/cassettes/transcription.yml b/spec/cassettes/transcription.yml index 51c7125..16e22e1 100644 --- a/spec/cassettes/transcription.yml +++ b/spec/cassettes/transcription.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: post - uri: https://api.scale.ai/v1/task/transcription + uri: https://api.scale.com/v1/task/transcription body: encoding: UTF-8 string: '{"callback_url":"http://www.example.com/callback","instruction":"Transcribe diff --git a/spec/lib/api/tasks/data_collection_task_spec.rb b/spec/lib/api/tasks/data_collection_task_spec.rb index a65593d..4d94886 100644 --- a/spec/lib/api/tasks/data_collection_task_spec.rb +++ b/spec/lib/api/tasks/data_collection_task_spec.rb @@ -6,7 +6,7 @@ scale.create_datacollection_task( callback_url: 'http://www.example.com/callback', instruction: 'Find the URL for the hiring page for the company with attached website.', - attachment: 'https://www.scaleapi.com/', + attachment: 'https://scale.com/', attachment_type: 'website', fields: { hiring_page: 'Hiring Page URL' From e6354d902d70bdb859e7861eb192c7a2dc33e612 Mon Sep 17 00:00:00 2001 From: Rilka Li Date: Thu, 9 Apr 2020 21:37:00 -0700 Subject: [PATCH 5/5] Update list of task types --- lib/scale.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/scale.rb b/lib/scale.rb index 4276011..5d33698 100644 --- a/lib/scale.rb +++ b/lib/scale.rb @@ -2,17 +2,22 @@ class Scale attr_accessor :api_key, :callback_auth_key, :default_request_params, :logging VALID_TASK_TYPES = [ - "datacollection", + "annotation", + "audiotranscription", "categorization", "comparison", - "annotation", - "polygonannotation", + "cuboidannotation", + "datacollection", + "imageannotation", "lineannotation", - "transcription", - "audiotranscription", + "namedentityrecognition", "pointannotation", - "cuboidannotation", - "segmentannotation" + "polygonannotation", + "segmentannotation", + "transcription", + "videoannotation", + "videoboxannotation", + "videocuboidannotation" ].freeze def method_missing(methodId, *args, &block)