Support ignore_class and queue to noparallel decorator

This commit is contained in:
shortcutme 2017-04-01 22:31:15 +02:00
parent cfb2276ecd
commit 233d5f31f2
No known key found for this signature in database
GPG key ID: 5B63BAE6CB9613AE
2 changed files with 49 additions and 3 deletions

View file

@ -14,6 +14,13 @@ class ExampleClass(object):
self.counted += 1 self.counted += 1
return "counted:%s" % i return "counted:%s" % i
@util.Noparallel(queue=True, ignore_class=True)
def countQueue(self, num=5):
for i in range(1, num+1):
time.sleep(0.01)
self.counted += 1
return "counted:%s" % i
@util.Noparallel(blocking=False) @util.Noparallel(blocking=False)
def countNoblocking(self, num=5): def countNoblocking(self, num=5):
for i in range(1, num+1): for i in range(1, num+1):
@ -57,3 +64,34 @@ class TestNoparallel:
obj1.countNoblocking().join() # Allow again and wait until finishes obj1.countNoblocking().join() # Allow again and wait until finishes
assert obj1.counted == 10 assert obj1.counted == 10
def testQueue(self):
obj1 = ExampleClass()
threads = [
gevent.spawn(obj1.countQueue),
gevent.spawn(obj1.countQueue),
gevent.spawn(obj1.countQueue)
]
gevent.joinall(threads)
assert obj1.counted == 15 # Calls should be executed sequentially
def testIngoreClass(self):
obj1 = ExampleClass()
obj2 = ExampleClass()
threads = [
gevent.spawn(obj1.countQueue),
gevent.spawn(obj1.countQueue),
gevent.spawn(obj1.countQueue),
gevent.spawn(obj2.countQueue),
gevent.spawn(obj2.countQueue)
]
s = time.time()
gevent.joinall(threads)
assert obj1.counted == 15
assert obj2.counted == 10
taken = time.time() - s
assert taken >= 0.25 # Every count takes 0.05sec

View file

@ -4,14 +4,18 @@ import time
class Noparallel(object): # Only allow function running once in same time class Noparallel(object): # Only allow function running once in same time
def __init__(self, blocking=True, ignore_args=False): def __init__(self, blocking=True, ignore_args=False, ignore_class=False, queue=False):
self.threads = {} self.threads = {}
self.blocking = blocking # Blocking: Acts like normal function else thread returned self.blocking = blocking # Blocking: Acts like normal function else thread returned
self.queue = queue
self.ignore_args = ignore_args self.ignore_args = ignore_args
self.ignore_class = ignore_class
def __call__(self, func): def __call__(self, func):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
if self.ignore_args: if self.ignore_class:
key = func # Unique key only by function and class object
elif self.ignore_args:
key = (func, args[0]) # Unique key only by function and class object key = (func, args[0]) # Unique key only by function and class object
else: else:
key = (func, tuple(args), str(kwargs)) # Unique key for function including parameters key = (func, tuple(args), str(kwargs)) # Unique key for function including parameters
@ -19,7 +23,11 @@ class Noparallel(object): # Only allow function running once in same time
thread = self.threads[key] thread = self.threads[key]
if self.blocking: if self.blocking:
thread.join() # Blocking until its finished thread.join() # Blocking until its finished
return thread.value # Return the value if self.queue:
return wrapper(*args, **kwargs) # Run again
else:
return thread.value # Return the value
else: # No blocking else: # No blocking
if thread.ready(): # Its finished, create a new if thread.ready(): # Its finished, create a new
thread = gevent.spawn(func, *args, **kwargs) thread = gevent.spawn(func, *args, **kwargs)