Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- # # Copyright (C) 2007,2008 Andrew Resch <andrewresch@gmail.com> # # This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with # the additional special exception to link portions of this program with the OpenSSL library. # See LICENSE for more details. #
bus = dbus.SessionBus() dbus_fileman = bus.get_object("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1")
"Allocating", "Checking", "Downloading", "Seeding", "Paused", "Error", "Queued", "Moving" ]
0: "Do Not Download", 1: "Normal Priority", 2: "High Priority", 3: "High Priority", 4: "High Priority", 5: "High Priority", 6: "High Priority", 7: "Highest Priority", "Do Not Download": 0, "Normal Priority": 1, "High Priority": 5, "Highest Priority": 7 }
""" Returns the program version from the egg metadata
:returns: the version of Deluge :rtype: string
"""
""" :param filename: if None, only the config path is returned, if provided, a path including the filename will be returned :type filename: string :returns: a file path to the config directory and optional filename :rtype: string
"""
def save_config_path(resource): app_data_path = os.environ.get("APPDATA") if not app_data_path: import _winreg hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders") app_data_reg = _winreg.QueryValueEx(hkey, "AppData") app_data_path = app_data_reg[0] _winreg.CloseKey(hkey) return os.path.join(app_data_path, resource) else: except OSError as ex: log.error("Unable to use default config directory, exiting... (%s)", ex) sys.exit(1)
""" :returns: the default download directory :rtype: string
""" for line in _file: if not line.startswith('#') and line.startswith('XDG_DOWNLOAD_DIR'): download_dir = os.path.expandvars(line.partition("=")[2].rstrip().strip('"')) break
""" Checks if the current platform is Windows
:returns: True or False :rtype: bool
"""
""" Checks if the current platform is Windows Vista
:returns: True or False :rtype: bool
""" return platform.release() == "Vista"
""" Checks if the current platform is Mac OS X
:returns: True or False :rtype: bool
""" return platform.system() == "Darwin"
""" Provides easy access to files in the deluge/ui/data/pixmaps folder within the Deluge egg
:param fname: the filename to look for :type fname: string :returns: a path to a pixmap file included with Deluge :rtype: string
""" return resource_filename("deluge", os.path.join("ui", "data", "pixmaps", fname))
# While developing, if there's a second deluge package, installed globally # and another in develop mode somewhere else, while pkg_resources.require("Deluge") # returns the proper deluge instance, pkg_resources.resource_filename does # not, it returns the first found on the python path, which is not good # enough. # This is a work-around that. pkg_resources._manager, os.path.join(*(module.split(".") + [path])) )
"""Opens a file or folder using the system configured program.
Args: path (str): The path to the file or folder to open. timestamp (int, optional): An event request timestamp.
""" if windows_check(): os.startfile(path) elif osx_check(): subprocess.Popen(["open", path]) else: if timestamp is None: timestamp = int(time.time()) env = os.environ.copy() env["DESKTOP_STARTUP_ID"] = "%s-%u-%s-xdg_open_TIME%d" % \ (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp) subprocess.Popen(["xdg-open", "%s" % path], env=env)
"""Shows (highlights) a file or folder using the system configured file manager.
Args: path (str): The path to the file or folder to show. timestamp (int, optional): An event request timestamp.
""" if windows_check(): subprocess.Popen(["explorer", "/select,", path]) elif osx_check(): subprocess.Popen(["open", "-R", path]) else: if timestamp is None: timestamp = int(time.time()) startup_id = "%s_%u_%s-dbus_TIME%d" % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp) if dbus_fileman: paths = [urlparse.urljoin("file:", urllib.pathname2url(utf8_encoded(path)))] dbus_fileman.ShowItems(paths, startup_id, dbus_interface="org.freedesktop.FileManager1") else: env = os.environ.copy() env["DESKTOP_STARTUP_ID"] = startup_id.replace("dbus", "xdg-open") # No option in xdg to highlight a file so just open parent folder. subprocess.Popen(["xdg-open", os.path.dirname(path.rstrip("/"))], env=env)
""" Opens a url in the desktop's default browser
:param url: the url to open :type url: string
""" import webbrowser webbrowser.open(url)
# Formatting text functions
# For performance reasons these fsize units are translated outside the function
global byte_txt, kib_txt, mib_txt, gib_txt
""" Formats the bytes value into a string with KiB, MiB or GiB units
:param fsize_b: the filesize in bytes :type fsize_b: int :returns: formatted string in KiB, MiB or GiB units :rtype: string
**Usage**
>>> fsize(112245) '109.6 KiB'
""" # Bigger than 1 GiB # Bigger than 1 MiB # Bigger than 1 KiB else:
""" Formats the bytes value into a string with K, M or G units
:param fsize_b: the filesize in bytes :type fsize_b: int :returns: formatted string in K, M or G units :rtype: string
**Usage**
>>> fsize(112245) '109.6 K'
""" fsize_kb = fsize_b / 1024.0 if fsize_kb < 1024: return "%.1f %s" % (fsize_kb, _("K")) fsize_mb = fsize_kb / 1024.0 if fsize_mb < 1024: return "%.1f %s" % (fsize_mb, _("M")) fsize_gb = fsize_mb / 1024.0 return "%.1f %s" % (fsize_gb, _("G"))
""" Formats a string to display a percentage with two decimal places
:param dec: the ratio in the range [0.0, 1.0] :type dec: float :returns: a formatted string representing a percentage :rtype: string
**Usage**
>>> fpcnt(0.9311) '93.11%'
"""
""" Formats a string to display a transfer speed utilizing :func:`fsize`
:param bps: bytes per second :type bps: int :returns: a formatted string representing transfer speed :rtype: string
**Usage**
>>> fspeed(43134) '42.1 KiB/s'
""" fspeed_mb = fspeed_kb / 1024.0 if fspeed_mb < 1024: return "%.1f %s" % (fspeed_mb, _("MiB/s")) fspeed_gb = fspeed_mb / 1024.0 return "%.1f %s" % (fspeed_gb, _("GiB/s"))
""" Formats a string to show 'num_peers' ('total_peers')
:param num_peers: the number of connected peers :type num_peers: int :param total_peers: the total number of peers :type total_peers: int :returns: a formatted string: num_peers (total_peers), if total_peers < 0, then it will not be shown :rtype: string
**Usage**
>>> fpeer(10, 20) '10 (20)' >>> fpeer(10, -1) '10'
""" else:
""" Formats a string to show time in a human readable form
:param seconds: the number of seconds :type seconds: int :returns: a formatted time string, will return '' if seconds == 0 :rtype: string
**Usage**
>>> ftime(23011) '6h 23m'
""" return "" return '%ds' % (seconds) seconds = seconds % 60 return '%dm %ds' % (minutes, seconds) days = hours / 24 if days < 7: hours = hours % 24 return '%dd %dh' % (days, hours) weeks = days / 7 if weeks < 52: days = days % 7 return '%dw %dd' % (weeks, days) years = weeks / 52 weeks = weeks % 52 return '%dy %dw' % (years, weeks)
""" Formats a date time string in the locale's date representation based on the systems timezone
:param seconds: time in seconds since the Epoch :type seconds: float :param precision_secs: include seconds in time format :type precision_secs: bool :returns: a string in the locale's datetime representation or "" if seconds < 0 :rtype: string
""" if precision_secs: return time.strftime("%x %X", time.localtime(seconds)) else: return time.strftime("%x %H:%M", time.localtime(seconds))
""" A simple test to check if the URL is valid
:param url: the url to test :type url: string :returns: True or False :rtype: bool
**Usage**
>>> is_url("http://deluge-torrent.org") True
"""
""" A check to determine if a uri is a valid bittorrent magnet uri
:param uri: the uri to check :type uri: string :returns: True or False :rtype: bool
**Usage**
>>> is_magnet("magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN") True
""" return False
""" Return information about a magnet link.
:param uri: the magnet link :type uri: string
:returns: information about the magnet link:
::
{ "name": the torrent name, "info_hash": the torrents info_hash, "files_tree": empty value for magnet links }
:rtype: dictionary """ elif len(xt_hash) == 40: info_hash = xt_hash else: break elif param.startswith(dn_param): name = urllib.unquote_plus(param[len(dn_param):])
return False
""" Creates a magnet uri
:param infohash: the info-hash of the torrent :type infohash: string :param name: the name of the torrent (optional) :type name: string :param trackers: the trackers to announce to (optional) :type trackers: list of strings
:returns: a magnet uri string :rtype: string
""" uri = uri + "&dn=" + name for t in trackers: uri = uri + "&tr=" + t
""" Gets the size in bytes of 'path'
:param path: the path to check for size :type path: string :returns: the size in bytes of the path or -1 if the path does not exist :rtype: int
"""
""" Gets the free space available at 'path'
:param path: the path to check :type path: string :returns: the free space at path in bytes :rtype: int
:raises InvalidPathError: if the path is not valid
"""
from win32file import GetDiskFreeSpaceEx return GetDiskFreeSpaceEx(path)[0] else:
""" A simple test to see if 'ip' is valid
:param ip: the ip to check :type ip: string :returns: True or False :rtype: bool
** Usage **
>>> is_ip("127.0.0.1") True
""" # first we test ipv4 if socket.inet_aton(ip): return True else: return False # now test ipv6 log.warning("ipv6 check unavailable on windows") return True else: return True
""" An implementation of os.path.join that always uses / for the separator to ensure that the correct paths are produced when working with internal paths on Windows. """ path = '' for part in parts: if not part: continue elif part[0] == '/': path = part elif not path: path = part else: path += '/' + part return path
('&', '&'), ('<', '<'), ('>', '>'), ('"', '"'), ("'", ''') )
""" Unescape a string that was previously encoded for use within xml.
:param string: The string to escape :type string: string :returns: The unescaped version of the string. :rtype: string """ for char, escape in XML_ESCAPES: string = string.replace(escape, char) return string
""" Escape a string for use within an xml element or attribute.
:param string: The string to escape :type string: string :returns: An escaped version of the string. :rtype: string """ for char, escape in XML_ESCAPES: string = string.replace(char, escape) return string
""" Decodes a string and return unicode. If it cannot decode using `:param:encoding` then it will try latin1, and if that fails, try to detect the string encoding. If that fails, decode with ignore.
:param s: string to decode :type s: string :keyword encoding: the encoding to use in the decoding :type encoding: string :returns: s converted to unicode :rtype: unicode
""" return s
lambda: ("iso-8859-1", 'strict'), lambda: (chardet.detect(s)["encoding"], 'strict'), lambda: (encoding, 'ignore')]
except UnicodeDecodeError: pass return u''
""" Returns a utf8 encoded string of s
:param s: (unicode) string to (re-)encode :type s: basestring :keyword encoding: the encoding to use in the decoding :type encoding: string :returns: a utf8 encoded string of s :rtype: str
"""
""" Used for comparing version numbers.
:param ver: the version :type ver: string
""" ^ (?P<version>\d+\.\d+) # minimum 'N.N' (?P<extraversion>(?:\.\d+)*) # any number of extra '.N' segments (?: (?P<prerel>[abc]|rc) # 'a'=alpha, 'b'=beta, 'c'=release candidate # 'rc'= alias for release candidate (?P<prerelversion>\d+(?:\.\d+)*) )? (?P<postdev>(\.post(?P<post>\d+))?(\.dev(?P<dev>\d+))?)? $''', re.VERBOSE)
# Check for PEP 386 compliant version else:
""" The comparison method.
:param ver: the version to compare with :type ver: VersionSplit
""" # PEP 386 versions with .devN precede release version
# If there is no suffix we use z because we want final # to appear after alpha, beta, and rc alphabetically.
# Common AUTH stuff
# Check for auth file and create if necessary # Change the permissions on the file so only this user can read/write it
"localclient", sha(str(random.random())).hexdigest(), str(AUTH_LEVEL_ADMIN) ]) + '\n')
"""Get the absolute path to the directory containing translation files"""
''' :param name: environment variable name :param value: environment variable value
This function ensures that changes to an environment variable are applied to each copy of the environment variables used by a process. Starting from Python 2.4, os.environ changes only apply to the copy Python keeps (os.environ) and are no longer automatically applied to the other copies for the process.
On Microsoft Windows, each process has multiple copies of the environment variables, one managed by the OS and one managed by the C library. We also need to take care of the fact that the C library used by Python is not necessarily the same as the C library used by pygtk and friends. This because the latest releases of pygtk and friends are built with mingw32 and are thus linked against msvcrt.dll. The official gtk+ binaries have always been built in this way.
Basen on _putenv in TransUtils.py from sourceforge project gramps http://sourceforge.net/p/gramps/code/HEAD/tree/branches/maintenance/gramps32/src/TransUtils.py ''' # Update Python's copy of the environment variables os.environ[name] = value
if windows_check(): from ctypes import windll from ctypes import cdll from ctypes.util import find_msvcrt
# Update the copy maintained by Windows (so SysInternals Process Explorer sees it) try: result = windll.kernel32.SetEnvironmentVariableW(name, value) if result == 0: raise Warning except Exception: log.warning('Failed to set Env Var \'%s\' (\'kernel32.SetEnvironmentVariableW\')' % name) else: log.debug('Set Env Var \'%s\' to \'%s\' (\'kernel32.SetEnvironmentVariableW\')' % (name, value))
# Update the copy maintained by msvcrt (used by gtk+ runtime) try: result = cdll.msvcrt._putenv('%s=%s' % (name, value)) if result != 0: raise Warning except Exception: log.warning('Failed to set Env Var \'%s\' (\'msvcrt._putenv\')' % name) else: log.debug('Set Env Var \'%s\' to \'%s\' (\'msvcrt._putenv\')' % (name, value))
# Update the copy maintained by whatever c runtime is used by Python try: msvcrt = find_msvcrt() msvcrtname = str(msvcrt).split('.')[0] if '.' in msvcrt else str(msvcrt) result = cdll.LoadLibrary(msvcrt)._putenv('%s=%s' % (name, value)) if result != 0: raise Warning except Exception: log.warning('Failed to set Env Var \'%s\' (\'%s._putenv\')' % (name, msvcrtname)) else: log.debug('Set Env Var \'%s\' to \'%s\' (\'%s._putenv\')' % (name, value, msvcrtname))
""" Set the language to use.
gettext and GtkBuilder will load the translations from the specified language.
:param lang: the language, e.g. "en", "de" or "en_GB" :type lang: str """ lang = str(lang) # Necessary to set these environment variables for GtkBuilder set_env_variable('LANGUAGE', lang) # Windows/Linux set_env_variable('LANG', lang) # For OSX
translations_path = get_translations_path() try: ro = gettext.translation("deluge", localedir=translations_path, languages=[lang]) ro.install() except IOError as ex: log.warn("IOError when loading translations: %s", ex)
# Initialize gettext
try: log.info("Setting up GTK translations from %s", translations_path)
if windows_check(): import ctypes libintl = ctypes.cdll.intl libintl.bindtextdomain(domain, translations_path.encode(sys.getfilesystemencoding())) libintl.textdomain(domain) libintl.bind_textdomain_codeset(domain, "UTF-8") libintl.gettext.restype = ctypes.c_char_p
# Use glade for plugins that still uses it import gtk import gtk.glade gtk.glade.bindtextdomain(domain, translations_path) gtk.glade.textdomain(domain) except Exception as ex: log.error("Unable to initialize glade translation!") log.exception(ex)
except Exception as ex: log.error("Unable to initialize gettext/locale!") log.exception(ex) import __builtin__ __builtin__.__dict__["_"] = lambda x: x
""" Gets sys.argv as list of unicode objects on any platform.""" if windows_check(): # Versions 2.x of Python don't support Unicode in sys.argv on # Windows, with the underlying Windows API instead replacing multi-byte # characters with '?'. from ctypes import POINTER, byref, cdll, c_int, windll from ctypes.wintypes import LPCWSTR, LPWSTR
get_cmd_linew = cdll.kernel32.GetCommandLineW get_cmd_linew.argtypes = [] get_cmd_linew.restype = LPCWSTR
cmdline_to_argvw = windll.shell32.CommandLineToArgvW cmdline_to_argvw.argtypes = [LPCWSTR, POINTER(c_int)] cmdline_to_argvw.restype = POINTER(LPWSTR)
cmd = get_cmd_linew() argc = c_int(0) argv = cmdline_to_argvw(cmd, byref(argc)) if argc.value > 0: # Remove Python executable and commands if present start = argc.value - len(sys.argv) return [argv[i] for i in xrange(start, argc.value)] else: # On other platforms, we have to find the likely encoding of the args and decode # First check if sys.stdout or stdin have encoding set encoding = getattr(sys.stdout, "encoding") or getattr(sys.stdin, "encoding") # If that fails, check what the locale is set to encoding = encoding or locale.getpreferredencoding() # As a last resort, just default to utf-8 encoding = encoding or "utf-8"
return [arg.decode(encoding) for arg in sys.argv] |