start documenting with reST syntax. devel
authorSandro Knauß <knauss@netzguerilla.net>
Sun, 25 Mar 2012 20:14:35 +0200
branchdevel
changeset 253 e8d56537c9cc
parent 252 d0de2ca7201a
child 254 de301b8c58d9
start documenting with reST syntax.
iro/controller/viewinterface.py
iro/offer/provider.py
iro/offer/smstrade.py
iro/offer/smtp.py
--- a/iro/controller/viewinterface.py	Sun Mar 25 20:11:34 2012 +0200
+++ b/iro/controller/viewinterface.py	Sun Mar 25 20:14:35 2012 +0200
@@ -7,8 +7,7 @@
 from .task import createJob
 
 class Interface(object):
-    '''class for a xmlrpc user
-    '''
+    '''Interface for views.'''
     
     @validate(kwd="detailed", func=vBool, need=False)
     @validate(kwd="id", func=vInteger, minv=0, need=False, none_allowed=True)
@@ -17,17 +16,23 @@
     def status(self, session, user, id=None, detailed=False):
         '''Gibt den aktuellen Status eines Auftrages oder Mehreren zurück.
 
-        Keywords:
-        apikey[string]: Der API Key
-        id[hash]: Eine Auftragsnummer
-        detailed[boolean]: Details ausgeben
+        :param string apikey: der API Key
+        :param hash id: Eine Auftragsnummer
+        :param `boolean` detailed: Details ausgeben
+
+        :return dict: 
+           - `key` ist die Auftragsnummer
+           - [`key`][**'status'**] -- Status des Auftrages
 
-        Return:
-        jobs[list]: Eine Liste der Aufträge.
-        job.name[string]: Angebener Name
-        job.status[string]: Status des Auftrages
+        .. warning:: detailed is not used yet.
+        
+        >>> status(APIKEY)
+        {"1":  {"status":"sended"},
+         "2":  {"status":"error"},
+         "10": {"status":"sending"}}
 
-
+        >>> status(APIKEY,"10")
+        {"10": {"status":"sending"}}
         '''
         user = session.merge(user)
         ret={}
@@ -45,16 +50,15 @@
     def sms(self, user, message, recipients, route="default", info=""):
         '''Versendet eine SMS.
 
-        Keywords:
-        apikey[string]: Der API Key
-        message[string]: Nachricht
-        recipients[list]: eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
-        route[string|list]: Route über den geschickt werden soll, 
+        :param string apikey: Der API Key
+        :param string message: Nachricht
+        :param list recipients: eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
+        :param route: Route über den geschickt werden soll, 
                             oder eine Liste von Routen, um Fallbacks anzugeben
-        info[string]: Infostring um eine Nachricht einer Gruppe zuorden zu können.
+        :type route: string|list
+        :param string info: Infostring um eine Nachricht einer Gruppe zuorden zu können.
 
-        Return:
-        id[hash]: Die ID des Auftrages
+        :return hash: Die ID des Auftrages
 
         '''
         d = createJob(user, recipients, SMS(message), route, info)
@@ -69,18 +73,16 @@
     def fax(self, user, subject, fax, recipients, route="default", info=""):
         '''Versendet ein FAX.
 
-        Keywords:
-        apikey[string]: Der API Key
-        subject[string]: Der Betreff
-        fax[string]: Der base64 kodierte content
-        recipients[list]: Eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
-        route[string|list]: Route über den geschickt werden soll, 
+        :param string apikey: Der API Key
+        :param string subject: Der Betreff
+        :param string fax: Der base64 kodierte content
+        :param list recipients: Eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
+        :param route: Route über den geschickt werden soll, 
                             oder eine Liste von Routen, um Fallbacks anzugeben
-        info[string]: Infostring um eine Nachricht einer Gruppe zuorden zu können.
+        :type route: string|list
+        :param string info: Infostring um eine Nachricht einer Gruppe zuorden zu können.
 
-        Return:
-        id[hash]: Die ID des Auftrages
-
+        :return hash: Die ID des Auftrages
         '''
         d = createJob(user, recipients, Fax(subject, fax), route, info)
         def ret(job):
