summaryrefslogtreecommitdiff
path: root/odoo/fields.py
diff options
context:
space:
mode:
Diffstat (limited to 'odoo/fields.py')
-rw-r--r--odoo/fields.py77
1 files changed, 38 insertions, 39 deletions
diff --git a/odoo/fields.py b/odoo/fields.py
index 18174f1d145..43ee8edbad1 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -11,6 +11,7 @@ import itertools
import logging
import pytz
+
try:
from xmlrpc.client import MAXINT
except ImportError:
@@ -19,12 +20,11 @@ except ImportError:
import psycopg2
-from odoo.sql_db import LazyCursor
-from odoo.tools import float_repr, float_round, frozendict, html_sanitize, human_size, pg_varchar, ustr, OrderedSet, pycompat
-from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
-from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
-from odoo.tools.translate import html_translate, _
-import odoo.tools.sql as sql
+from .sql_db import LazyCursor
+from .tools import float_repr, float_round, frozendict, html_sanitize, human_size, pg_varchar, ustr, OrderedSet, pycompat, sql
+from .tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
+from .tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
+from .tools.translate import html_translate, _
DATE_LENGTH = len(date.today().strftime(DATE_FORMAT))
DATETIME_LENGTH = len(datetime.now().strftime(DATETIME_FORMAT))
@@ -340,7 +340,7 @@ class Field(MetaField('DummyField', (object,), {})):
def __init__(self, string=Default, **kwargs):
kwargs['string'] = string
self._sequence = kwargs['_sequence'] = next(_global_seq)
- args = {key: val for key, val in pycompat.items(kwargs) if val is not Default}
+ args = {key: val for key, val in kwargs.items() if val is not Default}
self.args = args or EMPTY_DICT
self._setup_done = None
@@ -369,7 +369,7 @@ class Field(MetaField('DummyField', (object,), {})):
""" Set all field attributes at once (with slot defaults). """
# optimization: we assign slots only
assign = object.__setattr__
- for key, val in pycompat.items(self._slots):
+ for key, val in self._slots.items():
assign(self, key, attrs.pop(key, val))
if attrs:
assign(self, '_attrs', attrs)
@@ -498,7 +498,7 @@ class Field(MetaField('DummyField', (object,), {})):
def make_depends(deps):
return tuple(deps(model) if callable(deps) else deps)
- if isinstance(self.compute, basestring):
+ if isinstance(self.compute, pycompat.string_types):
# if the compute method has been overridden, concatenate all their _depends
self.depends = ()
for method in resolve_mro(model, self.compute, callable):
@@ -517,7 +517,7 @@ class Field(MetaField('DummyField', (object,), {})):
def _setup_related_full(self, model):
""" Setup the attributes of a related field. """
# fix the type of self.related if necessary
- if isinstance(self.related, basestring):
+ if isinstance(self.related, pycompat.string_types):
self.related = tuple(self.related.split('.'))
# determine the chain of fields, and make sure they are all set up
@@ -547,7 +547,7 @@ class Field(MetaField('DummyField', (object,), {})):
if not getattr(self, attr):
setattr(self, attr, getattr(field, prop))
- for attr, value in pycompat.items(field._attrs):
+ for attr, value in field._attrs.items():
if attr not in self._attrs:
setattr(self, attr, value)
@@ -655,7 +655,7 @@ class Field(MetaField('DummyField', (object,), {})):
model = model0.env.get(field.comodel_name)
# add self's model dependencies
- for mname, fnames in pycompat.items(model0._depends):
+ for mname, fnames in model0._depends.items():
model = model0.env[mname]
for fname in fnames:
field = model._fields[fname]
@@ -745,9 +745,7 @@ class Field(MetaField('DummyField', (object,), {})):
""" Convert ``value`` from the ``write`` format to the SQL format. """
if value is None or value is False:
return None
- if isinstance(value, unicode):
- return value.encode('utf8')
- return str(value)
+ return pycompat.to_native(value)
def convert_to_cache(self, value, record, validate=True):
""" Convert ``value`` to the cache format; ``value`` may come from an
@@ -973,7 +971,7 @@ class Field(MetaField('DummyField', (object,), {})):
for field in fields:
for record in records:
record._cache[field] = field.convert_to_cache(False, record, validate=False)
- if isinstance(self.compute, basestring):
+ if isinstance(self.compute, pycompat.string_types):
getattr(records, self.compute)()
else:
self.compute(records)
@@ -1047,14 +1045,14 @@ class Field(MetaField('DummyField', (object,), {})):
def determine_inverse(self, records):
""" Given the value of ``self`` on ``records``, inverse the computation. """
- if isinstance(self.inverse, basestring):
+ if isinstance(self.inverse, pycompat.string_types):
getattr(records, self.inverse)()
else:
self.inverse(records)
def determine_domain(self, records, operator, value):
""" Return a domain representing a condition on ``self``. """
- if isinstance(self.search, basestring):
+ if isinstance(self.search, pycompat.string_types):
return getattr(records, self.search)(operator, value)
else:
return self.search(records, operator, value)
@@ -1371,12 +1369,12 @@ class Char(_String):
return None
# we need to convert the string to a unicode object to be able
# to evaluate its length (and possibly truncate it) reliably
- return ustr(value)[:self.size].encode('utf8')
+ return pycompat.to_text(value)[:self.size]
def convert_to_cache(self, value, record, validate=True):
if value is None or value is False:
return False
- return ustr(value)[:self.size]
+ return pycompat.to_text(value)[:self.size]
class Text(_String):
@@ -1509,7 +1507,7 @@ class Date(Field):
def convert_to_cache(self, value, record, validate=True):
if not value:
return False
- if isinstance(value, basestring):
+ if isinstance(value, pycompat.string_types):
if validate:
# force parsing for validation
self.from_string(value)
@@ -1579,7 +1577,7 @@ class Datetime(Field):
def convert_to_cache(self, value, record, validate=True):
if not value:
return False
- if isinstance(value, basestring):
+ if isinstance(value, pycompat.string_types):
if validate:
# force parsing for validation
self.from_string(value)
@@ -1598,6 +1596,11 @@ class Datetime(Field):
assert record, 'Record expected'
return Datetime.to_string(Datetime.context_timestamp(record, Datetime.from_string(value)))
+# http://initd.org/psycopg/docs/usage.html#binary-adaptation
+# Received data is returned as buffer (in Python 2) or memoryview (in Python 3).
+_BINARY = memoryview
+if pycompat.PY2:
+ _BINARY = buffer #pylint: disable=buffer-builtin
class Binary(Field):
type = 'binary'
@@ -1619,11 +1622,15 @@ class Binary(Field):
# unicode in some circumstances, hence the str() cast here.
# This str() coercion will only work for pure ASCII unicode strings,
# on purpose - non base64 data must be passed as a 8bit byte strings.
- return psycopg2.Binary(str(value)) if value else None
+ if not value:
+ return None
+ if isinstance(value, bytes):
+ return psycopg2.Binary(value)
+ return psycopg2.Binary(pycompat.text_type(value).encode('ascii'))
def convert_to_cache(self, value, record, validate=True):
- if isinstance(value, buffer):
- return str(value)
+ if isinstance(value, _BINARY):
+ return bytes(value)
if isinstance(value, pycompat.integer_types) and \
(record._context.get('bin_size') or
record._context.get('bin_size_' + self.name)):
@@ -1724,14 +1731,14 @@ class Selection(Field):
if 'selection_add' in field.args:
# use an OrderedDict to update existing values
selection_add = field.args['selection_add']
- self.selection = list(pycompat.items(OrderedDict(self.selection + selection_add)))
+ self.selection = list(OrderedDict(self.selection + selection_add).items())
def _description_selection(self, env):
""" return the selection list (pairs (value, label)); labels are
translated according to context language
"""
selection = self.selection
- if isinstance(selection, basestring):
+ if isinstance(selection, pycompat.string_types):
return getattr(env[self.model_name], selection)()
if callable(selection):
return selection(env[self.model_name])
@@ -1748,7 +1755,7 @@ class Selection(Field):
def get_values(self, env):
""" return a list of the possible values """
selection = self.selection
- if isinstance(selection, basestring):
+ if isinstance(selection, pycompat.string_types):
selection = getattr(env[self.model_name], selection)()
elif callable(selection):
selection = selection(env[self.model_name])
@@ -1772,14 +1779,6 @@ class Selection(Field):
return item[1]
return False
- def convert_to_column(self, value, record, values=None):
- """ Convert ``value`` from the ``write`` format to the SQL format. """
- if value is None or value is False:
- return None
- if isinstance(value, unicode):
- return value.encode('utf8')
- return str(value)
-
class Reference(Selection):
type = 'reference'
@@ -1797,7 +1796,7 @@ class Reference(Selection):
if isinstance(value, BaseModel):
if not validate or (value._name in self.get_values(record.env) and len(value) <= 1):
return process(value._name, value.id) if value else False
- elif isinstance(value, basestring):
+ elif isinstance(value, pycompat.string_types):
res_model, res_id = value.split(',')
if record.env[res_model].browse(int(res_id)).exists():
return process(res_model, int(res_id))
@@ -1894,7 +1893,7 @@ class Many2one(_Relational):
super(Many2one, self)._setup_attrs(model, name)
# determine self.delegate
if not self.delegate:
- self.delegate = name in pycompat.values(model._inherits)
+ self.delegate = name in model._inherits.values()
def update_db(self, model, columns):
comodel = model.env[self.comodel_name]
@@ -2117,7 +2116,7 @@ class _RelationalMulti(_Relational):
self.depends += tuple(
self.name + '.' + arg[0]
for arg in self.domain
- if isinstance(arg, (tuple, list)) and isinstance(arg[0], basestring)
+ if isinstance(arg, (tuple, list)) and isinstance(arg[0], pycompat.string_types)
)