Skip to content

Commit

Permalink
A little bit of python 3 support work
Browse files Browse the repository at this point in the history
  • Loading branch information
katyukha committed Jul 21, 2015
1 parent 40e9369 commit b6fbd24
Show file tree
Hide file tree
Showing 20 changed files with 131 additions and 78 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
@@ -1,6 +1,9 @@
language: python
python:
- "2.6"
- "2.7"
- "3.3"
- "3.4"

env:
- ODOO_VERSION="8.0" ODOO_PACKAGE="odoo" ODOO_TEST_PROTOCOL='xml-rpc'
Expand Down
8 changes: 4 additions & 4 deletions openerp_proxy/__init__.py
Expand Up @@ -36,17 +36,17 @@ class returned by connect() method of session object.
def main():
""" Entry point for running as standalone APP
"""
from session import Session
from core import Client
from .session import Session
from .core import Client

session = Session()

header_databases = "\n"
for index, url in session.index.iteritems():
for index, url in session.index.items():
header_databases += " - [%3s] %s\n" % (index, url)

header_aliases = "\n"
for aliase, url in session.aliases.iteritems():
for aliase, url in session.aliases.items():
header_aliases += " - %7s: %s\n" % (aliase, url)

header = HELP_HEADER % {'databases': header_databases, 'aliases': header_aliases}
Expand Down
6 changes: 3 additions & 3 deletions openerp_proxy/connection/__init__.py
@@ -1,3 +1,3 @@
import xmlrpc
import jsonrpc
from connection import *
import openerp_proxy.connection.xmlrpc
import openerp_proxy.connection.jsonrpc
from .connection import *
4 changes: 2 additions & 2 deletions openerp_proxy/connection/connection.py
@@ -1,3 +1,4 @@
import six
from extend_me import ExtensibleByHashType

__all__ = ('get_connector', 'get_connector_names', 'ConnectorBase')
Expand All @@ -17,10 +18,9 @@ def get_connector_names():
return ConnectorType.get_registered_names()


class ConnectorBase(object):
class ConnectorBase(six.with_metaclass(ConnectorType)):
""" Base class for all connectors
"""
__metaclass__ = ConnectorType

def __init__(self, host, port, verbose=False):
self.host = host
Expand Down
31 changes: 15 additions & 16 deletions openerp_proxy/connection/jsonrpc.py
@@ -1,11 +1,12 @@
# python imports
import json
import urllib2
import random

#import urllib2
import requests

# project imports
from openerp_proxy.connection.connection import ConnectorBase
from openerp_proxy.utils import ustr
from .connection import ConnectorBase
import openerp_proxy.exceptions as exceptions


Expand All @@ -28,9 +29,6 @@ def __unicode__(self):
def __str__(self):
return unicode(self).encode('utf-8')

def _repr_pretty_(self):
return "TEST"


class JSONRPCMethod(object):
""" Class wrapper around XML-RPC method to wrap xmlrpclib.Fault
Expand All @@ -54,20 +52,21 @@ def __call__(self, *args):
},
"id": random.randint(0, 1000000000),
}
req = urllib2.Request(url=self.__url, data=json.dumps(data), headers={
"Content-Type": "application/json",
})
result = urllib2.urlopen(req)
content = result.read()
try:
result = json.loads(content)
res = requests.post(self.__url, data=data, headers={
"Content-Type": "application/json",
})
except requests.exceptions.RequestException:
raise JSONRPCError("Cannot connect to url %s" % self.__url)

try:
result = json.loads(res.text)
except ValueError:
info = {
"original_url": self.__url,
"url": result.geturl(),
"info": result.info(),
"code": result.getcode(),
"content": content,
"url": res.url,
"code": res.status_code,
"content": res.text,
}
raise JSONRPCError("Cannot decode JSON: %s" % info)

Expand Down
9 changes: 7 additions & 2 deletions openerp_proxy/connection/xmlrpc.py
@@ -1,8 +1,13 @@
# python imports
import xmlrpclib
import sys

if sys.version_info < (3, 0, 0):
import xmlrpclib
else:
import xmlrpc.client as xmlrpclib

# project imports
from openerp_proxy.connection.connection import ConnectorBase
from .connection import ConnectorBase
from openerp_proxy.utils import ustr
import openerp_proxy.exceptions as exceptions

Expand Down
14 changes: 7 additions & 7 deletions openerp_proxy/core.py
Expand Up @@ -48,20 +48,20 @@


# project imports
from openerp_proxy.connection import get_connector
from openerp_proxy.exceptions import (Error,
ClientException,
LoginException)
from openerp_proxy.service import ServiceManager
from openerp_proxy.plugin import PluginManager
from .connection import get_connector
from .exceptions import (Error,
ClientException,
LoginException)
from .service import ServiceManager
from .plugin import PluginManager


# Activate orm internal logic
# TODO: think about not enabling it by default, allowing users to choose what
# thay woudld like to use. Or simply create two entry points (one with all
# enabled by default and another with only basic stuff which may be useful for
# libraries that would like to get speed instead of better usability
import openerp_proxy.orm
from . import orm

from extend_me import Extensible

Expand Down
4 changes: 2 additions & 2 deletions openerp_proxy/ext/workflow.py
Expand Up @@ -5,7 +5,7 @@
Also it provides simple methods to easily send workflow signals
to records from Object and Record interfaces.
"""

