r114 - in /debtorrent/trunk/DebTorrent: BT1/AptListener.py BT1/Connecter.py HTTPCache.py HTTPHandler.py PSYCO.py RateLimiter.py iprangeparse.py natpunch.py parseargs.py parsedir.py piecebuffer.py

camrdale-guest at users.alioth.debian.org camrdale-guest at users.alioth.debian.org
Sun Jun 17 04:35:51 UTC 2007


Author: camrdale-guest
Date: Sun Jun 17 04:35:50 2007
New Revision: 114

URL: http://svn.debian.org/wsvn/debtorrent/?sc=1&rev=114
Log:
More documentation.

Modified:
    debtorrent/trunk/DebTorrent/BT1/AptListener.py
    debtorrent/trunk/DebTorrent/BT1/Connecter.py
    debtorrent/trunk/DebTorrent/HTTPCache.py
    debtorrent/trunk/DebTorrent/HTTPHandler.py
    debtorrent/trunk/DebTorrent/PSYCO.py
    debtorrent/trunk/DebTorrent/RateLimiter.py
    debtorrent/trunk/DebTorrent/iprangeparse.py
    debtorrent/trunk/DebTorrent/natpunch.py
    debtorrent/trunk/DebTorrent/parseargs.py
    debtorrent/trunk/DebTorrent/parsedir.py
    debtorrent/trunk/DebTorrent/piecebuffer.py

Modified: debtorrent/trunk/DebTorrent/BT1/AptListener.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/BT1/AptListener.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/BT1/AptListener.py (original)
+++ debtorrent/trunk/DebTorrent/BT1/AptListener.py Sun Jun 17 04:35:50 2007
@@ -527,8 +527,6 @@
         
         @type path: C{list} of C{string}
         @param path: the path of the file to download, starting with the mirror name
-        @type data: C{string}
-        @param data: the downloaded newly cached file
         @type r: (C{int}, C{string}, C{dictionary}, C{string})
         @param r: the HTTP status code, status message, headers, and cached data
         

Modified: debtorrent/trunk/DebTorrent/BT1/Connecter.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/BT1/Connecter.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/BT1/Connecter.py (original)
+++ debtorrent/trunk/DebTorrent/BT1/Connecter.py Sun Jun 17 04:35:50 2007
@@ -104,7 +104,7 @@
     @ivar download: the Downloader instance to use for the connection
     @type send_choke_queued: C{boolean}
     @ivar send_choke_queued: whether to suppress the next L{CHOKE} message
-    @type just_unchoked: C{long}
+    @type just_unchoked: C{int}
     @ivar just_unchoked: the time of a recent L{UNCHOKE}, if it was the first
     
     """

Modified: debtorrent/trunk/DebTorrent/HTTPCache.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/HTTPCache.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/HTTPCache.py (original)
+++ debtorrent/trunk/DebTorrent/HTTPCache.py Sun Jun 17 04:35:50 2007
@@ -57,7 +57,7 @@
     @type connection_status: C{int}
     @ivar connection_status: the status code returned by the server
     @type connection_response: C{string}
-    @ivar connection_status: the status message returned by the server
+    @ivar connection_response: the status message returned by the server
     
     """
     

