Big code clean-up and some refactoring. Added docstrings but more are

needed.
This commit is contained in:
Andrew Resch 2007-08-26 14:34:50 +00:00
parent f3c80eb816
commit 6a525530ee
16 changed files with 200 additions and 258 deletions

View File

@ -0,0 +1 @@
"""Deluge"""

View File

@ -31,15 +31,12 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
"""Common functions for various parts of Deluge to use."""
import os
import pkg_resources
import xdg, xdg.BaseDirectory
import gettext
# Get the logger
log = logging.getLogger("deluge")
def get_version():
"""Returns the program version from the egg metadata"""
@ -76,7 +73,7 @@ def estimate_eta(total_size, total_done, download_rate):
try:
return ftime(get_eta(total_size, total_done, download_rate))
except ZeroDivisionError:
return _("Infinity")
return "Infinity"
def get_eta(size, done, speed):
"""Returns the ETA in seconds
@ -93,20 +90,20 @@ def fsize(fsize_b):
"""
fsize_kb = float (fsize_b / 1024.0)
if fsize_kb < 1000:
return _("%.1f KiB")%fsize_kb
return "%.1f KiB" % fsize_kb
fsize_mb = float (fsize_kb / 1024.0)
if fsize_mb < 1000:
return _("%.1f MiB")%fsize_mb
return "%.1f MiB" % fsize_mb
fsize_gb = float (fsize_mb / 1024.0)
return _("%.1f GiB")%fsize_gb
return "%.1f GiB" % fsize_gb
def fpcnt(dec):
"""Returns a formatted string representing a percentage"""
return '%.2f%%'%(dec * 100)
return '%.2f%%' % (dec * 100)
def fspeed(bps):
"""Returns a formatted string representing transfer speed"""
return '%s/s'%(fsize(bps))
return '%s/s' % (fsize(bps))
def fseed(num_seeds, total_seeds):
"""Returns a formatted string num_seeds (total_seeds)"""
@ -119,21 +116,21 @@ def fpeer(num_peers, total_peers):
def ftime(seconds):
"""Returns a formatted time string"""
if seconds < 60:
return '%ds'%(seconds)
return '%ds' % (seconds)
minutes = int(seconds/60)
seconds = seconds % 60
if minutes < 60:
return '%dm %ds'%(minutes, seconds)
return '%dm %ds' % (minutes, seconds)
hours = int(minutes/60)
minutes = minutes % 60
if hours < 24:
return '%dh %dm'%(hours, minutes)
return '%dh %dm' % (hours, minutes)
days = int(hours/24)
hours = hours % 24
if days < 7:
return '%dd %dh'%(days, hours)
return '%dd %dh' % (days, hours)
weeks = int(days/7)
days = days % 7
if weeks < 10:
return '%dw %dd'%(weeks, days)
return '%dw %dd' % (weeks, days)
return 'unknown'

View File

@ -31,15 +31,16 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
"""Configuration class used to access/create/modify configuration files."""
import pickle
import deluge.common
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class Config:
"""This class is used to access configuration files."""
def __init__(self, filename, defaults=None):
log.debug("Config created with filename: %s", filename)
log.debug("Config defaults: %s", defaults)
@ -59,6 +60,8 @@ class Config:
self.save()
def load(self, filename=None):
"""Load a config file either by 'filename' or the filename set during
construction of this object."""
# Use self.config_file if filename is None
if filename is None:
filename = self.config_file
@ -76,6 +79,8 @@ class Config:
pkl_file.close()
def save(self, filename=None):
"""Save configuration to either 'filename' or the filename set during
construction of this object."""
# Saves the config dictionary
if filename is None:
filename = self.config_file
@ -89,6 +94,7 @@ class Config:
log.warning("IOError: Unable to save file '%s'", filename)
def set(self, key, value):
"""Set the 'key' with 'value'."""
# Sets the "key" with "value" in the config dict
log.debug("Setting '%s' to %s", key, value)
self.config[key] = value
@ -96,6 +102,8 @@ class Config:
self.save()
def get(self, key):
"""Get the value of 'key'. If it is an invalid key then get() will
return None."""
# Attempts to get the "key" value and returns None if the key is
# invalid
try:
@ -104,7 +112,7 @@ class Config:
return value
except KeyError:
log.warning("Key does not exist, returning None")
return
return None
def __getitem__(self, key):
return self.config[key]

View File

