[MERGE] docstrings improvements and preparation for api-doc structure
bzr revid: odo@openerp.com-20110701231956-93zu7xtibpo06eqm
This commit is contained in:
commit
7c8665bb69
|
@ -0,0 +1 @@
|
|||
excludes: pychart release openerp-server test run_tests addons/base_quality_interrogation
|
|
@ -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 = {}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
import osv
|
||||
import fields
|
||||
|
||||
#.apidoc title: Object Services and Relational Mapping
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
from openerp.tools import flatten, reverse_enumerate
|
||||
import fields
|
||||
|
||||
#.apidoc title: Domain Expressions
|
||||
|
||||
NOT_OPERATOR = '!'
|
||||
OR_OPERATOR = '|'
|
||||
AND_OPERATOR = '&'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
#
|
||||
# OSV: Objects Services
|
||||
#
|
||||
#.apidoc title: Objects Services (OSV)
|
||||
|
||||
import orm
|
||||
import openerp.netsvc as netsvc
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
#.apidoc title: Query object
|
||||
|
||||
def _quote(to_quote):
|
||||
if '"' not in to_quote:
|
||||
|
|
|
@ -31,5 +31,7 @@ import report_sxw
|
|||
|
||||
import printscreen
|
||||
|
||||
#.apidoc title: Reporting Support and Engines
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
from pdf import PdfFileReader, PdfFileWriter
|
||||
#.apidoc title: pyPdf Engine
|
||||
|
||||
__all__ = ["pdf"]
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -21,5 +21,7 @@
|
|||
|
||||
from html2html import parseString
|
||||
|
||||
#.apidoc title: HTML to HTML engine
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -19,4 +19,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from makohtml2html import parseNode
|
||||
from makohtml2html import parseNode
|
||||
|
||||
#.apidoc title: MAKO to HTML engine
|
||||
|
||||
|
|
|
@ -21,4 +21,6 @@
|
|||
|
||||
from odt2odt import parseNode
|
||||
|
||||
#.apidoc title: ODT to ODT engine
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -21,5 +21,7 @@
|
|||
|
||||
from rml2html import parseString
|
||||
|
||||
#.apidoc title: RML to HTML engine
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -21,3 +21,5 @@
|
|||
|
||||
from trml2pdf import parseString, parseNode
|
||||
|
||||
#.apidoc title: RML to PDF engine
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
#.apidoc title: NET-RPC Server
|
||||
|
||||
""" This file contains instance of the net-rpc server
|
||||
|
||||
|
||||
|
|
|
@ -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 = ('','','')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 []
|
||||
|
|
|
@ -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 <body>) starts.
|
||||
"""
|
||||
## (c) Fry-IT, www.fry-it.com, 2007
|
||||
## <peter@fry-it.com>
|
||||
## 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 <body>) 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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
import wkf_service
|
||||
|
||||
#.apidoc title: Workflow objects
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
Loading…
Reference in New Issue