import numbers
from openerp_proxy.orm.record import Record
from openerp_proxy.orm.record import ObjectRecords
from openerp_proxy.exceptions import ObjectException
Expand Down Expand Up @@ -42,7 +42,7 @@ def workflow(self):
def workflow_signal(self, obj_id, signal):
""" Triggers specified signal for object's workflow
"""
assert isinstance(obj_id, (int, long)), "obj_id must be integer"
assert isinstance(obj_id, numbers.Integral), "obj_id must be integer"
assert isinstance(signal, basestring), "signal must be string"
return self.service.execute_wkf(self.name, signal, obj_id)

Expand Down
7 changes: 4 additions & 3 deletions openerp_proxy/orm/cache.py
@@ -1,4 +1,5 @@
#import openerp_proxy.orm.record
import six
import collections
__all__ = ('empty_cache')

Expand Down Expand Up @@ -32,7 +33,7 @@ def update_keys(self, keys):
# and difference calls)
self.update({cid: {'id': cid} for cid in keys})
else:
self.update({cid: {'id': cid} for cid in set(keys).difference(self.viewkeys())})
self.update({cid: {'id': cid} for cid in set(keys).difference(six.viewkeys(self))})
return self

def update_context(self, new_context):
Expand All @@ -51,7 +52,7 @@ def update_context(self, new_context):
def get_ids_to_read(self, field):
""" Return list of ids, that have no specified field in cache
"""
return [key for key, val in self.viewitems() if field not in val]
return [key for key, val in six.viewitems(self) if field not in val]

def cache_field(self, rid, ftype, field_name, value):
""" This method impelment additional caching functionality,
Expand All @@ -66,7 +67,7 @@ def cache_field(self, rid, ftype, field_name, value):
if value and ftype == 'many2one':
rcache = self._root_cache[self._object.columns_info[field_name]['relation']]

if isinstance(value, (int, long)):
if isinstance(value, numbers.Integral):
rcache[value] # internal dict {'id': key} will be created by default (see ObjectCache)
elif isinstance(value, (list, tuple)):
rcache[value[0]]['__name_get_result'] = value[1]
Expand Down
4 changes: 2 additions & 2 deletions openerp_proxy/orm/object.py
@@ -1,3 +1,4 @@
import six
from extend_me import ExtensibleByHashType

from openerp_proxy.utils import AttrDict
Expand All @@ -24,7 +25,7 @@ def get_object(proxy, name):


# TODO: think about connecting it to service instead of Proxy
class Object(object):
class Object(six.with_metaclass(ObjectType)):
""" Base class for all Objects
Provides simple interface to remote osv.osv objects
Expand All @@ -33,7 +34,6 @@ class Object(object):
sale_obj = Object(erp, 'sale.order')
sale_obj.search([('state','not in',['done','cancel'])])
"""
__metaclass__ = ObjectType

def __init__(self, service, object_name):
self._service = service
Expand Down
25 changes: 12 additions & 13 deletions openerp_proxy/orm/record.py
Expand Up @@ -4,8 +4,10 @@
from openerp_proxy.orm.cache import empty_cache
from extend_me import ExtensibleType

import six
import collections
import abc
import numbers


__all__ = (
Expand Down Expand Up @@ -37,7 +39,7 @@ def get_record(obj, rid, cache=None, context=None):
return RecordMeta.get_object(obj, rid, cache=cache, context=context)


class Record(object):
class Record(six.with_metaclass(RecordMeta, object)):
""" Base class for all Records
Constructor
Expand All @@ -50,12 +52,11 @@ class Record(object):
Note, to create instance of cache call *empty_cache*
"""

__metaclass__ = RecordMeta
__slots__ = ['__dict__', '_object', '_cache', '_lcache', '_id']

def __init__(self, obj, rid, cache=None, context=None):
assert isinstance(obj, Object), "obj should be Object"
assert isinstance(rid, (int, long)), "rid must be int"
assert isinstance(rid, numbers.Integral), "rid must be int"

self._id = rid
self._object = obj
Expand Down Expand Up @@ -144,7 +145,7 @@ def __eq__(self, other):
if isinstance(other, Record):
return other.id == self._id

if isinstance(other, (int, long)):
if isinstance(other, numbers.Integral):
return self._id == other

return False
Expand Down Expand Up @@ -255,7 +256,7 @@ def get_record_list(obj, ids=None, fields=None, cache=None, context=None):
return RecordListMeta.get_object(obj, ids, fields=fields, cache=cache, context=context)


class RecordList(collections.MutableSequence):
class RecordList(six.with_metaclass(RecordListMeta), collections.MutableSequence):
"""Class to hold list of records with some extra functionality
:param obj: instance of Object to make this list related to
Expand All @@ -270,8 +271,6 @@ class RecordList(collections.MutableSequence):
:type context: dict
"""
__metaclass__ = RecordListMeta

__slots__ = ('_object', '_cache', '_lcache', '_records')

# TODO: expose object's methods via implementation of __dir__
Expand Down Expand Up @@ -364,7 +363,7 @@ def __len__(self):
return self.length

def __contains__(self, item):
if isinstance(item, (int, long)):
if isinstance(item, numbers.Integral):
return item in self.ids
if isinstance(item, Record):
return item in self._records
Expand All @@ -373,13 +372,13 @@ def __contains__(self, item):
def insert(self, index, item):
""" Insert record to list
:param item: Record instance to be inserted into list. if int or long passed, it considered to be ID of record
:type item: Record|int|long
:param item: Record instance to be inserted into list. if int passed, it considered to be ID of record
:type item: Record|int
:param int index: position where to place new element
:return: self
:rtype: RecordList
"""
assert isinstance(item, (Record, int, long)), "Only Record or int or long instances could be added to list"
assert isinstance(item, (Record, numbers.Integral)), "Only Record or int instances could be added to list"
if isinstance(item, Record):
self._records.insert(index, item)
else:
Expand Down Expand Up @@ -658,9 +657,9 @@ def read_records(self, ids, fields=None, context=None, cache=None):
>>> for order in data:
order.write({'note': 'order data is %s'%order.data})
"""
assert isinstance(ids, (int, long, list, tuple)), "ids must be instance of (int, long, list, tuple)"
assert isinstance(ids, (numbers.Integral, list, tuple)), "ids must be instance of (int, list, tuple)"