@@ -95,19 +97,17 @@
     def mail(self, user, subject, body, recipients, frm=None, route="default", info=""):
         '''Versendet eine Email.
 
-        Keywords:
-        apikey[string]: Der API Key
-        subject[string]: Der Betreff
-        body[string]: Der Email Body
-        recipients[list]: Eine Liste von Emailadressen
-        frm[string]: Die Absender Emailadresse
-        route[string|list]: Route über den geschickt werden soll, 
+        :param string apikey: Der API Key
+        :param string subject: Der Betreff
+        :param string body: Der Email Body
+        :param list recipients: Eine Liste von Emailadressen
+        :param string frm: Die Absender Emailadresse
+        :param route: Route über den geschickt werden soll, 
                             oder eine Liste von Routen, um Fallbacks anzugeben
-        info[string]: Infostring um eine Nachricht einer Gruppe zuorden zu können.
+        :type route: string|list
+        :param string info: Infostring um eine Nachricht einer Gruppe zuorden zu können.
 
-        Return:
-        id[hash]: Die ID des Auftrages
-
+        :return hash: Die ID des Auftrages
         '''
 
         d = createJob(user, recipients, Mail(subject, body, frm), route, info)
@@ -122,14 +122,11 @@
     def routes(self, session, user, typ):
         '''Gibt eine Liste aller verfügbaren Provider zurück.
 
-        Keywords:
-        apikey[string]: Der API Key
-        typ[string]: Der Typ zu dem die Providerloste ausgeben werden soll
+        :param string apikey: Der API Key
+        :param string typ: Der Typ zu dem die Providerloste ausgeben werden soll
                      Einer der Liste ["sms","fax","mail"]
 
-        Return:
-        providerlist[list]: Eine Liste aller möglichen Provider
-
+        :return list: Eine Liste aller möglichen Provider
         '''
         user = session.merge(user)
         offers = user.routes(typ)
@@ -141,15 +138,11 @@
     def defaultRoute(self, session, user, typ):
         '''Gibt den Standardprovider zurück.
  
-        Keywords:
-        apikey[string]: Der API Key
-        typ[string]: Der Typ zu dem die Providerliste ausgeben werden soll
+        :param string apikey: Der API Key
+        :param string typ: Der Typ zu dem die Providerliste ausgeben werden soll
                      Einer der Liste ["sms","fax","mail"]
 
-        Return:
-        provider[string]: Der Standardprovider für den angeben Typ
-
-
+        :return string: Der Standardprovider für den angeben Typ
         '''
         user = session.merge(user)
         offers = user.routes(typ, default=True)
@@ -160,17 +153,25 @@
     def bill(self, session, user):
         '''Gibt eine Rechnung zurück über die noch nicht abgerechneten Nachrichten und des Preises.
 
-        Keywords:
-        apikey[string]: Der API Key
+        :param string apikey: Der API Key
+
+        :return dict:
+            - `route` -- Entspricht einer Route; **"total"** für die Gesammtübersicht
+            - [`route`][`info`][**anz**] -- Anzahl der verschickten Nachrichten pro "Infoklasse"
+            - [`route`][`info`][**price**] -- Preis pro "Infoklasse"
+            - [`route` | **total**][**anz**] -- Anzahl der verschickten Nachrichten pro Route 
+            - [`route` | **total**][**price**] -- Preis für eine Route
 
-        Return:
-        bills[dict]: Eine Liste nach Nachrichtentypen
-        bill[route][info].anz: Anzahl der verschickten Nachrichten pro "Infoklasse"
-        bill[route][info].price: Preis pro "Infoklasse"
-        bill[route].anz: Anzahl der verschickten Nachrichten pro Route 
-        bill[route].price: Preis für eine Route
-        total.price: der Gesammtpreis
-        total.anz: die Gesammtanzahl
+        >>> bill(APIKEY)
+        {"route1": {"info1":{"anz":1,"price":2.00},
+                    "info2":{"anz":2,"price":5.00},
+                    "anz":3,"price":7.00},
+        "route2":  {"info1":{"anz":3, "price":1.00},
+                    "info3":{"anz":4, "price":8.00},
+                    "anz":7, "price":9.00},
+        "total":   {"anz":10, "price":16.00}
+        }
+
         '''
         ret={'total':{'price':0, 'anz':0}}
         user=session.merge(user)
@@ -192,11 +193,9 @@
     def telnumber(self,recipients):
         '''Gibt True zurück, falls alle übergebene Telefonnummern valide sind.
         
-        Keywords:
-        recipients[list]: Eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
+        :param list recipients: Eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
 
-        Return:
-        True: alle übergebene Nummern sind valide
+        :return: True -- alle übergebene Nummern sind valide
         '''
         return True
 
@@ -204,10 +203,8 @@
     def email(self,recipients):
         '''Gibt True zurück, falls alle übergebene Emailadressen valide sind.
         
-        Keywords:
-        recipients[list]: Eine Liste von Emailadressen
+        :param list recipients: Eine Liste von Emailadressen
 
-        Return:
-        True: alle übergebene Nummern sind valide
+        :return: True -- alle übergebene Nummern sind valide
         '''
         return True
