Last portion of doc-string and formatting refactoring

This commit is contained in:
Alexander Cherniuk 2009-11-26 18:12:52 +02:00
parent f084a1f78b
commit 4d904560a7
3 changed files with 159 additions and 116 deletions

View File

@ -26,16 +26,26 @@ import unicodedata
from encodings import idna
class ILookupTable:
""" Interface for character lookup classes. """
"""
Interface for character lookup classes
"""
def lookup(self, c):
""" Return whether character is in this table. """
"""
Return whether character is in this table
"""
pass
class IMappingTable:
""" Interface for character mapping classes. """
"""
Interface for character mapping classes
"""
def map(self, c):
""" Return mapping for character. """
"""
Return mapping for character
"""
pass
class LookupTableFromFunction:
@ -75,8 +85,8 @@ class EmptyMappingTable:
return c
class Profile:
def __init__(self, mappings=[], normalize=True, prohibiteds=[],
check_unassigneds=True, check_bidi=True):
def __init__(self, mappings=[], normalize=True, prohibiteds=[],
check_unassigneds=True, check_bidi=True):
self.mappings = mappings
self.normalize = normalize
self.prohibiteds = prohibiteds
@ -140,24 +150,25 @@ class Profile:
class NamePrep:
""" Implements preparation of internationalized domain names.
"""
Implements preparation of internationalized domain names
This class implements preparing internationalized domain names using the
rules defined in RFC 3491, section 4 (Conversion operations).
This class implements preparing internationalized domain names using the
rules defined in RFC 3491, section 4 (Conversion operations).
We do not perform step 4 since we deal with unicode representations of
domain names and do not convert from or to ASCII representations using
punycode encoding. When such a conversion is needed, the L{idna} standard
library provides the C{ToUnicode()} and C{ToASCII()} functions. Note that
L{idna} itself assumes UseSTD3ASCIIRules to be false.
We do not perform step 4 since we deal with unicode representations of
domain names and do not convert from or to ASCII representations using
punycode encoding. When such a conversion is needed, the L{idna} standard
library provides the C{ToUnicode()} and C{ToASCII()} functions. Note that
L{idna} itself assumes UseSTD3ASCIIRules to be false.
The following steps are performed by C{prepare()}:
The following steps are performed by C{prepare()}:
* Split the domain name in labels at the dots (RFC 3490, 3.1)
* Apply nameprep proper on each label (RFC 3491)
* Enforce the restrictions on ASCII characters in host names by
assuming STD3ASCIIRules to be true. (STD 3)
* Rejoin the labels using the label separator U+002E (full stop).
* Split the domain name in labels at the dots (RFC 3490, 3.1)
* Apply nameprep proper on each label (RFC 3491)
* Enforce the restrictions on ASCII characters in host names by
assuming STD3ASCIIRules to be true. (STD 3)
* Rejoin the labels using the label separator U+002E (full stop).
"""
# Prohibited characters.

View File

@ -54,13 +54,17 @@ def gattr(obj, attr, default=None):
class SSLWrapper:
'''
"""
Abstract SSLWrapper base class
'''
"""
class Error(IOError):
''' Generic SSL Error Wrapper '''
"""
Generic SSL Error Wrapper
"""
def __init__(self, sock=None, exc=None, errno=None, strerror=None,
peer=None):
peer=None):
self.parent = IOError
errno = errno or gattr(exc, 'errno') or exc[0]
@ -122,7 +126,7 @@ class SSLWrapper:
log.debug("%s.__init__ called with %s", self.__class__, sslobj)
def recv(self, data, flags=None):
'''
"""
Receive wrapper for SSL object
We can return None out of this function to signal that no data is
@ -130,16 +134,20 @@ class SSLWrapper:
depending on which SSL lib we're using. Unfortunately returning ''
can indicate that the socket has been closed, so to be sure, we avoid
this by returning None.
'''
"""
raise NotImplementedError
def send(self, data, flags=None, now=False):
''' Send wrapper for SSL object '''
"""
Send wrapper for SSL object
"""
raise NotImplementedError
class PyOpenSSLWrapper(SSLWrapper):
'''Wrapper class for PyOpenSSL's recv() and send() methods'''
"""
Wrapper class for PyOpenSSL's recv() and send() methods
"""
def __init__(self, *args):
self.parent = SSLWrapper
@ -202,7 +210,9 @@ class PyOpenSSLWrapper(SSLWrapper):
class StdlibSSLWrapper(SSLWrapper):
'''Wrapper class for Python socket.ssl read() and write() methods'''
"""
Wrapper class for Python socket.ssl read() and write() methods
"""
def __init__(self, *args):
self.parent = SSLWrapper
@ -230,18 +240,18 @@ class StdlibSSLWrapper(SSLWrapper):
class NonBlockingTLS(PlugIn):
'''
TLS connection used to encrypts already estabilished tcp connection.
"""
TLS connection used to encrypts already estabilished tcp connection
Can be plugged into NonBlockingTCP and will make use of StdlibSSLWrapper or
PyOpenSSLWrapper.
'''
"""
def __init__(self, cacerts, mycerts):
'''
"""
:param cacerts: path to pem file with certificates of known XMPP servers
:param mycerts: path to pem file with certificates of user trusted servers
'''
"""
PlugIn.__init__(self)
self.cacerts = cacerts
self.mycerts = mycerts
@ -254,10 +264,10 @@ class NonBlockingTLS(PlugIn):
"SSL_CB_HANDSHAKE_START": 0x10, "SSL_CB_HANDSHAKE_DONE": 0x20}
def plugin(self, owner):
'''
Use to PlugIn TLS into transport and start establishing immediately
Returns True if TLS/SSL was established correctly, otherwise False.
'''
"""
Use to PlugIn TLS into transport and start establishing immediately.
Returns True if TLS/SSL was established correctly, otherwise False
"""
log.info('Starting TLS estabilishing')
try:
res = self._startSSL()
@ -289,7 +299,9 @@ class NonBlockingTLS(PlugIn):
"Unknown"), pkey.type())
def _startSSL(self):
''' Immediatedly switch socket to TLS mode. Used internally.'''
"""
Immediatedly switch socket to TLS mode. Used internally
"""
log.debug("_startSSL called")
if USE_PYOPENSSL:

View File

@ -15,14 +15,14 @@
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
'''
"""
Transports are objects responsible for connecting to XMPP server and putting
data to wrapped sockets in in desired form (SSL, TLS, TCP, for HTTP proxy,
for SOCKS5 proxy...)
Transports are not aware of XMPP stanzas and only responsible for low-level
connection handling.
'''
"""
from simplexml import ustr
from plugin import PlugIn
@ -41,12 +41,12 @@ import logging
log = logging.getLogger('gajim.c.x.transports_nb')
def urisplit(uri):
'''
"""
Function for splitting URI string to tuple (protocol, host, port, path).
e.g. urisplit('http://httpcm.jabber.org:123/webclient') returns
('http', 'httpcm.jabber.org', 123, '/webclient')
return 443 as default port if proto is https else 80
'''
e.g. urisplit('http://httpcm.jabber.org:123/webclient') returns ('http',
'httpcm.jabber.org', 123, '/webclient') return 443 as default port if proto
is https else 80
"""
splitted = urlparse.urlsplit(uri)
proto, host, path = splitted.scheme, splitted.hostname, splitted.path
try:
@ -102,17 +102,18 @@ CONNECTED = 'CONNECTED'
STATES = (DISCONNECTED, CONNECTING, PROXY_CONNECTING, CONNECTED, DISCONNECTING)
class NonBlockingTransport(PlugIn):
'''
Abstract class representing a transport.
"""
Abstract class representing a transport
Subclasses CAN have different constructor signature but connect method SHOULD
be the same.
'''
"""
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
certs):
'''
certs):
"""
Each trasport class can have different constructor but it has to have at
least all the arguments of NonBlockingTransport constructor.
least all the arguments of NonBlockingTransport constructor
:param raise_event: callback for monitoring of sent and received data
:param on_disconnect: callback called on disconnection during runtime
@ -121,7 +122,7 @@ class NonBlockingTransport(PlugIn):
TCP connection is done
:param certs: tuple of (cacerts, mycerts) see constructor of
tls_nb.NonBlockingTLS for more details
'''
"""
PlugIn.__init__(self)
self.raise_event = raise_event
self.on_disconnect = on_disconnect
@ -157,14 +158,14 @@ class NonBlockingTransport(PlugIn):
self.disconnect(do_callback=False)
def connect(self, conn_5tuple, on_connect, on_connect_failure):
'''
"""
Creates and connects transport to server and port defined in conn_5tuple
which should be item from list returned from getaddrinfo.
which should be item from list returned from getaddrinfo
:param conn_5tuple: 5-tuple returned from getaddrinfo
:param on_connect: callback called on successful connect to the server
:param on_connect_failure: callback called on failure when connecting
'''
"""
self.on_connect = on_connect
self.on_connect_failure = on_connect_failure
self.server, self.port = conn_5tuple[4][:2]
@ -178,14 +179,18 @@ class NonBlockingTransport(PlugIn):
return self.state
def _on_connect(self):
''' preceeds call of on_connect callback '''
"""
Preceeds call of on_connect callback
"""
# data is reference to socket wrapper instance. We don't need it in client
# because
self.set_state(CONNECTED)
self.on_connect()
def _on_connect_failure(self, err_message):
''' preceeds call of on_connect_failure callback '''
"""
Preceeds call of on_connect_failure callback
"""
# In case of error while connecting we need to disconnect transport
# but we don't want to call DisconnectHandlers from client,
# thus the do_callback=False
@ -204,15 +209,16 @@ class NonBlockingTransport(PlugIn):
self.on_disconnect()
def onreceive(self, recv_handler):
'''
Sets the on_receive callback.
"""
Set the on_receive callback.
onreceive(None) sets callback to Dispatcher.ProcessNonBlocking which is
the default one that will decide what to do with received stanza based on
its tag name and namespace.
Do not confuse it with on_receive() method, which is the callback itself.
'''
Do not confuse it with on_receive() method, which is the callback
itself.
"""
if not recv_handler:
if hasattr(self, '_owner') and hasattr(self._owner, 'Dispatcher'):
self.on_receive = self._owner.Dispatcher.ProcessNonBlocking
@ -226,13 +232,17 @@ class NonBlockingTransport(PlugIn):
self.set_state(CONNECTING)
def read_timeout(self):
''' called when there's no response from server in defined timeout '''
"""
Called when there's no response from server in defined timeout
"""
if self.on_timeout:
self.on_timeout()
self.renew_send_timeout()
def read_timeout2(self):
''' called when there's no response from server in defined timeout '''
"""
called when there's no response from server in defined timeout
"""
if self.on_timeout2:
self.on_timeout2()
self.renew_send_timeout2()
@ -277,17 +287,17 @@ class NonBlockingTransport(PlugIn):
class NonBlockingTCP(NonBlockingTransport, IdleObject):
'''
Non-blocking TCP socket wrapper.
"""
Non-blocking TCP socket wrapper
It is used for simple XMPP connection. Can be connected via proxy and can
estabilish TLS connection.
'''
"""
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
certs, proxy_dict=None):
'''
certs, proxy_dict=None):
"""
:param proxy_dict: dictionary with proxy data as loaded from config file
'''
"""
NonBlockingTransport.__init__(self, raise_event, on_disconnect, idlequeue,
estabilish_tls, certs)
IdleObject.__init__(self)
@ -371,10 +381,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
proxy_creds=self.proxy_dict['credentials'])
def _on_connect(self):
'''
Preceeds invoking of on_connect callback. TCP connection is already
estabilished by this time.
'''
"""
Preceed invoking of on_connect callback. TCP connection is already
estabilished by this time
"""
if self.estabilish_tls:
self.tls_init(
on_succ = lambda: NonBlockingTransport._on_connect(self),
@ -384,10 +394,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
NonBlockingTransport._on_connect(self)
def tls_init(self, on_succ, on_fail):
'''
"""
Estabilishes TLS/SSL using this TCP connection by plugging a
NonBlockingTLS module
'''
"""
cacerts, mycerts = self.certs
result = tls_nb.NonBlockingTLS.get_instance(cacerts, mycerts).PlugIn(self)
if result:
@ -396,12 +406,16 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
on_fail()
def pollin(self):
'''called by idlequeu when receive on plugged socket is possible '''
"""
Called by idlequeu when receive on plugged socket is possible
"""
log.info('pollin called, state == %s' % self.get_state())
self._do_receive()
def pollout(self):
'''called by idlequeu when send to plugged socket is possible'''
"""
Called by idlequeu when send to plugged socket is possible
"""
log.info('pollout called, state == %s' % self.get_state())
if self.get_state() == CONNECTING:
@ -417,7 +431,9 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self._do_send()
def pollend(self):
'''called by idlequeue on TCP connection errors'''
"""
Called by idlequeue on TCP connection errors
"""
log.info('pollend called, state == %s' % self.get_state())
if self.get_state() == CONNECTING:
@ -465,10 +481,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
log.warn('remove_timeout: no self.fd state is %s' % self.get_state())
def send(self, raw_data, now=False):
'''
Append raw_data to the queue of messages to be send.
If supplied data is unicode string, encode it to utf-8.
'''
"""
Append raw_data to the queue of messages to be send. If supplied data is
unicode string, encode it to utf-8.
"""
NonBlockingTransport.send(self, raw_data, now)
r = self.encode_stanza(raw_data)
@ -482,7 +498,9 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self._plug_idle(writable=True, readable=True)
def encode_stanza(self, stanza):
''' Encode str or unicode to utf-8 '''
"""
Encode str or unicode to utf-8
"""
if isinstance(stanza, unicode):
stanza = stanza.encode('utf-8')
elif not isinstance(stanza, str):
@ -490,8 +508,8 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
return stanza
def _plug_idle(self, writable, readable):
'''
Plugs file descriptor of socket to Idlequeue.
"""
Plug file descriptor of socket to Idlequeue
Plugged socket will be watched for "send possible" or/and "recv possible"
events. pollin() callback is invoked on "recv possible", pollout() on
@ -499,15 +517,15 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
Plugged socket will always be watched for "error" event - in that case,
pollend() is called.
'''
"""
log.info('Plugging fd %d, W:%s, R:%s' % (self.fd, writable, readable))
self.idlequeue.plug_idle(self, writable, readable)
def _do_send(self):
'''
"""
Called when send() to connected socket is possible. First message from
sendqueue will be sent.
'''
sendqueue will be sent
"""
if not self.sendbuff:
if not self.sendqueue:
log.warn('calling send on empty buffer and queue')
@ -530,10 +548,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self.disconnect()
def _do_receive(self):
'''
"""
Reads all pending incoming data. Will call owner's disconnected() method
if appropriate.
'''
if appropriate
"""
received = None
errnum = 0
errstr = 'No Error Set'
@ -588,27 +606,29 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self.disconnect()
def _on_receive(self, data):
''' preceeds on_receive callback. It peels off and checks HTTP headers in
HTTP classes, in here it just calls the callback.'''
"""
Preceeds on_receive callback. It peels off and checks HTTP headers in
HTTP classes, in here it just calls the callback
"""
self.on_receive(data)
class NonBlockingHTTP(NonBlockingTCP):
'''
Socket wrapper that creates HTTP message out of sent data and peels-off
HTTP headers from incoming messages.
'''
"""
Socket wrapper that creates HTTP message out of sent data and peels-off HTTP
headers from incoming messages
"""
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
certs, on_http_request_possible, on_persistent_fallback, http_dict,
proxy_dict=None):
'''
certs, on_http_request_possible, on_persistent_fallback, http_dict,
proxy_dict=None):
"""
:param on_http_request_possible: method to call when HTTP request to
socket owned by transport is possible.
:param on_persistent_fallback: callback called when server ends TCP
connection. It doesn't have to be fatal for HTTP session.
:param http_dict: dictionary with data for HTTP request and headers
'''
"""
NonBlockingTCP.__init__(self, raise_event, on_disconnect, idlequeue,
estabilish_tls, certs, proxy_dict)
@ -639,10 +659,10 @@ class NonBlockingHTTP(NonBlockingTCP):
self.send(self.build_http_message(raw_data), now)
def _on_receive(self, data):
'''
"""
Preceeds passing received data to owner class. Gets rid of HTTP headers
and checks them.
'''
"""
if self.get_state() == PROXY_CONNECTING:
NonBlockingTCP._on_receive(self, data)
return
@ -686,10 +706,10 @@ class NonBlockingHTTP(NonBlockingTCP):
self.on_http_request_possible()
def build_http_message(self, httpbody, method='POST'):
'''
Builds http message with given body.
Values for headers and status line fields are taken from class variables.
'''
"""
Builds http message with given body. Values for headers and status line
fields are taken from class variables
"""
absolute_uri = '%s://%s:%s%s' % (self.http_protocol, self.http_host,
self.http_port, self.http_path)
headers = ['%s %s %s' % (method, absolute_uri, self.http_version),
@ -711,14 +731,14 @@ class NonBlockingHTTP(NonBlockingTCP):
return('%s%s' % (headers, httpbody))
def parse_http_message(self, message):
'''
splits http message to tuple:
"""
Split http message into a tuple:
(statusline - list of e.g. ['HTTP/1.1', '200', 'OK'],
headers - dictionary of headers e.g. {'Content-Length': '604',
'Content-Type': 'text/xml; charset=utf-8'},
httpbody - string with http body)
http_rest - what is left in the message after a full HTTP header + body
'''
"""
message = message.replace('\r','')
message = message.lstrip('\n')
splitted = message.split('\n\n')
@ -745,10 +765,10 @@ class NonBlockingHTTP(NonBlockingTCP):
class NonBlockingHTTPBOSH(NonBlockingHTTP):
'''
Class for BOSH HTTP connections. Slightly redefines HTTP transport by calling
bosh bodytag generating callback before putting data on wire.
'''
"""
Class for BOSH HTTP connections. Slightly redefines HTTP transport by
calling bosh bodytag generating callback before putting data on wire
"""
def set_stanza_build_cb(self, build_cb):
self.build_cb = build_cb