diff --git a/AUTHORS b/AUTHORS index c8b2a90..c0c1d66 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ Pedro A. Gracia Fajardo Gamaliel Toro +Raimon Esteve Cusiné diff --git a/README.md b/README.md index cad03d6..c60e4f4 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,16 @@ Connecting to server >>> o = OOOP(dbname='demo') +Pyro Protocol +-------------------- +1. Install PyRO library (openerp-server and web client). +http://www.xs4all.nl/~irmen/pyro3/ +2. Install PyRO Module OpenERP from Nan (thanks this contribution!) +https://launchpad.net/openobject-client-kde +

+  >>> o = OOOP(user='admin',pwd='admin',dbname='zikzakmedia',uri='localhost',port=8071,protocol='pyro')
+
+ Retrieving all from model ------------------------- @@ -185,9 +195,4 @@ but if you want to get deep in the tables just need: o.ResPartner.export(deep=1) - The deep param its relative to the model param, deep means how far you want to get with the relations. - - - - diff --git a/examples/basic.py b/examples/basic.py index b0c16b2..5dfd4b7 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -1,6 +1,8 @@ from ooop import OOOP o = OOOP(dbname="testv6") +#Pyro Demo +#o = OOOP(user='admin',pwd='admin',dbname='zikzakmedia',uri='localhost',port=8071,protocol='pyro') partners = o.ResPartner.all() for partner in partners: - print "id: %d, name: %s" % ( partner._ref, partner.name ) \ No newline at end of file + print "id: %d, name: %s" % ( partner._ref, partner.name ) diff --git a/ooop.py b/ooop.py old mode 100644 new mode 100755 index c99a206..b73cb1b --- a/ooop.py +++ b/ooop.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ######################################################################## # # OOOP, OpenObject On Python @@ -32,9 +32,15 @@ except: pydot = False +# check if pyro is installed +try: + import Pyro.core +except: + pyro = False + __author__ = "Pedro Gracia " __license__ = "GPLv3+" -__version__ = "0.2.3" +__version__ = "0.2.4" OOOPMODELS = 'ir.model' @@ -111,13 +117,14 @@ def execute(self, *args, **kargs): class OOOP: """ Main class to manage xml-rpc comunitacion with openerp-server """ def __init__(self, user='admin', pwd='admin', dbname='openerp', - uri='http://localhost', port=8069, debug=False, - exe=False, active=True, **kwargs): + uri='http://localhost', port=8069, protocol='xmlrpc', debug=False, + exe=False, active=True, lang='en_US', **kwargs): self.user = user # default: 'admin' self.pwd = pwd # default: 'admin' self.dbname = dbname # default: 'openerp' self.uri = uri self.port = port + self.protocol = protocol # default: 'xmlrpc' self.debug = debug self.exe = exe self.active = active @@ -127,13 +134,18 @@ def __init__(self, user='admin', pwd='admin', dbname='openerp', self.uid = None self.models = {} self.fields = {} + self.proxy = False + self.lang = lang #has to be uid, cr, parent (the openerp model to get the pool) if len(kwargs) == 3: self.uid = kwargs['uid'] self.objectsock = objectsock_mock(kwargs['parent'], kwargs['cr']) else: - self.connect() + if protocol == 'pyro': + self.connect_pyro() + else: + self.connect() self.load_models() @@ -147,46 +159,92 @@ def login(self, dbname, user, pwd): self.commonsock = xmlrpclib.ServerProxy('%s:%i/xmlrpc/common' % (self.uri, self.port)) return self.commonsock.login(dbname, user, pwd) + def connect_pyro(self): + """login and sockets to pyro services: common, object and report""" + url = 'PYROLOC://%s:%s/rpc' % (self.uri,self.port) + self.proxy = Pyro.core.getProxyForURI(url) + self.uid = self.proxy.dispatch( 'common', 'login', self.dbname, self.user, self.pwd) + self.reportsock = False + def execute(self, model, *args): if self.debug: print "DEBUG [execute]:", model, args - return self.objectsock.execute(self.dbname, self.uid, self.pwd, model, *args) + if self.protocol == 'pyro': + result = self.proxy.dispatch( 'object', 'execute', self.dbname, self.uid, self.pwd, model, *args) + else: + result = self.objectsock.execute(self.dbname, self.uid, self.pwd, model, *args) + return result def create(self, model, data): """ create a new register """ + context = {'lang':self.lang} if self.debug: print "DEBUG [create]:", model, data - return self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'create', data) + if 'id' in data: + del data['id'] + if self.protocol == 'pyro': + result = self.proxy.dispatch( 'object', 'execute', self.dbname, self.uid, self.pwd, model, 'create', data, context) + else: + result = self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'create', data, context) + return result def unlink(self, model, ids): """ remove register """ if self.debug: print "DEBUG [unlink]:", model, ids - return self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'unlink', ids) + if isinstance(ids, int): + ids = [ids] + if self.protocol == 'pyro': + result = self.proxy.dispatch( 'object', 'execute', self.dbname, self.uid, self.pwd, model, 'unlink', ids) + else: + result = self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'unlink', ids) + return result def write(self, model, ids, value): """ update register """ + context = {'lang':self.lang} if self.debug: print "DEBUG [write]:", model, ids, value - return self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'write', ids, value) + if isinstance(ids, int): + ids = [ids] + if self.protocol == 'pyro': + result = self.proxy.dispatch( 'object', 'execute', self.dbname, self.uid, self.pwd, model, 'write', ids, value, context) + else: + result = self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'write', ids, value, context) + return result def read(self, model, ids, fields=[]): """ update register """ + context = {'lang':self.lang} if self.debug: print "DEBUG [read]:", model, ids, fields - return self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'read', ids, fields) + if self.protocol == 'pyro': + result = self.proxy.dispatch( 'object', 'execute', self.dbname, self.uid, self.pwd, model, 'read', ids, fields, context) + else: + result = self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'read', ids, fields, context) + return result def read_all(self, model, fields=[]): """ update register """ + context = {'lang':self.lang} if self.debug: print "DEBUG [read_all]:", model, fields - return self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'read', self.all(model), fields) + if self.protocol == 'pyro': + result = self.proxy.dispatch( 'object', 'execute', self.dbname, self.uid, self.pwd, model, 'read', self.all(model), fields, context) + else: + result = self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'read', self.all(model), fields, context) + return result - def search(self, model, query): + def search(self, model, query, offset=0, limit=999, order=''): """ return ids that match with 'query' """ + context = {'lang':self.lang} if self.debug: - print "DEBUG [search]:", model, query - return self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'search', query) + print "DEBUG [search]:", model, query, offset, limit, order + if self.protocol == 'pyro': + result = self.proxy.dispatch( 'object', 'execute', self.dbname, self.uid, self.pwd, model, 'search', query, offset, limit, order, context) + else: + result = self.objectsock.execute(self.dbname, self.uid, self.pwd, model, 'search', query, offset, limit, order, context) + return result # TODO: verify if remove this def custom_execute(self, model, ids, remote_method, data): @@ -211,7 +269,7 @@ def insert_items(self, model, data): print 'Warning: %s already in %s model: %s' % (item, model) def load_models(self): - models = self.read_all(OOOPMODELS) + models = self.read_all(OOOPMODELS, fields=['model']) for model in models: self.models[model['model']] = model self.__dict__[self.normalize_model_name(model['model'])] = Manager(model['model'], self) @@ -451,15 +509,27 @@ def all(self, fields=[], offset=0, limit=999999, as_list=False): def filter(self, fields=[], as_list=False, **kargs): q = [] # query dict + offset = 0 + limit = 999 + order = '' for key, value in kargs.items(): - if not '__' in key: - op = '=' - else: + if key == 'offset': + if int(value): + offset = value + elif key == 'limit': + if int(value): + limit = value + elif key == 'order': + order = value + elif '__' in key: i = key.find('__') op = OPERATORS[key[i+2:]] key = key[:i] - q.append(('%s' % key, op, value)) - ids = self._ooop.search(self._model, q) + q.append(('%s' % key, op, value)) + else: + op = '=' + q.append(('%s' % key, op, value)) + ids = self._ooop.search(self._model, q, offset, limit, order) if as_list: return self.read(ids, fields) return List(self, ids) @@ -520,7 +590,10 @@ def __init__(self, manager, ref=None, model=None, copy=False, data=None, fields= # convert DateTime instance to datetime.datetime object for i in default_values: if self.fields[i]['ttype'] == 'datetime': - t = default_values[i].timetuple() + if isinstance(default_values[i], str): + t = datetime.strptime(default_values[i], "%Y-%m-%d %H:%M:%S").timetuple() + else: + t = default_values[i].timetuple() default_values[i] = datetime(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec) # active by default ? if self._ooop.active: @@ -539,7 +612,7 @@ def init_values(self, *args, **kargs): else: self.__dict__[name] = List(Manager(relation, self._ooop), data=self, model=relation) elif ttype == 'many2one': - if name in keys: + if name in keys and kargs[name]: # manager, ref=None, model=None, copy=False instance = Data(Manager(relation, self._ooop), kargs[name], relation) self.INSTANCES['%s:%s' % (relation, kargs[name])] = instance @@ -674,7 +747,7 @@ def save(self): for i in self.__dict__[name]: self.INSTANCES['%s:%s' % (relation, i._ref)] = i elif ttype == 'many2one': - if self.__dict__[name]: + if self.__dict__[name] and 'name' in dir(self.__dict__[name]): data[name] = self.__dict__[name]._ref # update __name and INSTANCES (cache) self.__dict__['__%s' % name] = [self.__dict__[name]._ref, self.__dict__[name].name]