r96 - in /debtorrent/branches/http-listen/DebTorrent: BT1/AptListener.py BT1/HTTPDownloader.py ServerPortHandler.py __init__.py launchmanycore.py

camrdale-guest at users.alioth.debian.org camrdale-guest at users.alioth.debian.org
Mon Jun 11 07:05:56 UTC 2007


Author: camrdale-guest
Date: Mon Jun 11 07:05:55 2007
New Revision: 96

URL: http://svn.debian.org/wsvn/debtorrent/?sc=1&rev=96
Log:
Some more documentation.

Modified:
    debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py
    debtorrent/branches/http-listen/DebTorrent/BT1/HTTPDownloader.py
    debtorrent/branches/http-listen/DebTorrent/ServerPortHandler.py
    debtorrent/branches/http-listen/DebTorrent/__init__.py
    debtorrent/branches/http-listen/DebTorrent/launchmanycore.py

Modified: debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py?rev=96&op=diff
==============================================================================
--- debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py (original)
+++ debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py Mon Jun 11 07:05:55 2007
@@ -389,7 +389,7 @@
         """Proxy the download of a file from a mirror.
         
         @type path: C{list} of C{string}
-        @param hash: the path of the file to download, starting with the mirror name
+        @param path: the path of the file to download, starting with the mirror name
         @rtype: (C{int}, C{string}, C{dictionary}, C{string})
         @return: the HTTP status code, status message, headers, and bencoded 
             metainfo file

Modified: debtorrent/branches/http-listen/DebTorrent/BT1/HTTPDownloader.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/branches/http-listen/DebTorrent/BT1/HTTPDownloader.py?rev=96&op=diff
==============================================================================
--- debtorrent/branches/http-listen/DebTorrent/BT1/HTTPDownloader.py (original)
+++ debtorrent/branches/http-listen/DebTorrent/BT1/HTTPDownloader.py Mon Jun 11 07:05:55 2007
@@ -394,7 +394,7 @@
     @ivar picker: the piece choosing instance
     @type rawserver: L{Debtorrent.RawServer.RawServer}
     @ivar rawserver: the server
-    @type finflag: C{Threading.Event}
+    @type finflag: C{threading.Event}
     @ivar finflag: the flag indicating when the download is complete
     @type errorfunc: C{method}
     @ivar errorfunc: the method to call when an error occurs
@@ -432,7 +432,7 @@
         @param picker: the piece choosing instance
         @type rawserver: L{Debtorrent.RawServer.RawServer}
         @param rawserver: the server
-        @type finflag: C{Threading.Event}
+        @type finflag: C{threading.Event}
         @param finflag: the flag indicating when the download is complete
         @type errorfunc: C{method}
         @param errorfunc: the method to call when an error occurs

Modified: debtorrent/branches/http-listen/DebTorrent/ServerPortHandler.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/branches/http-listen/DebTorrent/ServerPortHandler.py?rev=96&op=diff
==============================================================================
--- debtorrent/branches/http-listen/DebTorrent/ServerPortHandler.py (original)
+++ debtorrent/branches/http-listen/DebTorrent/ServerPortHandler.py Mon Jun 11 07:05:55 2007
@@ -1,8 +1,15 @@
 # Written by John Hoffman
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Wrappers to handle multiple torrent downloads.
+
+ at type default_task_id: C{mutable}
+ at var default_task_id: the default task ID to use for scheduling all unspecified tasks
+
+"""
 
 from cStringIO import StringIO
 #from RawServer import RawServer
@@ -18,7 +25,47 @@
 default_task_id = []
 
 class SingleRawServer:
+    """Simplified Server to handle one of many torrents.
+    
+    This class provides a wrapper around a master L{RawServer.RawServer} 
+    instance, processing requests with the same interface and passing them
+    on to the master server.
+    
+    @type info_hash: C{string}
+    @ivar info_hash: the torrent infohash this Server is responsible for
+    @type doneflag: C{threading.Event}
+    @ivar doneflag: flag to indicate this torrent is being shutdown
+    @type protocol: C{string}
+    @ivar protocol: the name of the communication protocol
+    @type multihandler: L{MultiHandler}
+    @ivar multihandler: the collection of all individual simplified servers
+    @type rawserver: L{RawServer.RawServer}
+    @ivar rawserver: the master Server instance
+    @type finished: C{boolean}
+    @ivar finished: whether this torrent has been shutdown
+    @type running: C{boolean}
+    @ivar running: whether this torrent has been started and is running
+    @type handler: unknown
+    @ivar handler: the data handler to use to process data received on the connection
+    @type taskqueue: C{list}
+    @ivar taskqueue: unknown
+    
+    """
+    
     def __init__(self, info_hash, multihandler, doneflag, protocol):