if isinstance(ids, (int, long)):
if isinstance(ids, numbers.Integral):
record = get_record(self, ids, context=context)
if fields is not None:
record.read(fields) # read specified fields
Expand Down
11 changes: 6 additions & 5 deletions openerp_proxy/plugin.py
@@ -1,9 +1,11 @@
# Python imports

import six
import extend_me

PluginMeta = extend_me.ExtensibleByHashType._('Plugin', hashattr='name')


class Plugin(object):
class Plugin(six.with_metaclass(PluginMeta)):
""" Base class for all plugins, extensible by name
(uses metaclass extend_me.ExtensibleByHashType)
Expand Down Expand Up @@ -31,7 +33,6 @@ def get_sign_state(self):
This plugin will automaticaly register itself in system, when module which contains it will be imported.
"""
__metaclass__ = extend_me.ExtensibleByHashType._('Plugin', hashattr='name')

def __init__(self, erp_proxy):
self._erp_proxy = erp_proxy
Expand Down Expand Up @@ -64,7 +65,7 @@ def test(self):
return self.proxy.get_url()


class PluginManager(object):
class PluginManager(extend_me.Extensible):
""" Class that holds information about all plugins
:param erp_proxy: instance of Client to bind plugins to
Expand All @@ -88,7 +89,7 @@ def __getitem__(self, name):
try:
pluginCls = type(Plugin).get_class(name)
except ValueError as e:
raise KeyError(e.message)
raise KeyError(str(e))

plugin = pluginCls(self.__erp_proxy)
self.__plugins[name] = plugin
Expand Down
2 changes: 1 addition & 1 deletion openerp_proxy/plugins/graph.py
Expand Up @@ -7,7 +7,7 @@
try:
import pydot
except ImportError:
print "PyDot not installed!!!"
print("PyDot not installed!!!")


class Model(Extensible):
Expand Down
2 changes: 1 addition & 1 deletion openerp_proxy/service/db.py
Expand Up @@ -67,4 +67,4 @@ def server_version(self):
(Already parsed with pkg_resources.parse_version)
"""
return parse_version(super(DBService, self).server_version())
return parse_version(self._service.server_version())
2 changes: 1 addition & 1 deletion openerp_proxy/service/object.py
Expand Up @@ -49,7 +49,7 @@ def execute_wkf(self, object_name, signal, object_id):
:param str object_name: name of object/model to trigger workflow on
:param str signal: name of signal to send to workflow
:param int|long object_id: ID of document (record) to send signal to
:param int object_id: ID of document (record) to send signal to
"""
result_wkf = self._service.exec_workflow(self.proxy.dbname, self.proxy.uid, self.proxy._pwd, object_name, signal, object_id)
return result_wkf
Expand Down

0 comments on commit b6fbd24

Please sign in to comment.