start documenting with reST syntax.
--- 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