@ -31,34 +31,20 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
import os.path
import pickle
try:
import dbus, dbus.service
dbus_version = getattr(dbus, "version", (0,0,0))
if dbus_version >= (0,41,0) and dbus_version < (0,80,0):
import dbus.glib
elif dbus_version >= (0,80,0):
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
else:
pass
except: dbus_imported = False
else: dbus_imported = True
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
import gobject
import deluge.libtorrent as lt
import pkg_resources
import deluge.libtorrent as lt
from deluge.config import Config
import deluge.common
from deluge.core.torrentmanager import TorrentManager
from deluge.core.pluginmanager import PluginManager
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
DEFAULT_PREFS = {
"compact_allocation": True,

View File

@ -30,25 +30,12 @@
# 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.
try:
import dbus, dbus.service
dbus_version = getattr(dbus, "version", (0,0,0))
if dbus_version >= (0,41,0) and dbus_version < (0,80,0):
import dbus.glib
elif dbus_version >= (0,80,0):
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
else:
pass
except: dbus_imported = False
else: dbus_imported = True
import logging
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from deluge.core.core import Core
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class Daemon:
def __init__(self):

View File

@ -31,15 +31,18 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
"""PluginManager for Core"""
import os.path
import pkg_resources
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class PluginManager:
"""PluginManager handles the loading of plugins and provides plugins with
functions to access parts of the core."""
def __init__(self):
# Set up the hooks dictionary
self.hooks = {
@ -61,7 +64,6 @@ class PluginManager:
for name in pkg_env:
egg = pkg_env[name][0]
egg.activate()
modules = []
for name in egg.get_entry_map("deluge.plugin.core"):
entry_point = egg.get_entry_info("deluge.plugin.core", name)
cls = entry_point.load()
@ -78,6 +80,7 @@ class PluginManager:
self.status_fields[field] = function
def get_status(self, torrent_id, fields):
"""Return the value of status fields for the selected torrent_id."""
status = {}
for field in fields:
try:
@ -94,22 +97,16 @@ class PluginManager:
except KeyError:
log.warning("Plugin attempting to register invalid hook.")
def run_hook(self, hook, data):
log.debug("Running hook %s", hook)
def run_post_torrent_add(self, torrent_id):
"""This hook is run after a torrent has been added to the session."""
log.debug("run_post_torrent_add")
try:
for function in self.hooks["post_torrent_add"]:
function(torrent_id)
except:
pass
def run_post_torrent_remove(self, torrent_id):
"""This hook is run after a torrent has been removed from the session.
"""
log.debug("run_post_torrent_remove")
try:
for function in self.hooks["post_torrent_remove"]:
function(torrent_id)
except:
pass

View File

@ -31,14 +31,11 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
import deluge.libtorrent as lt
# Get the logger
log = logging.getLogger("deluge")
"""Internal Torrent class"""
class Torrent:
"""Torrent holds information about torrents added to the libtorrent session.
"""
def __init__(self, filename, handle):
# Set the filename
self.filename = filename

View File

@ -31,7 +31,8 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
"""TorrentManager handles Torrent objects"""
import pickle
import os.path
@ -41,11 +42,13 @@ import deluge.common
from deluge.config import Config
from deluge.core.torrent import Torrent
from deluge.core.torrentmanagerstate import TorrentManagerState, TorrentState
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class TorrentManager:
"""TorrentManager contains a list of torrents in the current libtorrent
session. This object is also responsible for saving the state of the
session for use on restart."""
def __init__(self, session):
log.debug("TorrentManager init..")
# Set the libtorrent session
@ -79,7 +82,8 @@ class TorrentManager:
handle = None
try:
handle = self.session.add_torrent(lt.torrent_info(torrent_filedump),
handle = self.session.add_torrent(
lt.torrent_info(torrent_filedump),
config["download_location"],
config["compact_allocation"])
except RuntimeError:
@ -92,11 +96,11 @@ class TorrentManager:
# Write the .torrent file to the torrent directory
log.debug("Attemping to save torrent file: %s", filename)
try:
f = open(os.path.join(config["torrentfiles_location"],
save_file = open(os.path.join(config["torrentfiles_location"],
filename),
"wb")
f.write(filedump)
f.close()
save_file.write(filedump)
save_file.close()
except IOError:
log.warning("Unable to save torrent file: %s", filename)
@ -143,14 +147,15 @@ class TorrentManager:
"""Save the state of the TorrentManager to the torrents.state file"""
state = TorrentManagerState()
# Create the state for each Torrent and append to the list
for (key, torrent) in self.torrents:
t = TorrentState(torrent.get_state())
state.torrents.append(t)
for torrent in self.torrents.values():
torrent_state = TorrentState(torrent.get_state())
state.torrents.append(torrent_state)
# Pickle the TorrentManagerState object
try:
log.debug("Saving torrent state file.")
state_file = open(deluge.common.get_config_dir("torrents.state"), "wb")
state_file = open(deluge.common.get_config_dir("torrents.state"),
"wb")
pickle.dump(state, state_file)
state_file.close()
except IOError:

View File

@ -31,10 +31,7 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class TorrentState:
def __init__(self, torrent_id, filename):

View File

@ -34,24 +34,18 @@
# The main starting point for the program. This function is called when the
# user runs the command 'deluge'.
import logging
"""Main starting point for Deluge. Contains the main() entry point."""
import os
import signal
from optparse import OptionParser
from deluge.core.daemon import Daemon
from deluge.ui.ui import UI
from deluge.log import LOG as log
import deluge.common
# Setup the logger
logging.basicConfig(
level=logging.DEBUG,
format="[%(levelname)-8s] %(name)s:%(module)s:%(lineno)d %(message)s"
)
# Get the logger for deluge
log = logging.getLogger("deluge")
def main():
"""Entry point for Deluge"""
# Setup the argument parser
parser = OptionParser(usage="%prog [options] [actions]",
version=deluge.common.get_version())
@ -68,9 +62,7 @@ def main():
log.debug("options: %s", options)
log.debug("args: %s", args)
daemon = None
pid = None
uri = None
# Start the daemon
if options.daemon:
@ -82,9 +74,9 @@ def main():
# Since we are starting daemon this process will not start a UI
options.ui = False
# Create the daemon object
daemon = Daemon()
Daemon()
# Start the UI
if options.ui:
log.info("Starting ui..")
ui = UI()
UI()

View File

@ -31,29 +31,18 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
import os.path
import pickle
try:
import dbus, dbus.service
dbus_version = getattr(dbus, "version", (0,0,0))
if dbus_version >= (0,41,0) and dbus_version < (0,80,0):
import dbus.glib
elif dbus_version >= (0,80,0):
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
else:
pass
except: dbus_imported = False
else: dbus_imported = True
import dbus
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
import pygtk
pygtk.require('2.0')
import gtk, gtk.glade
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
def get_core():
"""Get the core object and return it"""

View File

@ -31,16 +31,13 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
import pygtk
pygtk.require('2.0')
import gtk, gtk.glade
import gettext
from deluge.config import Config
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class AddTorrentDialog:
def __init__(self, parent=None):
@ -55,14 +52,14 @@ class AddTorrentDialog:
self.chooser.set_property("skip-taskbar-hint", True)
# Add .torrent and * file filters
f0 = gtk.FileFilter()
f0.set_name(_("Torrent files"))
f0.add_pattern("*." + "torrent")
self.chooser.add_filter(f0)
f1 = gtk.FileFilter()
f1.set_name(_("All files"))
f1.add_pattern("*")
self.chooser.add_filter(f1)
file_filter = gtk.FileFilter()
file_filter.set_name(_("Torrent files"))
file_filter.add_pattern("*." + "torrent")
self.chooser.add_filter(file_filter)
file_filter = gtk.FileFilter()
file_filter.set_name(_("All files"))
file_filter.add_pattern("*")
self.chooser.add_filter(file_filter)
# Load the 'default_load_path' from the config
self.config = Config("gtkui.conf")

View File

@ -31,50 +31,51 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
import pygtk
pygtk.require('2.0')
import gtk
import gettext
import deluge.common
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
# Cell data functions to pass to add_func_column()
def cell_data_speed(column, cell, model, iter, data):
speed = int(model.get_value(iter, data))
def cell_data_speed(column, cell, model, row, data):
"""Display value as a speed, eg. 2 KiB/s"""
speed = int(model.get_value(row, data))
speed_str = deluge.common.fspeed(speed)
cell.set_property('text', speed_str)
def cell_data_size(column, cell, model, iter, data):
size = long(model.get_value(iter, data))
def cell_data_size(column, cell, model, row, data):
"""Display value in terms of size, eg. 2 MB"""
size = long(model.get_value(row, data))
size_str = deluge.common.fsize(size)
cell.set_property('text', size_str)
def cell_data_peer(column, cell, model, iter, data):
c1, c2 = data
a = int(model.get_value(iter, c1))
b = int(model.get_value(iter, c2))
cell.set_property('text', '%d (%d)'%(a, b))
def cell_data_peer(column, cell, model, row, data):
"""Display values as 'value1 (value2)'"""
column1, column2 = data
first = int(model.get_value(row, column1))
second = int(model.get_value(row, column2))
cell.set_property('text', '%d (%d)' % (first, second))
def cell_data_time(column, cell, model, iter, data):
time = int(model.get_value(iter, data))
def cell_data_time(column, cell, model, row, data):
"""Display value as time, eg 1m10s"""
time = int(model.get_value(row, data))
if time < 0 or time == 0:
time_str = _("Infinity")
else:
time_str = deluge.common.ftime(time)
cell.set_property('text', time_str)
def cell_data_ratio(column, cell, model, iter, data):
ratio = float(model.get_value(iter, data))
def cell_data_ratio(column, cell, model, row, data):
"""Display value as a ratio with a precision of 3."""
ratio = float(model.get_value(row, data))
if ratio == -1:
ratio_str = _("Unknown")
else:
ratio_str = "%.3f"%ratio
ratio_str = "%.3f" % ratio
cell.set_property('text', ratio_str)
class ListView:
@ -87,9 +88,6 @@ class ListView:
self.column_indices = column_indices
# Column is a reference to the GtkTreeViewColumn object
self.column = None
# The get_function is called when a column is in need of an update
# This is primarily used by plugins.
self.get_function = None
# This is the name of the status field that the column will query
# the core for if an update is called.
self.status_field = None
@ -126,11 +124,15 @@ class ListView:
self.menu = None
def set_treeview(self, treeview_widget):
"""Set the treeview widget that this listview uses."""
self.treeview = treeview_widget
self.treeview.set_model(self.liststore)
return
def get_column_index(self, name):
"""Get the liststore column indices belonging to this column.
Will return a list if greater than 1 column.
"""
# Only return as list if needed
if len(self.columns[name].column_indices) > 1:
return self.columns[name].column_indices
@ -218,37 +220,39 @@ class ListView:
return
def add_text_column(self, header, col_type=str, hidden=False,
position=None, get_function=None,
status_field=None):
# Create a new column object and add it to the list
def add_column(self, header, render, col_types, hidden, position,
status_field, sortid, text=0, value=0, function=None):
# Add the column types to liststore_columns
if type(col_types) is list:
for col_type in col_types:
self.liststore_columns.append(col_type)
else:
self.liststore_columns.append(col_types)
# Add to the index list so we know the order of the visible columns.
if position is not None:
self.column_index.insert(position, header)
else:
self.column_index.append(header)
# Create a new column object and add it to the list
self.columns[header] = self.ListViewColumn(header,
[len(self.liststore_columns) - 1])
# Set the get_function.. This function is used mainly for plugins.
# You can have your listview call this function to update the column
# value.
if get_function is not None:
self.columns[header].get_function = get_function
self.columns[header].status_field = status_field
# Create a new list with the added column
self.create_new_liststore()
# Now add the column to the treeview so the user can see it
render = gtk.CellRendererText()
if type(render) is gtk.CellRendererText:
column = gtk.TreeViewColumn(header, render,
text=self.columns[header].column_indices[0])
text=self.columns[header].column_indices[text])
else:
column = gtk.TreeViewColumn(header, render)
column.set_sort_column_id(self.columns[header].column_indices[sortid])
column.set_clickable(True)
column.set_sort_column_id(self.columns[header].column_indices[0])
column.set_resizable(True)
column.set_expand(False)
column.set_min_width(10)
@ -266,6 +270,17 @@ class ListView:
return True
def add_text_column(self, header, col_type=str, hidden=False,
position=None,
status_field=None,
sortid=0):
# Add a text column to the treeview
render = gtk.CellRendererText()
self.add_column(header, render, col_type, hidden, position,
status_field, sortid, text=0)
return True
def add_func_column(self, header, function, column_types, sortid=0,
hidden=False, position=None, get_function=None,
status_field=None):
@ -321,7 +336,8 @@ class ListView:
return True
def add_progress_column(self, header, hidden=False, position=None,
def add_progress_column(self, header, col_type=[float,str], hidden=False,
position=None,
get_function=None,
status_field=None):
# For the progress value

View File

@ -31,13 +31,11 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
import os.path
import pkg_resources
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class PluginManager:
def __init__(self, gtkui):
@ -56,7 +54,6 @@ class PluginManager:
for name in pkg_env:
egg = pkg_env[name][0]
egg.activate()
modules = []
for name in egg.get_entry_map("deluge.plugin.ui.gtk"):
entry_point = egg.get_entry_info("deluge.plugin.ui.gtk", name)
cls = entry_point.load()

View File

@ -31,30 +31,9 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
try:
import dbus, dbus.service
dbus_version = getattr(dbus, "version", (0,0,0))
if dbus_version >= (0,41,0) and dbus_version < (0,80,0):
import dbus.glib
elif dbus_version >= (0,80,0):
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
else:
pass
except: dbus_imported = False
else: dbus_imported = True
import pygtk
pygtk.require('2.0')
import gtk, gtk.glade
import deluge.ui.functions as functions
from deluge.config import Config
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
class Signals:
def __init__(self, ui):

View File

@ -31,21 +31,19 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
"""The torrent view component that lists all torrents in the session."""
import pygtk
pygtk.require('2.0')
import gtk, gtk.glade
import gobject
import gettext
import deluge.ui.functions as functions
import listview
# Get the logger
log = logging.getLogger("deluge")
from deluge.log import LOG as log
import deluge.ui.gtkui.listview as listview
class TorrentView(listview.ListView):
"""TorrentView handles the listing of torrents."""
def __init__(self, window):
self.window = window
# Call the ListView constructor
@ -108,28 +106,25 @@ class TorrentView(listview.ListView):
if self.liststore is not None:
self.liststore.foreach(self.update_row, columns)
def update_row(self, model, path, row, columns=None):
torrent_id = self.liststore.get_value(row,
def update_row(self, model=None, path=None, row=None, columns=None):
"""Updates the column values for 'row'. If columns is None it will
update all visible columns."""
torrent_id = model.get_value(row,
self.columns["torrent_id"].column_indices[0])
# Store the 'status_fields' we need to send to core
status_keys = []
# Store the actual columns we will be updating
columns_to_update = []
if columns is None:
# Iterate through the list of columns and only add the
# 'status-fields' of the visible ones.
for column in self.columns.values():
# Make sure column is visible and has 'status_field' set.
# If not, we can ignore it.
if column.column.get_visible() is True \
and column.hidden is False \
and column.status_field is not None:
for field in column.status_field:
status_keys.append(field)
columns_to_update.append(column.name)
else:
# We need to iterate through all columns
columns = self.columns.keys()
# Iterate through supplied list of columns to update
for column in columns:
# Make sure column is visible and has 'status_field' set.
# If not, we can ignore it.
if self.columns[column].column.get_visible() is True \
and self.columns[column].hidden is False \
and self.columns[column].status_field is not None:
@ -148,23 +143,23 @@ class TorrentView(listview.ListView):
# Set values for each column in the row
for column in columns_to_update:
if type(self.get_column_index(column)) is not list:
column_index = self.get_column_index(column)
if type(column_index) is not list:
# We only have a single list store column we need to update
self.liststore.set_value(row,
self.get_column_index(column),
model.set_value(row,
column_index,
status[self.columns[column].status_field[0]])
else:
# We have more than 1 liststore column to update
i = 0
for index in self.get_column_index(column):
for index in column_index:
# Only update the column if the status field exists
try:
self.liststore.set_value(row,
model.set_value(row,
index,
status[self.columns[column].status_field[i]])
status[self.columns[column].status_field[
column_index.index(index)]])
except:
pass
i = i + 1
def add_row(self, torrent_id):
"""Adds a new torrent row to the treeview"""
@ -176,7 +171,7 @@ class TorrentView(listview.ListView):
self.columns["torrent_id"].column_indices[0],
torrent_id)
# Update the new row so
self.update_row(None, None, row)
self.update_row(model=self.liststore, row=row)
def remove_row(self, torrent_id):
"""Removes a row with torrent_id"""
@ -206,6 +201,7 @@ class TorrentView(listview.ListView):
### Callbacks ###
def on_button_press_event(self, widget, event):
"""This is a callback for showing the right-click context menu."""
log.debug("on_button_press_event")
# We only care about right-clicks
if event.button == 3:
@ -215,5 +211,6 @@ class TorrentView(listview.ListView):
torrentmenu.popup(None, None, None, event.button, event.time)
def on_selection_changed(self, treeselection):
"""This callback is know when the selection has changed."""
log.debug("on_selection_changed")