diff --git a/openerp/.apidoc b/openerp/.apidoc new file mode 100644 index 00000000000..9109e4388fe --- /dev/null +++ b/openerp/.apidoc @@ -0,0 +1 @@ +excludes: pychart release openerp-server test run_tests addons/base_quality_interrogation \ No newline at end of file diff --git a/openerp/netsvc.py b/openerp/netsvc.py index 323062312b1..3a2add26421 100644 --- a/openerp/netsvc.py +++ b/openerp/netsvc.py @@ -57,6 +57,9 @@ def close_socket(sock): sock.close() +#.apidoc title: Common Services: netsvc +#.apidoc module-mods: member-order: bysource + class Service(object): """ Base class for *Local* services @@ -242,19 +245,22 @@ def init_alternative_logger(): logger.setLevel(logging.ERROR) class Agent(object): - """Singleton that keeps track of cancellable tasks to run at a given - timestamp. - The tasks are caracterised by: + """ Singleton that keeps track of cancellable tasks to run at a given + timestamp. + + The tasks are characterised by: + * a timestamp * the database on which the task run * the function to call * the arguments and keyword arguments to pass to the function Implementation details: - Tasks are stored as list, allowing the cancellation by setting - the timestamp to 0. - A heapq is used to store tasks, so we don't need to sort - tasks ourself. + + - Tasks are stored as list, allowing the cancellation by setting + the timestamp to 0. + - A heapq is used to store tasks, so we don't need to sort + tasks ourself. """ __tasks = [] __tasks_by_db = {} diff --git a/openerp/osv/__init__.py b/openerp/osv/__init__.py index 630090954e6..b32d81d659e 100644 --- a/openerp/osv/__init__.py +++ b/openerp/osv/__init__.py @@ -22,6 +22,7 @@ import osv import fields +#.apidoc title: Object Services and Relational Mapping # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py index c7fef6b5089..54726a289f2 100644 --- a/openerp/osv/expression.py +++ b/openerp/osv/expression.py @@ -23,6 +23,8 @@ from openerp.tools import flatten, reverse_enumerate import fields +#.apidoc title: Domain Expressions + NOT_OPERATOR = '!' OR_OPERATOR = '|' AND_OPERATOR = '&' diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index d3b37b9226f..b7979f03812 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -19,18 +19,19 @@ # ############################################################################## -# . Fields: -# - simple -# - relations (one2many, many2one, many2many) -# - function -# -# Fields Attributes: -# _classic_read: is a classic sql fields -# _type : field type -# readonly -# required -# size -# +""" Fields: + - simple + - relations (one2many, many2one, many2many) + - function + + Fields Attributes: + * _classic_read: is a classic sql fields + * _type : field type + * readonly + * required + * size +""" + import datetime as DT import string import sys @@ -51,6 +52,12 @@ def _symbol_set(symb): class _column(object): + """ Base of all fields, a database column + + An instance of this object is a *description* of a database column. It will + not hold any data, but only provide the methods to manipulate data of an + ORM record or even prepare/update the database to hold such a field of data. + """ _classic_read = True _classic_write = True _prefetch = True @@ -855,6 +862,15 @@ class function(_column): # --------------------------------------------------------- class related(function): + """Field that points to some data inside another field of the current record. + + Example:: + + _columns = { + 'foo_id': fields.many2one('my.foo', 'Foo'), + 'bar': fields.related('frol', 'foo_id', type='char', string='Frol of Foo'), + } + """ def _fnct_search(self, tobj, cr, uid, obj=None, name=None, domain=None, context=None): self._field_get2(cr, uid, obj, context) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index f4a7dfa8ed2..2ced177fdb9 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -19,24 +19,28 @@ # ############################################################################## -# -# Object relationnal mapping to postgresql module -# . Hierarchical structure -# . Constraints consistency, validations -# . Object meta Data depends on its status -# . Optimised processing by complex query (multiple actions at once) -# . Default fields value -# . Permissions optimisation -# . Persistant object: DB postgresql -# . Datas conversions -# . Multi-level caching system -# . 2 different inheritancies -# . Fields: -# - classicals (varchar, integer, boolean, ...) -# - relations (one2many, many2one, many2many) -# - functions -# -# +#.apidoc title: Object Relational Mapping +#.apidoc module-mods: member-order: bysource + +""" + Object relational mapping to database (postgresql) module + * Hierarchical structure + * Constraints consistency, validations + * Object meta Data depends on its status + * Optimised processing by complex query (multiple actions at once) + * Default fields value + * Permissions optimisation + * Persistant object: DB postgresql + * Datas conversions + * Multi-level caching system + * 2 different inheritancies + * Fields: + - classicals (varchar, integer, boolean, ...) + - relations (one2many, many2one, many2many) + - functions + +""" + import calendar import copy import datetime @@ -125,8 +129,9 @@ class except_orm(Exception): class BrowseRecordError(Exception): pass -# Readonly python database object browser class browse_null(object): + """ Readonly python database object browser + """ def __init__(self): self.id = False @@ -154,6 +159,11 @@ class browse_null(object): # TODO: execute an object method on browse_record_list # class browse_record_list(list): + """ Collection of browse objects + + Such an instance will be returned when doing a ``browse([ids..])`` + and will be iterable, yielding browse() objects + """ def __init__(self, lst, context=None): if not context: @@ -163,13 +173,25 @@ class browse_record_list(list): class browse_record(object): + """ An object that behaves like a row of an object's table. + It has attributes after the columns of the corresponding object. + + Examples:: + + uobj = pool.get('res.users') + user_rec = uobj.browse(cr, uid, 104) + name = user_rec.name + """ logger = netsvc.Logger() def __init__(self, cr, uid, id, table, cache, context=None, list_class=None, fields_process=None): - ''' - table : the object (inherited from orm) - context : dictionary with an optional context - ''' + """ + @param cache a dictionary of model->field->data to be shared accross browse + objects, thus reducing the SQL read()s . It can speed up things a lot, + but also be disastrous if not discarded after write()/unlink() operations + @param table the object (inherited from orm) + @param context dictionary with an optional context + """ if fields_process is None: fields_process = {} if context is None: @@ -363,10 +385,10 @@ class browse_record(object): def get_pg_type(f): - ''' + """ returns a tuple (type returned by postgres when the column was created, type expression to create the column) - ''' + """ type_dict = { fields.boolean: 'bool', @@ -732,7 +754,7 @@ class orm_template(object): :param cr: database cursor :param user: current user id - :param select: id or list of ids + :param select: id or list of ids. :param context: context arguments, like lang, time zone :rtype: object or list of objects requested diff --git a/openerp/osv/osv.py b/openerp/osv/osv.py index acf262af343..1327efe5731 100644 --- a/openerp/osv/osv.py +++ b/openerp/osv/osv.py @@ -19,9 +19,7 @@ # ############################################################################## -# -# OSV: Objects Services -# +#.apidoc title: Objects Services (OSV) import orm import openerp.netsvc as netsvc diff --git a/openerp/osv/query.py b/openerp/osv/query.py index ab4f4143634..0b2bf47305a 100644 --- a/openerp/osv/query.py +++ b/openerp/osv/query.py @@ -19,6 +19,7 @@ # ############################################################################## +#.apidoc title: Query object def _quote(to_quote): if '"' not in to_quote: diff --git a/openerp/report/__init__.py b/openerp/report/__init__.py index ca2b86d9731..646967f00d1 100644 --- a/openerp/report/__init__.py +++ b/openerp/report/__init__.py @@ -31,5 +31,7 @@ import report_sxw import printscreen +#.apidoc title: Reporting Support and Engines + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/report/printscreen/__init__.py b/openerp/report/printscreen/__init__.py index b9dd9702b7c..e940a7e467c 100644 --- a/openerp/report/printscreen/__init__.py +++ b/openerp/report/printscreen/__init__.py @@ -22,6 +22,11 @@ import ps_list import ps_form +#.apidoc title: Printscreen Support + +""" A special report, that is automatically formatted to look like the + screen contents of Form/List Views. +""" # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/report/printscreen/ps_form.py b/openerp/report/printscreen/ps_form.py index d997f1eb038..3afe9d5f401 100644 --- a/openerp/report/printscreen/ps_form.py +++ b/openerp/report/printscreen/ps_form.py @@ -28,6 +28,8 @@ from lxml import etree import time, os +#.apidoc title: Printscreen for Form Views + class report_printscreen_list(report_int): def __init__(self, name): report_int.__init__(self, name) diff --git a/openerp/report/printscreen/ps_list.py b/openerp/report/printscreen/ps_list.py index 8b0ece6eaa0..dc280a53e3e 100644 --- a/openerp/report/printscreen/ps_list.py +++ b/openerp/report/printscreen/ps_list.py @@ -31,6 +31,8 @@ import time, os from operator import itemgetter from datetime import datetime +#.apidoc title: Printscreen for List Views + class report_printscreen_list(report_int): def __init__(self, name): report_int.__init__(self, name) diff --git a/openerp/report/pyPdf/__init__.py b/openerp/report/pyPdf/__init__.py index af02553da69..8d17648d4b9 100644 --- a/openerp/report/pyPdf/__init__.py +++ b/openerp/report/pyPdf/__init__.py @@ -1,2 +1,5 @@ from pdf import PdfFileReader, PdfFileWriter +#.apidoc title: pyPdf Engine + __all__ = ["pdf"] + diff --git a/openerp/report/render/__init__.py b/openerp/report/render/__init__.py index 1becd5ee514..1b751fa4104 100644 --- a/openerp/report/render/__init__.py +++ b/openerp/report/render/__init__.py @@ -23,6 +23,8 @@ from simple import simple from rml import rml, rml2html, rml2txt, odt2odt , html2html, makohtml2html from render import render +#.apidoc title: Report Rendering + try: import Image except ImportError: diff --git a/openerp/report/render/html2html/__init__.py b/openerp/report/render/html2html/__init__.py index bb497aca94f..40917030f45 100644 --- a/openerp/report/render/html2html/__init__.py +++ b/openerp/report/render/html2html/__init__.py @@ -21,5 +21,7 @@ from html2html import parseString +#.apidoc title: HTML to HTML engine + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/report/render/makohtml2html/__init__.py b/openerp/report/render/makohtml2html/__init__.py index 9303d40b850..ee458d04718 100644 --- a/openerp/report/render/makohtml2html/__init__.py +++ b/openerp/report/render/makohtml2html/__init__.py @@ -19,4 +19,7 @@ # ############################################################################## -from makohtml2html import parseNode \ No newline at end of file +from makohtml2html import parseNode + +#.apidoc title: MAKO to HTML engine + diff --git a/openerp/report/render/odt2odt/__init__.py b/openerp/report/render/odt2odt/__init__.py index 775cbabb3d4..7155923b6b6 100644 --- a/openerp/report/render/odt2odt/__init__.py +++ b/openerp/report/render/odt2odt/__init__.py @@ -21,4 +21,6 @@ from odt2odt import parseNode +#.apidoc title: ODT to ODT engine + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/openerp/report/render/rml2html/__init__.py b/openerp/report/render/rml2html/__init__.py index 52c52863008..96b9afc6e70 100644 --- a/openerp/report/render/rml2html/__init__.py +++ b/openerp/report/render/rml2html/__init__.py @@ -21,5 +21,7 @@ from rml2html import parseString +#.apidoc title: RML to HTML engine + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/report/render/rml2pdf/__init__.py b/openerp/report/render/rml2pdf/__init__.py index 001aea413fd..ffe9339b659 100644 --- a/openerp/report/render/rml2pdf/__init__.py +++ b/openerp/report/render/rml2pdf/__init__.py @@ -21,3 +21,5 @@ from trml2pdf import parseString, parseNode +#.apidoc title: RML to PDF engine + diff --git a/openerp/report/render/rml2pdf/customfonts.py b/openerp/report/render/rml2pdf/customfonts.py index 17a8a9c0ab7..bc70d1f65ea 100644 --- a/openerp/report/render/rml2pdf/customfonts.py +++ b/openerp/report/render/rml2pdf/customfonts.py @@ -28,6 +28,8 @@ from reportlab import rl_config from openerp.tools import config +#.apidoc title: TTF Font Table + """This module allows the mapping of some system-available TTF fonts to the reportlab engine. diff --git a/openerp/report/render/rml2txt/__init__.py b/openerp/report/render/rml2txt/__init__.py index 56c577d51d3..cc0530eedb6 100644 --- a/openerp/report/render/rml2txt/__init__.py +++ b/openerp/report/render/rml2txt/__init__.py @@ -21,5 +21,14 @@ from rml2txt import parseString, parseNode +#.apidoc title: RML to TXT engine + +""" This engine is the minimalistic renderer of RML documents into text files, + using spaces and newlines to format. + + It was needed in some special applications, where legal reports need to be + printed in special (dot-matrix) printers. +""" + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/service/__init__.py b/openerp/service/__init__.py index a5f28e95678..b9ee98fcab0 100644 --- a/openerp/service/__init__.py +++ b/openerp/service/__init__.py @@ -23,6 +23,16 @@ import http_server import netrpc_server import web_services +#.apidoc title: RPC Services + +""" Classes of this module implement the network protocols that the + OpenERP server uses to communicate with remote clients. + + Some classes are mostly utilities, whose API need not be visible to + the average user/developer. Study them only if you are about to + implement an extension to the network protocols, or need to debug some + low-level behavior of the wire. +""" # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/service/http_server.py b/openerp/service/http_server.py index a7524186fe2..61713e9f2dd 100644 --- a/openerp/service/http_server.py +++ b/openerp/service/http_server.py @@ -26,10 +26,19 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ############################################################################### -""" This file contains instance of the http server. +#.apidoc title: HTTP and XML-RPC Server +""" This module offers the family of HTTP-based servers. These are not a single + class/functionality, but a set of network stack layers, implementing + extendable HTTP protocols. + The OpenERP server defines a single instance of a HTTP server, listening at + the standard 8069, 8071 ports (well, it is 2 servers, and ports are + configurable, of course). This "single" server then uses a `MultiHTTPHandler` + to dispatch requests to the appropriate channel protocol, like the XML-RPC, + static HTTP, DAV or other. """ + from websrv_lib import * import openerp.netsvc as netsvc import errno diff --git a/openerp/service/netrpc_server.py b/openerp/service/netrpc_server.py index b4d5a74dc48..70855a018e5 100644 --- a/openerp/service/netrpc_server.py +++ b/openerp/service/netrpc_server.py @@ -19,6 +19,8 @@ # ############################################################################## +#.apidoc title: NET-RPC Server + """ This file contains instance of the net-rpc server diff --git a/openerp/service/security.py b/openerp/service/security.py index ec13fe3de8c..86c381b683f 100644 --- a/openerp/service/security.py +++ b/openerp/service/security.py @@ -22,8 +22,11 @@ import openerp.pooler as pooler import openerp.tools as tools -# When rejecting a password, hide the traceback +#.apidoc title: Authentication helpers + class ExceptionNoTb(Exception): + """ When rejecting a password, hide the traceback + """ def __init__(self, msg): super(ExceptionNoTb, self).__init__(msg) self.traceback = ('','','') diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 39457807868..40e7ccf1d69 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -38,6 +38,15 @@ import locale import logging from cStringIO import StringIO +#.apidoc title: Exported Service methods +#.apidoc module-mods: member-order: bysource + +""" This python module defines the RPC methods available to remote clients. + + Each 'Export Service' is a group of 'methods', which in turn are RPC + procedures to be called. Each method has its own arguments footprint. +""" + class db(netsvc.ExportService): def __init__(self, name="db"): netsvc.ExportService.__init__(self, name) diff --git a/openerp/service/websrv_lib.py b/openerp/service/websrv_lib.py index 859845de8f8..2e098169bae 100644 --- a/openerp/service/websrv_lib.py +++ b/openerp/service/websrv_lib.py @@ -24,8 +24,12 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ############################################################################### +#.apidoc title: HTTP Layer library (websrv_lib) + """ Framework for generic http servers + This library contains *no* OpenERP-specific functionality. It should be + usable in other projects, too. """ import socket diff --git a/openerp/sql_db.py b/openerp/sql_db.py index e759a13e1d3..43a508f9082 100644 --- a/openerp/sql_db.py +++ b/openerp/sql_db.py @@ -20,6 +20,19 @@ # ############################################################################## +#.apidoc title: PostgreSQL interface + +""" +The PostgreSQL connector is a connectivity layer between the OpenERP code and +the database, *not* a database abstraction toolkit. Database abstraction is what +the ORM does, in fact. + +See also: the `pooler` module +""" + +#.apidoc add-functions: print_stats +#.apidoc add-classes: Cursor Connection ConnectionPool + __all__ = ['db_connect', 'close_db'] from threading import currentThread @@ -66,6 +79,13 @@ re_into = re.compile('.* into "?([a-zA-Z_0-9]+)"? .*$'); sql_counter = 0 class Cursor(object): + """ Cursor is an open transaction to Postgres, utilizing a TCP connection + + A lightweight wrapper around psycopg2's `psycopg1cursor` objects + + This is the object behind the `cr` variable used all over the OpenERP + code. + """ IN_MAX = 1000 # decent limit on size of IN queries - guideline = Oracle limit __logger = None @@ -233,22 +253,37 @@ class Cursor(object): @check def commit(self): + """ Perform an SQL `COMMIT` + """ return self._cnx.commit() @check def rollback(self): + """ Perform an SQL `ROLLBACK` + """ return self._cnx.rollback() @check def __getattr__(self, name): return getattr(self._obj, name) + """ Set the mode of postgres operations for all cursors + """ + """Obtain the mode of postgres operations for all cursors + """ class PsycoConnection(psycopg2.extensions.connection): pass class ConnectionPool(object): - + """ The pool of connections to database(s) + + Keep a set of connections to pg databases open, and reuse them + to open cursors for all transactions. + + The connections are *not* automatically closed. Only a close_db() + can trigger that. + """ __logger = logging.getLogger('db.connection_pool') def locked(fun): @@ -340,6 +375,8 @@ class ConnectionPool(object): class Connection(object): + """ A lightweight instance of a connection to postgres + """ __logger = logging.getLogger('db.connection') def __init__(self, pool, dbname): diff --git a/openerp/tiny_socket.py b/openerp/tiny_socket.py index cc0f09ec976..29782109347 100644 --- a/openerp/tiny_socket.py +++ b/openerp/tiny_socket.py @@ -26,9 +26,11 @@ import marshal import netsvc +#.apidoc title: Net-RPC classes + class Myexception(Exception): """ - custome exception object store + custom exception object store * faultcode * faulestring * args diff --git a/openerp/tools/__init__.py b/openerp/tools/__init__.py index 16042841b6e..3d1cdc960ab 100644 --- a/openerp/tools/__init__.py +++ b/openerp/tools/__init__.py @@ -32,5 +32,7 @@ from pdf_utils import * from yaml_import import * from sql import * +#.apidoc title: Tools + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/tools/amount_to_text.py b/openerp/tools/amount_to_text.py index 0b626af8a7a..331640a2c28 100644 --- a/openerp/tools/amount_to_text.py +++ b/openerp/tools/amount_to_text.py @@ -34,8 +34,9 @@ denom_fr = ( '', 'Décillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion', 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Icosillion', 'Vigintillion' ) -# convert a value < 100 to French. def _convert_nn_fr(val): + """ convert a value < 100 to French + """ if val < 20: return to_19_fr[val] for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_fr)): @@ -44,10 +45,13 @@ def _convert_nn_fr(val): return dcap + '-' + to_19_fr[val % 10] return dcap -# convert a value < 1000 to french, special cased because it is the level that kicks -# off the < 100 special case. The rest are more general. This also allows you to -# get strings in the form of 'forty-five hundred' if called directly. def _convert_nnn_fr(val): + """ convert a value < 1000 to french + + special cased because it is the level that kicks + off the < 100 special case. The rest are more general. This also allows you to + get strings in the form of 'forty-five hundred' if called directly. + """ word = '' (mod, rem) = (val % 100, val // 100) if rem > 0: @@ -98,8 +102,9 @@ denom_nl = ( '', 'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion', 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Novemdecillion', 'Vigintillion' ) -# convert a value < 100 to Dutch. def _convert_nn_nl(val): + """ convert a value < 100 to Dutch + """ if val < 20: return to_19_nl[val] for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_nl)): @@ -108,10 +113,13 @@ def _convert_nn_nl(val): return dcap + '-' + to_19_nl[val % 10] return dcap -# convert a value < 1000 to Dutch, special cased because it is the level that kicks -# off the < 100 special case. The rest are more general. This also allows you to -# get strings in the form of 'forty-five hundred' if called directly. def _convert_nnn_nl(val): + """ convert a value < 1000 to Dutch + + special cased because it is the level that kicks + off the < 100 special case. The rest are more general. This also allows you to + get strings in the form of 'forty-five hundred' if called directly. + """ word = '' (mod, rem) = (val % 100, val // 100) if rem > 0: @@ -160,10 +168,11 @@ def add_amount_to_text_function(lang, func): #TODO: we should use the country AND language (ex: septante VS soixante dix) #TODO: we should use en by default, but the translation func is yet to be implemented def amount_to_text(nbr, lang='fr', currency='euro'): - """ - Converts an integer to its textual representation, using the language set in the context if any. - Example: - 1654: mille six cent cinquante-quatre. + """ Converts an integer to its textual representation, using the language set in the context if any. + + Example:: + + 1654: mille six cent cinquante-quatre. """ # if nbr > 1000000: ##TODO: use logger diff --git a/openerp/tools/amount_to_text_en.py b/openerp/tools/amount_to_text_en.py index 77d18cbb55d..914794118aa 100644 --- a/openerp/tools/amount_to_text_en.py +++ b/openerp/tools/amount_to_text_en.py @@ -34,8 +34,9 @@ denom = ( '', 'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion', 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Novemdecillion', 'Vigintillion' ) -# convert a value < 100 to English. def _convert_nn(val): + """convert a value < 100 to English. + """ if val < 20: return to_19[val] for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)): @@ -44,10 +45,12 @@ def _convert_nn(val): return dcap + '-' + to_19[val % 10] return dcap -# convert a value < 1000 to english, special cased because it is the level that kicks -# off the < 100 special case. The rest are more general. This also allows you to -# get strings in the form of 'forty-five hundred' if called directly. def _convert_nnn(val): + """ + convert a value < 1000 to english, special cased because it is the level that kicks + off the < 100 special case. The rest are more general. This also allows you to + get strings in the form of 'forty-five hundred' if called directly. + """ word = '' (mod, rem) = (val % 100, val // 100) if rem > 0: @@ -94,10 +97,11 @@ _translate_funcs = {'en' : amount_to_text} #TODO: we should use the country AND language (ex: septante VS soixante dix) #TODO: we should use en by default, but the translation func is yet to be implemented def amount_to_text(nbr, lang='en', currency='euro'): - """ - Converts an integer to its textual representation, using the language set in the context if any. - Example: - 1654: thousands six cent cinquante-quatre. + """ Converts an integer to its textual representation, using the language set in the context if any. + + Example:: + + 1654: thousands six cent cinquante-quatre. """ import openerp.loglevels as loglevels # if nbr > 10000000: diff --git a/openerp/tools/config.py b/openerp/tools/config.py index 9a59235773a..18f40e0011f 100644 --- a/openerp/tools/config.py +++ b/openerp/tools/config.py @@ -45,6 +45,8 @@ class MyOption (optparse.Option, object): self.my_default = attrs.pop('my_default', None) super(MyOption, self).__init__(*opts, **attrs) +#.apidoc title: Server Configuration Loader + def check_ssl(): try: from OpenSSL import SSL diff --git a/openerp/tools/func.py b/openerp/tools/func.py index 4150b3e688b..03463678ffb 100644 --- a/openerp/tools/func.py +++ b/openerp/tools/func.py @@ -30,6 +30,10 @@ except ImportError: # http://svn.python.org/view/python/tags/r254/Lib/functools.py?view=markup def partial(fun, *args, **kwargs): + """ Partial implementation + + See: http://svn.python.org/view/python/tags/r254/Lib/functools.py + """ def _partial(*args2, **kwargs2): return fun(*(args+args2), **dict(kwargs, **kwargs2)) return _partial diff --git a/openerp/tools/graph.py b/openerp/tools/graph.py index 7f85bf1ba35..df3fb39ef47 100755 --- a/openerp/tools/graph.py +++ b/openerp/tools/graph.py @@ -25,11 +25,11 @@ import math class graph(object): def __init__(self, nodes, transitions, no_ancester=None): - """Initailize graph's object + """Initialize graph's object - @param nodes: list of ids of nodes in the graph - @param transitions: list of edges in the graph in the form (source_node, destination_node) - @param no_ancester: list of nodes with no incoming edges + @param nodes list of ids of nodes in the graph + @param transitions list of edges in the graph in the form (source_node, destination_node) + @param no_ancester list of nodes with no incoming edges """ self.nodes = nodes or [] @@ -210,8 +210,8 @@ class graph(object): def exchange(self, e, f): """Exchange edges to make feasible-tree optimized - @param edge: edge with negative cut-value - @param edge: new edge with minimum slack-value + @param edge edge with negative cut-value + @param edge new edge with minimum slack-value """ self.tree_edges.__delitem__(self.tree_edges.index(e)) self.tree_edges.append(f) @@ -221,7 +221,7 @@ class graph(object): def enter_edge(self, edge): """Finds a new_edge with minimum slack value to replace an edge with negative cut-value - @param edge: edge with negative cut-value + @param edge edge with negative cut-value """ self.head_nodes = [] @@ -345,8 +345,8 @@ class graph(object): def median_value(self, node, adj_rank): """Returns median value of a vertex , defined as the median position of the adjacent vertices - @param node: node to process - @param adj_rank: rank 1 less than the node's rank + @param node node to process + @param adj_rank rank 1 less than the node's rank """ adj_nodes = self.adj_position(node, adj_rank) l = len(adj_nodes) @@ -367,8 +367,8 @@ class graph(object): def adj_position(self, node, adj_rank): """Returns list of the present positions of the nodes adjacent to node in the given adjacent rank. - @param node: node to process - @param adj_rank: rank 1 less than the node's rank + @param node node to process + @param adj_rank rank 1 less than the node's rank """ pre_level_nodes = self.levels.get(adj_rank, []) @@ -606,7 +606,7 @@ class graph(object): def rank(self): """Finds the optimized rank of the nodes using Network-simplex algorithm - @param start: starting node of the component + @param start starting node of the component """ self.levels = {} self.critical_edges = [] @@ -668,7 +668,7 @@ class graph(object): def process(self, starting_node): """Process the graph to find ranks and order of the nodes - @param starting_node: node from where to start the graph search + @param starting_node node from where to start the graph search """ self.start_nodes = starting_node or [] diff --git a/openerp/tools/misc.py b/openerp/tools/misc.py index 4167befd42d..dc66142fc4a 100644 --- a/openerp/tools/misc.py +++ b/openerp/tools/misc.py @@ -20,6 +20,8 @@ # ############################################################################## +#.apidoc title: Utilities: tools.misc + """ Miscelleanous tools used by OpenERP. """ @@ -124,16 +126,18 @@ def exec_command_pipe(name, *args): def file_open(name, mode="r", subdir='addons', pathinfo=False): """Open a file from the OpenERP root, using a subdir folder. + Example:: + >>> file_open('hr/report/timesheer.xsl') >>> file_open('addons/hr/report/timesheet.xsl') >>> file_open('../../base/report/rml_template.xsl', subdir='addons/hr/report', pathinfo=True) - @param name: name of the file - @param mode: file open mode - @param subdir: subdirectory - @param pathinfo: if True returns tupple (fileobject, filepath) + @param name name of the file + @param mode file open mode + @param subdir subdirectory + @param pathinfo if True returns tupple (fileobject, filepath) - @return: fileobject if pathinfo is False else (fileobject, filepath) + @return fileobject if pathinfo is False else (fileobject, filepath) """ import openerp.modules as addons adps = addons.module.ad_paths @@ -217,7 +221,7 @@ def flatten(list): """Flatten a list of elements into a uniqu list Author: Christophe Simonis (christophe@tinyerp.com) - Examples: + Examples:: >>> flatten(['a']) ['a'] >>> flatten('b') @@ -246,6 +250,8 @@ def flatten(list): def reverse_enumerate(l): """Like enumerate but in the other sens + + Usage:: >>> a = ['a', 'b', 'c'] >>> it = reverse_enumerate(a) >>> it.next() @@ -285,16 +291,14 @@ priorities = { } def html2plaintext(html, body_id=None, encoding='utf-8'): + """ From an HTML text, convert the HTML to plain text. + If @param body_id is provided then this is the tag where the + body (not necessarily ) starts. + """ ## (c) Fry-IT, www.fry-it.com, 2007 ## ## download here: http://www.peterbe.com/plog/html2plaintext - - """ from an HTML text, convert the HTML to plain text. - If @body_id is provided then this is the tag where the - body (not necessarily ) starts. - """ - html = ustr(html) from lxml.etree import tostring @@ -351,14 +355,16 @@ def html2plaintext(html, body_id=None, encoding='utf-8'): return html def generate_tracking_message_id(openobject_id): - """Returns a string that can be used in the Message-ID RFC822 header field so we - can track the replies related to a given object thanks to the "In-Reply-To" or - "References" fields that Mail User Agents will set. + """Returns a string that can be used in the Message-ID RFC822 header field + + Used to track the replies related to a given object thanks to the "In-Reply-To" + or "References" fields that Mail User Agents will set. """ return "<%s-openobject-%s@%s>" % (time.time(), openobject_id, socket.gethostname()) def _email_send(smtp_from, smtp_to_list, message, openobject_id=None, ssl=False, debug=False): - """Low-level method to send directly a Message through the configured smtp server. + """ Low-level method to send directly a Message through the configured smtp server. + :param smtp_from: RFC-822 envelope FROM (not displayed to recipient) :param smtp_to_list: RFC-822 envelope RCPT_TOs (not displayed to recipient) :param message: an email.message.Message to send @@ -427,17 +433,16 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non """Send an email. - Arguments: - - `email_from`: A string used to fill the `From` header, if falsy, + @param email_from A string used to fill the `From` header, if falsy, config['email_from'] is used instead. Also used for the `Reply-To` header if `reply_to` is not provided - `email_to`: a sequence of addresses to send the mail to. + @param email_to a sequence of addresses to send the mail to. """ if x_headers is None: x_headers = {} + if not (email_from or config['email_from']): raise ValueError("Sending an email requires either providing a sender " @@ -507,10 +512,9 @@ def sms_send(user, password, api_id, text, to): # FIXME: Use the logger if there is an error return True -#--------------------------------------------------------- -# Class that stores an updateable string (used in wizards) -#--------------------------------------------------------- class UpdateableStr(local): + """ Class that stores an updateable string (used in wizards) + """ def __init__(self, string=''): self.string = string @@ -526,7 +530,8 @@ class UpdateableStr(local): class UpdateableDict(local): - '''Stores an updateable dict to use in wizards''' + """Stores an updateable dict to use in wizards + """ def __init__(self, dict=None): if dict is None: @@ -624,8 +629,13 @@ class UpdateableDict(local): return self.dict.__ne__(y) -# Don't use ! Use res.currency.round() class currency(float): + """ Deprecate + + .. warning:: + + Don't use ! Use res.currency.round() + """ def __init__(self, value, accuracy=2, rounding=None): if rounding is None: @@ -1168,7 +1178,7 @@ def detect_ip_addr(): # times. def get_win32_timezone(): """Attempt to return the "standard name" of the current timezone on a win32 system. - @return: the standard name of the current win32 timezone, or False if it cannot be found. + @return the standard name of the current win32 timezone, or False if it cannot be found. """ res = False if (sys.platform == "win32"): @@ -1186,7 +1196,7 @@ def get_win32_timezone(): def detect_server_timezone(): """Attempt to detect the timezone to use on the server side. Defaults to UTC if no working timezone can be found. - @return: the timezone identifier as expected by pytz.timezone. + @return the timezone identifier as expected by pytz.timezone. """ try: import pytz @@ -1312,7 +1322,7 @@ def server_to_local_timestamp(src_tstamp_str, src_format, dst_format, dst_tz_nam @param ignore_unparsable_time: if True, return False if src_tstamp_str cannot be parsed using src_format or formatted using dst_format. - @return: local/client formatted timestamp, expressed in the local/client timezone if possible + @return local/client formatted timestamp, expressed in the local/client timezone if possible and if tz_offset is true, or src_tstamp_str if timezone offset could not be determined. """ if not src_tstamp_str: diff --git a/openerp/tools/which.py b/openerp/tools/which.py index 66b264bddec..548b836247c 100755 --- a/openerp/tools/which.py +++ b/openerp/tools/which.py @@ -19,8 +19,8 @@ Return a generator which yields full paths in which the *file* name exists in a directory that is part of the file name, or on *path*, and has the given *mode*. - By default, *mode* matches an inclusive OR of os.F_OK and os.X_OK - - an existing executable file. + By default, *mode* matches an inclusive OR of os.F_OK and os.X_OK - an + existing executable file. The *path* is, by default, the ``PATH`` variable on the platform, or the string/iterable passed in as *path*. In the event that a ``PATH`` variable is not found, :const:`os.defpath` is used. diff --git a/openerp/workflow/__init__.py b/openerp/workflow/__init__.py index 50e6181fa5f..959a878f208 100644 --- a/openerp/workflow/__init__.py +++ b/openerp/workflow/__init__.py @@ -21,6 +21,8 @@ import wkf_service +#.apidoc title: Workflow objects + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: