Skip to content

Commit

Permalink
Added 'external_ids' plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
katyukha committed Mar 4, 2016
1 parent b2133a0 commit 1f22a1d
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
@@ -1,4 +1,5 @@
0.6.5:
- Added ``openerp_proxy.plugins.external_ids`` plugin
- ``openerp_proxy.ext.repr``: better support of ``IPython.display.HTML`` objects representation
- ``openerp_proxy.ext.sugar``: Added ability to access plugins directly from ``client`` instance
For example, instead of writing ``client.plugins.Test``, you may write ``client.Test``
Expand Down
15 changes: 14 additions & 1 deletion docs/source/module_ref/openerp_proxy.plugins.rst
Expand Up @@ -16,11 +16,24 @@
:undoc-members:
:show-inheritance:


:mod:`external_ids` Plugin
--------------------------

.. automodule:: openerp_proxy.plugins.external_ids
:members:
:undoc-members:
:show-inheritance:


----


:mod:`diagraming` Plugin
------------------------

**Warning!!!**
This plugins is in experimental stage!!!
This plugin is in experimental stage!!!

.. automodule:: openerp_proxy.plugins.diagraming
:members:
Expand Down
4 changes: 2 additions & 2 deletions openerp_proxy/ext/repr/__init__.py
Expand Up @@ -442,11 +442,11 @@ def _repr_html_(self):
u"<li>session[<b>url</b>]</li>"
u"<li>session.get_db(<b>url</b>|<b>index</b>|<b>aliase</b>)</li></ul>")

data = u"<tr><th>DB URL</th><th>DB Index</th><th>DB Aliases</th></tr>"
data = u"<tr><th>DB Index</th><th>DB URL</th><th>DB Aliases</th></tr>"
for url in self._databases.keys():
index = self._index_url(url)
aliases = u", ".join((_(al) for al, aurl in self.aliases.items() if aurl == url))
data += tr(td(url), td(index), td(aliases))
data += tr(td(index), td(url), td(aliases))