Modified: debtorrent/trunk/DebTorrent/HTTPHandler.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/HTTPHandler.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/HTTPHandler.py (original)
+++ debtorrent/trunk/DebTorrent/HTTPHandler.py Sun Jun 17 04:35:50 2007
@@ -1,8 +1,19 @@
 # Written by Bram Cohen
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Handles incoming HTTP connections from other clients to this server.
+
+ at type DEBUG: C{boolean}
+ at var DEBUG: whether to print debugging messages
+ at type weekdays: C{list} of C{string}
+ at var weekdays: the days of the week
+ at type months: C{list} of C{string}
+ at var months: the months of the year
+
+"""
 
 from cStringIO import StringIO
 from sys import stdout
@@ -23,7 +34,47 @@
     'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
 
 class HTTPConnection:
+    """A single connection from an HTTP client.
+    
+    Handles a single HTTP GET or HEAD request from a client using HTTP/1.0.
+    
+    @type handler: L{HTTPHandler}
+    @ivar handler: the handler for all incoming HTTP connections
+    @type connection: unknown
+    @ivar connection: the new connection that was created
+    @type buf: C{string}
+    @ivar buf: unknown
+    @type closed: C{boolean}
+    @ivar closed: unknown
+    @type done: C{boolean}
+    @ivar done: unknown
+    @type donereading: C{boolean}
+    @ivar donereading: unknown
+    @type next_func: C{method}
+    @ivar next_func: the next method to call to process data on this connection
+    @type header: unknown
+    @ivar header: unknown
+    @type command: unknown
+    @ivar command: unknown
+    @type pre1: unknown
+    @ivar pre1: unknown
+    @type headers: unknown
+    @ivar headers: unknown
+    @type encoding: unknown
+    @ivar encoding: unknown
+    
+    """
+    
     def __init__(self, handler, connection):
+        """Initialize the instance.
+        
+        @type handler: L{HTTPHandler}
+        @param handler: the handler for all incoming HTTP connections
+        @type connection: unknown
+        @param connection: the new connection that was created
+        
+        """
+        
         self.handler = handler
         self.connection = connection
         self.buf = ''
@@ -33,9 +84,28 @@
         self.next_func = self.read_type
 
     def get_ip(self):
+        """Get the IP address of the connection.
+        
+        @rtype: C{string}
+        @return: the IP address
+        
+        """
+        
         return self.connection.get_ip()
 
     def data_came_in(self, data):
+        """Process data that came in on the connection.
+        
+        Processes the request lines one at a time by calling the L{next_func}
+        method with the lines.
+        
+        @type data: C{string}
+        @param data: the data that came in
+        @rtype: C{boolean}
+        @return: whether to keep the connection open
+        
+        """
+        
         if self.donereading or self.next_func is None:
             return True
         self.buf += data
@@ -53,6 +123,15 @@
                 return False
 
     def read_type(self, data):
+        """Process the first header line that came in.
+        
+        @type data: C{string}
+        @param data: the line that came in
+        @rtype: C{method}
+        @return: the next method to call to process data on this connection
+        
+        """
+        
         self.header = data.strip()
         words = data.split()
         if len(words) == 3:
@@ -71,6 +150,15 @@
         return self.read_header
 
     def read_header(self, data):
+        """Process the next header line that came in.
+        
+        @type data: C{string}
+        @param data: the line that came in
+        @rtype: C{method}
+        @return: the next method to call to process data on this connection
+        
+        """
+        
         data = data.strip()
         if data == '':
             self.donereading = True
@@ -92,6 +180,19 @@
         return self.read_header
 
     def answer(self, (responsecode, responsestring, headers, data)):
+        """Send a response to the client on the connection and close it.
+        
+        @type responsecode: C{int}
+        @param responsecode: the response code to send
+        @type responsestring: C{string}
+        @param responsestring: the response string to send
+        @type headers: C{dictionary}
+        @param headers: the headers to send with the response
+        @type data: C{string}
+        @param data: the data to send with the response
+        
+        """
+        
         if self.closed:
             return
         if self.encoding == 'gzip':
@@ -133,20 +234,64 @@
             self.connection.shutdown(1)
 
 class HTTPHandler:
+    """The handler for all new and existing HTTP connections.
+    
+    @type connections: C{dictionary}
+    @ivar connections: all the existing connections, keys are the connection 
+        objects, values are the L{HTTPConnection} objects
+    @type getfunc: C{method}
+    @ivar getfunc: the method to call with the processed GET requests
+    @type minflush: C{float}
+    @ivar minflush: the minimum amount of time between flushing the log
+    @type lastflush: C{float}
+    @ivar lastflush: the time of the last log flush
+    
+    """
+    
     def __init__(self, getfunc, minflush):
+        """Initialize the instance.
+        
+        @type getfunc: C{method}
+        @param getfunc: the method to call with the processed GET requests
+        @type minflush: C{float}
+        @param minflush: the minimum amount of time between flushing the log
+        
+        """
+        
         self.connections = {}
         self.getfunc = getfunc
         self.minflush = minflush
         self.lastflush = clock()
 
     def external_connection_made(self, connection):
+        """Create a new HTTPConnection object.
+        
+        @type connection: unknown
+        @param connection: the connection
+        
+        """
+        
         self.connections[connection] = HTTPConnection(self, connection)
 
     def connection_flushed(self, connection):
+        """Flush a connection.
+        
+        @type connection: unknown
+        @param connection: the connection
+        
+        """
+        
         if self.connections[connection].done:
             connection.shutdown(1)
 
     def connection_lost(self, connection):
+        """Remove the lost connection from the existing ones.
+        
+        @type connection: unknown
+        @param connection: the connection
+        
+        """
+        
         ec = self.connections[connection]
         ec.closed = True
         del ec.connection
@@ -154,12 +299,42 @@
         del self.connections[connection]
 
     def data_came_in(self, connection, data):
+        """Process incoming data on an existing connection.
+        
+        @type connection: unknown
+        @param connection: the connection
+        @type data: C{string}
+        @param data: the data that came in
+        
+        """
+        
         c = self.connections[connection]
         if not c.data_came_in(data) and not c.closed:
             c.connection.shutdown(1)
 
     def log(self, ip, ident, username, header,
             responsecode, length, referrer, useragent):
+        """Print a log message.
+        
+        @type ip: C{string}
+        @param ip: the IP address of the connection
+        @type ident: C{string}
+        @param ident: the type of connection
+        @type username: C{string}
+        @param username: unknown
+        @type header: C{string}
+        @param header: the first header line of the request
+        @type responsecode: C{int}
+        @param responsecode: the HTTP status code of the response
+        @type length: C{int}
+        @param length: the number of bytes in the data returned
+        @type referrer: C{string}
+        @param referrer: the referer for the incoming request
+        @type useragent: C{string}
+        @param useragent: the client's useragent used to make the request
+        
+        """
+        
         year, month, day, hour, minute, second, a, b, c = time.localtime(time.time())
         print '%s %s %s [%02d/%3s/%04d:%02d:%02d:%02d] "%s" %i %i "%s" "%s"' % (
             ip, ident, username, day, months[month], year, hour,

Modified: debtorrent/trunk/DebTorrent/PSYCO.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/PSYCO.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/PSYCO.py (original)
+++ debtorrent/trunk/DebTorrent/PSYCO.py Sun Jun 17 04:35:50 2007
@@ -1,10 +1,19 @@
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
 
-# edit this file to enable/disable Psyco
-# psyco = 1 -- enabled
-# psyco = 0 -- disabled
+"""Whether to use the Psyco extension module.
+
+Edit this file to enable/disable the use of the Psyco extension module to 
+speed up the execution of the code.
+
+1 => enabled
+0 => disabled
+
+ at type psyco: C{int}
+ at var psyco: whether to use the Psyco extension module
+
+"""
 
 psyco = 0

Modified: debtorrent/trunk/DebTorrent/RateLimiter.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/RateLimiter.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/RateLimiter.py (original)
+++ debtorrent/trunk/DebTorrent/RateLimiter.py Sun Jun 17 04:35:50 2007
@@ -1,8 +1,43 @@
 # Written by Bram Cohen
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Limit the upload rate.
+
+ at type DEBUG: C{boolean}
+ at var DEBUG: whether to print debugging messages
+ at type MAX_RATE_PERIOD: C{float}
+ at var MAX_RATE_PERIOD: unknown
+ at type MAX_RATE: C{float}
+ at var MAX_RATE: the (very large) limit to use to not limit the upload rate
+ at type PING_BOUNDARY: C{int}
+ at var PING_BOUNDARY: unknown
+ at type PING_SAMPLES: C{int}
+ at var PING_SAMPLES: unknown
+ at type PING_DISCARDS: C{int}
+ at var PING_DISCARDS: unknown
+ at type PING_THRESHHOLD: C{int}
+ at var PING_THRESHHOLD: unknown
+ at type PING_DELAY: C{int}
+ at var PING_DELAY: unknown
+ at type PING_DELAY_NEXT: C{int}
+ at var PING_DELAY_NEXT: unknown
+ at type ADJUST_UP: C{float}
+ at var ADJUST_UP: unknown
+ at type ADJUST_DOWN: C{float}
+ at var ADJUST_DOWN: unknown
+ at type UP_DELAY_FIRST: C{int}
+ at var UP_DELAY_FIRST: unknown
+ at type UP_DELAY_NEXT: C{int}
+ at var UP_DELAY_NEXT: unknown
+ at type SLOTS_STARTING: C{int}
+ at var SLOTS_STARTING: unknown
+ at type SLOTS_FACTOR: C{float}
+ at var SLOTS_FACTOR: unknown
+
+"""
 
 from traceback import print_exc
 from binascii import b2a_hex
