Add error.py.

Remove old cache decorator classes from client.py.
Raise deluge.error.NoCoreError when attempting to use a client function 
when not connected to a daemon.
This commit is contained in:
Andrew Resch 2008-02-10 13:36:58 +00:00
commit 3ad87b0e91
2 changed files with 87 additions and 80 deletions

42
deluge/error.py Normal file
View file

@ -0,0 +1,42 @@
#
# error.py
#
# Copyright (C) 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
class DelugeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class NoCoreError(DelugeError):
pass

View file

@ -41,85 +41,20 @@ import gobject
import deluge.xmlrpclib as xmlrpclib import deluge.xmlrpclib as xmlrpclib
import deluge.common import deluge.common
import deluge.error
from deluge.log import LOG as log from deluge.log import LOG as log
CACHE_TTL = 1.5 # seconds class no_core_error:
# This decorator class will throw a NoCoreError exception if core is None
class cache:
def __init__(self, func): def __init__(self, func):
self.func = func self.func = func
#self.cache_values = {(args, kwargs): (time, ret)}
self.cache_values = {}
def __call__(self, *__args, **__kw):
# Turn the arguments into hashable values
if __args == ():
args = None
else:
args = __args
if __kw == {}:
kw = None
else:
kw = __kw
# See if there is a cached return value for this call
if self.cache_values.has_key((args, kw)):
# Check the timestamp on the value to ensure it's still valid
if time.time() - self.cache_values[(args, kw)][0] < CACHE_TTL:
return self.cache_values[(args, kw)][1]
# No return value in cache
ret = self.func(*__args, **__kw)
self.cache_values[(args, kw)] = [time.time(), ret]
return ret
class cache_dict:
"""Special cache decorator for get_torrent_status and the like.. It expects
passing a str, list and returns a dict"""
def __init__(self, func):
self.func = func
self.cache_values = {}
def __call__(self, *__args, **__kw): def __call__(self, *__args, **__kw):
if __args == (): if _core.get_core() == None:
return raise deluge.error.NoCoreError("The core proxy is invalid.")
# Check for a cache value for these parameters else:
if self.cache_values.has_key(__args[0]): return self.func(*__args, **__kw)
# Check the timestamp on the value to ensure it's still valid
if time.time() - self.cache_values[__args[0]][0] < CACHE_TTL:
# Check to see if we have the right keys in cache
cache_dict = self.cache_values[__args[0]][1]
if cache_dict == None:
cache_dict = {}
keys = __args[1]
non_cached = []
ret_dict = {}
for key in keys:
if key in cache_dict.keys():
ret_dict[key] = cache_dict[key]
else:
non_cached.append(key)
# If there aren't any non_cached keys then lets just return
# cached values
if len(non_cached) == 0:
return ret_dict
# We need to request the remaining non-cached keys from the func
ret = self.func(*(__args[0], non_cached), **__kw)
if ret == None:
return ret
ret.update(ret_dict)
self.cache_values[__args[0]] = [time.time(), ret]
return ret
# Not cached
ret = self.func(*__args, **__kw)
self.cache_values[__args[0]] = [time.time(), ret]
return ret
class CoreProxy(gobject.GObject): class CoreProxy(gobject.GObject):
__gsignals__ = { __gsignals__ = {
"new_core" : ( "new_core" : (
@ -253,12 +188,15 @@ def connected():
return True return True
return False return False
@no_core_error
def register_client(port): def register_client(port):
get_core().call("register_client", None, port) get_core().call("register_client", None, port)
@no_core_error
def deregister_client(): def deregister_client():
get_core().call("deregister_client", None) get_core().call("deregister_client", None)
@no_core_error
def shutdown(): def shutdown():
"""Shutdown the core daemon""" """Shutdown the core daemon"""
try: try:
@ -268,11 +206,13 @@ def shutdown():
# Ignore everything # Ignore everything
set_core_uri(None) set_core_uri(None)
@no_core_error
def force_call(block=True): def force_call(block=True):
"""Forces the multicall batch to go now and not wait for the timer. This """Forces the multicall batch to go now and not wait for the timer. This
call also blocks until all callbacks have been dealt with.""" call also blocks until all callbacks have been dealt with."""
get_core().do_multicall(block=block) get_core().do_multicall(block=block)
@no_core_error
def add_torrent_file(torrent_files, torrent_options=None): def add_torrent_file(torrent_files, torrent_options=None):
"""Adds torrent files to the core """Adds torrent files to the core
Expects a list of torrent files Expects a list of torrent files
@ -308,6 +248,7 @@ def add_torrent_file(torrent_files, torrent_options=None):
get_core().call("add_torrent_file", None, get_core().call("add_torrent_file", None,
filename, str(), fdump, options) filename, str(), fdump, options)
@no_core_error
def add_torrent_url(torrent_url, options=None): def add_torrent_url(torrent_url, options=None):
"""Adds torrents to the core via url""" """Adds torrents to the core via url"""
from deluge.common import is_url from deluge.common import is_url
@ -316,97 +257,121 @@ def add_torrent_url(torrent_url, options=None):
torrent_url, str(), options) torrent_url, str(), options)
else: else:
log.warning("Invalid URL %s", torrent_url) log.warning("Invalid URL %s", torrent_url)
@no_core_error
def remove_torrent(torrent_ids, remove_torrent=False, remove_data=False): def remove_torrent(torrent_ids, remove_torrent=False, remove_data=False):
"""Removes torrent_ids from the core.. Expects a list of torrent_ids""" """Removes torrent_ids from the core.. Expects a list of torrent_ids"""
log.debug("Attempting to removing torrents: %s", torrent_ids) log.debug("Attempting to removing torrents: %s", torrent_ids)
for torrent_id in torrent_ids: for torrent_id in torrent_ids:
get_core().call("remove_torrent", None, torrent_id, remove_torrent, remove_data) get_core().call("remove_torrent", None, torrent_id, remove_torrent, remove_data)
@no_core_error
def pause_torrent(torrent_ids): def pause_torrent(torrent_ids):
"""Pauses torrent_ids""" """Pauses torrent_ids"""
for torrent_id in torrent_ids: for torrent_id in torrent_ids:
get_core().call("pause_torrent", None, torrent_id) get_core().call("pause_torrent", None, torrent_id)
@no_core_error
def move_torrent(torrent_ids, folder): def move_torrent(torrent_ids, folder):
"""Pauses torrent_ids""" """Pauses torrent_ids"""
for torrent_id in torrent_ids: for torrent_id in torrent_ids:
get_core().call("move_torrent", None, torrent_id, folder) get_core().call("move_torrent", None, torrent_id, folder)
@no_core_error
def pause_all_torrents(): def pause_all_torrents():
"""Pauses all torrents""" """Pauses all torrents"""
get_core().call("pause_all_torrents", None) get_core().call("pause_all_torrents", None)
@no_core_error
def resume_all_torrents(): def resume_all_torrents():
"""Resumes all torrents""" """Resumes all torrents"""
get_core().call("resume_all_torrents", None) get_core().call("resume_all_torrents", None)
@no_core_error
def resume_torrent(torrent_ids): def resume_torrent(torrent_ids):
"""Resume torrent_ids""" """Resume torrent_ids"""
for torrent_id in torrent_ids: for torrent_id in torrent_ids:
get_core().call("resume_torrent", None, torrent_id) get_core().call("resume_torrent", None, torrent_id)
@no_core_error
def force_reannounce(torrent_ids): def force_reannounce(torrent_ids):
"""Reannounce to trackers""" """Reannounce to trackers"""
for torrent_id in torrent_ids: for torrent_id in torrent_ids:
get_core().call("force_reannounce", None, torrent_id) get_core().call("force_reannounce", None, torrent_id)
@no_core_error
def get_torrent_status(callback, torrent_id, keys): def get_torrent_status(callback, torrent_id, keys):
"""Builds the status dictionary and returns it""" """Builds the status dictionary and returns it"""
get_core().call("get_torrent_status", callback, torrent_id, keys) get_core().call("get_torrent_status", callback, torrent_id, keys)
@no_core_error
def get_torrents_status(callback, torrent_ids, keys): def get_torrents_status(callback, torrent_ids, keys):
"""Builds a dictionary of torrent_ids status. Expects 2 lists. This is """Builds a dictionary of torrent_ids status. Expects 2 lists. This is
asynchronous so the return value will be sent as the signal asynchronous so the return value will be sent as the signal
'torrent_status'""" 'torrent_status'"""
get_core().call("get_torrents_status", callback, torrent_ids, keys) get_core().call("get_torrents_status", callback, torrent_ids, keys)
@no_core_error
def get_session_state(callback): def get_session_state(callback):
get_core().call("get_session_state", callback) get_core().call("get_session_state", callback)
@no_core_error
def get_config(callback): def get_config(callback):
get_core().call("get_config", callback) get_core().call("get_config", callback)
@no_core_error
def get_config_value(callback, key): def get_config_value(callback, key):
get_core().call("get_config_value", callback, key) get_core().call("get_config_value", callback, key)
@no_core_error
def set_config(config): def set_config(config):
if config == {}: if config == {}:
return return
get_core().call("set_config", None, config) get_core().call("set_config", None, config)
@no_core_error
def get_listen_port(callback): def get_listen_port(callback):
get_core().call("get_listen_port", callback) get_core().call("get_listen_port", callback)
@no_core_error
def get_available_plugins(callback): def get_available_plugins(callback):
get_core().call("get_available_plugins", callback) get_core().call("get_available_plugins", callback)
@no_core_error
def get_enabled_plugins(callback): def get_enabled_plugins(callback):
get_core().call("get_enabled_plugins", callback) get_core().call("get_enabled_plugins", callback)
@no_core_error
def get_download_rate(callback): def get_download_rate(callback):
get_core().call("get_download_rate", callback) get_core().call("get_download_rate", callback)
@no_core_error
def get_upload_rate(callback): def get_upload_rate(callback):
get_core().call("get_upload_rate", callback) get_core().call("get_upload_rate", callback)
@no_core_error
def get_num_connections(callback): def get_num_connections(callback):
get_core().call("get_num_connections", callback) get_core().call("get_num_connections", callback)
@no_core_error
def get_dht_nodes(callback): def get_dht_nodes(callback):
get_core().call("get_dht_nodes", callback) get_core().call("get_dht_nodes", callback)
@no_core_error
def enable_plugin(plugin): def enable_plugin(plugin):
get_core().call("enable_plugin", None, plugin) get_core().call("enable_plugin", None, plugin)
@no_core_error
def disable_plugin(plugin): def disable_plugin(plugin):
get_core().call("disable_plugin", None, plugin) get_core().call("disable_plugin", None, plugin)
@no_core_error
def force_recheck(torrent_ids): def force_recheck(torrent_ids):
"""Forces a data recheck on torrent_ids""" """Forces a data recheck on torrent_ids"""
for torrent_id in torrent_ids: for torrent_id in torrent_ids:
get_core().call("force_recheck", None, torrent_id) get_core().call("force_recheck", None, torrent_id)
@no_core_error
def set_torrent_trackers(torrent_id, trackers): def set_torrent_trackers(torrent_id, trackers):
"""Sets the torrents trackers""" """Sets the torrents trackers"""
get_core().call("set_torrent_trackers", None, torrent_id, trackers) get_core().call("set_torrent_trackers", None, torrent_id, trackers)