Skip to content
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
2,380 changes: 1,220 additions & 1,160 deletions intermine/constraints.py

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions intermine/decorators.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
from functools import wraps
from intermine.errors import ServiceError

def requires_version(required):

error_fmt = "Service must be at version %s, but is at %s"

def decorator(f):

@wraps(f)
def wrapper(self, *args, **kwargs):
if self.version < required:
raise ServiceError(error_fmt % (required, self.version))
return f(self, *args, **kwargs)

return wrapper

return decorator

from functools import wraps
from intermine.errors import ServiceError
def requires_version(required):
error_fmt = "Service must be at version %s, but is at %s"
def decorator(f):
@wraps(f)
def wrapper(self, *args, **kwargs):
if self.version < required:
raise ServiceError(error_fmt % (required, self.version))
return f(self, *args, **kwargs)
return wrapper
return decorator
27 changes: 15 additions & 12 deletions intermine/errors.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from intermine.util import ReadableException

class UnimplementedError(Exception):
pass

class ServiceError(ReadableException):
"""Errors in the creation and use of the Service object"""
pass

class WebserviceError(IOError):
"""Errors from interaction with the webservice"""
pass
from intermine.util import ReadableException


class UnimplementedError(Exception):
pass


class ServiceError(ReadableException):
"""Errors in the creation and use of the Service object"""
pass


class WebserviceError(IOError):
"""Errors from interaction with the webservice"""
pass
185 changes: 94 additions & 91 deletions intermine/idresolution.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,94 @@
import weakref
import time

# Use core json for 2.6+, simplejson for <=2.5
try:
import json
except ImportError:
import simplejson as json

def get_json(service, path, key):
text = service.opener.read(service.root + path)
data = json.loads(text)
if data['error'] is not None:
raise Exception(data['error'])
if key not in data:
raise Exception(key + " not returned from " + path)
return data[key]

ONE_MINUTE = 60

COMPLETED = set(["SUCCESS", "ERROR"])

class Job(object):
"""
A Representation of an Identifier Resolution Job
================================================

Users can submit requests to resolve sets of IDs to
objects in the data-store. These jobs begin in a PENDING
state, and transition through RUNNING to either SUCCESS
or ERROR.

Upon completion, the results of the job may be fetched, and the
job may be deleted on the server.
"""

INITIAL_DECAY = 1.25
INITIAL_BACKOFF = 0.05
MAX_BACKOFF = ONE_MINUTE

def __init__(self, service, uid):
self.service = weakref.proxy(service)
self.uid = uid
self.status = None
self.backoff = Job.INITIAL_BACKOFF
self.decay = Job.INITIAL_DECAY
self.max_backoff = Job.MAX_BACKOFF
if self.uid is None:
raise Exception("No uid found")

def poll(self):
"""
Check to see if the job has been completed, updating the
status of the job in the process.

@return: Boolean Whether or not the job is complete.
"""
if self.status not in COMPLETED:
backoff = self.backoff
self.backoff = min(self.max_backoff, backoff * self.decay)
time.sleep(backoff)
self.status = self.fetch_status()
return self.status in COMPLETED

def fetch_status(self):
"""
Retrieve the results of this completed job from the server.

@rtype: dict
"""
return get_json(self.service, "/ids/{0}/status".format(self.uid), "status")

def delete(self):
"""
Delete the job from the server.

The job should not be used again once this method has been invoked.
"""
path = "/ids/" + self.uid
response = self.service.opener.delete(self.service.root + path)
response_data = json.loads(response)
if response_data['error'] is not None:
raise Exception(response_data['error'])

def fetch_results(self):
"""
Retrieve the current status of this job from the server.

@rtype String
"""
return get_json(self.service, "/ids/{0}/result".format(self.uid), "results")
import weakref
import time

# Use core json for 2.6+, simplejson for <=2.5
try:
import json
except ImportError:
import simplejson as json


def get_json(service, path, key):
text = service.opener.read(service.root + path)
data = json.loads(text)
if data['error'] is not None:
raise Exception(data['error'])
if key not in data:
raise Exception(key + " not returned from " + path)
return data[key]


ONE_MINUTE = 60

COMPLETED = set(["SUCCESS", "ERROR"])


class Job(object):
"""
A Representation of an Identifier Resolution Job
================================================

Users can submit requests to resolve sets of IDs to
objects in the data-store. These jobs begin in a PENDING
state, and transition through RUNNING to either SUCCESS
or ERROR.

Upon completion, the results of the job may be fetched, and the
job may be deleted on the server.
"""

INITIAL_DECAY = 1.25
INITIAL_BACKOFF = 0.05
MAX_BACKOFF = ONE_MINUTE

def __init__(self, service, uid):
self.service = weakref.proxy(service)
self.uid = uid
self.status = None
self.backoff = Job.INITIAL_BACKOFF
self.decay = Job.INITIAL_DECAY
self.max_backoff = Job.MAX_BACKOFF
if self.uid is None:
raise Exception("No uid found")

def poll(self):
"""
Check to see if the job has been completed, updating the
status of the job in the process.

@return: Boolean Whether or not the job is complete.
"""
if self.status not in COMPLETED:
backoff = self.backoff
self.backoff = min(self.max_backoff, backoff * self.decay)
time.sleep(backoff)
self.status = self.fetch_status()
return self.status in COMPLETED

def fetch_status(self):
"""
Retrieve the results of this completed job from the server.

@rtype: dict
"""
return get_json(self.service, "/ids/{0}/status".format(self.uid), "status")

def delete(self):
"""
Delete the job from the server.

The job should not be used again once this method has been invoked.
"""
path = "/ids/" + self.uid
response = self.service.opener.delete(self.service.root + path)
response_data = json.loads(response)
if response_data['error'] is not None:
raise Exception(response_data['error'])

def fetch_results(self):
"""
Retrieve the current status of this job from the server.

@rtype String
"""
return get_json(self.service, "/ids/{0}/result".format(self.uid), "results")
Loading