@@ -39,7 +74,48 @@
 SLOTS_FACTOR = 1.66/1000
 
 class RateLimiter:
+    """Limit the upload rate.
+    
+    @type sched: C{method}
+    @ivar sched: the method to call to schedule a task with the server
+    @type last: L{BT1.Connecter.Connection}
+    @ivar last: the last connection on the circular queue of connections to send on
+    @type unitsize: unknown
+    @ivar unitsize: unknown
+    @type slotsfunc: C{method}
+    @ivar slotsfunc: the method to call to set the number of connections limits
+    @type measure: L{CurrentRateMeasure.Measure}
+    @ivar measure: the measurer to use to help calculate the upload rate
+    @type autoadjust: C{boolean}
+    @ivar autoadjust: whether the upload limit is being automatically adjusted
+    @type upload_rate: C{float}
+    @ivar upload_rate: the maximum upload rate to limit to
+    @type slots: C{int}
+    @ivar slots: the number of upload slots to use (for automatic adjustment)
+    @type autoadjustup: C{int}
+    @ivar autoadjustup: unknown
+    @type pings: unknown
+    @ivar pings: unknown
+    @type lasttime: unknown
+    @ivar lasttime: unknown
+    @type bytes_sent: C{int}
+    @ivar bytes_sent: the number of bytes sent on the most recent attempt
+    
+    """
+    
     def __init__(self, sched, unitsize, slotsfunc = lambda x: None):
+        """Initialize the instance.
+        
+        @type sched: C{method}
+        @param sched: the method to call to schedule a task with the server
+        @type unitsize: unknown
+        @param unitsize: unknown
+        @type slotsfunc: C{method}
+        @param slotsfunc: the method to call to set the number of connections limits
+            (optional, defaults to not setting anything)
+        
+        """
+        
         self.sched = sched
         self.last = None
         self.unitsize = unitsize
@@ -50,7 +126,13 @@
         self.slots = SLOTS_STARTING    # garbage if not automatic
 
     def set_upload_rate(self, rate):
-        # rate = -1 # test automatic
+        """Set the upload rate to limit to.
+        
+        @type rate: C{float}
+        @param rate: maximum KB/s to upload at (0 = no limit, -1 = automatic)
+        
+        """
+        
         if rate < 0:
             if self.autoadjust:
                 return
@@ -69,6 +151,18 @@
         self.bytes_sent = 0
 
     def queue(self, conn):