table = TMPL_TABLE % {'styles': '',
'extra_classes': 'table-striped',
Expand Down
1 change: 1 addition & 0 deletions openerp_proxy/orm/object.py
Expand Up @@ -104,6 +104,7 @@ def __repr__(self):
return str(self)

def __eq__(self, other):
assert isinstance(other, Object), "Comparable only with instances of Object class"
return self.name == other.name and self.client == other.client

def _get_columns_info(self):
Expand Down
102 changes: 102 additions & 0 deletions openerp_proxy/plugins/external_ids.py
@@ -0,0 +1,102 @@
"""
"""

from ..plugin import Plugin
from ..orm.object import Object
from ..orm.record import (Record,
RecordList)

import six


class ExternalIDS(Plugin):
""" This plugin adds aditional methods to work with
external_ids (xml_id) for Odoo records.
"""
class Meta:
name = "external_ids"

def get_for(self, val, module=None):
""" Return RecordList of 'ir.model.data' for val or False
:param val: value to get 'ir.model.data' records for
:param str module: module name to search 'ir.model.data' for
:rtype: RecordList
:return: RecordList with 'ir.model.data' records found
:raises ValueError: if *val* argument could not be parsed
``val`` could be one of folowing types:
- ``Record`` instance
- ``RecordList`` instance
- ``tuple(model, res_id)``, for example ``('res.partner', 5)``
- ``str``, string in format 'module.name'.
Note, that if *module* specified as parametr, then *val*
supposed to be *name* only.
"""
data_obj = self.client['ir.model.data']
domain = [] if module is None else [('module', '=', module)]
if isinstance(val, Record):
domain +=[('model', '=', val._object.name),
('res_id', '=', val.id)]
elif isinstance(val, RecordList):
domain += [('model', '=', val._object.name),
('res_id', 'in', val.ids)]
elif isinstance(val, (tuple, list)) and len(val) == 2:
model, res_id = val
domain += [('model', '=', model),
('res_id', '=', res_id)]
elif isinstance(val, six.string_types):
if module is None:
try:
module, name = val.split('.')
except ValueError:
raise ValueError(
"Bad xml_id passed. cannot fetch module name.")
else:
name = val

domain = [('module', '=', module),
('name', '=', name)]
else:
raise ValueError("Cannot parse value [%r]" % val)

return data_obj.search_records(domain)

def get_xmlid(self, val, module=None):
""" Return *xml_id* for *val*.
Note, that only first xml_id will be returned!
:param val: look in documentation for
`get_for
<#openerp_proxy.plugins.external_ids.ExternalIDS.get_for>`__
method
:param str module: module name to search xml_id for
:rtype: str
:return: xml_id for *val* or False if not found
:raises ValueError: if *val* argument could not be parsed
Note, that if *module* specified as parametr, then *val*
supposed to be *name* only
"""
e_record = self.get_for(val, module=module)
if e_record:
return e_record[0].complete_name
return False

def get_record(self, xml_id, module=None):
""" Return *Record* instance for specified xml_id
:param str xml_id: string with xml_id to search record for
:param str module: module name to search Record in
:rtype: Record
:return: Record for *val* or False if not found
:raises ValueError: if *xml_id* argument could not be parsed
"""
assert isinstance(xml_id, six.string_types), "xml_id must be string"
e_record = self.get_for(xml_id, module=module)
if e_record:
e_record = e_record[0]
return self.client[e_record.model][e_record.res_id]
return False


123 changes: 122 additions & 1 deletion openerp_proxy/tests/test_plugins.py
@@ -1,6 +1,7 @@
from . import BaseTestCase
from .. import Client
from ..orm import Record
from ..orm import (Record,
RecordList)

import unittest

Expand Down Expand Up @@ -89,3 +90,123 @@ def test_50_module_upgrade(self):

self.assertEqual(smod.state, 'installed')
smod.upgrade() # just call it


class Test_26_Plugin_ModuleUtils(BaseTestCase):

def setUp(self):
super(self.__class__, self).setUp()
self.client = Client(self.env.host,
dbname=self.env.dbname,
user=self.env.user,
pwd=self.env.password,
protocol=self.env.protocol,
port=self.env.port)
self.data_obj = self.client['ir.model.data']
self.partner_obj = self.client['res.partner']
main_partner_domain = [
('module', '=', 'base'),
('model', '=', 'res.partner'),
('name', '=', 'main_partner'),
]
self.main_partner_data = self.data_obj.search_records(
main_partner_domain)[0]
self.main_partner = self.partner_obj[self.main_partner_data.res_id]

def test_10_init_module_utils(self):
self.assertNotIn('external_ids', self.client.plugins)
self.assertIn('Test', self.client.plugins)

import openerp_proxy.plugins.external_ids

self.assertIn('external_ids', self.client.plugins)

def test_20_get_for__record(self):
data = self.client.plugins.external_ids.get_for(self.main_partner)
self.assertIsInstance(data, RecordList)
self.assertEqual(data.object.name, 'ir.model.data')
self.assertEqual(len(data), 1)

data0 = data[0]
self.assertEqual(data0.model, 'res.partner')
self.assertEqual(data0.res_id, self.main_partner.id)
self.assertEqual(data0.module, 'base')

def test_21_get_for__recordlist(self):
recordlist = self.client['res.partner'].search_records([], limit=10)
res = self.client.plugins.external_ids.get_for(recordlist)

self.assertIsInstance(res, RecordList)
self.assertEqual(res.object.name, 'ir.model.data')

for data in res:
self.assertIn(data.res_id, recordlist.ids)

def test_22_get_for__tuple(self):
data = self.client.plugins.external_ids.get_for(('res.partner',
self.main_partner.id))
self.assertIsInstance(data, RecordList)
self.assertEqual(data.object.name, 'ir.model.data')
self.assertEqual(len(data), 1)

data0 = data[0]
self.assertEqual(data0.model, 'res.partner')
self.assertEqual(data0.res_id, self.main_partner.id)
self.assertEqual(data0.module, 'base')

def test_23_get_for__str(self):
data = self.client.plugins.external_ids.get_for('base.main_partner')
self.assertIsInstance(data, RecordList)
self.assertEqual(data.object.name, 'ir.model.data')
self.assertEqual(len(data), 1)

data0 = data[0]
self.assertEqual(data0.model, 'res.partner')
self.assertEqual(data0.res_id, self.main_partner.id)
self.assertEqual(data0.module, 'base')

def test_23_get_for__str_module(self):
data = self.client.plugins.external_ids.get_for('main_partner', 'base')
self.assertIsInstance(data, RecordList)
self.assertEqual(data.object.name, 'ir.model.data')
self.assertEqual(len(data), 1)

data0 = data[0]
self.assertEqual(data0.model, 'res.partner')
self.assertEqual(data0.res_id, self.main_partner.id)
self.assertEqual(data0.module, 'base')

def test_24_get_for__bad_value(self):
with self.assertRaises(ValueError):
self.client.plugins.external_ids.get_for(None, 'base')

def test_25_get_for__unexisting_xml_id(self):
data = self.client.plugins.external_ids.get_for('base.unexisting_xml_id')
self.assertIsInstance(data, RecordList)
self.assertEqual(data.length, 0)
self.assertFalse(data)

def test_26_get_for__wrong_xml_id(self):
with self.assertRaises(ValueError):
self.client.plugins.external_ids.get_for('bad_xml_id')

def test_30_get_xmlid(self):
xml_id = self.client.plugins.external_ids.get_xmlid(self.main_partner)
self.assertEqual(xml_id, "base.main_partner")

# Create new partner without xml_id
new_partner_id = self.client['res.partner'].create({'name': 'Test partner'})
new_partner = self.client['res.partner'].browse(new_partner_id)

no_xml_id = self.client.plugins.external_ids.get_xmlid(new_partner)
self.assertFalse(no_xml_id)

# Cleanup, remove created partner
new_partner.unlink()

def test_35_get_record(self):
mpartner = self.client.plugins.external_ids.get_record('base.main_partner')
self.assertEqual(mpartner, self.main_partner)

no_partner = self.client.plugins.external_ids.get_record('base.unexisting_xml_id')
self.assertFalse(no_partner)
2 changes: 1 addition & 1 deletion openerp_proxy/version.py
@@ -1 +1 @@
version = "0.6.5-dev" # pragma: no cover
version = "0.6.5.dev0" # pragma: no cover

0 comments on commit 1f22a1d

Please sign in to comment.