Skip to content
Merged
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
86 changes: 44 additions & 42 deletions pyipptool/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,18 @@ def __init__(self, value):
self.value = value


def ipptool_caller_marker(method):
def pyipptool_coroutine(method):
"""
Mark the method as a coroutine.
If use with tornado the side effect of this decorator will be
cancelled and the original_method will be wrapped by
tornado.gen.coroutine .
Otherwise the sync_coroutine_consumer wrapper
will take care to consume the generator synchronously.
"""
method.ipptool_caller = True
@functools.wraps(method)
def inner(*args, **kw):
def sync_coroutine_consumer(*args, **kw):
gen = method(*args, **kw)
while True:
value = gen.next()
Expand All @@ -63,8 +71,8 @@ def inner(*args, **kw):
return returned.value
except StopIteration:
return value
inner.real_method = method
return inner
sync_coroutine_consumer.original_method = method
return sync_coroutine_consumer


class MetaAsyncShifter(type):
Expand All @@ -81,10 +89,9 @@ def __new__(cls, name, bases, attrs):
method = getattr(bases[0], method_name)
if getattr(method, 'ipptool_caller', False):
# Patch Method with tornado.gen.coroutine
setattr(klass, method_name, coroutine(method.real_method))
return klass
else:
return klass
setattr(klass, method_name,
coroutine(method.original_method))
return klass



Expand Down Expand Up @@ -144,7 +151,7 @@ def _call_ipptool(self, uri, request):
raise TimeoutError
return plistlib.readPlistFromString(stdout)['Tests'][0]

@ipptool_caller_marker
@pyipptool_coroutine
def release_job(self, uri,
printer_uri=colander.null,
job_id=colander.null,
Expand All @@ -157,7 +164,7 @@ def release_job(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cancel_job(self, uri,
printer_uri=colander.null,
job_id=colander.null,
Expand All @@ -172,7 +179,7 @@ def cancel_job(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def create_job_subscription(self,
uri,
printer_uri=None,
Expand Down Expand Up @@ -203,7 +210,7 @@ def create_job_subscription(self,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def create_printer_subscription(
self,
uri,
Expand Down Expand Up @@ -235,7 +242,7 @@ def create_printer_subscription(
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_add_modify_printer(self, uri,
printer_uri=None,
auth_info_required=colander.null,
Expand Down Expand Up @@ -274,7 +281,7 @@ def cups_add_modify_printer(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_add_modify_class(self, uri,
printer_uri=None,
auth_info_required=colander.null,
Expand Down Expand Up @@ -307,21 +314,21 @@ def cups_add_modify_class(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_delete_printer(self, uri, printer_uri=None):
kw = {'header': {'operation_attributes': {'printer_uri': printer_uri}}}
request = cups_delete_printer_form.render(kw)
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_delete_class(self, uri, printer_uri=None):
kw = {'header': {'operation_attributes': {'printer_uri': printer_uri}}}
request = cups_delete_class_form.render(kw)
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_get_classes(self, uri,
first_printer_name=colander.null,
limit=colander.null,
Expand All @@ -342,7 +349,7 @@ def cups_get_classes(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_get_devices(self, uri,
device_class=colander.null,
exclude_schemes=colander.null,
Expand All @@ -361,7 +368,7 @@ def cups_get_devices(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_get_ppds(self, uri,
exclude_schemes=colander.null,
include_schemes=colander.null,
Expand Down Expand Up @@ -391,7 +398,7 @@ def cups_get_ppds(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_get_printers(self, uri,
first_printer_name=colander.null,
limit=colander.null,
Expand All @@ -412,7 +419,7 @@ def cups_get_printers(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_move_job(self, uri,
printer_uri=colander.null,
job_id=colander.null,
Expand All @@ -429,7 +436,7 @@ def cups_move_job(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cups_reject_jobs(self, uri,
printer_uri=None,
requesting_user_name=None,
Expand All @@ -442,7 +449,7 @@ def cups_reject_jobs(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def get_job_attributes(self, uri,
printer_uri=colander.null,
job_id=colander.null,
Expand All @@ -459,7 +466,7 @@ def get_job_attributes(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def get_jobs(self, uri,
printer_uri=None,
requesting_user_name=colander.null,
Expand All @@ -478,7 +485,7 @@ def get_jobs(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def get_printer_attributes(self, uri,
printer_uri=None,
requesting_user_name=colander.null,
Expand All @@ -491,7 +498,7 @@ def get_printer_attributes(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def get_subscriptions(self, uri,
printer_uri=None,
requesting_user_name=colander.null,
Expand All @@ -510,7 +517,7 @@ def get_subscriptions(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def get_notifications(self,
uri,
printer_uri=None,
Expand All @@ -529,7 +536,7 @@ def get_notifications(self,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def cancel_subscription(self, uri,
printer_uri=None,
requesting_user_name=colander.null,
Expand All @@ -543,7 +550,7 @@ def cancel_subscription(self, uri,
response = yield self._call_ipptool(uri, request)
raise Return(response)

@ipptool_caller_marker
@pyipptool_coroutine
def _pause_or_resume_printer(self, form, uri, printer_uri=None,
requesting_user_name=colander.null):
kw = {'header': {'operation_attributes':
Expand All @@ -559,7 +566,7 @@ def pause_printer(self, *args, **kw):
def resume_printer(self, *args, **kw):
return self._pause_or_resume_printer(resume_printer_form, *args, **kw)

@ipptool_caller_marker
@pyipptool_coroutine
def _hold_or_release_new_jobs(self, form, uri, printer_uri=None,
requesting_user_name=colander.null,
printer_message_from_operator=colander.null):
Expand Down Expand Up @@ -589,13 +596,6 @@ def __init__(self, config, io_loop):
self.config = config
self.io_loop = io_loop

@coroutine
def cleanup_fd(self, name):
try:
os.unlink(name)
except OSError:
pass

@coroutine
def _call_ipptool(self, uri, request):
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
Expand All @@ -612,10 +612,12 @@ def _call_ipptool(self, uri, request):
self.io_loop.add_timeout(self.io_loop.time() + self.config['timeout'],
functools.partial(self.timeout_handler,
process.proc, future))
stdout, stderr = yield [Task(process.stdout.read_until_close),
Task(process.stderr.read_until_close)]
if future:
raise TimeoutError
yield self.cleanup_fd(temp_file.name)
try:
stdout, stderr = yield [Task(process.stdout.read_until_close),
Task(process.stderr.read_until_close)]
if future:
raise TimeoutError
finally:
os.unlink(temp_file.name)

raise Return(plistlib.readPlistFromString(stdout)['Tests'][0])