ext Package

Extensions package.

This package provides some out-of-the-box extensions.

sugar Extension

Provides some syntax sugar to ease acces to objects, records, etc

class openerp_proxy.ext.sugar.ClientSugar(*args, **kwargs)[source]

Bases: odoo_rpc_client.client.Client, odoo_rpc_client.utils.DirMixIn

Provides some syntax sugar for Client class

As one of it’s features is ability to access objects as attributes via object aliases. Each aliase is object name with underscores replaced by double underscores and dots replaced by single underscores and prefixed by underscore.

For example all folowing lines will return same result

sm = client._stock_move
sm = client['stock.move']
sm = client.get_obj('stock.move')

One more features of this extension class, is ability to access plugins directly from client as it’s attributes. So folowing lines are equal

test_plugin = client.plugins.Test
test_plugin = client.Test

Clean client related caches


Property, that holds list of all object aliases for this Client instance

class openerp_proxy.ext.sugar.ObjectSugar(*args, **kwargs)[source]

Bases: odoo_rpc_client.orm.record.ObjectRecords

Provides aditional methods to work with data

Also defines __getitem__ and __call__ methods, to simplify acces to records via ID, name_search and simple search. Detailad below.

Imagine we have Object instance obj:

obj = db.get_obj('stock.move')   # get move obj object
so_obj = db['sale.order']        # get sale order object

And this class provides folowing features.

  1. get record by ID:

    move = obj[125]   # returns stock move record with ID=125
    moves = obj[125,126,127]  # returns record list of three move
                              # records for IDS 125, 126, 127
  2. get total number of records in model:

    len(so_obj)  # returns total number of sale order
  3. iterate over all records in model:

    for so in so_obj:
  4. name_search

    Calling object with record name as first argument will execute name search on passed name:

    so = so_obj('SO005')   # Returns sale order with name 'SO005'
    so2 = so_obj('5')      # If there are more than one records
                           # found by name, then RecordList
                           # will be returned. In this case
                           # this call may return list which will
                           # contain for example sale orders with
                           # names like 'SO005', 'SO015', etc.
  5. simple search.

    If pass domain as first argument when calling object, then search_records method will be called with all arguments forwarded:

    res = so_obj([('state','=','done')], limit=10)
    # res -> RecordList('sale.order', length=10)

    Also for simple searches without joins it is posible to pass just only keyword arguments which all will be converted to domain:

       res = so_obj(state='done')
    But note, that in last way, **all keyword arguments
    will be converted to domain, no one of them will be forwarded
    to search_records**, so it is not posible, for example, to limit
    results at this moment
search_record(*args, **kwargs)[source]

