# HG changeset patch # User Sandro Knauß # Date 1332699275 -7200 # Node ID e8d56537c9ccd245a8a7a1c9cf3c910bb3548cc7 # Parent d0de2ca7201a721c4ff69ca982832438fd21cead start documenting with reST syntax. diff -r d0de2ca7201a -r e8d56537c9cc iro/controller/viewinterface.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 diff -r d0de2ca7201a -r e8d56537c9cc iro/offer/provider.py --- 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` + +""" diff -r d0de2ca7201a -r e8d56537c9cc iro/offer/smstrade.py --- 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) diff -r d0de2ca7201a -r e8d56537c9cc iro/offer/smtp.py --- 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