+        """Initialize the instance.
+        
+        @type info_hash: C{string}
+        @param info_hash: the torrent infohash this Server is responsible for
+        @type multihandler: L{MultiHandler}
+        @param multihandler: the collection of all individual simplified servers
+        @type doneflag: C{threading.Event}
+        @param doneflag: flag to indicate this torrent is being shutdown
+        @type protocol: C{string}
+        @param protocol: the name of the communication protocol
+        
+        """
+        
         self.info_hash = info_hash
         self.doneflag = doneflag
         self.protocol = protocol
@@ -30,10 +77,12 @@
         self.taskqueue = []
 
     def shutdown(self):
+        """Tell the collection to shutdown this torrent."""
         if not self.finished:
             self.multihandler.shutdown_torrent(self.info_hash)
 
     def _shutdown(self):
+        """Shutdown this torrent."""
         if not self.finished:
             self.finished = True
             self.running = False
@@ -43,6 +92,20 @@
 
     def _external_connection_made(self, c, options, already_read,
                                   encrypted = None ):
+        """Processes a new socket connection to this torrent.
+        
+        @type c: unknown
+        @param c: the new connection
+        @type options: unknown
+        @param options: the protocol options the connected peer supports
+        @type already_read: C{string}
+        @param already_read: the data that has already been read from the connection
+        @type encrypted: L{BTcrypto.Crypto}
+        @param encrypted: the Crypto instance to use to encrypt this connections
+            communication (optional, defaults to None)
+        
+        """
+        
         if self.running:
             c.set_handler(self.handler)
             self.handler.externally_handshaked_connection_made(
@@ -51,6 +114,17 @@
     ### RawServer functions ###
 
     def add_task(self, func, delay=0, id = default_task_id):
+        """Passes a delayed call to a method on to the master Server.
+        
+        @type func: C{method}
+        @param func: the method to call
+        @type delay: C{int}
+        @param delay: the number of seconds to delay before calling
+        @type id: C{mutable}
+        @param id: the ID of the task
+        
+        """
+        
         if id is default_task_id:
             id = self.info_hash
         if not self.finished:
@@ -60,6 +134,18 @@
 #        pass    # not handled here
         
     def start_connection(self, dns, handler = None):
+        """Tell the master Server to start a new connection to a peer.
+        
+        @type dns: (C{string}, C{int})
+        @param dns: the IP address and port number to contact the peer on
+        @type handler: unknown
+        @param handler: the data handler to use to process data on the connection
+            (optional, defaults to the L{handler})
+        @rtype: L{SocketHandler.SingleSocket}
+        @return: the new connection made to the peer
+
+        """
+        
         if not handler:
             handler = self.handler
         c = self.rawserver.start_connection(dns, handler)
@@ -69,19 +155,89 @@
 #        pass    # don't call with this
     
     def start_listening(self, handler):
+        """Start the Server listening (but not forever).
+        
+        @type handler: unknown
+        @param handler: the default handler to call when data comes in
+        @rtype: C{method}
+        @return: the method to call to shutdown the torrent download
+        
+        """
+        
         self.handler = handler
         self.running = True
         return self.shutdown    # obviously, doesn't listen forever
 
     def is_finished(self):
+        """Check if the torrent download has been shutdown.
+        
+        @rtype: C{boolean}
+        @return: whether the torrent has been shutdown
+        
+        """
+        
         return self.finished
 
     def get_exception_flag(self):
+        """Get the master Server's exception flag.
+        
+        @rtype: C{threading.Event}
+        @return: the flag used to indicate exceptions
+        
+        """
+        
         return self.rawserver.get_exception_flag()
 
 
-class NewSocketHandler:     # hand a new socket off where it belongs
+class NewSocketHandler:
+    """Read the handshake and hand a new socket connection off to where it belongs.
+    
+    This class wraps some of the functionality of the 
+    L{BT1.Encrypter.Connection} class. It will receive connections from
+    the Server, read the protocol handshake, assign them to the proper 
+    torrent server, and pass the connection on to the Encrypter Connection.
+    
+    @type multihandler: L{MultiHandler}
+    @ivar multihandler: the collection of all torrent Servers
+    @type connection: unknown
+    @ivar connection: the connection to handle
+    @type closed: C{boolean}
+    @ivar closed: whether the connection has been closed
+    @type buffer: C{string}
+    @ivar buffer: the buffer of unprocessed data received on the connection
+    @type complete: C{boolean}
+    @ivar complete: whether the handshake is complete
+    @type read: C{method}
+    @ivar read: the method to call to read data from the connection
+    @type write: C{method}
+    @ivar write: the method to call to write data to the connnection
+    @type next_len: C{int}
+    @ivar next_len: the length of the protocol name header in the connection
+    @type next_func: C{method}
+    @ivar next_func: the method to call to read the protocol name from the connection
+    @type protocol: C{string}
+    @ivar protocol: the protocol name used by the connection
+    @type encrypted: C{boolean}
+    @ivar encrypted: whether the connection is encrypted
+    @type encrypter: L{BTcrypto.Crypto}
+    @ivar encrypter: the encrypter to use for the connection
+    @type _max_search: C{int}
+    @ivar _max_search: the number of remaining bytes to search for the pattern
+    @type options: C{string}
+    @ivar options: the protocol options read from the connection
+    
+    """
+    
     def __init__(self, multihandler, connection):
+        """Initialize the instance.
+        
+        @type multihandler: L{MultiHandler}
+        @param multihandler: the collection of all torrent Servers
+        @type connection: unknown
+        @param connection: the new connection to handle
+        
+        """
+        
         self.multihandler = multihandler
         self.connection = connection
         connection.set_handler(self)
@@ -94,10 +250,12 @@
         self.multihandler.rawserver.add_task(self._auto_close, 30)
 
     def _auto_close(self):
+        """Automatically close the connection if it is not fully connected."""
         if not self.complete:
             self.close()
         
     def close(self):
+        """Close the connection."""
         if not self.closed:
             self.connection.close()
             self.closed = True
@@ -105,12 +263,32 @@
     # copied from Encrypter and modified
     
     def _read_header(self, s):
+        """Check if the protocol header matches.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{int}, C{method}
+        @return: the next length to read and method to call with the data
+            (or None if something went wrong)
+        
+        """
+        
         if s == chr(len(protocol_name))+protocol_name:
             self.protocol = protocol_name
             return 8, self.read_options
         return None
 
     def read_header(self, s):
+        """Process the (possibly encrypted) protocol header from the connection.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{int}, C{method}
+        @return: the next length to read and method to call with the data
+            (or None if something went wrong)
+        
+        """
+        
         if self._read_header(s):
             if self.multihandler.config['crypto_only']:
                 return None
@@ -123,12 +301,32 @@
         return self.encrypter.keylength, self.read_crypto_header
 
     def read_crypto_header(self, s):
+        """Start to read an encrypted header from the connection.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{int}, C{method}
+        @return: the next length to read and method to call with the data
+        
+        """
+        
         self.encrypter.received_key(s)
         self.write(self.encrypter.pubkey+self.encrypter.padding())
         self._max_search = 520
         return 0, self.read_crypto_block3a
 
     def _search_for_pattern(self, s, pat):
+        """Search for a pattern in the initial connection data.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @type pat: C{string}
+        @param pat: the data to search for
+        @rtype: C{boolean}
+        @return: whether the pattern was found
+        
+        """
+        
         p = s.find(pat)
         if p < 0:
             self._max_search -= len(s)+1-len(pat)
@@ -141,11 +339,32 @@
         return True
 
     def read_crypto_block3a(self, s):
+        """Find the block3a crypto information in the connection.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{int}, C{method}
+        @return: the next length to read and method to call with the data
+        
+        """
+        
         if not self._search_for_pattern(s,self.encrypter.block3a):
             return -1, self.read_crypto_block3a     # wait for more data
         return 20, self.read_crypto_block3b
 
     def read_crypto_block3b(self, s):
+        """Process the block3b crypto information in the connection.
+        
+        Passes the connection off to the appropriate torrent's Server if the
+        correct block is found.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{boolean}
+        @return: whether the crypto block was found
+        
+        """
+        
         for k in self.multihandler.singlerawservers.keys():
             if self.encrypter.test_skey(s,k):
                 self.multihandler.singlerawservers[k]._external_connection_made(
@@ -155,10 +374,30 @@
         return None
 
     def read_options(self, s):
+        """Process the protocol options from the connection.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{int}, C{method}
+        @return: the next length to read and method to call with the data
+        
+        """
+        
         self.options = s
         return 20, self.read_download_id
 
     def read_download_id(self, s):
+        """Read the torrent infohash from the connection.
+        
+        Passes the connection off to the appropriate torrent's Server.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{boolean}
+        @return: whether a torrent was found to assign the connection to
+        
+        """
+        
         if self.multihandler.singlerawservers.has_key(s):
             if self.multihandler.singlerawservers[s].protocol == self.protocol:
                 self.multihandler.singlerawservers[s]._external_connection_made(
@@ -168,15 +407,56 @@
 
 
     def read_dead(self, s):
+        """Do nothing.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        @rtype: C{none}
+        @return: None
+        
+        """
+        
         return None
 
     def data_came_in(self, garbage, s):
+        """Process the read data from the connection.
+        
+        @type garbage: unknown
+        @param garbage: thrown away
+        @type s: C{string}
+        @param s: the data read from the conection
+        
+        """
+        
         self.read(s)
 
     def _write_buffer(self, s):
+        """Add the read data from the connection back onto the start of the buffer.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        
+        """
+        
         self.buffer = s+self.buffer
 
     def _read(self, s):
+        """Process the data read from the connection.
+        
+        Processes incoming data on the connection. The data is bufferred, then
+        the L{next_func} method is called with the L{next_len} amount of the
+        data. If it returns None, the connection is closed. If it returns True,
+        the connection handshake is complete and the connection is established.
+        Otherwise it returns C{int},C{method}, which is the next length to read 
+        and method to call with the data. If the length is 0, it will read all
+        the available data. If the length is -1 it will wait for more data to
+        caome in.
+        
+        @type s: C{string}
+        @param s: the data read from the conection
+        
+        """
+        
         self.buffer += s
         while True:
             if self.closed:
@@ -209,13 +489,56 @@
 
 
     def connection_flushed(self, ss):
+        """Do nothing.
+        
+        @type ss: unknown
+        @param ss: the connection that was flushed
+        
+        """
+        
         pass
 
     def connection_lost(self, ss):
+        """Close the lost connection.
+        
+        @type ss: unknown
+        @param ss: the connection that was lost
+        
+        """
+        
         self.closed = True
 
 class MultiHandler:
+    """Collection of Servers/Port Handlers for multiple torrents.
+    
+    @type rawserver: L{RawServer.RawServer}
+    @ivar rawserver: the master Server
+    @type masterdoneflag: C{threading.Event}
+    @ivar masterdoneflag: the flag to indicate stopping to the master Server
+    @type config: C{dictionary}
+    @ivar config: the configuration parameters
+    @type singlerawservers: C{dictionary}
+    @ivar singlerawservers: keys are torrent infohash strings, values are 
+        individual L{SingleRawServer} for the torrents
+    @type connections: C{dictionary}
+    @ivar connections: unknown
+    @type taskqueues: C{dictionary}
+    @ivar taskqueues: unknown
+    
+    """
+    
     def __init__(self, rawserver, doneflag, config):
+        """Initialize the instance.
+        
+        @type rawserver: L{RawServer.RawServer}
+        @param rawserver: the master Server
+        @type doneflag: C{threading.Event}
+        @param doneflag: the flag to indicate stopping to the master Server
+        @type config: C{dictionary}
+        @param config: the configuration parameters
+        
+        """
+        
         self.rawserver = rawserver
         self.masterdoneflag = doneflag
         self.config = config
@@ -224,15 +547,37 @@
         self.taskqueues = {}
 
     def newRawServer(self, info_hash, doneflag, protocol=protocol_name):
+        """Create a new Server for the torrent.
+        
+        @type info_hash: C{string}
+        @param info_hash: the torrent's infohash
+        @type doneflag: C{threading.Event}
+        @param doneflag: the flag to indicate stopping to the new Server
+        @type protocol: C{string}
+        @param protocol: the name to use for the communication protocol
+            (optional, defaults to L{DebTorrent.protocol_name})
+        @rtype: L{SingleRawServer}
+        @return: the new Server that was created
+        
+        """
+        
         new = SingleRawServer(info_hash, self, doneflag, protocol)
         self.singlerawservers[info_hash] = new
         return new
 
     def shutdown_torrent(self, info_hash):
+        """Shutdown a single torrent's Server.
+        
+        @type info_hash: C{string}
+        @param info_hash: the torrent's infohash
+
+        """
+        
         self.singlerawservers[info_hash]._shutdown()
         del self.singlerawservers[info_hash]
 
     def listen_forever(self):
+        """Call the master server's listen loop."""
         self.rawserver.listen_forever(self)
         for srs in self.singlerawservers.values():
             srs.finished = True
@@ -243,4 +588,11 @@
     # be wary of name collisions
 
     def external_connection_made(self, ss):
+        """Handle a new incoming connection from the master Server.
+        
+        @type ss: unknown
+        @param ss: unknown
+        
+        """
+        
         NewSocketHandler(self, ss)

Modified: debtorrent/branches/http-listen/DebTorrent/__init__.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/branches/http-listen/DebTorrent/__init__.py?rev=96&op=diff
==============================================================================
--- debtorrent/branches/http-listen/DebTorrent/__init__.py (original)
+++ debtorrent/branches/http-listen/DebTorrent/__init__.py Mon Jun 11 07:05:55 2007
@@ -3,7 +3,7 @@
 #
 # $Id$
 
-"""The main package to implement the debtorrent protocol.
+"""The main package to implement the DebTorrent protocol.
 
 This package, and it's subpackage L{BT1}, contains all the modules needed
 to implement the DebTorrent protocol.
@@ -12,6 +12,10 @@
 @var product_name: the name given for the package
 @type version_short: C{string}
 @var version_short: the short version number
+ at type protocol_name: C{string}
+ at var protocol_name: the protocol name to use in handshaking
+ at type mapbase64: C{string}
+ at var mapbase64: the mapping from 64 bit numbers to string characters
 
 """
 
@@ -45,6 +49,7 @@
 _idrandom = [None]
 
 def resetPeerIDs():
+    """Reset the generation of peer IDs before generating a new random one."""
     try:
         f = open('/dev/urandom','rb')
         x = f.read(20)
@@ -77,6 +82,17 @@
 resetPeerIDs()
 
 def createPeerID(ins = '---'):
+    """Generate a somewhat random peer ID
+    
+    @type ins: C{string}
+    @param ins: the length 3 string to insert in the middle of the peer ID
+        between the prefix and the random part of the ID
+        (optional, defaults to '---')
+    @rtype: C{string}
+    @return: the peer ID to use
+    
+    """
+    
     assert type(ins) is StringType
     assert len(ins) == 3
     return _idprefix + ins + _idrandom[0]

Modified: debtorrent/branches/http-listen/DebTorrent/launchmanycore.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/branches/http-listen/DebTorrent/launchmanycore.py?rev=96&op=diff
==============================================================================
--- debtorrent/branches/http-listen/DebTorrent/launchmanycore.py (original)
+++ debtorrent/branches/http-listen/DebTorrent/launchmanycore.py Mon Jun 11 07:05:55 2007
@@ -1,10 +1,12 @@
 #!/usr/bin/env python
-
+#
 # Written by John Hoffman
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Manage the downloading of multiple torrents in one process."""
 
 from DebTorrent import PSYCO
 if PSYCO.psyco:
@@ -41,6 +43,18 @@
 
 
 def fmttime(n):
+    """Formats seconds into a human-readable time.
+    
+    Formats a given number of seconds into a human-readable time appropriate
+    for display to the user.
+    
+    @type n: C{int}
+    @param n: the number of seconds
+    @rtype: C{string}
+    @return: a displayable representation of the number of seconds
+    
+    """
+    
     try:
         n = int(n)  # n may be None or too large
         assert n < 5184000  # 60 days
@@ -51,7 +65,63 @@
     return '%d:%02d:%02d' % (h, m, s)
 
 class SingleDownload:
+    """Manage a single torrent download.
+    
+    @type controller: L{LaunchMany}
+    @ivar controller: the manager for all torrent downloads
+    @type hash: C{string}
+    @ivar hash: the info hash of the torrent
+    @type response: C{dictionary}
+    @ivar response: the meta info for the torrent
+    @type config: C{dictionary}
+    @ivar config: the configuration parameters
+    @type doneflag: C{threading.Event}
+    @ivar doneflag: the flag that indicates when the torrent is to be shutdown
+    @type waiting: C{boolean}
+    @ivar waiting: unknown
+    @type checking: C{boolean}
+    @ivar checking: unknown
+    @type working: C{boolean}
+    @ivar working: unknown
+    @type seed: C{boolean}
+    @ivar seed: unknown
+    @type closed: C{boolean}
+    @ivar closed: unknown
+    @type status_msg: C{string}
+    @ivar status_msg: the current activity the torrent is engaged in
+    @type status_err: C{list} of C{string}
+    @ivar status_err: the list of errors that have occurred
+    @type status_errtime: C{int}
+    @ivar status_errtime: the time of the last error
+    @type status_done: C{float}
+    @ivar status_done: the fraction of the current activity that is complete
+    @type rawserver: L{ServerPortHandler.SingleRawServer}
+    @ivar rawserver: the simplified Server to use to handle this torrent
+    @type d: L{download_bt1.BT1Download}
+    @ivar d: the downloader for the torrent
+    @type _hashcheckfunc: C{method}
+    @ivar _hashcheckfunc: the method to call to hash check the torrent
+    @type statsfunc: C{method}
+    @ivar statsfunc: the method to call to get the statistics for the running download
+    
+    """
+    
     def __init__(self, controller, hash, response, config, myid):
+        """Initialize the instance and start a new downloader.
+        
+        @type controller: L{LaunchMany}
+        @param controller: the manager for all torrent downloads
+        @type hash: C{string}
+        @param hash: the info hash of the torrent
+        @type response: C{dictionary}
+        @param response: the meta info for the torrent
+        @type config: C{dictionary}
+        @param config: the configuration parameters
+        @type myid: C{string}
+        @param myid: the peer ID to use
+        
+        """
+        
         self.controller = controller
         self.hash = hash
         self.response = response
@@ -77,6 +147,7 @@
         self.d = d
 
     def start(self):
+        """Initialize the new torrent download and schedule it for hash checking."""
         if not self.d.saveAs(self.saveAs):
             self._shutdown()
             return
@@ -88,9 +159,31 @@
 
 
     def saveAs(self, name, length, saveas, isdir):
+        """Determine the location to save the torrent in.
+        
+        @type name: C{string}
+        @param name: the name from the torrent's metainfo
+        @type length: C{long}
+        @param length: the total length of the torrent download (not used)
+        @type saveas: C{string}
+        @param saveas: the user specified location to save to
+        @type isdir: C{boolean}
+        @param isdir: whether the torrent needs a directory
+        @rtype: C{string}
+        @return: the location to save the torrent in
+        
+        """
+        
         return self.controller.saveAs(self.hash, name, saveas, isdir)
 
     def hashcheck_start(self, donefunc):
+        """Start the hash checking of the torrent.
+        
+        @type donefunc: C{method}
+        @param donefunc: the method to call when the hash checking is complete
+        
+        """
+        
         if self.is_dead():
             self._shutdown()
             return
@@ -99,6 +192,7 @@
         self._hashcheckfunc(donefunc)
 
     def hashcheck_callback(self):
+        """Start the torrent running now that hash checking is complete."""
         self.checking = False
         if self.is_dead():
             self._shutdown()
@@ -112,12 +206,27 @@
         self.working = True
 
     def is_dead(self):
+        """Check if the torrent download has been shutdown.
+        
+        @rtype: C{boolean}
+        @return: whether the torrent download has been shutdown
+        
+        """
+        
         return self.doneflag.isSet()
 
     def _shutdown(self):
+        """Loudly shutdown the running torrent."""
         self.shutdown(False)
 
     def shutdown(self, quiet=True):
+        """Shutdown the running torrent.
+        
+        @type quiet: C{boolean}
+        @param quiet: whether to announce the shutdown (optional, defaults to True)
+        
+        """
+        
         if self.closed:
             return
         self.doneflag.set()
@@ -134,16 +243,36 @@
             
 
     def display(self, activity = None, fractionDone = None):
-        # really only used by StorageWrapper now
+        """Update the current activity's status for later display.
+        
+        Really only used by StorageWrapper now.
+        
+        @type activity: C{string}
+        @param activity: the activity currently under way 
+            (optional, defaults to not changing the current activity)
+        @type fractionDone: C{float}
+        @param fractionDone: the fraction of the activity that is complete
+            (optional, defaults to not changing the current fraction done)
+        
+        """
+        
         if activity:
             self.status_msg = activity
         if fractionDone is not None:
             self.status_done = float(fractionDone)
 
     def finished(self):
+        """Indicate that the download has completed."""
         self.seed = True
 
     def error(self, msg):
+        """Add a new error to the list of errors that have occurred.
+        
+        @type msg: C{string}
+        @param msg: the error message
+        
+        """
+        
         if self.doneflag.isSet():
             self._shutdown()
         self.status_err.append(msg)
@@ -151,7 +280,59 @@
 
 
 class LaunchMany:
+    """Manage the collection of all single torrent downloads.
+    
+    @type config: C{dictionary}
+    @ivar config: the configuration parameters
+    @type Output: unknown
+    @ivar Output: the displayer instance to use
+    @type torrent_dir: C{string}
+    @ivar torrent_dir: the directory to parse for torrent files
+    @type torrent_cache: C{dictionary}
+    @ivar torrent_cache: the cache of known torrents, keys are info hashes
+    @type file_cache: C{dictionary}
+    @ivar file_cache: the files found in the parsing of the torrent directory
+    @type blocked_files: C{dictionary}
+    @ivar blocked_files: the torrents in the torrent directory that will not be run
+    @type scan_period: C{int}
+    @ivar scan_period: the number of seconds between scans of L{torrent_dir}
+    @type stats_period: C{int}
+    @ivar stats_period: the number of seconds between printing the stats for the user
+    @type torrent_list: C{list} of C{string}
+    @ivar torrent_list: the list of known torrents' info hashes
+    @type downloads: C{dictionary}
+    @ivar downloads: the currently running downloaders, keys are info hashes
+    @type counter: C{int}
+    @ivar counter: the number of torrents that have been started so far
+    @type doneflag: C{threading.Event}
+    @ivar doneflag: flag to indicate all is to be stopped
+    @type hashcheck_queue: C{list} of C{string}
+    @ivar hashcheck_queue: the list of torrent info hashes waiting to be hash checked
+    @type hashcheck_current: C{string}
+    @ivar hashcheck_current: the info hash of the torrent currently being hash checked
+    @type rawserver: L{RawServer.RawServer}
+    @ivar rawserver: the Server instance to use for the downloads
+    @type listen_port: C{int}
+    @ivar listen_port: the port to listen on for incoming torrent connections
+    @type aptlistener: L{BT1.AptListener.AptListener}
+    @ivar aptlistener: the AptListener instance used to listen for incoming connections from Apt
+    @type ratelimiter: L{RateLimiter.RateLimiter}
+    @ivar ratelimiter: the limiter used to cap the maximum upload rate
+    @type handler: L{ServerPortHandler.MultiHandler}
+    @ivar handler: the multi torrent port listener used to handle connections
+    
+    """
+    
     def __init__(self, config, Output):
+        """Initialize the instance.
+        
+        @type config: C{dictionary}
+        @param config: the configuration parameters
+        @type Output: unknown
+        @param Output: the displayer instance to use
+        
+        """
+        
         try:
             self.config = config
             self.Output = Output
@@ -222,6 +403,7 @@
 
 
     def scan(self):
+        """Scan the torrent directory for changes."""
         self.rawserver.add_task(self.scan, self.scan_period)
                                 
         r = parsedir(self.torrent_dir, self.torrent_cache,
@@ -238,7 +420,8 @@
             self.Output.message('added "'+data['path']+'"')
             self.add(hash, data)
 
-    def stats(self):            
+    def stats(self):
+        """Call the Output display with the currently running torrents' statistics."""
         self.rawserver.add_task(self.stats, self.stats_period)
         data = []
         for hash in self.torrent_list:
@@ -305,11 +488,27 @@
             self.doneflag.set()
 
     def remove(self, hash):
+        """Stop and remove a running torrent.
+        
+        @type hash: C{string}
+        @param hash: the info hash of the torrent
+        
+        """
+        
         self.torrent_list.remove(hash)
         self.downloads[hash].shutdown()
         del self.downloads[hash]
         
     def add(self, hash, data):
+        """Start a new torrent running.
+        
+        @type hash: C{string}
+        @param hash: the info hash of the torrent
+        @type data: C{dictionary}
+        @param data: various info about the torrent, including the metainfo
+        
+        """
+        
         c = self.counter
         self.counter += 1
         x = ''
@@ -324,6 +523,21 @@
 
 
     def saveAs(self, hash, name, saveas, isdir):
+        """Determine the location to save the torrent in.
+        
+        @type hash: C{string}
+        @param hash: the info hash of the torrent
+        @type name: C{string}
+        @param name: the name from the torrent's metainfo
+        @type saveas: C{string}
+        @param saveas: the user specified location to save to
+        @type isdir: C{boolean}
+        @param isdir: whether the torrent needs a directory
+        @rtype: C{string}
+        @return: the location to save the torrent in
+        
+        """
+        
         x = self.torrent_cache[hash]
         style = self.config['saveas_style']
         if style == 1 or style == 3:
@@ -356,16 +570,26 @@
 
 
     def hashchecksched(self, hash = None):
+        """Schedule a new torrent for hash checking.
+        
+        @type hash: C{string}
+        @param hash: the info hash of the torrent to schedule 
+            (optional, default is to start the next torrent in the queue)
+        
+        """
+        
         if hash:
             self.hashcheck_queue.append(hash)
         if not self.hashcheck_current:
             self._hashcheck_start()
 
     def _hashcheck_start(self):
+        """Start hash checking the next torrent in the queue."""
         self.hashcheck_current = self.hashcheck_queue.pop(0)
         self.downloads[self.hashcheck_current].hashcheck_start(self.hashcheck_callback)
 
     def hashcheck_callback(self):
+        """Start another torrent's hash check now that the current one is complete."""
         self.downloads[self.hashcheck_current].hashcheck_callback()
         if self.hashcheck_queue:
             self._hashcheck_start()
@@ -373,10 +597,24 @@
             self.hashcheck_current = None
 
     def died(self, hash):
+        """Inform the Output that the torrent has died.
+        
+        @type hash: C{string}
+        @param hash: the info hash of the torrent
+        
+        """
+        
         if self.torrent_cache.has_key(hash):
             self.Output.message('DIED: "'+self.torrent_cache[hash]['path']+'"')
         
     def was_stopped(self, hash):
+        """Remove the torrent from the hash check queue, even if it's already happening.
+        
+        @type hash: C{string}
+        @param hash: the info hash of the torrent
+        
+        """
+        
         try:
             self.hashcheck_queue.remove(hash)
         except:
@@ -387,7 +625,21 @@
                 self._hashcheck_start()
 
     def failed(self, s):
+        """Indicate to the Output that a failure has occurred.
+        
+        @type s: C{string}
+        @param s: the failure message
+        
+        """
+        
         self.Output.message('FAILURE: '+s)
 
     def exchandler(self, s):
+        """Indicate to the Output that an exception has occurred.
+        
+        @type s: C{string}
+        @param s: the exception that occurred
+        
+        """
+        
         self.Output.exception(s)




More information about the Debtorrent-commits mailing list