+        """Queue the connection for later uploading.
+        
+        The queue is actually stored in the L{BT1.Connecter.Connection} objects
+        using their next_upload instance variable, and is circular.
+        
+        If the queue is empty, this will start the queue processer.
+        
+        @type conn: L{BT1.Connecter.Connection}
+        @param conn: the connection to add to the queue for uploading to
+        
+        """
+        
         assert conn.next_upload is None
         if self.last is None:
             self.last = conn
@@ -80,18 +174,33 @@
             self.last = conn
 
     def try_send(self, check_time = False):
+        """Loop through the circular queue of upload connections, trying to send on each.
+        
+        @type check_time: C{boolean}
+        @param check_time: unknown
+        
+        """
+        
         t = clock()
         self.bytes_sent -= (t - self.lasttime) * self.upload_rate
         self.lasttime = t
         if check_time:
             self.bytes_sent = max(self.bytes_sent, 0)
+            
+        # Get the first connection (the next one after the last one)
         cur = self.last.next_upload
+        
+        # Loop until some data has been sent (or the queue is empty)
         while self.bytes_sent <= 0:
+            # Try sending bytes on it
             bytes = cur.send_partial(self.unitsize)
             self.bytes_sent += bytes
             self.measure.update_rate(bytes)
+            
+            # If nothing could be sent, remove the connection from the queue
             if bytes == 0 or cur.backlogged():
                 if self.last is cur:
+                    # If this is the only connection in the queue, stop the processer
                     self.last = None
                     cur.next_upload = None
                     break
@@ -100,17 +209,33 @@
                     cur.next_upload = None
                     cur = self.last.next_upload
             else:
+                # Go to the next connection
                 self.last = cur
                 cur = cur.next_upload
         else:
+            # The queue is not empty, so schedule a future attempt to send
             self.sched(self.try_send, self.bytes_sent / self.upload_rate)
 
     def adjust_sent(self, bytes):
+        """Add data from other places to this measure.
+        
+        @type bytes: C{int}
+        @param bytes: the amount of data that was sent/received
+        
+        """
+        
         self.bytes_sent = min(self.bytes_sent+bytes, self.upload_rate*3)
         self.measure.update_rate(bytes)
 
 
     def ping(self, delay):
+        """Use the new ping time to calculate an automatically adjusted upload limit.
+        
+        @type delay: C{float}
+        @param delay: the elapsed time between unchoking and receiving a request
+        
+        """
+        
         if DEBUG:
             print 'ping delay:', delay
         if not self.autoadjust:
@@ -150,7 +275,3 @@
             self.lasttime = clock()
             self.bytes_sent = 0
             self.autoadjustup = UP_DELAY_NEXT
-
-
-
-

