Skip to content

v1.0.4 - bug fixes, useragent extension, endpoint quotation, pytest updates #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ __ https://docs.scale.com/reference#list-multiple-tasks
Cancel Task
^^^^^^^^^^^

Cancel a task given its id if work has not stared on the task (task status is `queued` in the UI). Check out `Scale's API documentation`__ for more information.
Cancel a task given its id if work has not started on the task (task status is `Queued` in the UI). Check out `Scale's API documentation`__ for more information.

__ https://docs.scale.com/reference#cancel-task

.. code-block :: python

task = client.cancel_task('asdfasdfasdfasdfasdfasdf')
task = client.cancel_task('30553edd0b6a93f8f05f0fee')

Batches
_______
Expand Down Expand Up @@ -162,7 +162,7 @@ __ https://docs.scale.com/reference#batch-retrieval

.. code-block:: python

client.get_batch( batch_name = "batch_name_01_07_2021" )
client.get_batch(batch_name = 'batch_name_01_07_2021')

List Batches
^^^^^^^^^^^^
Expand Down
42 changes: 31 additions & 11 deletions scaleapi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import requests
import platform
import urllib.parse

from .tasks import Task
from .batches import Batch
Expand Down Expand Up @@ -63,11 +64,11 @@ class Batchlist(Paginator):


class ScaleClient(object):
def __init__(self, api_key):
def __init__(self, api_key, user_agent_extension=None):
self.api_key = api_key
self._headers = {
"Content-Type": "application/json",
"User-Agent": _generate_useragent()
"User-Agent": _generate_useragent(user_agent_extension)
}

def _getrequest(self, endpoint, params=None):
Expand Down Expand Up @@ -171,15 +172,15 @@ def create_batch(self, project, batch_name, callback):
return Batch(batchdata, self)

def finalize_batch(self, batch_name):
batchdata = self._postrequest('batches/%s/finalize' % batch_name)
batchdata = self._postrequest('batches/%s/finalize' % quote_string(batch_name))
return Batch(batchdata, self)

def batch_status(self, batch_name):
batchdata = self._getrequest('batches/%s/status' % batch_name)
return Batch.get_status(self)
status_data = self._getrequest('batches/%s/status' % quote_string(batch_name))
return status_data

def get_batch(self, batch_name):
batchdata = self._getrequest('batches/%s' % batch_name)
batchdata = self._getrequest('batches/%s' % quote_string(batch_name))
return Batch(batchdata, self)

def list_batches(self, **kwargs):
Expand All @@ -202,7 +203,7 @@ def create_project(self, project_name, type, params):
return Project(projectdata, self)

def get_project(self, project_name):
projectdata = self._getrequest('projects/%s' % project_name)
projectdata = self._getrequest('projects/%s' % quote_string(project_name))
return Project(projectdata, self)

def projects(self):
Expand All @@ -215,19 +216,38 @@ def update_project(self, project_name, **kwargs):
if key not in allowed_kwargs:
raise ScaleInvalidRequest('Illegal parameter %s for ScaleClient.update_project()'
% key, None)
projectdata = self._postrequest('projects/%s/setParams' % project_name, payload=kwargs)
projectdata = self._postrequest('projects/%s/setParams' % quote_string(project_name), payload=kwargs)
return projectdata

def _generate_useragent():
def _generate_useragent(extension=None):
try:
python_version = platform.python_version()
os_platform = platform.platform()

user_agent = '%s/%s Python/%s OS/%s' % (__name__, __version__, python_version, os_platform)
user_agent = " ".join(
filter(
None,
[
"{}/{}".format(__name__, __version__),
"Python/{}".format(python_version),
"OS/{}".format(os_platform),
extension,
],
)
)
return user_agent
except:

except Exception:
return "scaleapi-python-client"

def quote_string(text):
"""`quote_string('a bc/def')` -> `a%20bc%2Fdef`
Project and Batch names can be a part of URL, which causes an error
in case of a special character used. Quotation assures
the right object to be retrieved from API.
"""
return urllib.parse.quote(text, safe="")