Aliase to search_records method to fetch only one record (aditionaly adds limit=1 keyword argument

workflow Extension

This extension module provides aditional logic to ease work with workflows. For example it provides methods to easily get workflow instance or workflow workitems related to specific record, or to easily get workflow related to Object. Also it provides simple methods to easily send workflow signals to records from Object and Record interfaces.

class openerp_proxy.ext.workflow.RecordWorkflow(*args, **kwargs)[source]

Bases: odoo_rpc_client.orm.record.Record

Adds ability to browse related fields from record


Cleanup record caches and reread data


Retunrs workflow instance related to this record


Returns list of related workflow.woritem objects


trigger’s specified signal on record’s related workflow

class openerp_proxy.ext.workflow.ObjectWorkflow(*args, **kwargs)[source]

Bases: odoo_rpc_client.orm.record.ObjectRecords

Modifies Object class, adding methods related to Workflow


Returns Record instance of “workflow” object related to this Object

If there are no workflow for an object then False will be returned

workflow_signal(obj_id, signal)[source]

Triggers specified signal for object’s workflow

field_datetime Extension

class openerp_proxy.ext.field_datetime.RecordDateTime(obj, rid, cache=None, context=None)[source]

Bases: odoo_rpc_client.orm.record.Record

Provides auto conversion of datetime fields from string got from server to comparable datetime objects

repr Extension

This module provides additional representation capabilities for most of standard classes like Record or RecordList.

This allows them to be represented as HTML tables in Jupyter notebook, or for example show RecordList data as table in IPython console.

exception openerp_proxy.ext.repr.FieldNotFoundException(obj, name, original_exc=None)[source]

Bases: Exception

Exception raised when HField cannot find field in object been processed

  • obj – object to field not found in
  • name – field that is not found in object obj
  • original_exc – Exception that was raised on attempt to get field
class openerp_proxy.ext.repr.HField(field, name=None, silent=False, default=None, is_header=False, parent=None, args=None, highlighters=None, kwargs=None)[source]

Bases: object

Describes how to get a field. Primaraly used in html representation logic.

  • field (str | func(record)->value) – path to field or function to get value from record if path is string, then it should be dot separated list of fields/subfields to get value from. for example sale_line_id.order_id.name or picking_id.move_lines.0.location_id
  • name (str) – name of field. (optional) if specified, then this value will be used in column header of table.
  • silent (bool) – If set to True, then no exceptions will be raised and default value will be returned. (default=False)
  • default – default value to be returned if field not found. default=None
  • is_header (bool) – if set to True, then this field will be displayed as header in HTMLTable representation, Useful for columns like ID. Have no effect in text representation (default: False)
  • parent (HField) – (for internal usage) parent field. First get value of parent field for record, and then get value of current field based on value of parent field: (self.get_field(self._parent.get_field(record)))
  • args (list | tuple) –
    if specified, then it means that field is callable,
    and args should be passed to it as positional arguments. This may be useful to call as_html_table method of internal field. for example:
           args=('id', '_name',
                 HField('location_id._name', 'Location')))

    or better way:

    HField('picking_id.move_lines.as_html_table').                             with_args('id',
                  HField('location_id._name', 'Location')

    Another approach is use AnyField lib, but at moment of writing this, it is in experimental stage still

  • highlighters (dict) – Field highlighters. dictionary, where key is HTML Color, and value is function with signature f(record, field_value)->bool If function return True, ther highlighter is used
  • kwargs (dict) – same as args but for keyword arguments
F(field, **kwargs)[source]

Create chained field Could be used for complicated field. for example:

HField('myfield.myvalue', default={'a': 5}).F('a')
get_field(record, mode='text')[source]

Returns requested value from specified record (object)

  • record (Record) – Record instance to get field from (also should work on any other object)
  • mode (str) – (optional) specify field mode. possible values: (‘text’, ‘html’) default: ‘text’

requested value

with_args(*args, **kwargs)[source]

If field is string pointing to function (or method), all arguments and keyword arguments passed to this method, will be passed to field (function).

For example:

    'id', '_name', HField('location_id._name', 'Location'))

This arguments (‘id’, ‘_name’, HField(‘location_id._name’, ‘Location’)) will be passed to picking_id.move_lines.as_html_table method


Convert value to HField instance

Parameters:field – value to convert to HField instance.
Returns:HField instance based on passed value
Return type:HField
Raises:ValueError – if field value cannot be automaticaly convereted to HField instance

field argument may be one of following types:

  • HField: in this case field will be returned unchanged
  • str: in this case field assumend to be field path, so HField instance will be created for it as HField(field)
  • tuple(str, str): In this case field assumed to be pair of (field_path, field_name), so new HField instance will be constructed with following arguments: HField(field[0], name=field[1])
  • callable: if field is callable, then it is assumed to be custom getter function, so new HField instance will be created as HField(field)

For more information look at HField documentation

class openerp_proxy.ext.repr.PrettyTable(*args, **kwargs)[source]

Bases: object

Just a simple warapper around tabulate to show IPython displayable table

Only ‘pretty’ representation, yet.

class openerp_proxy.ext.repr.BaseTable(data, fields, tablefmt='simple')[source]

Bases: object

Base class for table representation

  • data (RecordList|iterable) – record list (or iterable of anything other) to create represetation for
  • fields (list(str | callable | HField | tuple(field, name))) – list of fields to display. each field should be string with dot splitted names of related object, or callable of one argument (record instance) or HField instance or tuple(field_path|callable, field_name)
  • tablefmt (str) – (optional) table format param passed directly to tabulate.tabulate() method in _pretty_repr_ logic.