Modified: debtorrent/trunk/DebTorrent/iprangeparse.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/iprangeparse.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/iprangeparse.py (original)
+++ debtorrent/trunk/DebTorrent/iprangeparse.py Sun Jun 17 04:35:50 2007
@@ -1,8 +1,16 @@
 # Written by John Hoffman
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Deal with all types of IP addresses and IP address ranges.
+
+ at type ipv4addrmask: C{long}
+ at var ipv4addrmask: the address mask used to determine if the IP address 
+    in C{long} format is v4 encapsulated in a v6 address
+
+"""
 
 from bisect import bisect, insort
 
@@ -15,6 +23,16 @@
 
 
 def to_long_ipv4(ip):
+    """Convert an IP address from a string to a long.
+    
+    @type ip: C{string}
+    @param ip: the IP address
+    @rtype: C{long}
+    @return: the same IP address
+    @raises ValueError: if the input IP address is poorly formatted
+    
+    """
+    
     ip = ip.split('.')
     if len(ip) != 4:
         raise ValueError, "bad address"
@@ -26,6 +44,16 @@
 
 
 def to_long_ipv6(ip):
+    """Convert an IPv6 address from a string to a long.
+    
+    @type ip: C{string}
+    @param ip: the IPv6 address
+    @rtype: C{long}
+    @return: the same IPv6 address
+    @raises ValueError: if the input IPv6 address is poorly formatted
+    
+    """
+    
     if ip == '':
         raise ValueError, "bad address"
     if ip == '::':      # boundary handling
@@ -71,7 +99,30 @@
 ipv4addrmask = 65535L*256*256*256*256
 
 class IP_List:
+    """Stores mutltiple IP address ranges.
+    
+    @type ipv4list: C{list} of C{long}
+    @ivar ipv4list: the starting IP addresses of the ranges
+    @type ipv4dict: C{dictionary} of {C{long}: C{long}}
+    @ivar ipv4dict: the IP address ranges, keys are the starting 
+        IP addresses, values are the ends of the IP address ranges
+    @type ipv6list: C{list} of C{long}
+    @ivar ipv6list: the starting IPv6 addresses of the ranges
+    @type ipv6dict: C{dictionary} of {C{long}: C{long}}
+    @ivar ipv6dict: the IPv6 address ranges, keys are the starting 
+        IPv6 addresses, values are the ends of the IPv6 address ranges
+    
+    """
+    
     def __init__(self, entrylist=None):
+        """Initialize the instance.
+        
+        @type entrylist: C{list} of (C{string}, C{string})
+        @param entrylist: the IP address ranges to start with
+            (optional, defaults to None)
+        
+        """
+        
         self.ipv4list = []  # starts of ranges
         self.ipv4dict = {}  # start: end of ranges
         self.ipv6list = []  # "
@@ -100,10 +151,27 @@
             self._import_ipv6(l6)
 
     def __nonzero__(self):
+        """Check whether there are any IP address ranges stored.
+        
+        @rtype: C{boolean}
+        @return: whether there are IP address ranges stored
+        
+        """
+        
         return bool(self.ipv4list or self.ipv6list)
 
 
     def append(self, ip_beg, ip_end = None):
+        """Add a new IP address range.
+        
+        @type ip_beg: C{string}
+        @param ip_beg: the beginning IP address for the range
+        @type ip_end: C{string}
+        @param ip_end: the neding Ip address for the range
+            (optional, defaults to the beginning IP address)
+        
+        """
+        
         if ip_end is None:
             ip_end = ip_beg
         else:
@@ -151,7 +219,14 @@
         d[ip_beg] = ip_end
 
 
-    def _import_ipv4(self, entrylist):  #entrylist = sorted list of pairs of ipv4s converted to longs
+    def _import_ipv4(self, entrylist):
+        """Initialize an empty IPv4 storage with IPv4 address ranges.
+        
+        @type entrylist: C{list} of (C{long}, C{long})
+        @param entrylist: the IPv4 address ranges to start with
+        
+        """
+        
         assert not self.ipv4list
         if not entrylist:
             return
@@ -170,7 +245,14 @@
         for b,e in l:
             self.ipv4dict[b] = e
 
-    def _import_ipv6(self, entrylist):  #entrylist = sorted list of pairs of ipv6s converted to longs
+    def _import_ipv6(self, entrylist):
+        """Initialize an empty IPv6 storage with IPv6 address ranges.
+        
+        @type entrylist: C{list} of (C{long}, C{long})
+        @param entrylist: the IPv6 address ranges to start with
+        
+        """
+        
         assert not self.ipv6list
         if not entrylist:
             return
@@ -191,6 +273,15 @@
 
 
     def includes(self, ip):
+        """Determine whether the IP address is included in any of the ranges.
+        
+        @type ip: C{string}
+        @param ip: the IP address to check
+        @rtype: C{boolean}
+        @return: whether the IP address is in one of the ranges
+       
+        """
+        
         if not (self.ipv4list or self.ipv6list):
             return False
         if ip.find(':') < 0:        # IPv4
@@ -215,10 +306,20 @@
                 return True
         return False
 
-
-    # reads a list from a file in the format 'whatever:whatever:ip-ip'
-    # (not IPv6 compatible at all)
     def read_rangelist(self, file):
+        """Parse a file for lists of IPv4 address ranges to initialize the empty storage with.
+        
+        The file to parse must have lines in the format 'whatever:whatever:ip-ip'.
+        The 'whatever' will be ignored, and the IP addresses must be in IPv4 
+        format. If the rang is only a single IP address, omit the '-' and the 
+        second 'ip'. Empty lines will be ignored, as will lines beginning with
+        '#' which can be used for comments.
+        
+        @type file: C{string}
+        @param file: the name of the file to parse
+        
+        """
+        
         l = []
         f = open(file, 'r')
         while True:
@@ -246,9 +347,27 @@
 
 
 def is_ipv4(ip):
+    """Determine whether the IP address is in the IPv4 format.
+    
+    @type ip: C{string}
+    @param ip: the IP address to check
+    @rtype: C{boolean}
+    @return: whether the IP address is for IPv4
+   
+    """
+    
     return ip.find(':') < 0
 
 def is_valid_ip(ip):
+    """Determine whether the IP address is a valid IPv4 or IPv6 address.
+    
+    @type ip: C{string}
+    @param ip: the IP address to check
+    @rtype: C{boolean}
+    @return: whether the IP address is valid
+   
+    """
+    
     try:
         if is_ipv4(ip):
             a = ip.split('.')

Modified: debtorrent/trunk/DebTorrent/natpunch.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/natpunch.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/natpunch.py (original)
+++ debtorrent/trunk/DebTorrent/natpunch.py Sun Jun 17 04:35:50 2007
@@ -3,8 +3,29 @@
 # and from example code by Myers Carpenter
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""UPnP methods for opening ports in firewalls (Windows only).
+
+ at type DEBUG: C{boolean}
+ at var DEBUG: whether to print debugging messages
+ at type EXPIRE_CACHE: C{int}
+ at var EXPIRE_CACHE: unknown
+ at type ID: unknown
+ at var ID: unknown
+ at type _upnp_: unknown
+ at var _upnp_: unknown
+ at type UPnP_test: unknown
+ at var UPnP_test: unknown
+ at type UPnP_open_port: unknown
+ at var UPnP_open_port: unknown
+ at type UPnP_close_port: unknown
+ at var UPnP_close_port: unknown
+ at type UPnP_reset: unknown
+ at var UPnP_reset: unknown
+
+"""
 
 import socket
 from traceback import print_exc
@@ -30,9 +51,18 @@
 
 
 