def _AddTaskTypeCreator(task_type):
def create_task_wrapper(self, **kwargs):
return self.create_task(task_type, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion scaleapi/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.0.3"
__version__ = "1.0.4"
11 changes: 9 additions & 2 deletions scaleapi/batches.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ class Batch(object):
def __init__(self, param_dict, client):
self.param_dict = param_dict
self.name = param_dict['name']
self.status = param_dict["status"]

self.pending = None
self.completed = None
self.error = None
self.canceled = None
self.client = client
self.get_status()

def __hash__(self):
return hash(self.name)
Expand All @@ -18,9 +21,13 @@ def __repr__(self):
return 'Batch(%s)' % self.param_dict

def finalize(self):
return self.client._postrequest("batches/%s/finalize" % self.name)
res = self.client.finalize_batch(self.name)
self.status = res.status
return res

def get_status(self):
res = self.client._getrequest("batches/%s/status" % self.name)
res = self.client.batch_status(self.name)
self.status = res["status"]
for stat in ["pending", "completed", "error", "canceled"]:
setattr(self, stat, res.get(stat, 0))
return res
2 changes: 1 addition & 1 deletion scaleapi/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Project(object):
def __init__(self, param_dict, client):
self.param_dict = param_dict
self.name = param_dict['name']
self.client = client
self.client = client

def __hash__(self):
return hash(self.name)
Expand Down
34 changes: 24 additions & 10 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import scaleapi
import time
from datetime import datetime
from random import randint
import os

try:
test_api_key = os.environ['SCALE_TEST_API_KEY']
client = scaleapi.ScaleClient(test_api_key)
client = scaleapi.ScaleClient(test_api_key, 'pytest')
except KeyError:
raise Exception("Please set the environment variable SCALE_TEST_API_KEY to run tests.")

Expand All @@ -32,6 +33,7 @@ def test_categorize_ok():
callback_url='http://www.example.com/callback',
instruction='Is this company public or private?',
attachment_type='website',
force=True,
attachment='http://www.google.com/',
categories=['public', 'private'])

Expand Down Expand Up @@ -172,6 +174,7 @@ def test_audiotranscription_ok():
task = client.create_audiotranscription_task(
callback_url='http://www.example.com/callback',
attachment_type='audio',
instruction='Listen to the audio file and transcript.',
attachment='https://storage.googleapis.com/deepmind-media/pixie/knowing-what-to-say/second-list/speaker-3.wav',
verbatim=False,
phrases=['avocado', 'stone']
Expand Down Expand Up @@ -202,14 +205,13 @@ def test_cancel():
def test_task_retrieval():
task = make_a_task()
task2 = client.fetch_task(task.id)
assert task.status == 'pending'
assert task2.status == 'completed'
assert task2.id == task.id
assert task2.callback_url == task.callback_url
assert task2.instruction == task.instruction
assert task2.attachment_type == task.attachment_type
assert task2.attachments == task.attachments
assert task2.choices == task.choices
assert task2.attachment == task.attachment
assert task2.geometries == task.geometries
assert task2.metadata == task.metadata
assert task2.type == task.type
assert task2.created_at == task.created_at
Expand Down Expand Up @@ -242,18 +244,30 @@ def test_tasks_invalid():
def create_a_batch():
return client.create_batch(
callback = "http://www.example.com/callback",
batch_name = "kitten_labeling_2020-07",
project = "kitten_labeling"
batch_name = "scaleapi-python-sdk-" + str(randint(0, 99999)),
project = "scaleapi-python-sdk"
)

def test_finalize_batch():
batch = create_a_batch()
client.finalize_batch(batch.name)
batch = client.finalize_batch(batch.name)
assert batch.status == 'in_progress'

def get_batch_status():
batch2 = create_a_batch()
batch2.finalize()
assert batch2.status == 'in_progress'

def test_get_batch_status():
batch = create_a_batch()
client.batch_status(batch.name)
assert batch.status == 'staging'

batch.finalize()
batch.get_status() # Test status update
assert batch.status == 'in_progress'

def get_batch():
def test_get_batch():
batch = create_a_batch()
client.get_batch(batch.name)
batch2 = client.get_batch(batch.name)
assert batch.name == batch2.name
assert batch2.status == 'staging'