Event fixes
This commit is contained in:
1 parent
e4588a5e7e
commit
cfadd851bf
14 files changed
+115
-98
No files matched your search
@@ -15,7 +15,7 @@ import os
|
|||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__, static_folder = 'nope')
|
||||||
web = Blueprint('web', __name__)
|
web = Blueprint('web', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class Core(Plugin):
|
|||||||
|
|
||||||
def crappyShutdown(self):
|
def crappyShutdown(self):
|
||||||
try:
|
try:
|
||||||
self.urlopen('%sapp.shutdown' % self.createApiUrl(), show_error = False)
|
self.urlopen('%s/app.shutdown' % self.createApiUrl(), show_error = False)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
self.initShutdown()
|
self.initShutdown()
|
||||||
@@ -78,7 +78,7 @@ class Core(Plugin):
|
|||||||
|
|
||||||
def crappyRestart(self):
|
def crappyRestart(self):
|
||||||
try:
|
try:
|
||||||
self.urlopen('%sapp.restart' % self.createApiUrl(), show_error = False)
|
self.urlopen('%s/app.restart' % self.createApiUrl(), show_error = False)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
self.initShutdown(restart = True)
|
self.initShutdown(restart = True)
|
||||||
@@ -163,8 +163,7 @@ class Core(Plugin):
|
|||||||
host = 'localhost'
|
host = 'localhost'
|
||||||
port = Env.setting('port')
|
port = Env.setting('port')
|
||||||
|
|
||||||
return '%s:%d' % (cleanHost(host).rstrip('/'), int(port))
|
return '%s:%d%s' % (cleanHost(host).rstrip('/'), int(port), '/' + Env.setting('url_base').lstrip('/') if Env.setting('url_base') else '')
|
||||||
|
|
||||||
def createApiUrl(self):
|
def createApiUrl(self):
|
||||||
|
return '%s/%s' % (self.createBaseUrl(), Env.setting('api_key'))
|
||||||
return '%s/%s/' % (self.createBaseUrl(), Env.setting('api_key'))
|
|
||||||
@@ -17,7 +17,7 @@ def requires_auth(f):
|
|||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated(*args, **kwargs):
|
def decorated(*args, **kwargs):
|
||||||
auth = getattr(request, 'authorization')
|
auth = getattr(request, 'authorization')
|
||||||
if Env.setting('username') and (not auth or not check_auth(auth.username, md5(auth.password))):
|
if Env.setting('username') and Env.setting('password') and (not auth or not check_auth(auth.username, md5(auth.password))):
|
||||||
return authenticate()
|
return authenticate()
|
||||||
|
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from axl.axel import Event
|
|||||||
from couchpotato.core.helpers.variable import mergeDicts
|
from couchpotato.core.helpers.variable import mergeDicts
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
@@ -25,15 +26,17 @@ def addEvent(name, handler, priority = 100):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
parent = handler.im_self
|
parent = handler.im_self
|
||||||
parent.beforeCall(handler)
|
bc = hasattr(parent, 'beforeCall')
|
||||||
|
if bc: parent.beforeCall(handler)
|
||||||
h = runHandler(name, handler, *args, **kwargs)
|
h = runHandler(name, handler, *args, **kwargs)
|
||||||
parent.afterCall(handler)
|
ac = hasattr(parent, 'afterCall')
|
||||||
|
if ac: parent.afterCall(handler)
|
||||||
except:
|
except:
|
||||||
h = runHandler(name, handler, *args, **kwargs)
|
h = runHandler(name, handler, *args, **kwargs)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
|
|
||||||
e.handle(createHandle, priority = priority)
|
e.handle(handler, priority = priority)
|
||||||
|
|
||||||
def removeEvent(name, handler):
|
def removeEvent(name, handler):
|
||||||
e = events[name]
|
e = events[name]
|
||||||
@@ -64,8 +67,10 @@ def fireEvent(name, *args, **kwargs):
|
|||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
e = events[name]
|
e = events[name]
|
||||||
|
e.lock.acquire()
|
||||||
e.asynchronous = False
|
e.asynchronous = False
|
||||||
result = e(*args, **kwargs)
|
result = e(*args, **kwargs)
|
||||||
|
e.lock.release()
|
||||||
|
|
||||||
if single and not merge:
|
if single and not merge:
|
||||||
results = None
|
results = None
|
||||||
@@ -123,10 +128,11 @@ def fireEventAsync(name, *args, **kwargs):
|
|||||||
#log.debug('Async "%s": %s, %s' % (name, args, kwargs))
|
#log.debug('Async "%s": %s, %s' % (name, args, kwargs))
|
||||||
try:
|
try:
|
||||||
e = events[name]
|
e = events[name]
|
||||||
|
e.lock.acquire()
|
||||||
e.asynchronous = True
|
e.asynchronous = True
|
||||||
e.error_handler = errorHandler
|
e.error_handler = errorHandler
|
||||||
|
|
||||||
e(*args, **kwargs)
|
e(*args, **kwargs)
|
||||||
|
e.lock.release()
|
||||||
return True
|
return True
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.error('%s: %s' % (name, e))
|
log.error('%s: %s' % (name, e))
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
from couchpotato.core.event import fireEvent
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.notifications.base import Notification
|
from couchpotato.core.notifications.base import Notification
|
||||||
from gntp import notifier
|
from gntp import notifier
|
||||||
import logging
|
import logging
|
||||||
|
import thread
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
|
|
||||||
@@ -15,13 +19,19 @@ class Growl(Notification):
|
|||||||
logger.disabled = True
|
logger.disabled = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.growl = notifier.GrowlNotifier(
|
def startGrowl():
|
||||||
applicationName = 'CouchPotato',
|
time.sleep(2)
|
||||||
notifications = ["Updates"],
|
try:
|
||||||
defaultNotifications = ["Updates"],
|
self.growl = notifier.GrowlNotifier(
|
||||||
applicationIcon = 'http://couchpota.to/media/images/couch.png',
|
applicationName = 'CouchPotato',
|
||||||
)
|
notifications = ["Updates"],
|
||||||
self.growl.register()
|
defaultNotifications = ["Updates"],
|
||||||
|
applicationIcon = '%s/static/images/couch.png' % fireEvent('app.api_url', single = True),
|
||||||
|
)
|
||||||
|
self.growl.register()
|
||||||
|
except:
|
||||||
|
log.error('Failed register of growl: %s' % traceback.format_exc())
|
||||||
|
thread.start_new_thread(startGrowl, ())
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class Plugin(object):
|
|||||||
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', self.__class__.__name__)
|
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', self.__class__.__name__)
|
||||||
class_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
class_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
||||||
|
|
||||||
path = 'static/' + class_name + '/'
|
path = '%s/static/%s/' % (Env.setting('api_key'), class_name)
|
||||||
addView(path + '<path:filename>', self.showStatic, static = True)
|
addView(path + '<path:filename>', self.showStatic, static = True)
|
||||||
|
|
||||||
if add_to_head:
|
if add_to_head:
|
||||||
@@ -94,8 +94,6 @@ class Plugin(object):
|
|||||||
# http request
|
# http request
|
||||||
def urlopen(self, url, timeout = 10, params = {}, headers = {}, multipart = False, show_error = True):
|
def urlopen(self, url, timeout = 10, params = {}, headers = {}, multipart = False, show_error = True):
|
||||||
|
|
||||||
socket.setdefaulttimeout(timeout)
|
|
||||||
|
|
||||||
# Fill in some headers
|
# Fill in some headers
|
||||||
if not headers.get('Referer'):
|
if not headers.get('Referer'):
|
||||||
headers['Referer'] = urlparse(url).hostname
|
headers['Referer'] = urlparse(url).hostname
|
||||||
@@ -114,13 +112,13 @@ class Plugin(object):
|
|||||||
cookies = cookielib.CookieJar()
|
cookies = cookielib.CookieJar()
|
||||||
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), MultipartPostHandler)
|
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), MultipartPostHandler)
|
||||||
|
|
||||||
data = opener.open(request).read()
|
data = opener.open(request, timeout = timeout).read()
|
||||||
else:
|
else:
|
||||||
log.info('Opening url: %s, params: %s' % (url, [x for x in params.iterkeys()]))
|
log.info('Opening url: %s, params: %s' % (url, [x for x in params.iterkeys()]))
|
||||||
data = urllib.urlencode(params) if len(params) > 0 else None
|
data = urllib.urlencode(params) if len(params) > 0 else None
|
||||||
request = urllib2.Request(url, data, headers)
|
request = urllib2.Request(url, data, headers)
|
||||||
|
|
||||||
data = urllib2.urlopen(request).read()
|
data = urllib2.urlopen(request, timeout = timeout).read()
|
||||||
except IOError:
|
except IOError:
|
||||||
if show_error:
|
if show_error:
|
||||||
log.error('Failed opening url in %s: %s %s' % (self.getName(), url, traceback.format_exc(1)))
|
log.error('Failed opening url in %s: %s %s' % (self.getName(), url, traceback.format_exc(1)))
|
||||||
|
|||||||
@@ -290,11 +290,11 @@ class Renamer(Plugin):
|
|||||||
|
|
||||||
# Remove files
|
# Remove files
|
||||||
for src in remove_files:
|
for src in remove_files:
|
||||||
log.info('Removing "%s"' % src)
|
log.info('(fake) Removing "%s"' % src)
|
||||||
|
|
||||||
# Remove matching releases
|
# Remove matching releases
|
||||||
for release in remove_releases:
|
for release in remove_releases:
|
||||||
log.info('Removing release %s' % release)
|
log.info('(fake) Removing release %s' % release)
|
||||||
|
|
||||||
# Search for trailers etc
|
# Search for trailers etc
|
||||||
fireEventAsync('renamer.after', group)
|
fireEventAsync('renamer.after', group)
|
||||||
|
|||||||
@@ -528,7 +528,9 @@ class Scanner(Plugin):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def isSampleFile(self, filename):
|
def isSampleFile(self, filename):
|
||||||
return re.search('(^|[\W_])sample\d*[\W_]', filename.lower())
|
is_sample = re.search('(^|[\W_])sample\d*[\W_]', filename.lower())
|
||||||
|
if is_sample: log.debug('Is sample file: %s' % filename)
|
||||||
|
return is_sample
|
||||||
|
|
||||||
def filesizeBetween(self, file, min = 0, max = 100000):
|
def filesizeBetween(self, file, min = 0, max = 100000):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -16,18 +16,18 @@ log = CPLog(__name__)
|
|||||||
class Searcher(Plugin):
|
class Searcher(Plugin):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addEvent('searcher.all', self.all)
|
addEvent('searcher.all', self.all_movies)
|
||||||
addEvent('searcher.single', self.single)
|
addEvent('searcher.single', self.single)
|
||||||
addEvent('searcher.correct_movie', self.correctMovie)
|
addEvent('searcher.correct_movie', self.correctMovie)
|
||||||
addEvent('searcher.download', self.download)
|
addEvent('searcher.download', self.download)
|
||||||
|
|
||||||
# Schedule cronjob
|
# Schedule cronjob
|
||||||
fireEvent('schedule.cron', 'searcher.all', self.all, day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute'))
|
fireEvent('schedule.cron', 'searcher.all', self.all_movies, day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute'))
|
||||||
|
|
||||||
if not Env.setting('development'):
|
if not Env.setting('development'):
|
||||||
addEvent('app.load', self.all)
|
addEvent('app.load', self.all_movies)
|
||||||
|
|
||||||
def all(self):
|
def all_movies(self):
|
||||||
|
|
||||||
db = get_session()
|
db = get_session()
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import os.path
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
class Settings():
|
class Settings(object):
|
||||||
|
|
||||||
options = {}
|
options = {}
|
||||||
types = {}
|
types = {}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import locale
|
|||||||
import logging
|
import logging
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
|
||||||
import time
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
def getOptions(base_path, args):
|
def getOptions(base_path, args):
|
||||||
|
|
||||||
@@ -180,7 +180,8 @@ def runCouchPotato(options, base_path, args, desktop = None):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Static path
|
# Static path
|
||||||
web.add_url_rule('static/<path:filename>',
|
app.static_folder = os.path.join(base_path, 'couchpotato', 'static')
|
||||||
|
web.add_url_rule('%s/static/<path:filename>' % api_key,
|
||||||
endpoint = 'static',
|
endpoint = 'static',
|
||||||
view_func = app.send_static_file)
|
view_func = app.send_static_file)
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
@@ -13,6 +13,7 @@ Page.Wanted = new Class({
|
|||||||
// Wanted movies
|
// Wanted movies
|
||||||
self.wanted = new MovieList({
|
self.wanted = new MovieList({
|
||||||
'status': 'active',
|
'status': 'active',
|
||||||
|
'navigation': true,
|
||||||
'actions': MovieActions
|
'actions': MovieActions
|
||||||
});
|
});
|
||||||
$(self.wanted).inject(self.el);
|
$(self.wanted).inject(self.el);
|
||||||
|
|||||||
+65
-65
@@ -6,59 +6,61 @@
|
|||||||
# http://www.valuedlessons.com/2008/04/events-in-python.html
|
# http://www.valuedlessons.com/2008/04/events-in-python.html
|
||||||
#
|
#
|
||||||
# This module is part of Axel and is released under
|
# This module is part of Axel and is released under
|
||||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||||
#
|
#
|
||||||
# Source: http://pypi.python.org/pypi/axel
|
# Source: http://pypi.python.org/pypi/axel
|
||||||
# Docs: http://packages.python.org/axel
|
# Docs: http://packages.python.org/axel
|
||||||
|
|
||||||
from couchpotato.core.helpers.variable import natcmp
|
from couchpotato.core.helpers.variable import natcmp
|
||||||
import Queue
|
import Queue
|
||||||
|
import hashlib
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
class Event(object):
|
class Event(object):
|
||||||
"""
|
"""
|
||||||
Event object inspired by C# events. Handlers can be registered and
|
Event object inspired by C# events. Handlers can be registered and
|
||||||
unregistered using += and -= operators. Execution and result are
|
unregistered using += and -= operators. Execution and result are
|
||||||
influenced by the arguments passed to the constructor and += method.
|
influenced by the arguments passed to the constructor and += method.
|
||||||
|
|
||||||
from axel import Event
|
from axel import Event
|
||||||
|
|
||||||
event = Event()
|
event = Event()
|
||||||
def on_event(*args, **kwargs):
|
def on_event(*args, **kwargs):
|
||||||
return (args, kwargs)
|
return (args, kwargs)
|
||||||
|
|
||||||
event += on_event # handler registration
|
event += on_event # handler registration
|
||||||
print(event(10, 20, y=30))
|
print(event(10, 20, y=30))
|
||||||
>> ((True, ((10, 20), {'y': 30}), <function on_event at 0x00BAA270>),)
|
>> ((True, ((10, 20), {'y': 30}), <function on_event at 0x00BAA270>),)
|
||||||
|
|
||||||
event -= on_event # handler is unregistered
|
event -= on_event # handler is unregistered
|
||||||
print(event(10, 20, y=30))
|
print(event(10, 20, y=30))
|
||||||
>> None
|
>> None
|
||||||
|
|
||||||
class Mouse(object):
|
class Mouse(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.click = Event(self)
|
self.click = Event(self)
|
||||||
self.click += self.on_click # handler registration
|
self.click += self.on_click # handler registration
|
||||||
|
|
||||||
def on_click(self, sender, *args, **kwargs):
|
def on_click(self, sender, *args, **kwargs):
|
||||||
assert isinstance(sender, Mouse), 'Wrong sender'
|
assert isinstance(sender, Mouse), 'Wrong sender'
|
||||||
return (args, kwargs)
|
return (args, kwargs)
|
||||||
|
|
||||||
mouse = Mouse()
|
mouse = Mouse()
|
||||||
print(mouse.click(10, 20))
|
print(mouse.click(10, 20))
|
||||||
>> ((True, ((10, 20), {}),
|
>> ((True, ((10, 20), {}),
|
||||||
>> <bound method Mouse.on_click of <__main__.Mouse object at 0x00B6F470>>),)
|
>> <bound method Mouse.on_click of <__main__.Mouse object at 0x00B6F470>>),)
|
||||||
|
|
||||||
mouse.click -= mouse.on_click # handler is unregistered
|
mouse.click -= mouse.on_click # handler is unregistered
|
||||||
print(mouse.click(10, 20))
|
print(mouse.click(10, 20))
|
||||||
>> None
|
>> None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, sender = None, asynch = False, exc_info = False,
|
def __init__(self, sender = None, asynch = False, exc_info = False,
|
||||||
lock = None, threads = 3, traceback = False):
|
lock = None, threads = 3, traceback = False):
|
||||||
""" Creates an event
|
""" Creates an event
|
||||||
|
|
||||||
asynch
|
asynch
|
||||||
if True handler's are executes asynchronous
|
if True handler's are executes asynchronous
|
||||||
exc_info
|
exc_info
|
||||||
@@ -66,31 +68,31 @@ class Event(object):
|
|||||||
lock
|
lock
|
||||||
threading.RLock used to synchronize execution
|
threading.RLock used to synchronize execution
|
||||||
sender
|
sender
|
||||||
event's sender. The sender is passed as the first argument to the
|
event's sender. The sender is passed as the first argument to the
|
||||||
handler, only if is not None. For this case the handler must have
|
handler, only if is not None. For this case the handler must have
|
||||||
a placeholder in the arguments to receive the sender
|
a placeholder in the arguments to receive the sender
|
||||||
threads
|
threads
|
||||||
maximum number of threads that will be started
|
maximum number of threads that will be started
|
||||||
traceback
|
traceback
|
||||||
if True, the execution result will contain sys.exc_info()
|
if True, the execution result will contain sys.exc_info()
|
||||||
on error. exc_info must be also True to get the traceback
|
on error. exc_info must be also True to get the traceback
|
||||||
|
|
||||||
hash = hash(handler)
|
hash = self.hash(handler)
|
||||||
|
|
||||||
Handlers are stored in a dictionary that has as keys the handler's hash
|
Handlers are stored in a dictionary that has as keys the handler's hash
|
||||||
handlers = {
|
handlers = {
|
||||||
hash : (handler, memoize, timeout),
|
hash : (handler, memoize, timeout),
|
||||||
hash : (handler, memoize, timeout), ...
|
hash : (handler, memoize, timeout), ...
|
||||||
|
}
|
||||||
|
The execution result is cached using the following structure
|
||||||
|
memoize = {
|
||||||
|
hash : ((args, kwargs, result), (args, kwargs, result), ...),
|
||||||
|
hash : ((args, kwargs, result), ...), ...
|
||||||
}
|
}
|
||||||
The execution result is cached using the following structure
|
|
||||||
memoize = {
|
|
||||||
hash : ((args, kwargs, result), (args, kwargs, result), ...),
|
|
||||||
hash : ((args, kwargs, result), ...), ...
|
|
||||||
}
|
|
||||||
The execution result is returned as a tuple having this structure
|
The execution result is returned as a tuple having this structure
|
||||||
exec_result = (
|
exec_result = (
|
||||||
(True, result, handler), # on success
|
(True, result, handler), # on success
|
||||||
(False, error_info, handler), # on error
|
(False, error_info, handler), # on error
|
||||||
(None, None, handler), ... # asynchronous execution
|
(None, None, handler), ... # asynchronous execution
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
@@ -103,31 +105,34 @@ class Event(object):
|
|||||||
self.handlers = {}
|
self.handlers = {}
|
||||||
self.memoize = {}
|
self.memoize = {}
|
||||||
|
|
||||||
|
def hash(self, handler):
|
||||||
|
return hashlib.md5(str(handler)).hexdigest()
|
||||||
|
|
||||||
def handle(self, handler, priority = 0):
|
def handle(self, handler, priority = 0):
|
||||||
""" Registers a handler. The handler can be transmitted together
|
""" Registers a handler. The handler can be transmitted together
|
||||||
with two arguments as a list or dictionary. The arguments are:
|
with two arguments as a list or dictionary. The arguments are:
|
||||||
|
|
||||||
memoize
|
memoize
|
||||||
if True, the execution result will be cached in self.memoize
|
if True, the execution result will be cached in self.memoize
|
||||||
timeout
|
timeout
|
||||||
will allocate a predefined time interval for the execution
|
will allocate a predefined time interval for the execution
|
||||||
|
|
||||||
If arguments are provided as a list, they are considered to have
|
If arguments are provided as a list, they are considered to have
|
||||||
this sequence: (handler, memoize, timeout)
|
this sequence: (handler, memoize, timeout)
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
event += handler
|
event += handler
|
||||||
event += (handler, True, 1.5)
|
event += (handler, True, 1.5)
|
||||||
event += {'handler':handler, 'memoize':True, 'timeout':1.5}
|
event += {'handler':handler, 'memoize':True, 'timeout':1.5}
|
||||||
"""
|
"""
|
||||||
handler_, memoize, timeout = self._extract(handler)
|
handler_, memoize, timeout = self._extract(handler)
|
||||||
self.handlers['%s.%s' % (priority, hash(handler_))] = (handler_, memoize, timeout)
|
self.handlers['%s.%s' % (priority, self.hash(handler_))] = (handler_, memoize, timeout)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def unhandle(self, handler):
|
def unhandle(self, handler):
|
||||||
""" Unregisters a handler """
|
""" Unregisters a handler """
|
||||||
handler_, memoize, timeout = self._extract(handler)
|
handler_, memoize, timeout = self._extract(handler)
|
||||||
key = hash(handler_)
|
key = self.hash(handler_)
|
||||||
if not key in self.handlers:
|
if not key in self.handlers:
|
||||||
raise ValueError('Handler "%s" was not found' % str(handler_))
|
raise ValueError('Handler "%s" was not found' % str(handler_))
|
||||||
del self.handlers[key]
|
del self.handlers[key]
|
||||||
@@ -139,6 +144,7 @@ class Event(object):
|
|||||||
self.result = []
|
self.result = []
|
||||||
|
|
||||||
if self.handlers:
|
if self.handlers:
|
||||||
|
|
||||||
max_threads = self._threads()
|
max_threads = self._threads()
|
||||||
|
|
||||||
for i in range(max_threads):
|
for i in range(max_threads):
|
||||||
@@ -172,10 +178,8 @@ class Event(object):
|
|||||||
""" Executes all handlers stored in the queue """
|
""" Executes all handlers stored in the queue """
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
handler, memoize, timeout = self.handlers[self.queue.get()]
|
h_ = self.queue.get()
|
||||||
|
handler, memoize, timeout = self.handlers[h_]
|
||||||
if isinstance(self.lock, threading._RLock):
|
|
||||||
self.lock.acquire() #synchronization
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = self._memoize(memoize, timeout, handler, *args, **kwargs)
|
r = self._memoize(memoize, timeout, handler, *args, **kwargs)
|
||||||
@@ -189,14 +193,9 @@ class Event(object):
|
|||||||
else:
|
else:
|
||||||
self.error_handler(sys.exc_info())
|
self.error_handler(sys.exc_info())
|
||||||
finally:
|
finally:
|
||||||
if isinstance(self.lock, threading._RLock):
|
|
||||||
self.lock.release()
|
|
||||||
|
|
||||||
if not self.asynchronous:
|
if not self.asynchronous:
|
||||||
try:
|
self.queue.task_done()
|
||||||
self.queue.task_done()
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if self.queue.empty():
|
if self.queue.empty():
|
||||||
raise Queue.Empty
|
raise Queue.Empty
|
||||||
@@ -205,9 +204,9 @@ class Event(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
def _extract(self, queue_item):
|
def _extract(self, queue_item):
|
||||||
""" Extracts a handler and handler's arguments that can be provided
|
""" Extracts a handler and handler's arguments that can be provided
|
||||||
as list or dictionary. If arguments are provided as list, they are
|
as list or dictionary. If arguments are provided as list, they are
|
||||||
considered to have this sequence: (handler, memoize, timeout)
|
considered to have this sequence: (handler, memoize, timeout)
|
||||||
Examples:
|
Examples:
|
||||||
event += handler
|
event += handler
|
||||||
event += (handler, True, 1.5)
|
event += (handler, True, 1.5)
|
||||||
@@ -234,11 +233,11 @@ class Event(object):
|
|||||||
return (handler, bool(memoize), float(timeout))
|
return (handler, bool(memoize), float(timeout))
|
||||||
|
|
||||||
def _memoize(self, memoize, timeout, handler, *args, **kwargs):
|
def _memoize(self, memoize, timeout, handler, *args, **kwargs):
|
||||||
""" Caches the execution result of successful executions
|
""" Caches the execution result of successful executions
|
||||||
hash = hash(handler)
|
hash = self.hash(handler)
|
||||||
memoize = {
|
memoize = {
|
||||||
hash : ((args, kwargs, result), (args, kwargs, result), ...),
|
hash : ((args, kwargs, result), (args, kwargs, result), ...),
|
||||||
hash : ((args, kwargs, result), ...), ...
|
hash : ((args, kwargs, result), ...), ...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
if not isinstance(handler, Event) and self.sender is not None:
|
if not isinstance(handler, Event) and self.sender is not None:
|
||||||
@@ -247,7 +246,8 @@ class Event(object):
|
|||||||
|
|
||||||
if not memoize:
|
if not memoize:
|
||||||
if timeout <= 0: #no time restriction
|
if timeout <= 0: #no time restriction
|
||||||
return [True, handler(*args, **kwargs), handler]
|
result = [True, handler(*args, **kwargs), handler]
|
||||||
|
return result
|
||||||
|
|
||||||
result = self._timeout(timeout, handler, *args, **kwargs)
|
result = self._timeout(timeout, handler, *args, **kwargs)
|
||||||
if isinstance(result, tuple) and len(result) == 3:
|
if isinstance(result, tuple) and len(result) == 3:
|
||||||
@@ -255,7 +255,7 @@ class Event(object):
|
|||||||
return [False, self._error(result), handler]
|
return [False, self._error(result), handler]
|
||||||
return [True, result, handler]
|
return [True, result, handler]
|
||||||
else:
|
else:
|
||||||
hash_ = hash(handler)
|
hash_ = self.hash(handler)
|
||||||
if hash_ in self.memoize:
|
if hash_ in self.memoize:
|
||||||
for args_, kwargs_, result in self.memoize[hash_]:
|
for args_, kwargs_, result in self.memoize[hash_]:
|
||||||
if args_ == args and kwargs_ == kwargs:
|
if args_ == args and kwargs_ == kwargs:
|
||||||
|
|||||||
Reference in new issue
Block a user