Data, table is based on


List of fields of table. :type: list of HField instances


Write table to CSV file and return FileLink object for it

Returns:instance of FileLink
Return type:FileLink
This method is used to change BaseTable fields,

thus, changing representation

arguments same as for constructor, except ‘data’ arg, which is absent in this method

Parameters:fields (list(str) | callable | HField | tuple(field, name))) – list of fields to display. each field should be string with dot splitted names of related object, or callable of one argument (record instance) or HField instance or tuple(field_path|callable, field_name)
class openerp_proxy.ext.repr.HTMLTable(data, fields, caption=None, highlighters=None, display_help=True, tablefmt='simple', **kwargs)[source]

Bases: openerp_proxy.ext.repr.generic.BaseTable

HTML Table representation object for RecordList

  • data (RecordList|iterable) – record list (or iterable of anything other) to create represetation for
  • fields (list(str | callable | HField | tuple(field, name))) – list of fields to display. each field should be string with dot splitted names of related object, or callable of one argument (record instance) or HField instance or tuple(field_path|callable, field_name)
  • caption (str) – String to be used as table caption
  • highlighters (dict) –

    dictionary in format:

    {color: callable(record)->bool}

    where color any color suitable for HTML and callable is function of Record instance which decides, if record should be colored by this color

  • display_help (bool) – if set to False, then no help message will be displayed
  • tablefmt (str) – (optional) table format param passed directly to tabulate.tabulate() method in _pretty_repr_ logic.

Table caption


Checks all highlighters related to this representation object and return color of firest match highlighter


system property. Which is automaticaly set if HTML table should be diplayed in other html table. If set to True, then caption and help message will not be displayed


render html table to string

update(fields=None, caption=None, highlighters=None, **kwargs)[source]

This method is used to change HTMLTable initial data, thus, changing representation

Can be used for example, when some function returns partly configured HTMLTable instance, but user want’s to display more fields or add some custom highlighters

arguments same as for constructor, except ‘data’ arg, which is absent in this method


all Extension pack

Just imports of all extensions

Importing this module, will automaticaly enable folowing extensions:
  • field_datetime - Automaticaly convert ‘date / time’ fields to
    datetime objects, thus allowing to compare them in python
  • sugar - Extra syntax sugar. Make code require less typing
  • workflow - Odoo workflows related functionality
  • repr - Rich representation of objects.
    IPython / Jupyter integration layer
Folowing names could be imported from this module:
  • HField
  • HTMLTable
  • FieldNotFoundException

log_execute_console Extension

Simple extension which makes all client.services.object.execute calls to be logged

NOTE: this exension is not included in openerp_proxy.ext.all so it should be enabled (imported) manualy

Also allows to measure tim spent on rpc calls

Ususaly used for debug and performance tests

class openerp_proxy.ext.log_execute_console.ObjectServiceLog(*args, **kwargs)[source]

Bases: odoo_rpc_client.service.object.ObjectService

Simply logs all calls to execute method of object service to console (displying all arguments). If module level variable LOG_SIMPLE set to True,then only simple lines like ‘Execute [<obj>, <method>] will be displayed

execute(obj, method, *args, **kwargs)[source]

First arguments should be ‘object’ and ‘method’ and next will be passed to method of given object

class openerp_proxy.ext.log_execute_console.TimeTracker(name)[source]

Bases: object

Context manager to track separatly total time that some request took and time spent on rpc queries.


with TimeTracker('my-code-block') as t:
    product = db._product_product.serch_records([], limit=400000)
print("Query time: %s, Total time: %s" % (p.query_time,
classmethod get_query_times(name)[source]

Get time spent for queries for timer named name

Parameters:name (str) – name of timer to be started

Return current query time (if not finished) or total query time

query_timers = {}
classmethod remove_timer(name)[source]

Remove timer for timers list.

classmethod start_timing(name)[source]

Start timer named name

Parameters:name (str) – name of timer to be started

if not started, returns 0.0 if started and not finished returns current time - start time if finished return total time (time finished - start time