--- a/iro/offer/provider.py	Sun Mar 25 20:11:34 2012 +0200
+++ b/iro/offer/provider.py	Sun Mar 25 20:14:35 2012 +0200
@@ -4,7 +4,20 @@
 from ..config import Option, Config
 
 class Provider(Config):
+    """Base class for Providerbackends."""
+
+    testmode = False
+    """- **True** -- no message to external provider should be send.
+    - **False** (default) -- message are send to external provider."""
     def __init__(self, name, typs={}):
+        """Constructor for Provider class.
+        
+        :param string name: Name of the Provider.
+        :param dict typs: A Dictonary with typs and routes.
+
+        >>> p = Provider("myProvider",{"sms":["route1","route2"]})
+        """
+
         Config.__init__(self, name)
         self.typs=typs
         self.testmode = False
@@ -12,13 +25,33 @@
         self.options = {
                 "typ":Option(vProvider, long="One available provider typ.", must=True, default=name)
                 }
+        """Options dict for Options used in configuration file (see :class:`iro.config.Option`). Ordering of configuration fields are done by :attr:`order`. 
+        
+        Sample::
+        
+               {"typ":Option(vProvider, long="One available provider typ.", must=True, default="default")}
+        
+        A child class typically use update to add more options (see code of :class:`iro.offer.smtp.SMTP`).
+        """
 
         self.order = ["typ"]
+        """ A list for ordering the options dict (:attr:`options`). """
 
     def send(self, typ, route, recipient, message):
+        """Main send function, that is called, for every single message.
+
+        .. note::
+            This function is not used directly. Normally :func:`~iro.offer.provider.Provider.getSendFunc` return this function with typ and route bound."""
         pass
 
     def getSendFunc(self, typ, route):
+        """Returns the actually send Functionfor a given typ and route.
+        
+        Normally it returns the send function with typ and route bound.
+
+        :raises: :exc:`~iro.error.NoRoute`, :exc:`~iro.error.NoTyp`
+        """
+
         try:
             if route not in self.typs[typ]:
                 raise NoRoute(route)
@@ -27,6 +60,12 @@
         return partial(self.send, typ, route)
 
 def getProvider(name, typ, config):
+    '''creates a provider object and init this with config.
+   
+    :param dict config: The Configuration dict. Normally you use ``configParser.items("section")``.
+    :param string typ: A valid typ
+    :raises: :exc:`~iro.error.NoProvider`
+    '''
     try:
         p = providers[typ](name)
         p.load(config)
@@ -35,8 +74,26 @@
         raise NoProvider(typ)
 
 def vProvider(typ, field):
+    '''validator to test the existence of the typ.
+
+    :param string typ: A typ
+    :param string field: A field name used for the Exception.
+    :return:
+        - valid -- returns typ
+        - invalid -- raises :class:`~iro.error.ValidateException`
+
+    :raises: :exc:`~iro.error.ValidateException`
+    '''
     if typ not in providers.keys():
         raise ValidateException()
     return typ
 
 providers={}
+"""Avalable Providers.
+    - **key** -- typ of provider (see configuration typ field).
+    - **value** -- class to handle specific Providertyp.
+
+To extend provider typs, just add this new typ to this dict.
+see :doc:`provider`
+   
+"""
--- a/iro/offer/smstrade.py	Sun Mar 25 20:11:34 2012 +0200
+++ b/iro/offer/smstrade.py	Sun Mar 25 20:14:35 2012 +0200
@@ -38,9 +38,11 @@
     90 : "Versand nicht moeglich.",
     100 : "SMS wurde versendet.",
     }
+"""statuscodes of external smstrade API"""
 
 
 class SmstradeException(ExternalException):
+    """An excetion that connects the status code with the excetion string (see :attr:`statusCodes`)"""
     def __init__(self,status):
         ExternalException.__init__(self)
         self.status = status
@@ -51,25 +53,32 @@
 
 
 class StatusCode:
-     def __init__(self,code, exID=None, costs=Decimal("0.0"), count=0):
+    """Class that represents the output of one smstrade request."""
+    def __init__(self,code, exID=None, costs=Decimal("0.0"), count=0):
         self.code = code
         
         self.exID = exID
         self.costs = Decimal(costs)
         self.count = int(count)
      
-     def __str__(self):
+    def __str__(self):
         if self.code in statusCodes.keys():
             return "%i: %s"%(self.code, statusCodes[self.code])
         
         return "%i: unknown statuscode."%self.code
 
-     def __int__(self):
+    def __int__(self):
         return self.code
 
 class Smstrade(Provider):
