mirror of
https://github.com/correl/Transmission-XBMC.git
synced 2024-11-21 19:18:41 +00:00
Merge branch 'master' into eden-pre
This commit is contained in:
commit
bc5abe6d06
8 changed files with 350 additions and 262 deletions
|
@ -1,8 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2008-2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
from transmissionrpc.constants import DEFAULT_PORT, DEFAULT_TIMEOUT, STATUS, PRIORITY, RATIO_LIMIT, LOGGER
|
||||
from transmissionrpc.constants import DEFAULT_PORT, DEFAULT_TIMEOUT, PRIORITY, RATIO_LIMIT, LOGGER
|
||||
from transmissionrpc.error import TransmissionError, HTTPHandlerError
|
||||
from transmissionrpc.httphandler import HTTPHandler, DefaultHTTPHandler
|
||||
from transmissionrpc.torrent import Torrent
|
||||
|
@ -11,6 +11,6 @@ from transmissionrpc.client import Client
|
|||
from transmissionrpc.utils import add_stdout_logger
|
||||
|
||||
__author__ = u'Erik Svensson <erik.public@gmail.com>'
|
||||
__version__ = u'0.7'
|
||||
__copyright__ = u'Copyright (c) 2008-2010 Erik Svensson'
|
||||
__version__ = u'0.8'
|
||||
__copyright__ = u'Copyright (c) 2008-2011 Erik Svensson'
|
||||
__license__ = u'MIT'
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2008-2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
import os, re, time
|
||||
import warnings
|
||||
import httplib, urllib2, urlparse, base64
|
||||
import sys
|
||||
import re, time
|
||||
import urllib2, urlparse, base64
|
||||
|
||||
try:
|
||||
import json
|
||||
|
@ -20,7 +20,7 @@ from transmissionrpc.session import Session
|
|||
|
||||
def debug_httperror(error):
|
||||
"""
|
||||
Log the Transmission RPC HTTP error.
|
||||
Log the Transmission RPC HTTP error.
|
||||
"""
|
||||
try:
|
||||
data = json.loads(error.data)
|
||||
|
@ -41,56 +41,60 @@ def debug_httperror(error):
|
|||
)
|
||||
)
|
||||
|
||||
def _urlparse(address):
|
||||
if sys.version_info[:2] < (2, 5):
|
||||
"""
|
||||
Mimic python 2.5+ urlparse.urlparse
|
||||
"""
|
||||
class ParsedResult(tuple):
|
||||
def __init__(self, address = None):
|
||||
self.scheme = ''
|
||||
self.netloc = ''
|
||||
self.path = ''
|
||||
self.params = ''
|
||||
self.query = ''
|
||||
self.fragment = ''
|
||||
self.username = None
|
||||
self.password = None
|
||||
self.hostname = None
|
||||
self.port = None
|
||||
_old_urlparse = urlparse.urlparse
|
||||
def _urlparse(address):
|
||||
class ParsedResult(tuple):
|
||||
def __init__(self, address = None):
|
||||
self.scheme = ''
|
||||
self.netloc = ''
|
||||
self.path = ''
|
||||
self.params = ''
|
||||
self.query = ''
|
||||
self.fragment = ''
|
||||
self.username = None
|
||||
self.password = None
|
||||
self.hostname = None
|
||||
self.port = None
|
||||
|
||||
if address:
|
||||
self.parse(address)
|
||||
def parse(self, address):
|
||||
(
|
||||
self.scheme,
|
||||
self.netloc,
|
||||
self.path,
|
||||
self.params,
|
||||
self.query,
|
||||
self.fragment
|
||||
) = urlparse.urlparse(address)
|
||||
self.hostname = self.netloc
|
||||
if '@' in self.netloc:
|
||||
(login, self.hostname) = self.netloc.split('@')
|
||||
if ':' in login:
|
||||
(self.username, self.password) = login.split(':')
|
||||
else:
|
||||
self.username = login
|
||||
if ':' in self.hostname:
|
||||
(self.hostname, self.port) = self.hostname.split(':')
|
||||
try:
|
||||
self.port = int(self.port)
|
||||
except:
|
||||
self.port = None
|
||||
if address:
|
||||
self.parse(address)
|
||||
def parse(self, address):
|
||||
(
|
||||
self.scheme,
|
||||
self.netloc,
|
||||
self.path,
|
||||
self.params,
|
||||
self.query,
|
||||
self.fragment
|
||||
) = _old_urlparse(address)
|
||||
self.hostname = self.netloc
|
||||
if '@' in self.netloc:
|
||||
(login, self.hostname) = self.netloc.split('@')
|
||||
if ':' in login:
|
||||
(self.username, self.password) = login.split(':')
|
||||
else:
|
||||
self.username = login
|
||||
if ':' in self.hostname:
|
||||
(self.hostname, self.port) = self.hostname.split(':')
|
||||
try:
|
||||
self.port = int(self.port)
|
||||
except:
|
||||
self.port = None
|
||||
|
||||
result = ParsedResult(address)
|
||||
return result
|
||||
result = ParsedResult(address)
|
||||
return result
|
||||
|
||||
urlparse.urlparse = _urlparse
|
||||
|
||||
"""
|
||||
Torrent ids
|
||||
|
||||
Many functions in Client takes torrent id. A torrent id can either be id or
|
||||
hashString. When suppling multiple id's it is possible to use a list mixed
|
||||
hashString. When supplying multiple id's it is possible to use a list mixed
|
||||
with both id and hashString.
|
||||
|
||||
Timeouts
|
||||
|
@ -110,7 +114,7 @@ class Client(object):
|
|||
self._query_timeout = float(timeout)
|
||||
else:
|
||||
self._query_timeout = DEFAULT_TIMEOUT
|
||||
urlo = _urlparse(address)
|
||||
urlo = urlparse.urlparse(address)
|
||||
if urlo.scheme == '':
|
||||
base_url = 'http://' + address + ':' + str(port)
|
||||
self.url = base_url + '/transmission/rpc'
|
||||
|
@ -125,7 +129,7 @@ class Client(object):
|
|||
password = urlo.password
|
||||
elif urlo.username or urlo.password:
|
||||
LOGGER.warning('Either user or password missing, not using authentication.')
|
||||
if http_handler == None:
|
||||
if http_handler is None:
|
||||
self.http_handler = DefaultHTTPHandler()
|
||||
else:
|
||||
if hasattr(http_handler, 'set_authentication') and hasattr(http_handler, 'request'):
|
||||
|
@ -150,19 +154,19 @@ class Client(object):
|
|||
Get current timeout for HTTP queries.
|
||||
"""
|
||||
return self._query_timeout
|
||||
|
||||
|
||||
def _set_timeout(self, value):
|
||||
"""
|
||||
Set timeout for HTTP queries.
|
||||
"""
|
||||
self._query_timeout = float(value)
|
||||
|
||||
|
||||
def _del_timeout(self):
|
||||
"""
|
||||
Reset the HTTP query timeout to the default.
|
||||
"""
|
||||
self._query_timeout = DEFAULT_TIMEOUT
|
||||
|
||||
|
||||
timeout = property(_get_timeout, _set_timeout, _del_timeout, doc="HTTP query timeout.")
|
||||
|
||||
def _http_query(self, query, timeout=None):
|
||||
|
@ -170,8 +174,9 @@ class Client(object):
|
|||
Query Transmission through HTTP.
|
||||
"""
|
||||
headers = {'x-transmission-session-id': str(self.session_id)}
|
||||
result = {}
|
||||
request_count = 0
|
||||
if timeout == None:
|
||||
if timeout is None:
|
||||
timeout = self._query_timeout
|
||||
while True:
|
||||
LOGGER.debug(json.dumps({'url': self.url, 'headers': headers, 'query': query, 'timeout': timeout}, indent=2))
|
||||
|
@ -192,7 +197,7 @@ class Client(object):
|
|||
else:
|
||||
debug_httperror(error)
|
||||
raise TransmissionError('Request failed.', error)
|
||||
request_count = request_count + 1
|
||||
request_count += 1
|
||||
return result
|
||||
|
||||
def _request(self, method, arguments=None, ids=None, require_ids=False, timeout=None):
|
||||
|
@ -201,7 +206,7 @@ class Client(object):
|
|||
"""
|
||||
if not isinstance(method, (str, unicode)):
|
||||
raise ValueError('request takes method as string')
|
||||
if arguments == None:
|
||||
if arguments is None:
|
||||
arguments = {}
|
||||
if not isinstance(arguments, dict):
|
||||
raise ValueError('request takes arguments as dict')
|
||||
|
@ -263,8 +268,8 @@ class Client(object):
|
|||
Take things and make them valid torrent identifiers
|
||||
"""
|
||||
ids = []
|
||||
|
||||
if args == None:
|
||||
|
||||
if args is None:
|
||||
pass
|
||||
elif isinstance(args, (int, long)):
|
||||
ids.append(args)
|
||||
|
@ -298,7 +303,7 @@ class Client(object):
|
|||
if not addition:
|
||||
raise ValueError(u'Invalid torrent id, \"%s\"' % item)
|
||||
ids.extend(addition)
|
||||
elif isinstance(args, (list)):
|
||||
elif isinstance(args, list):
|
||||
for item in args:
|
||||
ids.extend(self._format_ids(item))
|
||||
else:
|
||||
|
@ -312,14 +317,14 @@ class Client(object):
|
|||
self.session.update(data)
|
||||
|
||||
def _update_server_version(self):
|
||||
if self.server_version == None:
|
||||
if self.server_version is None:
|
||||
version_major = 1
|
||||
version_minor = 30
|
||||
version_changeset = 0
|
||||
version_parser = re.compile('(\d).(\d+) \((\d+)\)')
|
||||
if hasattr(self.session, 'version'):
|
||||
match = version_parser.match(self.session.version)
|
||||
if (match):
|
||||
if match:
|
||||
version_major = int(match.group(1))
|
||||
version_minor = int(match.group(2))
|
||||
version_changeset = match.group(3)
|
||||
|
@ -330,9 +335,12 @@ class Client(object):
|
|||
"""
|
||||
Get the Transmission RPC version. Trying to deduct if the server don't have a version value.
|
||||
"""
|
||||
if self.protocol_version == None:
|
||||
if self.protocol_version is None:
|
||||
# Ugly fix for 2.20 - 2.22 reporting rpc-version 11, but having new arguments
|
||||
if self.server_version and (self.server_version[0] == 2 and self.server_version[1] in [20, 21, 22]):
|
||||
self.protocol_version = 12
|
||||
# Ugly fix for 2.12 reporting rpc-version 10, but having new arguments
|
||||
if (self.server_version and (self.server_version[0] == 2 and self.server_version[1] == 12)):
|
||||
elif self.server_version and (self.server_version[0] == 2 and self.server_version[1] == 12):
|
||||
self.protocol_version = 11
|
||||
elif hasattr(self.session, 'rpc_version'):
|
||||
self.protocol_version = self.session.rpc_version
|
||||
|
@ -354,21 +362,21 @@ class Client(object):
|
|||
Add torrent to transfers list. Takes a base64 encoded .torrent file in data.
|
||||
Additional arguments are:
|
||||
|
||||
===================== ==== =============================================================
|
||||
Argument RPC Description
|
||||
===================== ==== =============================================================
|
||||
``bandwidthPriority`` 8 - Priority for this transfer.
|
||||
``download_dir`` 1 - The directory where the downloaded contents will be saved in.
|
||||
``filename`` 1 - A filepath or URL to a torrent file or a magnet link.
|
||||
``files_unwanted`` 1 - A list of file id's that shouldn't be downloaded.
|
||||
``files_wanted`` 1 - A list of file id's that should be downloaded.
|
||||
``metainfo`` 1 - The content of a torrent file, base64 encoded.
|
||||
``paused`` 1 - If True, does not start the transfer when added.
|
||||
``peer_limit`` 1 - Maximum number of peers allowed.
|
||||
``priority_high`` 1 - A list of file id's that should have high priority.
|
||||
``priority_low`` 1 - A list of file id's that should have low priority.
|
||||
``priority_normal`` 1 - A list of file id's that should have normal priority.
|
||||
===================== ==== =============================================================
|
||||
===================== ===== =========== =============================================================
|
||||
Argument RPC Replaced by Description
|
||||
===================== ===== =========== =============================================================
|
||||
``bandwidthPriority`` 8 - Priority for this transfer.
|
||||
``cookies`` 13 - One or more HTTP cookie(s).
|
||||
``download_dir`` 1 - The directory where the downloaded contents will be saved in.
|
||||
``files_unwanted`` 1 - A list of file id's that shouldn't be downloaded.
|
||||
``files_wanted`` 1 - A list of file id's that should be downloaded.
|
||||
``paused`` 1 - If True, does not start the transfer when added.
|
||||
``peer_limit`` 1 - Maximum number of peers allowed.
|
||||
``priority_high`` 1 - A list of file id's that should have high priority.
|
||||
``priority_low`` 1 - A list of file id's that should have low priority.
|
||||
``priority_normal`` 1 - A list of file id's that should have normal priority.
|
||||
===================== ===== =========== =============================================================
|
||||
|
||||
"""
|
||||
args = {}
|
||||
if data:
|
||||
|
@ -381,41 +389,42 @@ class Client(object):
|
|||
argument, value, self.rpc_version)
|
||||
args[arg] = val
|
||||
return self._request('torrent-add', args, timeout=timeout)
|
||||
|
||||
|
||||
def add_uri(self, uri, **kwargs):
|
||||
"""
|
||||
Add torrent to transfers list. Takes a uri to a torrent, supporting
|
||||
all uri's supported by Transmissions torrent-add 'filename'
|
||||
argument. Additional arguments are:
|
||||
|
||||
===================== ==== =============================================================
|
||||
Argument RPC Description
|
||||
===================== ==== =============================================================
|
||||
``bandwidthPriority`` 8 - Priority for this transfer.
|
||||
``download_dir`` 1 - The directory where the downloaded contents will be saved in.
|
||||
``files_unwanted`` 1 - A list of file id's that shouldn't be downloaded.
|
||||
``files_wanted`` 1 - A list of file id's that should be downloaded.
|
||||
``paused`` 1 - If True, does not start the transfer when added.
|
||||
``peer_limit`` 1 - Maximum number of peers allowed.
|
||||
``priority_high`` 1 - A list of file id's that should have high priority.
|
||||
``priority_low`` 1 - A list of file id's that should have low priority.
|
||||
``priority_normal`` 1 - A list of file id's that should have normal priority.
|
||||
===================== ==== =============================================================
|
||||
===================== ===== =========== =============================================================
|
||||
Argument RPC Replaced by Description
|
||||
===================== ===== =========== =============================================================
|
||||
``bandwidthPriority`` 8 - Priority for this transfer.
|
||||
``cookies`` 13 - One or more HTTP cookie(s).
|
||||
``download_dir`` 1 - The directory where the downloaded contents will be saved in.
|
||||
``files_unwanted`` 1 - A list of file id's that shouldn't be downloaded.
|
||||
``files_wanted`` 1 - A list of file id's that should be downloaded.
|
||||
``paused`` 1 - If True, does not start the transfer when added.
|
||||
``peer_limit`` 1 - Maximum number of peers allowed.
|
||||
``priority_high`` 1 - A list of file id's that should have high priority.
|
||||
``priority_low`` 1 - A list of file id's that should have low priority.
|
||||
``priority_normal`` 1 - A list of file id's that should have normal priority.
|
||||
===================== ===== =========== =============================================================
|
||||
"""
|
||||
if uri == None:
|
||||
if uri is None:
|
||||
raise ValueError('add_uri requires a URI.')
|
||||
# there has been some problem with T's built in torrent fetcher,
|
||||
# use a python one instead
|
||||
parseduri = _urlparse(uri)
|
||||
parsed_uri = urlparse.urlparse(uri)
|
||||
torrent_data = None
|
||||
if parseduri.scheme in ['file', 'ftp', 'ftps', 'http', 'https']:
|
||||
if parsed_uri.scheme in ['file', 'ftp', 'ftps', 'http', 'https']:
|
||||
torrent_file = urllib2.urlopen(uri)
|
||||
torrent_data = base64.b64encode(torrent_file.read())
|
||||
if torrent_data:
|
||||
return self.add(torrent_data, **kwargs)
|
||||
else:
|
||||
return self.add(None, filename=uri, **kwargs)
|
||||
|
||||
|
||||
def remove(self, ids, delete_data=False, timeout=None):
|
||||
"""
|
||||
remove torrent(s) with provided id(s). Local data is removed if
|
||||
|
@ -425,9 +434,12 @@ class Client(object):
|
|||
self._request('torrent-remove',
|
||||
{'delete-local-data':rpc_bool(delete_data)}, ids, True, timeout=timeout)
|
||||
|
||||
def start(self, ids, timeout=None):
|
||||
def start(self, ids, bypass_queue=False, timeout=None):
|
||||
"""start torrent(s) with provided id(s)"""
|
||||
self._request('torrent-start', {}, ids, True, timeout=timeout)
|
||||
method = 'torrent-start'
|
||||
if bypass_queue and self.rpc_version >= 14:
|
||||
method = 'torrent-start-now'
|
||||
self._request(method, {}, ids, True, timeout=timeout)
|
||||
|
||||
def stop(self, ids, timeout=None):
|
||||
"""stop torrent(s) with provided id(s)"""
|
||||
|
@ -451,7 +463,7 @@ class Client(object):
|
|||
def get_files(self, ids=None, timeout=None):
|
||||
"""
|
||||
Get list of files for provided torrent id(s). If ids is empty,
|
||||
information for all torrents are fetched. This function returns a dictonary
|
||||
information for all torrents are fetched. This function returns a dictionary
|
||||
for each requested torrent id holding the information about the files.
|
||||
|
||||
::
|
||||
|
@ -481,7 +493,7 @@ class Client(object):
|
|||
|
||||
def set_files(self, items, timeout=None):
|
||||
"""
|
||||
Set file properties. Takes a dictonary with similar contents as the result
|
||||
Set file properties. Takes a dictionary with similar contents as the result
|
||||
of `get_files`.
|
||||
|
||||
::
|
||||
|
@ -506,9 +518,9 @@ class Client(object):
|
|||
continue
|
||||
wanted = []
|
||||
unwanted = []
|
||||
priority_high = []
|
||||
priority_normal = []
|
||||
priority_low = []
|
||||
high = []
|
||||
normal = []
|
||||
low = []
|
||||
for fid, file_desc in files.iteritems():
|
||||
if not isinstance(file_desc, dict):
|
||||
continue
|
||||
|
@ -518,22 +530,29 @@ class Client(object):
|
|||
unwanted.append(fid)
|
||||
if 'priority' in file_desc:
|
||||
if file_desc['priority'] == 'high':
|
||||
priority_high.append(fid)
|
||||
high.append(fid)
|
||||
elif file_desc['priority'] == 'normal':
|
||||
priority_normal.append(fid)
|
||||
normal.append(fid)
|
||||
elif file_desc['priority'] == 'low':
|
||||
priority_low.append(fid)
|
||||
self.change([tid], files_wanted = wanted
|
||||
, files_unwanted = unwanted
|
||||
, priority_high = priority_high
|
||||
, priority_normal = priority_normal
|
||||
, priority_low = priority_low, timeout=timeout)
|
||||
low.append(fid)
|
||||
args = {
|
||||
'timeout': timeout,
|
||||
'files_wanted': wanted,
|
||||
'files_unwanted': unwanted,
|
||||
}
|
||||
if len(high) > 0:
|
||||
args['priority_high'] = high
|
||||
if len(normal) > 0:
|
||||
args['priority_normal'] = normal
|
||||
if len(low) > 0:
|
||||
args['priority_low'] = low
|
||||
self.change([tid], **args)
|
||||
|
||||
def list(self, timeout=None):
|
||||
"""list all torrents"""
|
||||
fields = ['id', 'hashString', 'name', 'sizeWhenDone', 'leftUntilDone'
|
||||
, 'eta', 'status', 'rateUpload', 'rateDownload', 'uploadedEver'
|
||||
, 'downloadedEver']
|
||||
, 'downloadedEver', 'uploadRatio']
|
||||
return self._request('torrent-get', {'fields': fields}, timeout=timeout)
|
||||
|
||||
def change(self, ids, timeout=None, **kwargs):
|
||||
|
@ -542,32 +561,33 @@ class Client(object):
|
|||
parameters are:
|
||||
|
||||
============================ ===== =============== =======================================================================================
|
||||
Argument RPC Replaced by Description
|
||||
Argument RPC Replaced by Description
|
||||
============================ ===== =============== =======================================================================================
|
||||
``bandwidthPriority`` 5 - Priority for this transfer.
|
||||
``downloadLimit`` 5 - Set the speed limit for download in Kib/s.
|
||||
``downloadLimited`` 5 - Enable download speed limiter.
|
||||
``files_unwanted`` 1 - A list of file id's that shouldn't be downloaded.
|
||||
``files_wanted`` 1 - A list of file id's that should be downloaded.
|
||||
``honorsSessionLimits`` 5 - Enables or disables the transfer to honour the upload limit set in the session.
|
||||
``ids`` 1 - Local download location.
|
||||
``peer_limit`` 1 - The peer limit for the torrents.
|
||||
``priority_high`` 1 - A list of file id's that should have high priority.
|
||||
``priority_low`` 1 - A list of file id's that should have normal priority.
|
||||
``priority_normal`` 1 - A list of file id's that should have low priority.
|
||||
``seedIdleLimit`` 10 - Seed inactivity limit in minutes.
|
||||
``bandwidthPriority`` 5 - Priority for this transfer.
|
||||
``downloadLimit`` 5 - Set the speed limit for download in Kib/s.
|
||||
``downloadLimited`` 5 - Enable download speed limiter.
|
||||
``files_unwanted`` 1 - A list of file id's that shouldn't be downloaded.
|
||||
``files_wanted`` 1 - A list of file id's that should be downloaded.
|
||||
``honorsSessionLimits`` 5 - Enables or disables the transfer to honour the upload limit set in the session.
|
||||
``location`` 1 - Local download location.
|
||||
``peer_limit`` 1 - The peer limit for the torrents.
|
||||
``priority_high`` 1 - A list of file id's that should have high priority.
|
||||
``priority_low`` 1 - A list of file id's that should have normal priority.
|
||||
``priority_normal`` 1 - A list of file id's that should have low priority.
|
||||
``queuePosition`` 14 - Position of this transfer in its queue.
|
||||
``seedIdleLimit`` 10 - Seed inactivity limit in minutes.
|
||||
``seedIdleMode`` 10 - Seed inactivity mode. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.
|
||||
``seedRatioLimit`` 5 - Seeding ratio.
|
||||
``seedRatioMode`` 5 - Which ratio to use. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.
|
||||
``speed_limit_down`` 1 - 5 downloadLimit Set the speed limit for download in Kib/s.
|
||||
``speed_limit_down_enabled`` 1 - 5 downloadLimited Enable download speed limiter.
|
||||
``speed_limit_up`` 1 - 5 uploadLimit Set the speed limit for upload in Kib/s.
|
||||
``speed_limit_up_enabled`` 1 - 5 uploadLimited Enable upload speed limiter.
|
||||
``trackerAdd`` 10 - Array of string with announce URLs to add.
|
||||
``trackerRemove`` 10 - Array of ids of trackers to remove.
|
||||
``trackerReplace`` 10 - Array of (id, url) tuples where the announce URL should be replaced.
|
||||
``uploadLimit`` 5 - Set the speed limit for upload in Kib/s.
|
||||
``uploadLimited`` 5 - Enable upload speed limiter.
|
||||
``seedRatioLimit`` 5 - Seeding ratio.
|
||||
``seedRatioMode`` 5 - Which ratio to use. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.
|
||||
``speed_limit_down`` 1 - 5 downloadLimit Set the speed limit for download in Kib/s.
|
||||
``speed_limit_down_enabled`` 1 - 5 downloadLimited Enable download speed limiter.
|
||||
``speed_limit_up`` 1 - 5 uploadLimit Set the speed limit for upload in Kib/s.
|
||||
``speed_limit_up_enabled`` 1 - 5 uploadLimited Enable upload speed limiter.
|
||||
``trackerAdd`` 10 - Array of string with announce URLs to add.
|
||||
``trackerRemove`` 10 - Array of ids of trackers to remove.
|
||||
``trackerReplace`` 10 - Array of (id, url) tuples where the announce URL should be replaced.
|
||||
``uploadLimit`` 5 - Set the speed limit for upload in Kib/s.
|
||||
``uploadLimited`` 5 - Enable upload speed limiter.
|
||||
============================ ===== =============== =======================================================================================
|
||||
|
||||
.. NOTE::
|
||||
|
@ -584,19 +604,39 @@ class Client(object):
|
|||
self._request('torrent-set', args, ids, True, timeout=timeout)
|
||||
else:
|
||||
ValueError("No arguments to set")
|
||||
|
||||
|
||||
def move(self, ids, location, timeout=None):
|
||||
"""Move torrent data to the new location."""
|
||||
self._rpc_version_warning(6)
|
||||
args = {'location': location, 'move': True}
|
||||
self._request('torrent-set-location', args, ids, True, timeout=timeout)
|
||||
|
||||
|
||||
def locate(self, ids, location, timeout=None):
|
||||
"""Locate torrent data at the location."""
|
||||
self._rpc_version_warning(6)
|
||||
args = {'location': location, 'move': False}
|
||||
self._request('torrent-set-location', args, ids, True, timeout=timeout)
|
||||
|
||||
|
||||
def queue_top(self, ids, timeout=None):
|
||||
"""Move transfer to the top of the queue."""
|
||||
self._rpc_version_warning(14)
|
||||
self._request('queue-move-top', ids=ids, require_ids=True, timeout=timeout)
|
||||
|
||||
def queue_bottom(self, ids, timeout=None):
|
||||
"""Move transfer to the bottom of the queue."""
|
||||
self._rpc_version_warning(14)
|
||||
self._request('queue-move-bottom', ids=ids, require_ids=True, timeout=timeout)
|
||||
|
||||
def queue_up(self, ids, timeout=None):
|
||||
"""Move transfer up in the queue."""
|
||||
self._rpc_version_warning(14)
|
||||
self._request('queue-move-up', ids=ids, require_ids=True, timeout=timeout)
|
||||
|
||||
def queue_down(self, ids, timeout=None):
|
||||
"""Move transfer down in the queue."""
|
||||
self._rpc_version_warning(14)
|
||||
self._request('queue-move-down', ids=ids, require_ids=True, timeout=timeout)
|
||||
|
||||
def get_session(self, timeout=None):
|
||||
"""Get session parameters"""
|
||||
self._request('session-get', timeout=timeout)
|
||||
|
@ -606,47 +646,55 @@ class Client(object):
|
|||
def set_session(self, timeout=None, **kwargs):
|
||||
"""
|
||||
Set session parameters. The parameters are:
|
||||
|
||||
|
||||
================================ ===== ================= ==========================================================================================================================
|
||||
Argument RPC Replaced by Description
|
||||
Argument RPC Replaced by Description
|
||||
================================ ===== ================= ==========================================================================================================================
|
||||
``alt_speed_down`` 5 - Alternate session download speed limit (in Kib/s).
|
||||
``alt_speed_enabled`` 5 - Enables alternate global download speed limiter.
|
||||
``alt_speed_time_begin`` 5 - Time when alternate speeds should be enabled. Minutes after midnight.
|
||||
``alt_speed_time_day`` 5 - Enables alternate speeds scheduling these days.
|
||||
``alt_speed_time_enabled`` 5 - Enables alternate speeds scheduling.
|
||||
``alt_speed_time_end`` 5 - Time when alternate speeds should be disabled. Minutes after midnight.
|
||||
``alt_speed_up`` 5 - Alternate session upload speed limit (in Kib/s).
|
||||
``blocklist_enabled`` 5 - Enables the block list
|
||||
``cache_size_mb`` 10 - The maximum size of the disk cache in MB
|
||||
``dht_enabled`` 6 - Enables DHT.
|
||||
``download_dir`` 1 - Set the session download directory.
|
||||
``encryption`` 1 - Set the session encryption mode, one of ``required``, ``preferred`` or ``tolerated``.
|
||||
``idle_seeding_limit`` 10 - The default seed inactivity limit in minutes.
|
||||
``idle_seeding_limit_enabled`` 10 - Enables the default seed inactivity limit
|
||||
``incomplete_dir`` 7 - The path to the directory of incomplete transfer data.
|
||||
``alt_speed_down`` 5 - Alternate session download speed limit (in Kib/s).
|
||||
``alt_speed_enabled`` 5 - Enables alternate global download speed limiter.
|
||||
``alt_speed_time_begin`` 5 - Time when alternate speeds should be enabled. Minutes after midnight.
|
||||
``alt_speed_time_day`` 5 - Enables alternate speeds scheduling these days.
|
||||
``alt_speed_time_enabled`` 5 - Enables alternate speeds scheduling.
|
||||
``alt_speed_time_end`` 5 - Time when alternate speeds should be disabled. Minutes after midnight.
|
||||
``alt_speed_up`` 5 - Alternate session upload speed limit (in Kib/s).
|
||||
``blocklist_enabled`` 5 - Enables the block list
|
||||
``blocklist_url`` 11 - Location of the block list. Updated with blocklist-update.
|
||||
``cache_size_mb`` 10 - The maximum size of the disk cache in MB
|
||||
``dht_enabled`` 6 - Enables DHT.
|
||||
``download_dir`` 1 - Set the session download directory.
|
||||
``download_queue_enabled`` 14 - Enable parallel download restriction.
|
||||
``download_queue_size`` 14 - Number of parallel downloads.
|
||||
``encryption`` 1 - Set the session encryption mode, one of ``required``, ``preferred`` or ``tolerated``.
|
||||
``idle_seeding_limit`` 10 - The default seed inactivity limit in minutes.
|
||||
``idle_seeding_limit_enabled`` 10 - Enables the default seed inactivity limit
|
||||
``incomplete_dir`` 7 - The path to the directory of incomplete transfer data.
|
||||
``incomplete_dir_enabled`` 7 - Enables the incomplete transfer data directory. Otherwise data for incomplete transfers are stored in the download target.
|
||||
``lpd_enabled`` 9 - Enables local peer discovery for public torrents.
|
||||
``peer_limit`` 1 - 5 peer-limit-global Maximum number of peers
|
||||
``peer_limit_global`` 5 - Maximum number of peers
|
||||
``peer_limit_per_torrent`` 5 - Maximum number of peers per transfer
|
||||
``peer_port`` 5 - Peer port.
|
||||
``peer_port_random_on_start`` 5 - Enables randomized peer port on start of Transmission.
|
||||
``pex_allowed`` 1 - 5 pex-enabled Allowing PEX in public torrents.
|
||||
``pex_enabled`` 5 - Allowing PEX in public torrents.
|
||||
``port`` 1 - 5 peer-port Peer port.
|
||||
``port_forwarding_enabled`` 1 - Enables port forwarding.
|
||||
``rename_partial_files`` 8 - Appends ".part" to incomplete files
|
||||
``script_torrent_done_enabled`` 9 - Whether or not to call the "done" script.
|
||||
``script_torrent_done_filename`` 9 - Filename of the script to run when the transfer is done.
|
||||
``seedRatioLimit`` 5 - Seed ratio limit. 1.0 means 1:1 download and upload ratio.
|
||||
``seedRatioLimited`` 5 - Enables seed ration limit.
|
||||
``speed_limit_down`` 1 - Download speed limit (in Kib/s).
|
||||
``speed_limit_down_enabled`` 1 - Enables download speed limiting.
|
||||
``speed_limit_up`` 1 - Upload speed limit (in Kib/s).
|
||||
``speed_limit_up_enabled`` 1 - Enables upload speed limiting.
|
||||
``start_added_torrents`` 9 - Added torrents will be started right away.
|
||||
``trash_original_torrent_files`` 9 - The .torrent file of added torrents will be deleted.
|
||||
``lpd_enabled`` 9 - Enables local peer discovery for public torrents.
|
||||
``peer_limit`` 1 - 5 peer-limit-global Maximum number of peers
|
||||
``peer_limit_global`` 5 - Maximum number of peers
|
||||
``peer_limit_per_torrent`` 5 - Maximum number of peers per transfer
|
||||
``peer_port`` 5 - Peer port.
|
||||
``peer_port_random_on_start`` 5 - Enables randomized peer port on start of Transmission.
|
||||
``pex_allowed`` 1 - 5 pex-enabled Allowing PEX in public torrents.
|
||||
``pex_enabled`` 5 - Allowing PEX in public torrents.
|
||||
``port`` 1 - 5 peer-port Peer port.
|
||||
``port_forwarding_enabled`` 1 - Enables port forwarding.
|
||||
``queue_stalled_enabled`` 14 - Enable tracking of stalled transfers.
|
||||
``queue_stalled_minutes`` 14 - Number of minutes of idle that marks a transfer as stalled.
|
||||
``rename_partial_files`` 8 - Appends ".part" to incomplete files
|
||||
``script_torrent_done_enabled`` 9 - Whether or not to call the "done" script.
|
||||
``script_torrent_done_filename`` 9 - Filename of the script to run when the transfer is done.
|
||||
``seed_queue_enabled`` 14 - Enable parallel upload restriction.
|
||||
``seed_queue_size`` 14 - Number of parallel uploads.
|
||||
``seedRatioLimit`` 5 - Seed ratio limit. 1.0 means 1:1 download and upload ratio.
|
||||
``seedRatioLimited`` 5 - Enables seed ration limit.
|
||||
``speed_limit_down`` 1 - Download speed limit (in Kib/s).
|
||||
``speed_limit_down_enabled`` 1 - Enables download speed limiting.
|
||||
``speed_limit_up`` 1 - Upload speed limit (in Kib/s).
|
||||
``speed_limit_up_enabled`` 1 - Enables upload speed limiting.
|
||||
``start_added_torrents`` 9 - Added torrents will be started right away.
|
||||
``trash_original_torrent_files`` 9 - The .torrent file of added torrents will be deleted.
|
||||
``utp_enabled`` 13 - Enables Micro Transport Protocol (UTP).
|
||||
================================ ===== ================= ==========================================================================================================================
|
||||
|
||||
.. NOTE::
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2008-2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
import logging
|
||||
|
@ -18,20 +18,6 @@ DEFAULT_PORT = 9091
|
|||
|
||||
DEFAULT_TIMEOUT = 30.0
|
||||
|
||||
TR_STATUS_CHECK_WAIT = (1<<0)
|
||||
TR_STATUS_CHECK = (1<<1)
|
||||
TR_STATUS_DOWNLOAD = (1<<2)
|
||||
TR_STATUS_SEED = (1<<3)
|
||||
TR_STATUS_STOPPED = (1<<4)
|
||||
|
||||
STATUS = mirror_dict({
|
||||
'check pending' : TR_STATUS_CHECK_WAIT,
|
||||
'checking' : TR_STATUS_CHECK,
|
||||
'downloading' : TR_STATUS_DOWNLOAD,
|
||||
'seeding' : TR_STATUS_SEED,
|
||||
'stopped' : TR_STATUS_STOPPED,
|
||||
})
|
||||
|
||||
TR_PRI_LOW = -1
|
||||
TR_PRI_NORMAL = 0
|
||||
TR_PRI_HIGH = 1
|
||||
|
@ -103,6 +89,7 @@ TORRENT_ARGS = {
|
|||
'id': ('number', 1, None, None, None, ''),
|
||||
'isFinished': ('boolean', 9, None, None, None, ''),
|
||||
'isPrivate': ('boolean', 1, None, None, None, ''),
|
||||
'isStalled': ('boolean', 14, None, None, None, ''),
|
||||
'lastAnnounceTime': ('number', 1, 7, None, None, ''),
|
||||
'lastScrapeTime': ('number', 1, 7, None, None, ''),
|
||||
'leechers': ('number', 1, 7, None, None, ''),
|
||||
|
@ -119,13 +106,14 @@ TORRENT_ARGS = {
|
|||
'peersConnected': ('number', 1, None, None, None, ''),
|
||||
'peersFrom': ('object', 1, None, None, None, ''),
|
||||
'peersGettingFromUs': ('number', 1, None, None, None, ''),
|
||||
'peersKnown': ('number', 1, None, None, None, ''),
|
||||
'peersKnown': ('number', 1, 13, None, None, ''),
|
||||
'peersSendingToUs': ('number', 1, None, None, None, ''),
|
||||
'percentDone': ('double', 5, None, None, None, ''),
|
||||
'pieces': ('string', 5, None, None, None, ''),
|
||||
'pieceCount': ('number', 1, None, None, None, ''),
|
||||
'pieceSize': ('number', 1, None, None, None, ''),
|
||||
'priorities': ('array', 1, None, None, None, ''),
|
||||
'queuePosition': ('number', 14, None, None, None, ''),
|
||||
'rateDownload': ('number', 1, None, None, None, ''),
|
||||
'rateUpload': ('number', 1, None, None, None, ''),
|
||||
'recheckProgress': ('double', 1, None, None, None, ''),
|
||||
|
@ -161,11 +149,12 @@ TORRENT_ARGS = {
|
|||
'files-wanted': ('array', 1, None, None, None, "A list of file id's that should be downloaded."),
|
||||
'files-unwanted': ('array', 1, None, None, None, "A list of file id's that shouldn't be downloaded."),
|
||||
'honorsSessionLimits': ('boolean', 5, None, None, None, "Enables or disables the transfer to honour the upload limit set in the session."),
|
||||
'ids': ('array', 1, None, None, None, 'Local download location.'),
|
||||
'location': ('array', 1, None, None, None, 'Local download location.'),
|
||||
'peer-limit': ('number', 1, None, None, None, 'The peer limit for the torrents.'),
|
||||
'priority-high': ('array', 1, None, None, None, "A list of file id's that should have high priority."),
|
||||
'priority-low': ('array', 1, None, None, None, "A list of file id's that should have normal priority."),
|
||||
'priority-normal': ('array', 1, None, None, None, "A list of file id's that should have low priority."),
|
||||
'queuePosition': ('number', 14, None, None, None, 'Position of this transfer in its queue.'),
|
||||
'seedIdleLimit': ('number', 10, None, None, None, 'Seed inactivity limit in minutes.'),
|
||||
'seedIdleMode': ('number', 10, None, None, None, 'Seed inactivity mode. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.'),
|
||||
'seedRatioLimit': ('double', 5, None, None, None, 'Seeding ratio.'),
|
||||
|
@ -183,7 +172,8 @@ TORRENT_ARGS = {
|
|||
'add': {
|
||||
'bandwidthPriority': ('number', 8, None, None, None, 'Priority for this transfer.'),
|
||||
'download-dir': ('string', 1, None, None, None, 'The directory where the downloaded contents will be saved in.'),
|
||||
'filename': ('string', 1, None, None, None, "A filepath or URL to a torrent file or a magnet link."),
|
||||
'cookies': ('string', 13, None, None, None, 'One or more HTTP cookie(s).'),
|
||||
'filename': ('string', 1, None, None, None, "A file path or URL to a torrent file or a magnet link."),
|
||||
'files-wanted': ('array', 1, None, None, None, "A list of file id's that should be downloaded."),
|
||||
'files-unwanted': ('array', 1, None, None, None, "A list of file id's that shouldn't be downloaded."),
|
||||
'metainfo': ('string', 1, None, None, None, 'The content of a torrent file, base64 encoded.'),
|
||||
|
@ -212,6 +202,9 @@ SESSION_ARGS = {
|
|||
"config-dir": ('string', 8, None, None, None, ''),
|
||||
"dht-enabled": ('boolean', 6, None, None, None, ''),
|
||||
"download-dir": ('string', 1, None, None, None, ''),
|
||||
"download-dir-free-space": ('number', 12, None, None, None, ''),
|
||||
"download-queue-size": ('number', 14, None, None, None, ''),
|
||||
"download-queue-enabled": ('boolean', 14, None, None, None, ''),
|
||||
"encryption": ('string', 1, None, None, None, ''),
|
||||
"idle-seeding-limit": ('number', 10, None, None, None, ''),
|
||||
"idle-seeding-limit-enabled": ('boolean', 10, None, None, None, ''),
|
||||
|
@ -227,6 +220,8 @@ SESSION_ARGS = {
|
|||
"peer-port": ('number', 5, None, None, None, ''),
|
||||
"peer-port-random-on-start": ('boolean', 5, None, None, None, ''),
|
||||
"port-forwarding-enabled": ('boolean', 1, None, None, None, ''),
|
||||
"queue-stalled-minutes": ('number', 14, None, None, None, ''),
|
||||
"queue-stalled-enabled": ('boolean', 14, None, None, None, ''),
|
||||
"rename-partial-files": ('boolean', 8, None, None, None, ''),
|
||||
"rpc-version": ('number', 4, None, None, None, ''),
|
||||
"rpc-version-minimum": ('number', 4, None, None, None, ''),
|
||||
|
@ -234,6 +229,8 @@ SESSION_ARGS = {
|
|||
"script-torrent-done-filename": ('string', 9, None, None, None, ''),
|
||||
"seedRatioLimit": ('double', 5, None, None, None, ''),
|
||||
"seedRatioLimited": ('boolean', 5, None, None, None, ''),
|
||||
"seed-queue-size": ('number', 14, None, None, None, ''),
|
||||
"seed-queue-enabled": ('boolean', 14, None, None, None, ''),
|
||||
"speed-limit-down": ('number', 1, None, None, None, ''),
|
||||
"speed-limit-down-enabled": ('boolean', 1, None, None, None, ''),
|
||||
"speed-limit-up": ('number', 1, None, None, None, ''),
|
||||
|
@ -241,6 +238,7 @@ SESSION_ARGS = {
|
|||
"start-added-torrents": ('boolean', 9, None, None, None, ''),
|
||||
"trash-original-torrent-files": ('boolean', 9, None, None, None, ''),
|
||||
'units': ('object', 10, None, None, None, ''),
|
||||
'utp-enabled': ('boolean', 13, None, None, None, ''),
|
||||
"version": ('string', 3, None, None, None, ''),
|
||||
},
|
||||
'set': {
|
||||
|
@ -252,10 +250,12 @@ SESSION_ARGS = {
|
|||
"alt-speed-time-day": ('number', 5, None, None, None, 'Enables alternate speeds scheduling these days.'),
|
||||
"alt-speed-up": ('number', 5, None, None, None, 'Alternate session upload speed limit (in Kib/s).'),
|
||||
"blocklist-enabled": ('boolean', 5, None, None, None, 'Enables the block list'),
|
||||
"blocklist-url": ('string', 11, None, None, None, 'Location of the blocklist. Updated with blocklist-update.'),
|
||||
"blocklist-url": ('string', 11, None, None, None, 'Location of the block list. Updated with blocklist-update.'),
|
||||
"cache-size-mb": ('number', 10, None, None, None, 'The maximum size of the disk cache in MB'),
|
||||
"dht-enabled": ('boolean', 6, None, None, None, 'Enables DHT.'),
|
||||
"download-dir": ('string', 1, None, None, None, 'Set the session download directory.'),
|
||||
"download-queue-size": ('number', 14, None, None, None, 'Number of parallel downloads.'),
|
||||
"download-queue-enabled": ('boolean', 14, None, None, None, 'Enable parallel download restriction.'),
|
||||
"encryption": ('string', 1, None, None, None, 'Set the session encryption mode, one of ``required``, ``preferred`` or ``tolerated``.'),
|
||||
"idle-seeding-limit": ('number', 10, None, None, None, 'The default seed inactivity limit in minutes.'),
|
||||
"idle-seeding-limit-enabled": ('boolean', 10, None, None, None, 'Enables the default seed inactivity limit'),
|
||||
|
@ -272,8 +272,12 @@ SESSION_ARGS = {
|
|||
"peer-port-random-on-start": ('boolean', 5, None, None, None, 'Enables randomized peer port on start of Transmission.'),
|
||||
"port-forwarding-enabled": ('boolean', 1, None, None, None, 'Enables port forwarding.'),
|
||||
"rename-partial-files": ('boolean', 8, None, None, None, 'Appends ".part" to incomplete files'),
|
||||
"queue-stalled-minutes": ('number', 14, None, None, None, 'Number of minutes of idle that marks a transfer as stalled.'),
|
||||
"queue-stalled-enabled": ('boolean', 14, None, None, None, 'Enable tracking of stalled transfers.'),
|
||||
"script-torrent-done-enabled": ('boolean', 9, None, None, None, 'Whether or not to call the "done" script.'),
|
||||
"script-torrent-done-filename": ('string', 9, None, None, None, 'Filename of the script to run when the transfer is done.'),
|
||||
"seed-queue-size": ('number', 14, None, None, None, 'Number of parallel uploads.'),
|
||||
"seed-queue-enabled": ('boolean', 14, None, None, None, 'Enable parallel upload restriction.'),
|
||||
"seedRatioLimit": ('double', 5, None, None, None, 'Seed ratio limit. 1.0 means 1:1 download and upload ratio.'),
|
||||
"seedRatioLimited": ('boolean', 5, None, None, None, 'Enables seed ration limit.'),
|
||||
"speed-limit-down": ('number', 1, None, None, None, 'Download speed limit (in Kib/s).'),
|
||||
|
@ -282,5 +286,6 @@ SESSION_ARGS = {
|
|||
"speed-limit-up-enabled": ('boolean', 1, None, None, None, 'Enables upload speed limiting.'),
|
||||
"start-added-torrents": ('boolean', 9, None, None, None, 'Added torrents will be started right away.'),
|
||||
"trash-original-torrent-files": ('boolean', 9, None, None, None, 'The .torrent file of added torrents will be deleted.'),
|
||||
'utp-enabled': ('boolean', 13, None, None, None, 'Enables Micro Transport Protocol (UTP).'),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2008-2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
class TransmissionError(Exception):
|
||||
"""
|
||||
This exception is raised when there has occured an error related to
|
||||
This exception is raised when there has occurred an error related to
|
||||
communication with Transmission. It is a subclass of Exception.
|
||||
"""
|
||||
def __init__(self, message='', original=None):
|
||||
Exception.__init__(self)
|
||||
self.message = message
|
||||
self._message = message
|
||||
self.original = original
|
||||
|
||||
def __str__(self):
|
||||
|
@ -21,14 +21,14 @@ class TransmissionError(Exception):
|
|||
|
||||
class HTTPHandlerError(Exception):
|
||||
"""
|
||||
This exception is raised when there has occured an error related to
|
||||
This exception is raised when there has occurred an error related to
|
||||
the HTTP handler. It is a subclass of Exception.
|
||||
"""
|
||||
def __init__(self, httpurl=None, httpcode=None, httpmsg=None, httpheaders=None, httpdata=None):
|
||||
Exception.__init__(self)
|
||||
self.url = ''
|
||||
self.code = 600
|
||||
self.message = ''
|
||||
self._message = ''
|
||||
self.headers = {}
|
||||
self.data = ''
|
||||
if isinstance(httpurl, (str, unicode)):
|
||||
|
@ -36,17 +36,17 @@ class HTTPHandlerError(Exception):
|
|||
if isinstance(httpcode, (int, long)):
|
||||
self.code = httpcode
|
||||
if isinstance(httpmsg, (str, unicode)):
|
||||
self.message = httpmsg
|
||||
if isinstance(httpheaders, (dict)):
|
||||
self._message = httpmsg
|
||||
if isinstance(httpheaders, dict):
|
||||
self.headers = httpheaders
|
||||
if isinstance(httpdata, (str, unicode)):
|
||||
self.data = httpdata
|
||||
|
||||
def __repr__(self):
|
||||
return '<HTTPHandlerError %d, %s>' % (self.code, self.message)
|
||||
return '<HTTPHandlerError %d, %s>' % (self.code, self._message)
|
||||
|
||||
def __str__(self):
|
||||
return '<HTTPHandlerError %d, %s>' % (self.code, self.message)
|
||||
return 'HTTPHandlerError %d: %s' % (self.code, self._message)
|
||||
|
||||
def __unicode__(self):
|
||||
return u'<HTTPHandlerError %d, %s>' % (self.code, self.message)
|
||||
return u'HTTPHandlerError %d: %s' % (self.code, self._message)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
import sys, httplib, urllib2
|
||||
|
@ -14,17 +14,17 @@ class HTTPHandler(object):
|
|||
"""
|
||||
Transmission use basic authentication in earlier versions and digest
|
||||
authentication in later versions.
|
||||
|
||||
|
||||
* uri, the authentication realm URI.
|
||||
* login, the authentication login.
|
||||
* password, the authentication password.
|
||||
"""
|
||||
raise NotImplementedError("Bad HTTPHandler, failed to implement set_authentication.")
|
||||
|
||||
|
||||
def request(self, url, query, headers, timeout):
|
||||
"""
|
||||
Implement a HTTP POST request here.
|
||||
|
||||
|
||||
* url, The URL to request.
|
||||
* query, The query data to send. This is a JSON data string.
|
||||
* headers, a dictionary of headers to send.
|
||||
|
@ -56,12 +56,12 @@ class DefaultHTTPHandler(HTTPHandler):
|
|||
else:
|
||||
response = urllib2.urlopen(request)
|
||||
except urllib2.HTTPError, error:
|
||||
if error.fp == None:
|
||||
if error.fp is None:
|
||||
raise HTTPHandlerError(error.filename, error.code, error.msg, dict(error.hdrs))
|
||||
else:
|
||||
raise HTTPHandlerError(error.filename, error.code, error.msg, dict(error.hdrs), error.read())
|
||||
except urllib2.URLError, error:
|
||||
# urllib2.URLError documentation is absymal!
|
||||
# urllib2.URLError documentation is horrendous!
|
||||
# Try to get the tuple arguments of URLError
|
||||
if hasattr(error.reason, 'args') and isinstance(error.reason.args, tuple) and len(error.reason.args) == 2:
|
||||
raise HTTPHandlerError(httpcode=error.reason.args[0], httpmsg=error.reason.args[1])
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2008-2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
class Session(object):
|
||||
|
@ -8,17 +8,17 @@ class Session(object):
|
|||
|
||||
Access the session field can be done through attributes.
|
||||
The attributes available are the same as the session arguments in the
|
||||
Transmission RPC specification, but with underscore instead of hypen.
|
||||
Transmission RPC specification, but with underscore instead of hyphen.
|
||||
``download-dir`` -> ``download_dir``.
|
||||
"""
|
||||
|
||||
def __init__(self, fields=None):
|
||||
self.fields = {}
|
||||
if fields != None:
|
||||
if fields is not None:
|
||||
self.update(fields)
|
||||
|
||||
def update(self, other):
|
||||
"""Update the session data from a session arguments dictinary"""
|
||||
"""Update the session data from a session arguments dictionary"""
|
||||
|
||||
fields = None
|
||||
if isinstance(other, dict):
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2008-2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
import sys, datetime
|
||||
|
||||
from transmissionrpc.constants import STATUS, PRIORITY
|
||||
from transmissionrpc.constants import PRIORITY
|
||||
from transmissionrpc.utils import format_timedelta
|
||||
|
||||
class Torrent(object):
|
||||
"""
|
||||
Torrent is a class holding the data raceived from Transmission regarding a bittorrent transfer.
|
||||
All fetched torrent fields are accessable through this class using attributes.
|
||||
Torrent is a class holding the data received from Transmission regarding a bittorrent transfer.
|
||||
All fetched torrent fields are accessible through this class using attributes.
|
||||
This class has a few convenience properties using the torrent data.
|
||||
"""
|
||||
|
||||
|
@ -22,7 +22,7 @@ class Torrent(object):
|
|||
self.client = client
|
||||
|
||||
def _getNameString(self, codec=None):
|
||||
if codec == None:
|
||||
if codec is None:
|
||||
codec = sys.getdefaultencoding()
|
||||
name = None
|
||||
# try to find name
|
||||
|
@ -50,13 +50,47 @@ class Torrent(object):
|
|||
return 'Torrent \"%s\"' % (name)
|
||||
else:
|
||||
return 'Torrent'
|
||||
|
||||
|
||||
def __copy__(self):
|
||||
return Torrent(self.client, self.fields)
|
||||
|
||||
def _rpc_version(self):
|
||||
if self.client:
|
||||
return self.client.rpc_version
|
||||
return 2
|
||||
|
||||
def _status_old(self, code):
|
||||
mapping = {
|
||||
(1<<0): 'check pending',
|
||||
(1<<1): 'checking',
|
||||
(1<<2): 'downloading',
|
||||
(1<<3): 'seeding',
|
||||
(1<<4): 'stopped',
|
||||
}
|
||||
return mapping[code]
|
||||
|
||||
def _status_new(self, code):
|
||||
mapping = {
|
||||
0: 'stopped',
|
||||
1: 'check pending',
|
||||
2: 'checking',
|
||||
3: 'download pending',
|
||||
4: 'downloading',
|
||||
5: 'seed pending',
|
||||
6: 'seeding',
|
||||
}
|
||||
return mapping[code]
|
||||
|
||||
def _status(self):
|
||||
code = self.fields['status']
|
||||
if self._rpc_version() >= 14:
|
||||
return self._status_new(code)
|
||||
else:
|
||||
return self._status_old(code)
|
||||
|
||||
def update(self, other):
|
||||
"""
|
||||
Update the torrent data from a Transmission JSON-RPC arguments dictinary
|
||||
Update the torrent data from a Transmission JSON-RPC arguments dictionary
|
||||
"""
|
||||
fields = None
|
||||
if isinstance(other, dict):
|
||||
|
@ -70,32 +104,33 @@ class Torrent(object):
|
|||
|
||||
def files(self):
|
||||
"""
|
||||
Get list of files for this torrent.
|
||||
Get list of files for this torrent.
|
||||
|
||||
This function returns a dictionary with file information for each file.
|
||||
The file information is has following fields:
|
||||
::
|
||||
This function returns a dictionary with file information for each file.
|
||||
The file information is has following fields:
|
||||
::
|
||||
|
||||
{
|
||||
<file id>: {
|
||||
'name': <file name>,
|
||||
'size': <file size in bytes>,
|
||||
'completed': <bytes completed>,
|
||||
'priority': <priority ('high'|'normal'|'low')>,
|
||||
'selected': <selected for download>
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
{
|
||||
<file id>: {
|
||||
'name': <file name>,
|
||||
'size': <file size in bytes>,
|
||||
'completed': <bytes completed>,
|
||||
'priority': <priority ('high'|'normal'|'low')>,
|
||||
'selected': <selected for download>
|
||||
}
|
||||
...
|
||||
}
|
||||
"""
|
||||
result = {}
|
||||
if 'files' in self.fields:
|
||||
indicies = xrange(len(self.fields['files']))
|
||||
indices = xrange(len(self.fields['files']))
|
||||
files = self.fields['files']
|
||||
priorities = self.fields['priorities']
|
||||
wanted = self.fields['wanted']
|
||||
for item in zip(indicies, files, priorities, wanted):
|
||||
selected = bool(item[3])
|
||||
for item in zip(indices, files, priorities, wanted):
|
||||
selected = False
|
||||
if item[3]:
|
||||
selected = True
|
||||
priority = PRIORITY[item[2]]
|
||||
result[item[0]] = {
|
||||
'selected': selected,
|
||||
|
@ -115,10 +150,10 @@ class Torrent(object):
|
|||
def status(self):
|
||||
"""
|
||||
Returns the torrent status. Is either one of 'check pending', 'checking',
|
||||
'downloading', 'seeding' or 'stopped'. The first two is related to
|
||||
verification.
|
||||
"""
|
||||
return STATUS[self.fields['status']]
|
||||
'downloading', 'seeding' or 'stopped'. The first two is related to
|
||||
verification.
|
||||
"""
|
||||
return self._status()
|
||||
|
||||
@property
|
||||
def progress(self):
|
||||
|
@ -131,10 +166,7 @@ class Torrent(object):
|
|||
@property
|
||||
def ratio(self):
|
||||
"""Get the upload/download ratio."""
|
||||
try:
|
||||
return self.fields['uploadedEver'] / float(self.fields['downloadedEver'])
|
||||
except ZeroDivisionError:
|
||||
return 0.0
|
||||
return float(self.fields['uploadRatio'])
|
||||
|
||||
@property
|
||||
def eta(self):
|
||||
|
@ -167,12 +199,12 @@ class Torrent(object):
|
|||
|
||||
def format_eta(self):
|
||||
"""
|
||||
Returns the attribute *eta* formatted as a string.
|
||||
Returns the attribute *eta* formatted as a string.
|
||||
|
||||
* If eta is -1 the result is 'not available'
|
||||
* If eta is -2 the result is 'unknown'
|
||||
* Otherwise eta is formatted as <days> <hours>:<minutes>:<seconds>.
|
||||
"""
|
||||
* If eta is -1 the result is 'not available'
|
||||
* If eta is -2 the result is 'unknown'
|
||||
* Otherwise eta is formatted as <days> <hours>:<minutes>:<seconds>.
|
||||
"""
|
||||
eta = self.fields['eta']
|
||||
if eta == -1:
|
||||
return 'not available'
|
||||
|
@ -180,11 +212,11 @@ class Torrent(object):
|
|||
return 'unknown'
|
||||
else:
|
||||
return format_timedelta(self.eta)
|
||||
|
||||
|
||||
@property
|
||||
def priority(self):
|
||||
"""
|
||||
Get the priority as string.
|
||||
Can be one of 'low', 'normal', 'high'.
|
||||
"""
|
||||
return PRIORITY[self.fields['bandwidthPriority']]
|
||||
return PRIORITY[self.fields['bandwidthPriority']]
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010 Erik Svensson <erik.public@gmail.com>
|
||||
# Copyright (c) 2008-2011 Erik Svensson <erik.public@gmail.com>
|
||||
# Licensed under the MIT license.
|
||||
|
||||
import socket, datetime, logging
|
||||
|
@ -28,18 +28,21 @@ def format_speed(size):
|
|||
|
||||
def format_timedelta(delta):
|
||||
"""
|
||||
Format datetime.timedelta into <days> <hours>:<mminutes>:<seconds>.
|
||||
Format datetime.timedelta into <days> <hours>:<minutes>:<seconds>.
|
||||
"""
|
||||
minutes, seconds = divmod(delta.seconds, 60)
|
||||
hours, minutes = divmod(minutes, 60)
|
||||
return '%d %02d:%02d:%02d' % (delta.days, hours, minutes, seconds)
|
||||
|
||||
def format_timestamp(timestamp):
|
||||
def format_timestamp(timestamp, utc=False):
|
||||
"""
|
||||
Format unix timestamp into ISO date format.
|
||||
"""
|
||||
if timestamp > 0:
|
||||
dt_timestamp = datetime.datetime.fromtimestamp(timestamp)
|
||||
if utc:
|
||||
dt_timestamp = datetime.datetime.utcfromtimestamp(timestamp)
|
||||
else:
|
||||
dt_timestamp = datetime.datetime.fromtimestamp(timestamp)
|
||||
return dt_timestamp.isoformat(' ')
|
||||
else:
|
||||
return '-'
|
||||
|
@ -178,7 +181,7 @@ def add_stdout_logger(level='debug'):
|
|||
Add a stdout target for the transmissionrpc logging.
|
||||
"""
|
||||
levels = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR}
|
||||
|
||||
|
||||
trpc_logger = logging.getLogger('transmissionrpc')
|
||||
loghandler = logging.StreamHandler()
|
||||
if level in levels.keys():
|
||||
|
|
Loading…
Reference in a new issue