-class _UPnP1:   # derived from Myers Carpenter's code
-                # seems to use the machine's local UPnP
-                # system for its operation.  Runs fairly fast
+class _UPnP1:
+    """A UPnP method.
+    
+    Derived from Myers Carpenter's code. Seems to use the machine's local 
+    UPnP system for its operation. Runs fairly fast.
+                
+    @type map: unknown
+    @ivar map: unknown
+    @type last_got_map: unknown
+    @ivar last_got_map: unknown
+                
+    """
 
     def __init__(self):
         self.map = None
@@ -58,6 +88,15 @@
 
 
     def open(self, ip, p):
+        """
+        
+        @type ip: unknown
+        @param ip: unknown
+        @type p: unknown
+        @param p: unknown
+        
+        """
+        
         map = self._get_map()
         try:
             map.Add(p,'TCP',p,ip,True,ID)
@@ -73,6 +112,13 @@
 
 
     def close(self, p):
+        """
+        
+        @type p: unknown
+        @param p: unknown
+        
+        """
+        
         map = self._get_map()
         try:
             map.Remove(p,'TCP')
@@ -88,6 +134,13 @@
 
 
     def clean(self, retry = False):
+        """
+        
+        @type retry: unknown
+        @param retry: unknown
+        
+        """
+        
         if not _supported:
             return
         try:
@@ -115,10 +168,20 @@
             pass
 
 
-class _UPnP2:   # derived from Yejun Yang's code
-                # apparently does a direct search for UPnP hardware
-                # may work in some cases where _UPnP1 won't, but is slow
-                # still need to implement "clean" method
+class _UPnP2:
+    """Another UPnP method.
+    
+    Derived from Yejun Yang's code
+    # apparently does a direct search for UPnP hardware
+    # may work in some cases where _UPnP1 won't, but is slow
+    # still need to implement "clean" method
+    
+    @type services: unknown
+    @ivar services: unknown
+    @type last_got_services: unknown
+    @ivar last_got_services: unknown
+    
+    """
 
     def __init__(self):
         self.services = None
@@ -160,6 +223,15 @@
 
 
     def open(self, ip, p):
+        """
+        
+        @type ip: unknown
+        @param ip: unknown
+        @type p: unknown
+        @param p: unknown
+        
+        """
+        
         svcs = self._get_services()
         success = False
         for s in svcs:
@@ -175,6 +247,13 @@
 
 
     def close(self, p):
+        """
+        
+        @type p: unknown
+        @param p: unknown
+        
+        """
+        
         svcs = self._get_services()
         success = False
         for s in svcs:
@@ -189,7 +268,24 @@
         return success
 
 
-class _UPnP:    # master holding class
+class _UPnP:
+    """Master holding class.
+    
+    @type upnp1: unknown
+    @ivar upnp1: unknown
+    @type upnp2: unknown
+    @ivar upnp2: unknown
+    @type upnplist: unknown
+    @ivar upnplist: unknown
+    @type upnp: unknown
+    @ivar upnp: unknown
+    @type local_ip: unknown
+    @ivar local_ip: unknown
+    @type last_got_ip: unknown
+    @ivar last_got_ip: unknown
+    
+    """
+    
     def __init__(self):
         self.upnp1 = _UPnP1()
         self.upnp2 = _UPnP2()
@@ -221,6 +317,13 @@
         return self.local_ip
 
     def test(self, upnp_type):
+        """
+        
+        @type upnp_type: unknown
+        @param upnp_type: unknown
+        
+        """
+        
         if DEBUG:
             print 'testing UPnP type '+str(upnp_type)
         if not upnp_type or not _supported or self.get_ip() is None:
@@ -238,10 +341,24 @@
         return 0
 
     def open(self, p):
+        """
+        
+        @type p: unknown
+        @param p: unknown
+        
+        """
+        
         assert self.upnp, "must run UPnP_test() with the desired UPnP access type first"
         return self.upnp.open(self.get_ip(), p)
 
     def close(self, p):
+        """
+        
+        @type p: unknown
+        @param p: unknown
+        
+        """
+        
         assert self.upnp, "must run UPnP_test() with the desired UPnP access type first"
         return self.upnp.close(p)
 