-    """
-    s. auch http://kundencenter.smstrade.de/sites/smstrade.de.kundencenter/__pdf/SMS-Gateway_HTTP_API_v2.pdf
+    """A Provider to send SMS to recipients using smstrade.
+    Smstrade only supports to send SMS  and four diffrent routes: ``["basic","economy","gold","direct"]``.
+
+    It needs a smstrade Gateway Key https://login.smstrade.de/index.php?gateway in configuration file.
+
+    smstrade API documentation:  http://kundencenter.smstrade.de/sites/smstrade.de.kundencenter/__pdf/SMS-Gateway_HTTP_API_v2.pdf
+
+    The smstrade API supports a debug mode, that can be set  with :attr:`~iro.offer.provider.Provider.testmode`.
     """
     params= {"debug":("boolean",False),
             "concat_sms":('boolean',False),
@@ -77,6 +86,8 @@
             "count":('boolean',False),
             "cost":('boolean',False),
            }
+    '''dict for standrd values of the smstrade api, it is used to get the right values to the API.'''
+
     def __init__(self, name):       
         self.url = "https://gateway.smstrade.de"
         Provider.__init__(self, name, {"sms":["basic","economy","gold","direct"]})
@@ -86,7 +97,15 @@
         self.order.append("key")
 
     def send(self, route, recipient, sms):
-        """send SMS with $sms to $recipients"""
+        """send on SMS to recipients via route
+        
+        :param string route: A valid route ``["basic", "economy", "gold", "direct"]
+        :param string recipient: Mobilenumber of recipient
+        :param `iro.model.message.sms` sms: the sms to send
+        :return:
+            - All went ok -- :class:`iro.model.status.Status` object
+            - otherwise -- an exception
+        """
         #logger.debug('smstrade.sendSMS(%s,%s)'%(sms,  recipient))
 
         route = unicode(route)
@@ -105,9 +124,14 @@
             raise SmstradeException(s)
 
     def __send(self, route, to, sms):
-        """ This function is the main part of the request to the sms service.    
-        The function has to return a unicode formated string that will represent the answer of the sms service
-        to the request."""
+        """ This is the main function to request to the sms service.    
+
+        :param string route: A valid route ``["basic", "economy", "gold", "direct"]
+        :param string recipient: Mobilenumber of recipient
+        :param `iro.model.message.sms` sms: the sms to send
+        :return: a :class:`.StatusCode` object
+        """
+        
         #logger.debug('smstrade._send(%s,%s,%s)'%( route, to, sms))
         parameters= {"key": self.key,
                 "route": route,
@@ -151,6 +175,8 @@
         return StatusCode(int(data[0]),exID=data[1],costs=data[2],count=data[3])
 
     def getSendFunc(self, typ, route):
+        """returns  a partial :meth:`send` methed with bounded route, if typ and route is valid."""
+
         Provider.getSendFunc(self, typ, route)
         return partial(self.send,route)
 
--- a/iro/offer/smtp.py	Sun Mar 25 20:11:34 2012 +0200
+++ b/iro/offer/smtp.py	Sun Mar 25 20:14:35 2012 +0200
@@ -21,6 +21,12 @@
 from .provider import Provider, providers
 
 class SMTP(Provider):
+    """A SMTP Provider to send emails.
+    This Provider has only one typ ``"mail"`` and one route ``None``. 
+    
+    If :attr:`~iro.offer.provider.Provider.testmode` is **True** no mail will be send, only a connection is created to server.
+
+    """
     def __init__(self, name):
         Provider.__init__(self,name,{"mail":[None]})
         self.options.update({
@@ -35,6 +41,14 @@
         self.order.extend(["host","port","user","password","SSL","TLS","send_from"])
 
     def send(self, recipient, mail):   
+        """sends a mail to recipient
+        
+        :param string recipient: A valid email address.
+        :param `iro.model.message.Mail` mail: Mail to send.
+        :return: 
+            - All went ok -- :class:`iro.model.status.Status` object
+            - otherwise -- an exception
+        """
         if not self.testmode:
             if self.SSL:
                 smtp = smtplib.SMTP_SSL(self.host,self.port)
@@ -54,7 +68,7 @@
             
             tmpmail=copy.deepcopy(mail)
             tmpmail.content['From'] = frm 
-            tmpmail.content['To']=recipient
+            tmpmail.content['To'] = recipient
             if not self.testmode:
                 smtp.sendmail(frm,  recipient, tmpmail.as_string())
             return Status(self, None)
@@ -62,6 +76,8 @@
             smtp.quit()
 
     def getSendFunc(self, typ, route):
+        """returns :meth:`send` method, if typ and route is valid."""
+
         Provider.getSendFunc(self, typ, route)
         return self.send