Modified: debtorrent/trunk/DebTorrent/parseargs.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/parseargs.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/parseargs.py (original)
+++ debtorrent/trunk/DebTorrent/parseargs.py Sun Jun 17 04:35:50 2007
@@ -1,14 +1,31 @@
 # Written by Bill Bumgarner and Bram Cohen
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Functions for dealing with arguments, defaults and options."""
 
 from types import *
 from cStringIO import StringIO
 
 
 def splitLine(line, COLS=80, indent=10):
+    """Split an output line to a screen width (with indenting).
+    
+    @type line: C{string}
+    @param line: the output line to split
+    @type COLS: C{int}
+    @param COLS: the number of columns in the screen width
+        (optional, defaults to 80)
+    @type indent: C{int}
+    @param indent: the number of columns to indent the output lines with spaces
+        (optional, defaults to 10)
+    @rtype: C{string}
+    @return: the multiple lines formatted for output
+    
+    """
+    
     indent = " " * indent
     width = COLS - (len(indent) + 1)
     if indent and width < 15:
@@ -30,6 +47,20 @@
     return s.getvalue()
 
 def formatDefinitions(options, COLS, presets = {}):
+    """Format configuration options for printing to the user.
+    
+    @type options: C{list} of (C{string}, unknown, C{string})
+    @param options: the name, default value, and description for each of 
+        the configuration options
+    @type COLS: C{int}
+    @param COLS: the width of the screen to format the output for
+    @type presets: C{dictionary}
+    @param presets: other default values to use instead (optional)
+    @rtype: C{string}
+    @return: the formatted options for output
+    
+    """
+    
     s = StringIO()
     for (longname, default, doc) in options:
         s.write('--' + longname + ' <arg>\n')
@@ -47,10 +78,28 @@
 
 
 def usage(str):
+    """Raise an error to indicate a problem.
+    
+    @type str: C{string}
+    @param str: the error that occurred
+    @raise ValueError: always
+    
+    """
+    
     raise ValueError(str)
 
 
 def defaultargs(options):
+    """Make a dictionary of all the default options.
+    
+    @type options: C{list} of (C{string}, unknown, C{string})
+    @param options: the name, default value, and description for each of 
+        the configuration options
+    @rtype: C{dictionary}
+    @return: the default options, keys are the option names
+    
+    """
+    
     l = {}
     for (longname, default, doc) in options:
         if default is not None:
@@ -59,6 +108,33 @@
         
 
 def parseargs(argv, options, minargs = None, maxargs = None, presets = {}):
+    """Parse a list of input arguments and set the configuration options variable.
+    
+    All configuration options must begin with '--', must be followed by a space 
+    and then the new setting to use, and must appear in the options variable 
+    keys. Non-options can appear anywhere in the arguments (except between an
+    option and it's setting), and there must be between minargs and maxargs of
+    them.
+    
+    @type argv: C{list} of C{string}
+    @param argv: the input command-line arguments
+    @type options: C{list} of (C{string}, unknown, C{string})
+    @param options: the name, default value, and description for each of 
+        the configuration options
+    @type minargs: C{int}
+    @param minargs: the minimum number of non-option arguments required 
+        (optional, defaults to no minimum)
+    @type maxargs: C{int}
+    @param maxargs: the maximum number of non-option arguments required 
+        (optional, defaults to no maximum)
+    @type presets: C{dictionary}
+    @param presets: other default values to use instead (optional)
+    @rtype: (C{dictionary}, C{list})
+    @return: the configuration options, and any remaining non-option arguments
+    @raise ValueError: by calling L{usage} if something goes wrong
+    
+    """
+    
     config = {}
     longkeyed = {}
     for option in options:
@@ -104,6 +180,8 @@
     return (config, args)
 
 def test_parseargs():
+    """Test the L{parseargs} function for errors."""
+    
     assert parseargs(('d', '--a', 'pq', 'e', '--b', '3', '--c', '4.5', 'f'), (('a', 'x', ''), ('b', 1, ''), ('c', 2.3, ''))) == ({'a': 'pq', 'b': 3, 'c': 4.5}, ['d', 'e', 'f'])
     assert parseargs([], [('a', 'x', '')]) == ({'a': 'x'}, [])
     assert parseargs(['--a', 'x', '--a', 'y'], [('a', '', '')]) == ({'a': 'y'}, [])

Modified: debtorrent/trunk/DebTorrent/parsedir.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/parsedir.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/parsedir.py (original)
+++ debtorrent/trunk/DebTorrent/parsedir.py Sun Jun 17 04:35:50 2007
@@ -1,8 +1,15 @@
 # Written by John Hoffman and Uoti Urpala
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Parse a directory for torrent files.
+
+ at type NOISY: C{boolean}
+ at var NOISY: whether to print additional status messages about the parsing
+
+"""
 
 from bencode import bencode, bdecode
 from download_bt1 import get_response
@@ -19,11 +26,43 @@
 NOISY = True
 
 def _errfunc(x):
+    """The default output printing function to use.
+    
+    @type x: C{string}
+    @param x: the output message to print
+    
+    """
+    
     print ":: "+x
 
 def parsedir(directory, parsed, files, blocked,
              exts = ['dtorrent','Packages'], 
              return_metainfo = False, errfunc = _errfunc):
+    """Parse a directory for torrent files.
+    
+    @type directory: C{string}
+    @param directory: the directory to parse (somewhat recursively)
+    @type parsed: C{dictionary}
+    @param parsed: the torrent files that were previously found
+    @type files: C{dictionary}
+    @param files: the files that were previously found
+    @type blocked: C{dictionary}
+    @param blocked: the files that were previously blocked
+    @type exts: C{list} of C{string}
+    @param exts: the extensions to look for torrent files in
+        (optional, defaults to 'dtorrent' and 'Packages')
+    @type return_metainfo: C{boolean}
+    @param return_metainfo: whether to return the torrent metainfo 
+        (optional, defaults to False)
+    @type errfunc: C{method}
+    @param errfunc: the method to call to print status/warning/error messages
+        (optional, defaults to the L{_errfunc} function)
+    @rtype: (C{dictionary}, C{dictionary}, C{dictionary}, C{dictionary}, C{dictionary})
+    @return: all the torrents found, all the files found, all the files blocked,
+        the new torrents that were found, the torrents that are now missing
+    
+    """
+    
     if NOISY:
         errfunc('checking dir')
     dirs_to_check = [directory]
@@ -120,9 +159,22 @@
             a['numfiles'] = nf
             a['length'] = l
             a['name'] = d.get('name', f)
+            
             def setkey(k, d = d, a = a):
+                """Set the key of a dictionary with the value from another dictionary.
+                
+                @type k: unknown
+                @param k: the key to set
+                @type d: C{dictionary}
+                @param d: the dictionary to get the value from
+                @type a: C{dictionary}
+                @param a: the dictionary to set the {k: d[k]} value in
+                
+                """
+                
                 if d.has_key(k):
                     a[k] = d[k]
+
             setkey('failure reason')
             setkey('warning message')
             setkey('announce-list')

Modified: debtorrent/trunk/DebTorrent/piecebuffer.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/piecebuffer.py?rev=114&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/piecebuffer.py (original)
+++ debtorrent/trunk/DebTorrent/piecebuffer.py Sun Jun 17 04:35:50 2007
@@ -1,8 +1,19 @@
 # Written by John Hoffman
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
+#
+# $Id$
 
-# $Id$
+"""Store buffers of piece data.
+
+ at type DEBUG: C{boolean}
+ at var DEBUG: whether to print debugging messages
+ at type _pool: L{BufferPool}
+ at var _pool: example buffer pool
+ at type PieceBuffer: L{SingleBuffer}
+ at var PieceBuffer: example buffer
+
+"""
 
 from array import array
 from threading import Lock
@@ -16,34 +27,69 @@
 DEBUG = False
 
 class SingleBuffer:
+    """A single piece buffer.
+    
+    @type pool: L{BufferPool}
+    @ivar pool: the pool of all piece buffers
+    @type buf: C{array.array}
+    @ivar buf: the character buffer used to store the piece
+    @type length: C{int}
+    @ivar length: the amount of data in the piece buffer
+    
+    """
+    
     def __init__(self, pool):
+        """Initialize the instance.
+        
+        @type pool: L{BufferPool}
+        @param pool: the pool of all piece buffers
+        
+        """
+        
         self.pool = pool
         self.buf = array('c')
 
     def init(self):
+        """Initialize the new piece buffer."""
         if DEBUG:
             print 'new/pooled buffer index:', self.count
-            '''
-            for x in xrange(6,1,-1):
-                try:
-                    f = inspect.currentframe(x).f_code
-                    print (f.co_filename,f.co_firstlineno,f.co_name)
-                    del f
-                except:
-                    pass
-            print ''
-            '''
         self.length = 0
 
     def append(self, s):
+        """Add new data to the end of the buffer.
+        
+        @type s: C{string}
+        @param s: the new data to add
+        
+        """
+        
         l = self.length+len(s)
         self.buf[self.length:l] = array('c',s)
         self.length = l
 
     def __len__(self):
+        """Get the length of the buffer.
+        
+        @rtype: C{int}
+        @return: the length of the data in the buffer
+        
+        """
+        
         return self.length
 
     def __getslice__(self, a, b):
+        """Get a slice of data from the buffer.
+        
+        @type a: C{int}
+        @param a: the starting offset to get data from
+        @type b: C{int}
+        @param b: the ending offset to stop getting data at, can be negative 
+            to count from the end of the buffer
+        @rtype: C{array.array}
+        @return: the requested data from the buffer
+        
+        """
+        
         if b > self.length:
             b = self.length
         if b < 0:
@@ -53,22 +99,49 @@
         return self.buf[a:b]
 
     def getarray(self):
+        """Get al the data from the buffer.
+        
+        @rtype: C{array.array}
+        @return: the requested data from the buffer
+        
+        """
+        
         return self.buf[:self.length]
 
     def release(self):
+        """Release this buffer to the pool for reuse."""
         if DEBUG:
             print 'released buffer with index:', self.count
         self.pool.release(self)
 
 
 class BufferPool:
+    """The pool of all created piece buffers.
+    
+    @type pool: C{list} of L{SingleBuffer}
+    @ivar pool: the pooled buffers available for use
+    @type lock: C{threading.Lock}
+    @ivar lock: serializes access to the pool across different threads
+    @type count: C{int}
+    @ivar count: the number of created buffers (for debugging)
+    
+    """
+    
     def __init__(self):
+        """Initialize the instance."""
         self.pool = []
         self.lock = Lock()
         if DEBUG:
             self.count = 0
 
     def new(self):
+        """Get a SingleBuffer from the pool, or create a new one.
+        
+        @rtype: L{SingleBuffer}
+        @return: a usable piece buffer
+        
+        """
+        
         self.lock.acquire()
         if self.pool:
             x = self.pool.pop()
@@ -82,6 +155,13 @@
         return x
 
     def release(self, x):
+        """Add an existing buffer to the pool of available ones.
+        
+        @type x: L{SingleBuffer}
+        @param x: the buffer to add to the pool
+        
+        """
+        
         self.pool.append(x)
 
 




More information about the Debtorrent-commits mailing list