Refactoring by validation with pylint
This commit is contained in:
1 parent
5a2baacef4
commit
b5fb4d1ef3
34 files changed
+438
-416
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Refactoring by validation with pylint
|
||||
* Modify ondelete attribute of Many2One according to required attribute value
|
||||
* Refactor import_data of ModelStorage
|
||||
* Raise exception when search function is missing on Function fields
|
||||
|
||||
+2
-2
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import sys, os
|
||||
import sys
|
||||
import os
|
||||
DIR = os.path.abspath(os.path.normpath(os.path.join(__file__,
|
||||
'..', '..', 'trytond')))
|
||||
if os.path.isdir(DIR):
|
||||
@@ -11,7 +12,6 @@ if '--profile' in sys.argv:
|
||||
import profile
|
||||
import pstats
|
||||
import tempfile
|
||||
import os
|
||||
sys.argv.remove('--profile')
|
||||
|
||||
statfile = tempfile.mkstemp(".stat","trytond-")[1]
|
||||
|
||||
@@ -23,7 +23,7 @@ class Field(object):
|
||||
|
||||
@staticmethod
|
||||
def sql_type(field):
|
||||
return None
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class Boolean(Field):
|
||||
|
||||
@@ -5,7 +5,7 @@ from trytond.backend.database import DatabaseInterface, CursorInterface
|
||||
from trytond.config import CONFIG
|
||||
from trytond.session import Session
|
||||
from psycopg2.pool import ThreadedConnectionPool
|
||||
from psycopg2.extensions import cursor
|
||||
from psycopg2.extensions import cursor as PsycopgCursor
|
||||
from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE
|
||||
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
|
||||
from psycopg2.extensions import register_type, register_adapter
|
||||
@@ -238,7 +238,7 @@ class Database(DatabaseInterface):
|
||||
(0, module_id, dependency))
|
||||
|
||||
|
||||
class _Cursor(cursor):
|
||||
class _Cursor(PsycopgCursor):
|
||||
|
||||
def __build_dict(self, row):
|
||||
return dict((desc[0], row[i])
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.backend.table import TableHandlerInterface
|
||||
from trytond.backend.postgresql.fields import FIELDS
|
||||
import logging
|
||||
|
||||
|
||||
@@ -25,8 +24,8 @@ class TableHandler(TableHandlerInterface):
|
||||
if not self.table_exist(self.cursor, self.table_name):
|
||||
self.cursor.execute('CREATE TABLE "%s" ()' % self.table_name)
|
||||
|
||||
self.cursor.execute('COMMENT ON TABLE "%s" IS \'%s\'' % (self.table_name,
|
||||
model._description.replace("'", "''")))
|
||||
self.cursor.execute('COMMENT ON TABLE "%s" IS \'%s\'' %
|
||||
(self.table_name, model._description.replace("'", "''")))
|
||||
|
||||
self._update_definitions()
|
||||
if 'id' not in self._columns:
|
||||
@@ -140,9 +139,10 @@ class TableHandler(TableHandlerInterface):
|
||||
self.cursor.execute("SELECT co.contype, co.confdeltype, at.attname, "\
|
||||
"cl2.relname, co.conname "\
|
||||
"FROM pg_constraint co "\
|
||||
"LEFT JOIN pg_class cl on (co.conrelid = cl.oid) "\
|
||||
"LEFT JOIN pg_class cl2 on (co.confrelid = cl2.oid) "\
|
||||
"LEFT JOIN pg_attribute at on (co.conkey[1] = at.attnum) "\
|
||||
"LEFT JOIN pg_class cl ON (co.conrelid = cl.oid) "\
|
||||
"LEFT JOIN pg_class cl2 ON (co.confrelid = cl2.oid) "\
|
||||
"LEFT JOIN pg_attribute at ON " \
|
||||
"(co.conkey[1] = at.attnum) "\
|
||||
"WHERE cl.relname = %s AND at.attrelid = cl.oid",
|
||||
(self.table_name,))
|
||||
self._constraints = []
|
||||
@@ -237,7 +237,6 @@ class TableHandler(TableHandlerInterface):
|
||||
if field_size == None:
|
||||
if self._columns[column_name]['size'] > 0:
|
||||
self.alter_size(column_name, base_type)
|
||||
pass
|
||||
elif self._columns[column_name]['size'] == field_size:
|
||||
pass
|
||||
elif self._columns[column_name]['size'] > 0 and \
|
||||
@@ -318,7 +317,7 @@ class TableHandler(TableHandlerInterface):
|
||||
return
|
||||
self.cursor.execute('CREATE INDEX "' + index_name + '" ' \
|
||||
'ON "' + self.table_name + '" ( ' + \
|
||||
','.join(['"' + x + '"' for x in column_name]) + \
|
||||
','.join(['"' + x + '"' for x in column_name]) +\
|
||||
')')
|
||||
self._update_definitions()
|
||||
elif action == 'remove':
|
||||
@@ -354,9 +353,11 @@ class TableHandler(TableHandlerInterface):
|
||||
'of table %s not null !\n'\
|
||||
'Try to re-run: ' \
|
||||
'trytond.py --update=module\n' \
|
||||
'If it doesn\'t work, update records and execute manually:\n' \
|
||||
'ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % \
|
||||
(column_name, self.table_name, self.table_name, column_name))
|
||||
'If it doesn\'t work, update records ' \
|
||||
'and execute manually:\n' \
|
||||
'ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' %
|
||||
(column_name, self.table_name, self.table_name,
|
||||
column_name))
|
||||
elif action == 'remove':
|
||||
if not self._columns[column_name]['notnull']:
|
||||
return
|
||||
@@ -424,7 +425,7 @@ class TableHandler(TableHandlerInterface):
|
||||
self._update_definitions()
|
||||
|
||||
@staticmethod
|
||||
def dropTable(cursor, model, table, cascade=False):
|
||||
def drop_table(cursor, model, table, cascade=False):
|
||||
cursor.execute('DELETE from ir_model_data where '\
|
||||
'model = \'%s\'' % model)
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
from trytond.backend.database import DatabaseInterface, CursorInterface
|
||||
from trytond.config import CONFIG
|
||||
from trytond.session import Session
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from decimal import Decimal
|
||||
@@ -180,12 +179,12 @@ class Database(DatabaseInterface):
|
||||
@staticmethod
|
||||
def list(cursor):
|
||||
res = []
|
||||
for file in os.listdir(CONFIG['data_path']) + [':memory:']:
|
||||
if file.endswith('.sqlite') or file == ':memory:':
|
||||
if file == ':memory:':
|
||||
for db_file in os.listdir(CONFIG['data_path']) + [':memory:']:
|
||||
if db_file.endswith('.sqlite') or db_file == ':memory:':
|
||||
if db_file == ':memory:':
|
||||
db_name = ':memory:'
|
||||
else:
|
||||
db_name = file[:-7]
|
||||
db_name = db_file[:-7]
|
||||
try:
|
||||
database = Database(db_name)
|
||||
except:
|
||||
@@ -270,12 +269,12 @@ class Cursor(CursorInterface):
|
||||
|
||||
def execute(self, sql, params=None):
|
||||
buf = ""
|
||||
for nq, q in QUOTE_SEPARATION.findall(sql+"''"):
|
||||
nq = nq.replace('?', '??')
|
||||
nq = nq.replace('%s', '?')
|
||||
nq = nq.replace('ilike', 'like')
|
||||
nq = re.sub(EXTRACT_PATTERN, r'EXTRACT("\1",', nq)
|
||||
buf += nq + q
|
||||
for nquote, quote in QUOTE_SEPARATION.findall(sql+"''"):
|
||||
nquote = nquote.replace('?', '??')
|
||||
nquote = nquote.replace('%s', '?')
|
||||
nquote = nquote.replace('ilike', 'like')
|
||||
nquote = re.sub(EXTRACT_PATTERN, r'EXTRACT("\1",', nquote)
|
||||
buf += nquote + quote
|
||||
sql = buf[:-2]
|
||||
try:
|
||||
if params:
|
||||
@@ -345,8 +344,8 @@ class Cursor(CursorInterface):
|
||||
return select
|
||||
|
||||
sqlite.register_converter('NUMERIC', lambda val: Decimal(str(val)))
|
||||
sqlite.register_adapter(Decimal, lambda val: float(val))
|
||||
sqlite.register_adapter(Session, lambda val: int(val))
|
||||
sqlite.register_adapter(Decimal, float)
|
||||
sqlite.register_adapter(Session, int)
|
||||
def adapt_datetime(val):
|
||||
return val.replace(tzinfo=None).isoformat(" ")
|
||||
sqlite.register_adapter(datetime.datetime, adapt_datetime)
|
||||
@@ -2,7 +2,6 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.backend.table import TableHandlerInterface
|
||||
from trytond.backend.sqlite.fields import FIELDS
|
||||
import logging
|
||||
import re
|
||||
|
||||
@@ -160,7 +159,6 @@ class TableHandler(TableHandlerInterface):
|
||||
if field_size == None:
|
||||
if self._columns[column_name]['size'] > 0:
|
||||
self.alter_size(column_name, base_type)
|
||||
pass
|
||||
elif self._columns[column_name]['size'] == field_size:
|
||||
pass
|
||||
elif self._columns[column_name]['size'] > 0 and \
|
||||
@@ -268,7 +266,7 @@ class TableHandler(TableHandlerInterface):
|
||||
(column_name, self.table_name))
|
||||
|
||||
@staticmethod
|
||||
def dropTable(cursor, model, table, cascade=False):
|
||||
def drop_table(cursor, model, table, cascade=False):
|
||||
cursor.execute('DELETE from ir_model_data where '\
|
||||
'model = \'%s\'' % model)
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ class TableHandlerInterface(object):
|
||||
raise
|
||||
|
||||
@staticmethod
|
||||
def dropTable(cursor, model, table, cascade=False):
|
||||
def drop_table(cursor, model, table, cascade=False):
|
||||
'''
|
||||
Remove a table and clean ir_model_data from the given model.
|
||||
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import ConfigParser, optparse, os, sys
|
||||
from version import VERSION
|
||||
from trytond.version import VERSION
|
||||
|
||||
|
||||
class ConfigManager(object):
|
||||
@@ -52,6 +52,7 @@ class ConfigManager(object):
|
||||
'init': {},
|
||||
'update': {},
|
||||
}
|
||||
self.configfile = None
|
||||
|
||||
def parse(self):
|
||||
parser = optparse.OptionParser(version=VERSION)
|
||||
@@ -75,7 +76,7 @@ class ConfigManager(object):
|
||||
parser.add_option("--logfile", dest="logfile",
|
||||
help="file where the server log will be stored")
|
||||
|
||||
(opt, args) = parser.parse_args()
|
||||
(opt, _) = parser.parse_args()
|
||||
|
||||
if opt.config:
|
||||
self.configfile = opt.config
|
||||
|
||||
@@ -16,7 +16,7 @@ class BrowseRecordList(list):
|
||||
res = []
|
||||
for record in self:
|
||||
res2 = {}
|
||||
for field_name, field in record._model._columns.iteritems():
|
||||
for field_name, _ in record._model._columns.iteritems():
|
||||
if not isinstance(record[field_name], BrowseRecordList):
|
||||
res2[field_name] = record.get_eval(field_name)
|
||||
res.append(res2)
|
||||
@@ -68,7 +68,7 @@ class BrowseRecord(object):
|
||||
self._data[record_id] = {'id': record_id}
|
||||
self._cache = cache
|
||||
if local_cache is None:
|
||||
local_cache ={}
|
||||
local_cache = {}
|
||||
self._local_cache = local_cache
|
||||
self._local_cache.setdefault(model._name, {})
|
||||
self._local_cache.setdefault('_language_cache', {})
|
||||
@@ -145,8 +145,8 @@ class BrowseRecord(object):
|
||||
for data in datas:
|
||||
for i, j in ffields:
|
||||
model = None
|
||||
if hasattr(j, 'model_name') \
|
||||
and j.model_name in self._model.pool.object_name_list():
|
||||
if hasattr(j, 'model_name') and \
|
||||
j.model_name in self._model.pool.object_name_list():
|
||||
model = self._model.pool.get(j.model_name)
|
||||
elif hasattr(j, 'get_target'):
|
||||
model = j.get_target(self._model.pool)
|
||||
@@ -156,12 +156,13 @@ class BrowseRecord(object):
|
||||
data[i] = BrowseRecordNull()
|
||||
else:
|
||||
ctx = self._context
|
||||
if hasattr(j, 'datetime_field') and j.datetime_field:
|
||||
if hasattr(j, 'datetime_field') and \
|
||||
j.datetime_field:
|
||||
ctx = self._context.copy()
|
||||
ctx['_datetime'] = data[j.datetime_field]
|
||||
data[i] = BrowseRecord(self._cursor, self._user,
|
||||
data[i], model, local_cache=self._local_cache,
|
||||
context=ctx)
|
||||
data[i], model,
|
||||
local_cache=self._local_cache, context=ctx)
|
||||
elif model and j._type in ('one2many', 'many2many') \
|
||||
and len(data[i]):
|
||||
ctx = self._context
|
||||
|
||||
@@ -6,6 +6,7 @@ import time
|
||||
|
||||
|
||||
class Cacheable(object):
|
||||
_name = None
|
||||
|
||||
def __init__(self):
|
||||
super(Cacheable, self).__init__()
|
||||
|
||||
@@ -10,7 +10,8 @@ class Binary(Field):
|
||||
'''
|
||||
_type = 'binary'
|
||||
|
||||
def get(self, cursor, user, ids, model, name, values=None, context=None):
|
||||
@staticmethod
|
||||
def get(cursor, user, ids, model, name, values=None, context=None):
|
||||
'''
|
||||
Convert the binary value into ``str``
|
||||
|
||||
|
||||
@@ -13,9 +13,10 @@ class Property(Function):
|
||||
|
||||
def __init__(self, type='float', model_name=None, selection=None,
|
||||
digits=None, relation=None, add_remove=None, string='', help='',
|
||||
required=False, readonly=False, domain=None, states=None, priority=0,
|
||||
change_default=False, translate=False, select=0, on_change=None,
|
||||
on_change_with=None, depends=None, order_field=None, context=None):
|
||||
required=False, readonly=False, domain=None, states=None,
|
||||
priority=0, change_default=False, translate=False, select=0,
|
||||
on_change=None, on_change_with=None, depends=None,
|
||||
order_field=None, context=None):
|
||||
'''
|
||||
:param type: The type of the field.
|
||||
:param fnct_search: The name of the search function.
|
||||
@@ -69,8 +70,8 @@ class Property(Function):
|
||||
'''
|
||||
property_obj = model.pool.get('ir.property')
|
||||
return property_obj.set(cursor, user, name, model._name, record_id,
|
||||
(value and (self.model_name or '') + ',' + str(value)) or False,
|
||||
context=context)
|
||||
(value and (self.model_name or '') + ',' + str(value)) or
|
||||
False, context=context)
|
||||
|
||||
|
||||
def search(self, cursor, user, model, name, args, context=None):
|
||||
@@ -106,16 +107,21 @@ class Property(Function):
|
||||
|
||||
#Fetch res ids that comply with the domain
|
||||
cursor.execute(
|
||||
'SELECT cast(split_part("' + property_obj._table + '".res,\',\',2) as integer), ' + \
|
||||
'SELECT CAST(' \
|
||||
'SPLIT_PART("' + property_obj._table + '".res,\',\',2) ' \
|
||||
'AS INTEGER), '\
|
||||
'"' + property_obj._table + '".id '\
|
||||
'FROM "' + property_obj._table + '" '\
|
||||
'JOIN "' + field_obj._table + '" on ("' + field_obj._table + '"'+ \
|
||||
'.id = "' + property_obj._table + '".field) '\
|
||||
'JOIN "' + model_obj._table +'" on ("' + model_obj._table + \
|
||||
'".id = "' + field_obj._table + '".model) '\
|
||||
'JOIN "' + field_obj._table + '" ON ' \
|
||||
'("' + field_obj._table + '"'+ \
|
||||
'.id = "' + property_obj._table + '".field) '\
|
||||
'JOIN "' + model_obj._table +'" ON ' \
|
||||
'("' + model_obj._table + \
|
||||
'".id = "' + field_obj._table + '".model) '\
|
||||
'WHERE '\
|
||||
'CASE WHEN "' +\
|
||||
model_obj._table + '".model = %s AND "' + field_obj._table + '".name = %s AND ' \
|
||||
model_obj._table + '".model = %s ' \
|
||||
'AND "' + field_obj._table + '".name = %s AND ' \
|
||||
+ property_query + \
|
||||
' THEN ' + \
|
||||
conditions + \
|
||||
@@ -126,9 +132,9 @@ class Property(Function):
|
||||
|
||||
props = cursor.fetchall()
|
||||
default = None
|
||||
for x in props:
|
||||
if not x[0]:
|
||||
default = x[1]
|
||||
for prop in props:
|
||||
if not prop[0]:
|
||||
default = prop[1]
|
||||
break
|
||||
|
||||
if not default:
|
||||
|
||||
+21
-14
@@ -3,7 +3,7 @@
|
||||
|
||||
from trytond.model import fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import PYSONEncoder, CONTEXT
|
||||
from trytond.pyson import PYSONEncoder
|
||||
import copy
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ class Model(object):
|
||||
:_error_messages: a dictionary mapping keywords to an error message. Eg.:
|
||||
|
||||
``{'recursive_categories': 'You can not create recursive categories!'}``
|
||||
:_rec_name: The name of the main field of the model.
|
||||
By default the field ``name``.
|
||||
:id: An Integer field for unique identifier.
|
||||
"""
|
||||
_name = None
|
||||
_inherits = {}
|
||||
@@ -28,6 +31,9 @@ class Model(object):
|
||||
__columns = None
|
||||
__xxx2many_targets = None
|
||||
__defaults = None
|
||||
_rec_name = 'name'
|
||||
|
||||
id = fields.Integer('ID', readonly=True)
|
||||
|
||||
def _reset_columns(self):
|
||||
self.__columns = None
|
||||
@@ -245,9 +251,9 @@ class Model(object):
|
||||
'WHERE f.model = m.id ' \
|
||||
'AND m.model = %s ',
|
||||
(self._name,))
|
||||
fields = {}
|
||||
model_fields = {}
|
||||
for field in cursor.dictfetchall():
|
||||
fields[field['name']] = field
|
||||
model_fields[field['name']] = field
|
||||
|
||||
# Prefetch field translations
|
||||
if self._columns:
|
||||
@@ -278,17 +284,17 @@ class Model(object):
|
||||
relation = field.model_name
|
||||
elif hasattr(field, 'relation_name'):
|
||||
relation = field.relation_name
|
||||
if field_name not in fields:
|
||||
if field_name not in model_fields:
|
||||
cursor.execute("INSERT INTO ir_model_field " \
|
||||
"(model, name, field_description, ttype, " \
|
||||
"relation, help, module) " \
|
||||
"VALUES (%s, %s, %s, %s, %s, %s, %s)",
|
||||
(model_id, field_name, field.string, field._type,
|
||||
relation, field.help, module_name))
|
||||
elif fields[field_name]['field_description'] != field.string \
|
||||
or fields[field_name]['ttype'] != field._type \
|
||||
or fields[field_name]['relation'] != relation \
|
||||
or fields[field_name]['help'] != field.help:
|
||||
elif model_fields[field_name]['field_description'] != field.string \
|
||||
or model_fields[field_name]['ttype'] != field._type \
|
||||
or model_fields[field_name]['relation'] != relation \
|
||||
or model_fields[field_name]['help'] != field.help:
|
||||
cursor.execute('UPDATE ir_model_field ' \
|
||||
'SET field_description = %s, ' \
|
||||
'ttype = %s, ' \
|
||||
@@ -296,7 +302,7 @@ class Model(object):
|
||||
'help = %s ' \
|
||||
'WHERE id = %s ',
|
||||
(field.string, field._type, relation,
|
||||
field.help, fields[field_name]['id']))
|
||||
field.help, model_fields[field_name]['id']))
|
||||
trans_name = self._name + ',' + field_name
|
||||
if trans_name not in trans_fields:
|
||||
if field_name not in ('create_uid', 'create_date',
|
||||
@@ -328,7 +334,7 @@ class Model(object):
|
||||
and ((hasattr(field, 'translate_selection') \
|
||||
and field.translate_selection)
|
||||
or not hasattr(field, 'translate_selection')):
|
||||
for (key, val) in field.selection:
|
||||
for (_, val) in field.selection:
|
||||
if trans_name not in trans_selection \
|
||||
or val not in trans_selection[trans_name]:
|
||||
cursor.execute('INSERT INTO ir_translation ' \
|
||||
@@ -338,13 +344,14 @@ class Model(object):
|
||||
(trans_name, 'en_US', 'selection', val, '',
|
||||
module_name, False))
|
||||
# Clean ir_model_field from field that are no more existing.
|
||||
for field_name in fields:
|
||||
if fields[field_name]['module'] == module_name \
|
||||
for field_name in model_fields:
|
||||
if model_fields[field_name]['module'] == module_name \
|
||||
and field_name not in self._columns:
|
||||
# XXX This delete field even when it is defined later in the module
|
||||
#XXX This delete field even when it is defined later
|
||||
# in the module
|
||||
cursor.execute('DELETE FROM ir_model_field '\
|
||||
'WHERE id = %s',
|
||||
(fields[field_name]['id'],))
|
||||
(model_fields[field_name]['id'],))
|
||||
|
||||
# Add error messages in ir_translation
|
||||
cursor.execute('SELECT id, src FROM ir_translation ' \
|
||||
|
||||
+92
-55
@@ -5,7 +5,6 @@ from trytond.model import ModelStorage
|
||||
from trytond.model import fields
|
||||
from trytond.backend import FIELDS, TableHandler
|
||||
from trytond.backend import DatabaseIntegrityError, Database
|
||||
from trytond.model.browse import BrowseRecord, BrowseRecordNull
|
||||
from trytond.tools import reduce_ids
|
||||
from trytond.const import OPERATORS
|
||||
import datetime
|
||||
@@ -62,7 +61,8 @@ class ModelSQL(ModelStorage):
|
||||
# create/update table in the database
|
||||
table = TableHandler(cursor, self, module_name)
|
||||
if self._history:
|
||||
history_table = TableHandler(cursor, self, module_name, history=True)
|
||||
history_table = TableHandler(cursor, self, module_name,
|
||||
history=True)
|
||||
timestamp_field = FIELDS['timestamp']
|
||||
integer_field = FIELDS['integer']
|
||||
logs = (
|
||||
@@ -168,7 +168,7 @@ class ModelSQL(ModelStorage):
|
||||
and field.left and field.right:
|
||||
self._rebuild_tree(cursor, 0, field_name, False, 0)
|
||||
|
||||
for ident, constraint, msg in self._sql_constraints:
|
||||
for ident, constraint, _ in self._sql_constraints:
|
||||
table.add_constraint(ident, constraint)
|
||||
|
||||
if self._history:
|
||||
@@ -179,7 +179,8 @@ class ModelSQL(ModelStorage):
|
||||
if not cursor.fetchone():
|
||||
columns = ['"' + str(x) + '"' for x in self._columns
|
||||
if not hasattr(self._columns[x], 'set')]
|
||||
cursor.execute('INSERT INTO "' + self._table + '__history" '\
|
||||
cursor.execute('INSERT ' \
|
||||
'INTO "' + self._table + '__history" '\
|
||||
'(' + ','.join(columns) + ') ' \
|
||||
'SELECT ' + ','.join(columns) + \
|
||||
' FROM "' + self._table + '"')
|
||||
@@ -204,6 +205,24 @@ class ModelSQL(ModelStorage):
|
||||
res.append(error)
|
||||
return res
|
||||
|
||||
def default_sequence(self, cursor, user, context=None):
|
||||
'''
|
||||
Return the default value for sequence field.
|
||||
'''
|
||||
table = self._table
|
||||
if 'sequence' not in self._columns:
|
||||
for model in self._inherits:
|
||||
model_obj = self.pool.get(model)
|
||||
if 'sequence' in model_obj._columns:
|
||||
table = model_obj._table
|
||||
break
|
||||
cursor.execute('SELECT MAX(sequence) ' \
|
||||
'FROM "' + table + '"')
|
||||
res = cursor.fetchone()
|
||||
if res:
|
||||
return res[0]
|
||||
return 0
|
||||
|
||||
def table_query(self, context=None):
|
||||
'''
|
||||
Return None if the model is a real table in the database
|
||||
@@ -269,7 +288,7 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
for i in values.keys():
|
||||
if i in self._inherit_fields:
|
||||
(inherits, col, col_detail) = self._inherit_fields[i]
|
||||
(inherits, _, _) = self._inherit_fields[i]
|
||||
if i in self._columns:
|
||||
continue
|
||||
if inherits in tocreate:
|
||||
@@ -388,8 +407,8 @@ class ModelSQL(ModelStorage):
|
||||
upd_todo.sort(lambda x, y: self._columns[x].priority - \
|
||||
self._columns[y].priority)
|
||||
for field in upd_todo:
|
||||
self._columns[field].set(cursor, user, id_new, self, field, values[field],
|
||||
context=context)
|
||||
self._columns[field].set(cursor, user, id_new, self, field,
|
||||
values[field], context=context)
|
||||
|
||||
if self._history:
|
||||
cursor.execute('INSERT INTO "' + self._table + '__history" ' \
|
||||
@@ -406,7 +425,8 @@ class ModelSQL(ModelStorage):
|
||||
if isinstance(field, fields.Many2One) \
|
||||
and field.model_name == self._name \
|
||||
and field.left and field.right:
|
||||
self._update_tree(cursor, user, id_new, k, field.left, field.right)
|
||||
self._update_tree(cursor, user, id_new, k, field.left,
|
||||
field.right)
|
||||
|
||||
return id_new
|
||||
|
||||
@@ -502,7 +522,7 @@ class ModelSQL(ModelStorage):
|
||||
else:
|
||||
cursor.execute('SELECT ' + \
|
||||
','.join(fields_pre2 + ['id']) + \
|
||||
' FROM ' + table_query + '\"' + self._table + '\" ' \
|
||||
' FROM ' + table_query + '\"' + self._table + '\" '\
|
||||
'WHERE ' + red_sql + \
|
||||
history_clause + history_order + history_limit,
|
||||
table_args + red_ids + history_args)
|
||||
@@ -647,8 +667,8 @@ class ModelSQL(ModelStorage):
|
||||
record_id = record2['id']
|
||||
del record2['id']
|
||||
fields_related2values[field].setdefault(record_id, {})
|
||||
fields_related2values[field][record_id][record['id']] = \
|
||||
record2
|
||||
fields_related2values[
|
||||
field][record_id][record['id']] = record2
|
||||
else:
|
||||
for record in obj.read(cursor, user, [x[field] for x in res
|
||||
if x[field]], fields_related[field], context=context):
|
||||
@@ -876,9 +896,9 @@ class ModelSQL(ModelStorage):
|
||||
.get(field.model_name, set())
|
||||
if not ((model_obj.search(cursor2, 0, [
|
||||
('id', '=', values[field_name]),
|
||||
], order=[], context=context) \
|
||||
or values[field_name] in create_records) \
|
||||
and values[field_name] not in delete_records):
|
||||
], order=[], context=context) or
|
||||
values[field_name] in create_records) and
|
||||
values[field_name] not in delete_records):
|
||||
self.raise_user_error(cursor2,
|
||||
'foreign_model_missing',
|
||||
error_args=self._get_error_args(
|
||||
@@ -948,8 +968,9 @@ class ModelSQL(ModelStorage):
|
||||
and field.model_name == self._name \
|
||||
and field.left and field.right:
|
||||
if field.left in values or field.right in values:
|
||||
raise Exception('ValidateError', 'You can not update fields: ' \
|
||||
'"%s", "%s"' % (field.left, field.right))
|
||||
raise Exception('ValidateError',
|
||||
'You can not update fields: "%s", "%s"' %
|
||||
(field.left, field.right))
|
||||
if len(ids) == 1:
|
||||
self._update_tree(cursor, user, ids[0], k,
|
||||
field.left, field.right)
|
||||
@@ -1104,10 +1125,12 @@ class ModelSQL(ModelStorage):
|
||||
error_args = []
|
||||
error_args.append(self._get_error_args(cursor2,
|
||||
user, 'id', context=context)[1])
|
||||
error_args.extend(list(model._get_error_args(cursor2,
|
||||
user, field_name, context=context)))
|
||||
self.raise_user_error(cursor2, 'foreign_model_exist',
|
||||
error_args=tuple(error_args), context=context)
|
||||
error_args.extend(list(model._get_error_args(
|
||||
cursor2, user, field_name, context=context)))
|
||||
self.raise_user_error(cursor2,
|
||||
'foreign_model_exist',
|
||||
error_args=tuple(error_args),
|
||||
context=context)
|
||||
for name, _, error in self._sql_constraints:
|
||||
if name in exception[0]:
|
||||
self.raise_user_error(cursor2, error,
|
||||
@@ -1269,7 +1292,8 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
return [x['id'] for x in datas]
|
||||
|
||||
def search_domain(self, cursor, user, domain, active_test=True, context=None):
|
||||
def search_domain(self, cursor, user, domain, active_test=True,
|
||||
context=None):
|
||||
'''
|
||||
Return SQL clause and arguments for the domain
|
||||
|
||||
@@ -1377,7 +1401,7 @@ class ModelSQL(ModelStorage):
|
||||
self._inherits[itable._name])
|
||||
if table_join not in tables:
|
||||
tables.append(table_join)
|
||||
tables_args += table_arg
|
||||
tables_args.extend(table_arg)
|
||||
field = table._columns.get(fargs[0], False)
|
||||
if not field:
|
||||
if not fargs[0] in self._inherit_fields:
|
||||
@@ -1389,21 +1413,25 @@ class ModelSQL(ModelStorage):
|
||||
if field._type == 'many2one':
|
||||
if hasattr(field, 'search'):
|
||||
domain.extend([(fargs[0], 'in',
|
||||
self.pool.get(field.model_name).search(cursor, user,
|
||||
[(fargs[1], domain[i][1], domain[i][2])],
|
||||
order=[], context=context))])
|
||||
self.pool.get(field.model_name).search(cursor,
|
||||
user,[
|
||||
(fargs[1], domain[i][1], domain[i][2]),
|
||||
], order=[], context=context))])
|
||||
domain.pop(i)
|
||||
else:
|
||||
domain[i] = (fargs[0], 'inselect',
|
||||
self.pool.get(field.model_name).search(cursor, user,
|
||||
[(fargs[1], domain[i][1], domain[i][2])],
|
||||
order=[], context=context, query_string=True),
|
||||
self.pool.get(field.model_name).search(cursor,
|
||||
user, [
|
||||
(fargs[1], domain[i][1], domain[i][2]),
|
||||
], order=[], context=context,
|
||||
query_string=True),
|
||||
table)
|
||||
i += 1
|
||||
continue
|
||||
else:
|
||||
raise Exception('ValidateError', 'Clause on field "%s" ' \
|
||||
'doesn\'t work on "%s"' % (domain[i][0], self._name))
|
||||
'doesn\'t work on "%s"' %
|
||||
(domain[i][0], self._name))
|
||||
if hasattr(field, 'search'):
|
||||
arg = [domain.pop(i)]
|
||||
domain.extend(field.search(cursor, user, table,
|
||||
@@ -1427,7 +1455,8 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
if ids2 == True or ids2 == False:
|
||||
query1 = 'SELECT "' + field.field + '" ' \
|
||||
'FROM ' + table_query + '"' + field_obj._table + '" ' \
|
||||
'FROM ' + table_query + \
|
||||
'"' + field_obj._table + '" ' \
|
||||
'WHERE "' + field.field + '" IS NOT NULL'
|
||||
query2 = table_args
|
||||
clause = 'inselect'
|
||||
@@ -1440,7 +1469,8 @@ class ModelSQL(ModelStorage):
|
||||
if len(ids2) < cursor.IN_MAX:
|
||||
red_sql, red_ids = reduce_ids('id', ids2)
|
||||
query1 = 'SELECT "' + field.field + '" ' \
|
||||
'FROM ' + table_query + '"' + field_obj._table + '" ' \
|
||||
'FROM ' + table_query + \
|
||||
'"' + field_obj._table + '" ' \
|
||||
'WHERE ' + red_sql
|
||||
query2 = table_args + red_ids
|
||||
domain[i] = ('id', 'inselect', (query1, query2))
|
||||
@@ -1450,8 +1480,9 @@ class ModelSQL(ModelStorage):
|
||||
sub_ids2 = ids2[i:i + cursor.IN_MAX]
|
||||
red_sql, red_ids = reduce_ids('id', sub_ids2)
|
||||
cursor.execute(
|
||||
'SELECT "' + field.field + \
|
||||
'" FROM ' + table_query + '"' + field_obj._table + '" ' \
|
||||
'SELECT "' + field.field + '" ' \
|
||||
'FROM ' + table_query + \
|
||||
'"' + field_obj._table + '" ' \
|
||||
'WHERE ' + red_sql,
|
||||
table_args + red_ids)
|
||||
|
||||
@@ -1570,9 +1601,10 @@ class ModelSQL(ModelStorage):
|
||||
raise Exception('Error', 'Programming error: ' \
|
||||
'child_of on field "%s" is not allowed!' % \
|
||||
(domain[i][0],))
|
||||
ids2 = self.pool.get(field.model_name).search(cursor, user,
|
||||
[(domain[i][3], 'child_of', ids2)], order=[],
|
||||
context=context)
|
||||
ids2 = self.pool.get(field.model_name).search(cursor,
|
||||
user, [
|
||||
(domain[i][3], 'child_of', ids2),
|
||||
], order=[], context=context)
|
||||
if domain[i][1] == 'child_of':
|
||||
domain[i] = (domain[i][0], 'in', ids2, table)
|
||||
else:
|
||||
@@ -1667,7 +1699,8 @@ class ModelSQL(ModelStorage):
|
||||
query1 = 'SELECT "' + table._table + '".id ' \
|
||||
'FROM ' + table_query + '"' + table._table + '" ' \
|
||||
+ table_join + ' ' \
|
||||
'WHERE (' + trans_field + ' ' + domain[i][1] + ' %s)'
|
||||
'WHERE ' \
|
||||
'(' + trans_field + ' ' + domain[i][1] + ' %s)'
|
||||
query2 = table_args + table_join_args + [domain[i][2]]
|
||||
domain[i] = ('id', 'inselect', (query1, query2), table)
|
||||
else:
|
||||
@@ -1684,8 +1717,8 @@ class ModelSQL(ModelStorage):
|
||||
clause = 'IN'
|
||||
if arg[1] == 'notinselect':
|
||||
clause = 'NOT IN'
|
||||
qu1.append('("%s"."%s" %s (%s))' % (table._table, arg[0], clause,
|
||||
arg[2][0]))
|
||||
qu1.append('("%s"."%s" %s (%s))' % (table._table, arg[0],
|
||||
clause, arg[2][0]))
|
||||
qu2 += arg[2][1]
|
||||
elif arg[1] in ('in', 'not in'):
|
||||
if len(arg[2]) > 0:
|
||||
@@ -1793,13 +1826,15 @@ class ModelSQL(ModelStorage):
|
||||
add_null = True
|
||||
else:
|
||||
if arg[0] in table._columns:
|
||||
qu2.append(FIELDS[table._columns[arg[0]]._type].\
|
||||
sql_format(arg[2]))
|
||||
qu2.append(FIELDS[
|
||||
table._columns[arg[0]]._type
|
||||
].sql_format(arg[2]))
|
||||
qu1.append('("%s"."%s" %s %%s)' % (table._table,
|
||||
arg[0], arg[1]))
|
||||
if add_null:
|
||||
qu1[-1] = '(' + qu1[-1] + ' OR ' + \
|
||||
'"' + table._table + '".' + arg[0] +' IS NULL)'
|
||||
qu1[-1] = '(' + qu1[-1] + ' OR ' \
|
||||
'"' + table._table + '".' + arg[0] + \
|
||||
' IS NULL)'
|
||||
|
||||
return qu1, qu2
|
||||
|
||||
@@ -1963,7 +1998,8 @@ class ModelSQL(ModelStorage):
|
||||
FIELDS['boolean'].sql_format(False))
|
||||
if table_join not in tables:
|
||||
tables.append(table_join)
|
||||
tables_args[table_join] = [context.get('language') or 'en_US']
|
||||
tables_args[table_join] = [
|
||||
context.get('language') or 'en_US']
|
||||
order_by.append('COALESCE(NULLIF(' \
|
||||
+ '"' + translation_table + '".value, \'\'), ' \
|
||||
+ '"' + table_name + '".' + field_name + ') ' + otype)
|
||||
@@ -1992,7 +2028,8 @@ class ModelSQL(ModelStorage):
|
||||
'order': otype,
|
||||
})
|
||||
else:
|
||||
order_by.append('"' + table_name + '".' + field_name + ' ' + otype)
|
||||
order_by.append('"' + table_name + '".' + field_name + \
|
||||
' ' + otype)
|
||||
return order_by, tables, tables_args
|
||||
|
||||
if field in self._inherit_fields.keys():
|
||||
@@ -2126,14 +2163,14 @@ class ModelSQL(ModelStorage):
|
||||
], context={'active_test': False})
|
||||
if brother_ids[-1] != object_id:
|
||||
next_id = brother_ids[brother_ids.index(object_id) + 1]
|
||||
cursor.execute('SELECT "' + left + '", "' + right + '" ' \
|
||||
cursor.execute('SELECT "' + left + '" ' \
|
||||
'FROM "' + self._table + '" ' \
|
||||
'WHERE id = %s', (next_id,))
|
||||
next_left, next_right = cursor.fetchone()
|
||||
cursor.execute('SELECT "' + left + '", "' + right + '" '\
|
||||
next_left = cursor.fetchone()[0]
|
||||
cursor.execute('SELECT "' + left + '" '\
|
||||
'FROM "' + self._table + '" ' \
|
||||
'WHERE id = %s', (object_id,))
|
||||
current_left, current_right = cursor.fetchone()
|
||||
current_left = cursor.fetchone()[0]
|
||||
|
||||
|
||||
cursor.execute('UPDATE "' + self._table + '" ' \
|
||||
@@ -2157,9 +2194,9 @@ class ModelSQL(ModelStorage):
|
||||
return
|
||||
# Works only for a single transaction
|
||||
for _, sql, error in self._sql_constraints:
|
||||
m = _RE_UNIQUE.match(sql)
|
||||
if m:
|
||||
sql = m.group(1)
|
||||
match = _RE_UNIQUE.match(sql)
|
||||
if match:
|
||||
sql = match.group(1)
|
||||
sql_clause = ' AND '.join('%s = %%s' % \
|
||||
i for i in sql.split(','))
|
||||
sql_clause = '(id != %s AND ' + sql_clause + ')'
|
||||
@@ -2182,9 +2219,9 @@ class ModelSQL(ModelStorage):
|
||||
if cursor.fetchone():
|
||||
self.raise_user_error(cursor, error, context=context)
|
||||
continue
|
||||
m = _RE_CHECK.match(sql)
|
||||
if m:
|
||||
sql = m.group(1)
|
||||
match = _RE_CHECK.match(sql)
|
||||
if match:
|
||||
sql = match.group(1)
|
||||
for i in range(0, len(ids), cursor.IN_MAX):
|
||||
sub_ids = ids[i:i + cursor.IN_MAX]
|
||||
red_sql, red_ids = reduce_ids('id', sub_ids)
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
from trytond.model import Model
|
||||
from trytond.model import fields
|
||||
from trytond.model.browse import BrowseRecordList, BrowseRecord, BrowseRecordNull
|
||||
from trytond.model.browse import BrowseRecordList, BrowseRecord, \
|
||||
BrowseRecordNull
|
||||
from trytond.model.browse import EvalEnvironment
|
||||
from trytond.tools import safe_eval
|
||||
from trytond.pyson import PYSONEncoder, PYSONDecoder, PYSON
|
||||
@@ -15,7 +16,7 @@ import logging
|
||||
from itertools import chain
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
except ImprotError:
|
||||
except ImportError:
|
||||
import StringIO
|
||||
import csv
|
||||
|
||||
@@ -24,9 +25,6 @@ class ModelStorage(Model):
|
||||
"""
|
||||
Define a model with storage capability in Tryton.
|
||||
|
||||
:_rec_name: The name of the main field of the model.
|
||||
By default the field ``name``.
|
||||
:id: An Integer field for unique identifier.
|
||||
:create_uid: A Many2One that points to the
|
||||
user who created the record.
|
||||
:create_date: A Date field for date of creation of the record.
|
||||
@@ -40,9 +38,7 @@ class ModelStorage(Model):
|
||||
violated). ``error_keyword`` must be one of the key of
|
||||
``_sql_error_messages``.
|
||||
"""
|
||||
_rec_name = 'name'
|
||||
|
||||
id = fields.Integer('ID', readonly=True)
|
||||
create_uid = fields.Many2One('res.user', 'Create User', readonly=True)
|
||||
create_date = fields.DateTime('Create Date', readonly=True)
|
||||
write_uid = fields.Many2One('res.user', 'Write User', readonly=True)
|
||||
@@ -74,24 +70,6 @@ class ModelStorage(Model):
|
||||
"Default value for create_date field."
|
||||
return datetime.datetime.today()
|
||||
|
||||
def default_sequence(self, cursor, user, context=None):
|
||||
'''
|
||||
Return the default value for sequence field.
|
||||
'''
|
||||
table = self._table
|
||||
if 'sequence' not in self._columns:
|
||||
for model in self._inherits:
|
||||
model_obj = self.pool.get(model)
|
||||
if 'sequence' in model_obj._columns:
|
||||
table = model_obj._table
|
||||
break
|
||||
cursor.execute('SELECT MAX(sequence) ' \
|
||||
'FROM "' + table + '"')
|
||||
res = cursor.fetchone()
|
||||
if res:
|
||||
return res[0]
|
||||
return 0
|
||||
|
||||
def __clean_xxx2many_cache(self, cursor, user, context=None):
|
||||
# Clean cursor cache
|
||||
to_clean = [(model._name, field_name)
|
||||
@@ -157,8 +135,6 @@ class ModelStorage(Model):
|
||||
:return: True if succeed
|
||||
'''
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
rule_group_obj = self.pool.get('ir.rule.group')
|
||||
rule_obj = self.pool.get('ir.rule')
|
||||
|
||||
model_access_obj.check(cursor, user, self._name, 'write',
|
||||
context=context)
|
||||
@@ -241,11 +217,11 @@ class ModelStorage(Model):
|
||||
default['state'] = self._defaults['state'](cursor, user,
|
||||
context)
|
||||
|
||||
def convert_data(fields, data):
|
||||
def convert_data(field_defs, data):
|
||||
data = data.copy()
|
||||
data_o2m = {}
|
||||
for field_name in fields:
|
||||
ftype = fields[field_name]['type']
|
||||
for field_name in field_defs:
|
||||
ftype = field_defs[field_name]['type']
|
||||
|
||||
if field_name in (
|
||||
'create_date',
|
||||
@@ -280,21 +256,22 @@ class ModelStorage(Model):
|
||||
fields_names = self._columns.keys()
|
||||
datas = self.read(cursor, user, ids, fields_names=fields_names,
|
||||
context=context)
|
||||
fields = self.fields_get(cursor, user, fields_names=fields_names,
|
||||
field_defs = self.fields_get(cursor, user, fields_names=fields_names,
|
||||
context=context)
|
||||
for data in datas:
|
||||
data_id = data['id']
|
||||
data, data_o2m = convert_data(fields, data)
|
||||
data, data_o2m = convert_data(field_defs, data)
|
||||
new_ids[data_id] = self.create(cursor, user, data, context=context)
|
||||
for field_name in data_o2m:
|
||||
relation_model = self.pool.get(fields[field_name]['relation'])
|
||||
relation_field = fields[field_name]['relation_field']
|
||||
relation_model = self.pool.get(
|
||||
field_defs[field_name]['relation'])
|
||||
relation_field = field_defs[field_name]['relation_field']
|
||||
relation_model.copy(cursor, user, data_o2m[field_name],
|
||||
default={relation_field: new_ids[data_id]},
|
||||
context=context)
|
||||
|
||||
fields_translate = {}
|
||||
for field_name, field in fields.iteritems():
|
||||
for field_name, field in field_defs.iteritems():
|
||||
if field_name in self._columns and \
|
||||
self._columns[field_name].translate:
|
||||
fields_translate[field_name] = field
|
||||
@@ -317,7 +294,8 @@ class ModelStorage(Model):
|
||||
for data in datas:
|
||||
data_id = data['id']
|
||||
data, _ = convert_data(fields_translate, data)
|
||||
self.write(cursor, user, new_ids[data_id], data, context=ctx)
|
||||
self.write(cursor, user, new_ids[data_id], data,
|
||||
context=ctx)
|
||||
if int_id:
|
||||
return new_ids.values()[0]
|
||||
return new_ids.values()
|
||||
@@ -367,8 +345,8 @@ class ModelStorage(Model):
|
||||
return len(res)
|
||||
return res
|
||||
|
||||
def search_read(self, cursor, user, domain, offset=0, limit=None, order=None,
|
||||
context=None, fields_names=None):
|
||||
def search_read(self, cursor, user, domain, offset=0, limit=None,
|
||||
order=None, context=None, fields_names=None):
|
||||
'''
|
||||
Call search and read functions at once.
|
||||
Useful for the client to reduce the number of calls.
|
||||
@@ -400,9 +378,9 @@ class ModelStorage(Model):
|
||||
for model in self.browse(cursor, user, ids, context=context):
|
||||
record = {}
|
||||
for fields_name in set(fields_names):
|
||||
fields = fields_name.split('.')
|
||||
while fields:
|
||||
field_name = fields.pop(0)
|
||||
fields_split = fields_name.split('.')
|
||||
while fields_split:
|
||||
field_name = fields_split.pop(0)
|
||||
if fields_name not in record:
|
||||
record[fields_name] = model[field_name]
|
||||
else:
|
||||
@@ -602,7 +580,7 @@ class ModelStorage(Model):
|
||||
if not isinstance(selection, (tuple, list)):
|
||||
selection = getattr(self, selection)(cursor, user,
|
||||
context=context)
|
||||
for key, val in selection:
|
||||
for key, _ in selection:
|
||||
if str(key) == value:
|
||||
res = key
|
||||
break
|
||||
@@ -673,11 +651,11 @@ class ModelStorage(Model):
|
||||
if not value:
|
||||
return False
|
||||
relation = None
|
||||
type = fields_def[field[-1][:-3]]['type']
|
||||
if type == 'many2many':
|
||||
ftype = fields_def[field[-1][:-3]]['type']
|
||||
if ftype == 'many2many':
|
||||
value = csv.reader(StringIO.StringIO(value), delimiter=',',
|
||||
quoting=csv.QUOTE_NONE, escapechar='\\').next()
|
||||
elif type == 'reference':
|
||||
elif ftype == 'reference':
|
||||
try:
|
||||
relation, value = value.split(',', 1)
|
||||
except:
|
||||
@@ -696,9 +674,9 @@ class ModelStorage(Model):
|
||||
db_id = ir_model_data_obj.get_id(cursor, user,
|
||||
module, xml_id)
|
||||
res_ids.append(db_id)
|
||||
if type == 'many2many' and res_ids:
|
||||
if ftype == 'many2many' and res_ids:
|
||||
return [('set', res_ids)]
|
||||
elif type == 'reference' and res_ids:
|
||||
elif ftype == 'reference' and res_ids:
|
||||
return '%s,%s' % (relation, str(res_ids[0]))
|
||||
return res_ids and res_ids[0] or False
|
||||
|
||||
@@ -763,7 +741,7 @@ class ModelStorage(Model):
|
||||
cursor, user, context=context)
|
||||
res = process_lines(self, datas, prefix + [field], newfd,
|
||||
position)
|
||||
(newrow, max2, translate2) = res
|
||||
(newrow, max2, _) = res
|
||||
nbrmax = max(nbrmax, max2)
|
||||
reduce(lambda x, y: x and y, newrow)
|
||||
row[field] = (reduce(lambda x, y: x or y, newrow.values()) and
|
||||
@@ -778,7 +756,7 @@ class ModelStorage(Model):
|
||||
break
|
||||
if not test:
|
||||
break
|
||||
(newrow, max2, translate2) = \
|
||||
(newrow, max2, _) = \
|
||||
process_lines(self, datas, prefix + [field], newfd,
|
||||
position + i)
|
||||
if reduce(lambda x, y: x or y, newrow.values()):
|
||||
@@ -810,7 +788,7 @@ class ModelStorage(Model):
|
||||
while len(datas):
|
||||
res = {}
|
||||
try:
|
||||
(res, other, translate) = \
|
||||
(res, _, translate) = \
|
||||
process_lines(self, datas, [], fields_def)
|
||||
warning = warning_stream.getvalue()
|
||||
if warning:
|
||||
@@ -909,12 +887,12 @@ class ModelStorage(Model):
|
||||
walker = record[parent]
|
||||
while walker:
|
||||
if parent_type == 'many2many':
|
||||
for w in walker:
|
||||
walked.add(w.id)
|
||||
if w.id == record.id:
|
||||
for walk in walker:
|
||||
walked.add(walk.id)
|
||||
if walk.id == record.id:
|
||||
return False
|
||||
walker = list(chain(*(w[parent] for w in walker
|
||||
if w.id not in visited)))
|
||||
walker = list(chain(*(walk[parent] for walk in walker
|
||||
if walk.id not in visited)))
|
||||
else:
|
||||
walked.add(walker.id)
|
||||
if walker.id == record.id:
|
||||
@@ -952,8 +930,6 @@ class ModelStorage(Model):
|
||||
return self._validate(cursor, context['user'], ids, context=ctx)
|
||||
|
||||
context = context.copy()
|
||||
field_error = []
|
||||
field_err_str = []
|
||||
for field in self._constraints:
|
||||
if not getattr(self, field[0])(cursor, user, ids):
|
||||
self.raise_user_error(cursor, field[1], context=context)
|
||||
|
||||
@@ -30,10 +30,10 @@ def _inherit_apply(src, inherit):
|
||||
pos = element2.get('position', 'inside')
|
||||
if pos == 'replace':
|
||||
parent = element.getparent()
|
||||
next = element.getnext()
|
||||
if next is not None:
|
||||
enext = element.getnext()
|
||||
if enext is not None:
|
||||
for child in element2:
|
||||
index = parent.index(next)
|
||||
index = parent.index(enext)
|
||||
parent.insert(index, child)
|
||||
else:
|
||||
parent.extend(element2.getchildren())
|
||||
@@ -46,10 +46,10 @@ def _inherit_apply(src, inherit):
|
||||
element.extend(element2.getchildren())
|
||||
elif pos == 'after':
|
||||
parent = element.getparent()
|
||||
next = element.getnext()
|
||||
if next is not None:
|
||||
enext = element.getnext()
|
||||
if enext is not None:
|
||||
for child in element2:
|
||||
index = parent.index(next)
|
||||
index = parent.index(enext)
|
||||
parent.insert(index, child)
|
||||
else:
|
||||
parent.extend(element2.getchildren())
|
||||
|
||||
@@ -66,7 +66,7 @@ class ModelWorkflow(ModelStorage):
|
||||
], context=context)
|
||||
for res_id in ids:
|
||||
for wkf_id in workflow_ids:
|
||||
instance_id = instance_obj.create(cursor, user, {
|
||||
instance_obj.create(cursor, user, {
|
||||
'res_type': self._name,
|
||||
'res_id': res_id,
|
||||
'workflow': wkf_id,
|
||||
|
||||
+15
-17
@@ -6,30 +6,28 @@ import subprocess
|
||||
from threading import Lock
|
||||
from trytond.modules import get_module_list
|
||||
|
||||
_lock = Lock()
|
||||
_times = {}
|
||||
_modules = None
|
||||
_LOCK = Lock()
|
||||
_TIMES = {}
|
||||
_MODULES = None
|
||||
|
||||
def _modified(path):
|
||||
global _times
|
||||
global _lock
|
||||
_lock.acquire()
|
||||
_LOCK.acquire()
|
||||
try:
|
||||
try:
|
||||
if not os.path.isfile(path):
|
||||
return path in _times
|
||||
return path in _TIMES
|
||||
|
||||
mtime = os.stat(path).st_mtime
|
||||
if path not in _times:
|
||||
_times[path] = mtime
|
||||
if path not in _TIMES:
|
||||
_TIMES[path] = mtime
|
||||
|
||||
if mtime != _times[path]:
|
||||
_times[path] = mtime
|
||||
if mtime != _TIMES[path]:
|
||||
_TIMES[path] = mtime
|
||||
return True
|
||||
except:
|
||||
return True
|
||||
finally:
|
||||
_lock.release()
|
||||
_LOCK.release()
|
||||
return False
|
||||
|
||||
def monitor():
|
||||
@@ -38,7 +36,7 @@ def monitor():
|
||||
|
||||
:return: True if at least one file has changed
|
||||
'''
|
||||
global _modules
|
||||
global _MODULES
|
||||
modified = False
|
||||
for module in sys.modules.keys():
|
||||
if not module.startswith('trytond.'):
|
||||
@@ -58,13 +56,13 @@ def monitor():
|
||||
break
|
||||
modified = True
|
||||
modules = set(get_module_list())
|
||||
if _modules is None:
|
||||
_modules = modules
|
||||
for module in modules.difference(_modules):
|
||||
if _MODULES is None:
|
||||
_MODULES = modules
|
||||
for module in modules.difference(_MODULES):
|
||||
if subprocess.call((sys.executable, '-c',
|
||||
'import trytond.modules.%s' % module)):
|
||||
modified = False
|
||||
break
|
||||
modified = True
|
||||
_modules = modules
|
||||
_MODULES = modules
|
||||
return modified
|
||||
+6
-4
@@ -42,17 +42,19 @@ class Pool(object):
|
||||
lock.release()
|
||||
|
||||
@staticmethod
|
||||
def register(cls, type='model'):
|
||||
def register(klass, type='model'):
|
||||
'''
|
||||
Register a class
|
||||
|
||||
:param cls: the class
|
||||
:param klass: the class
|
||||
:param type: the type
|
||||
'''
|
||||
for module in cls.__module__.split('.'):
|
||||
module = None
|
||||
for module in klass.__module__.split('.'):
|
||||
if module != 'trytond' and module != 'modules':
|
||||
break
|
||||
Pool.classes[type].setdefault(module, []).append(cls)
|
||||
if module:
|
||||
Pool.classes[type].setdefault(module, []).append(klass)
|
||||
|
||||
@staticmethod
|
||||
def start():
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from trytond.pool import Pool
|
||||
from trytond import security
|
||||
from trytond.tools import Cache, find_language_context
|
||||
from trytond.backend import Database, DatabaseIntegrityError
|
||||
from trytond.tools import Cache
|
||||
from trytond.backend import Database
|
||||
from trytond.config import CONFIG
|
||||
from trytond.version import VERSION
|
||||
from trytond.monitor import monitor
|
||||
@@ -39,7 +39,8 @@ def dispatch(host, port, protocol, database_name, user, session, object_type,
|
||||
elif method == 'logout':
|
||||
name = security.logout(database_name, user, session)
|
||||
logger = logging.getLogger('dispatcher')
|
||||
logger.info('logout \'%s\' from %s:%d using %s on database \'%s\'' % \
|
||||
logger.info('logout \'%s\' from %s:%d ' \
|
||||
'using %s on database \'%s\'' %
|
||||
(name, host, port, protocol, database_name))
|
||||
return True
|
||||
elif method == 'version':
|
||||
@@ -206,7 +207,6 @@ def create(database_name, password, lang, admin_password):
|
||||
res = True
|
||||
except:
|
||||
logger.error('CREATE DB: %s failed' % (database_name,))
|
||||
import traceback, sys
|
||||
tb_s = reduce(lambda x, y: x+y,
|
||||
traceback.format_exception(*sys.exc_info()))
|
||||
logger.error('Exception in call: \n' + tb_s)
|
||||
@@ -233,7 +233,6 @@ def drop(database_name, password):
|
||||
cursor.commit()
|
||||
except:
|
||||
logger.error('DROP DB: %s failed' % (database_name,))
|
||||
import traceback, sys
|
||||
tb_s = reduce(lambda x, y: x+y,
|
||||
traceback.format_exception(*sys.exc_info()))
|
||||
logger.error('Exception in call: \n' + tb_s)
|
||||
|
||||
@@ -6,7 +6,6 @@ from trytond.config import CONFIG
|
||||
import SimpleXMLRPCServer
|
||||
import SimpleHTTPServer
|
||||
import SocketServer
|
||||
from xmlrpclib import Fault
|
||||
import threading
|
||||
import traceback
|
||||
import socket
|
||||
@@ -56,7 +55,7 @@ class JSONEncoder(json.JSONEncoder):
|
||||
}
|
||||
elif isinstance(obj, Decimal):
|
||||
return float(obj)
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
return super(JSONEncoder, self).default(obj)
|
||||
|
||||
|
||||
class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
|
||||
@@ -80,11 +79,11 @@ class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
|
||||
"""
|
||||
rawreq = json.loads(data, object_hook=object_hook)
|
||||
|
||||
id = rawreq.get('id', 0)
|
||||
req_id = rawreq.get('id', 0)
|
||||
method = rawreq['method']
|
||||
params = rawreq.get('params', [])
|
||||
|
||||
response = {'id': id}
|
||||
response = {'id': req_id}
|
||||
|
||||
try:
|
||||
#generate response
|
||||
@@ -210,8 +209,8 @@ class SimpleJSONRPCRequestHandler(GenericJSONRPCRequestHandler,
|
||||
|
||||
"""
|
||||
# abandon query parameters
|
||||
path = path.split('?',1)[0]
|
||||
path = path.split('#',1)[0]
|
||||
path = path.split('?', 1)[0]
|
||||
path = path.split('#', 1)[0]
|
||||
path = posixpath.normpath(urllib.unquote(path))
|
||||
words = path.split('/')
|
||||
words = filter(None, words)
|
||||
@@ -252,12 +251,14 @@ class SimpleJSONRPCServer(SocketServer.TCPServer,
|
||||
_send_traceback_header = False
|
||||
|
||||
def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler,
|
||||
logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
|
||||
logRequests=True, allow_none=False, encoding=None,
|
||||
bind_and_activate=True):
|
||||
self.logRequests = logRequests
|
||||
|
||||
SimpleJSONRPCDispatcher.__init__(self, allow_none, encoding)
|
||||
try:
|
||||
SocketServer.TCPServer.__init__(self, addr, requestHandler, bind_and_activate)
|
||||
SocketServer.TCPServer.__init__(self, addr, requestHandler,
|
||||
bind_and_activate)
|
||||
except TypeError:
|
||||
SocketServer.TCPServer.__init__(self, addr, requestHandler)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class NetRPCClientThread(threading.Thread):
|
||||
return False
|
||||
timeout = 0
|
||||
while self.running:
|
||||
(rlist, wlist, xlist) = select.select([self.sock], [], [], 1)
|
||||
(rlist, _, _) = select.select([self.sock], [], [], 1)
|
||||
if not rlist:
|
||||
timeout += 1
|
||||
if timeout > 600:
|
||||
@@ -61,7 +61,8 @@ class NetRPCClientThread(threading.Thread):
|
||||
tback = sys.exc_info()[2]
|
||||
pdb.post_mortem(tback)
|
||||
try:
|
||||
pysocket.send(exception.args, exception=True, traceback=tb_s)
|
||||
pysocket.send(exception.args, exception=True,
|
||||
traceback=tb_s)
|
||||
except:
|
||||
pysocket.disconnect()
|
||||
self.threads.remove(self)
|
||||
@@ -101,7 +102,7 @@ class NetRPCServerThread(threading.Thread):
|
||||
while self.running:
|
||||
if not int(CONFIG['max_thread']) \
|
||||
or len(self.threads) < int(CONFIG['max_thread']):
|
||||
(clientsocket, address) = self.socket.accept()
|
||||
(clientsocket, _) = self.socket.accept()
|
||||
c_thread = NetRPCClientThread(clientsocket, self.threads,
|
||||
self.secure)
|
||||
self.threads.append(c_thread)
|
||||
|
||||
+12
-12
@@ -14,11 +14,10 @@ import socket
|
||||
import os
|
||||
import BaseHTTPServer
|
||||
import urlparse
|
||||
import base64
|
||||
import time
|
||||
from DAV import AuthServer, WebDAVServer, iface
|
||||
from DAV.errors import *
|
||||
from DAV.constants import COLLECTION, OBJECT, DAV_VERSION_1, DAV_VERSION_2
|
||||
from DAV.constants import COLLECTION, DAV_VERSION_1, DAV_VERSION_2
|
||||
from DAV.utils import get_uriparentpath, get_urifilename, quote_uri
|
||||
from DAV.davcmd import copyone, copytree, moveone, movetree, delone, deltree
|
||||
import urllib
|
||||
@@ -36,6 +35,7 @@ DAV_VERSION_2['version'] += ',access-control'
|
||||
class LocalInt(local):
|
||||
|
||||
def __init__(self, value=0):
|
||||
super(LocalInt, self).__init__()
|
||||
self.value = value
|
||||
|
||||
def __int__(self):
|
||||
@@ -153,7 +153,8 @@ class TrytonDAVInterface(iface.dav_interface):
|
||||
protocol = 'https'
|
||||
else:
|
||||
protocol = 'http'
|
||||
self.baseuri = '%s://%s:%s/' % (protocol, interface or socket.gethostname(), port)
|
||||
self.baseuri = '%s://%s:%s/' % (protocol, interface or
|
||||
socket.gethostname(), port)
|
||||
self.verbose = False
|
||||
|
||||
def _log_exception(self, exception):
|
||||
@@ -221,10 +222,12 @@ class TrytonDAVInterface(iface.dav_interface):
|
||||
def get_data(self, uri):
|
||||
dbname, dburi = self._get_dburi(uri)
|
||||
if not dbname or (self.exists(uri) and self.is_collection(uri)):
|
||||
res = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">'
|
||||
res = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 '\
|
||||
'Transitional//EN">'
|
||||
res += '<html>'
|
||||
res += '<head>'
|
||||
res += '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
|
||||
res += '<meta http-equiv="Content-Type" content="text/html; '\
|
||||
'charset=utf-8">'
|
||||
res += '<title>%s - WebDAV - %s</title>' \
|
||||
% (PACKAGE, dbname or 'root')
|
||||
res += '</head>'
|
||||
@@ -461,7 +464,8 @@ class TrytonDAVInterface(iface.dav_interface):
|
||||
pool = Pool(DATABASE['dbname'])
|
||||
collection_obj = pool.get('webdav.collection')
|
||||
try:
|
||||
res = collection_obj.exists(cursor, int(USER_ID), dburi, cache=CACHE)
|
||||
res = collection_obj.exists(cursor, int(USER_ID), dburi,
|
||||
cache=CACHE)
|
||||
except (DAV_Error, DAV_NotFound, DAV_Secret, DAV_Forbidden), exception:
|
||||
self._log_exception(exception)
|
||||
raise
|
||||
@@ -542,15 +546,14 @@ class TrytonDAVInterface(iface.dav_interface):
|
||||
privilege.appendChild(unbind)
|
||||
return privilege
|
||||
|
||||
TrytonDAVInterface.PROPS['DAV:'] = tuple(list(TrytonDAVInterface.PROPS['DAV:']) \
|
||||
+ ['current-user-privilege-set'])
|
||||
TrytonDAVInterface.PROPS['DAV:'] = tuple(list(TrytonDAVInterface.PROPS['DAV:']
|
||||
) + ['current-user-privilege-set'])
|
||||
|
||||
|
||||
class WebDAVAuthRequestHandler(AuthServer.BufferedAuthRequestHandler,
|
||||
WebDAVServer.DAVRequestHandler):
|
||||
|
||||
def finish(self):
|
||||
global DATABASE
|
||||
dbname = None
|
||||
if 'dbname' in DATABASE:
|
||||
dbname = DATABASE['dbname']
|
||||
@@ -564,9 +567,6 @@ class WebDAVAuthRequestHandler(AuthServer.BufferedAuthRequestHandler,
|
||||
Cache.resets(dbname)
|
||||
|
||||
def get_userinfo(self, user, password, command=''):
|
||||
global USER_ID
|
||||
global DATABASE
|
||||
|
||||
dbname = urllib.unquote_plus(self.path.split('/', 2)[1])
|
||||
DATABASE['dbname'] = dbname
|
||||
if not dbname:
|
||||
|
||||
@@ -44,8 +44,9 @@ class GenericXMLRPCRequestHandler:
|
||||
args = (host, port, 'XML-RPC', database_name, None, None,
|
||||
object_type, None, method) + params
|
||||
else:
|
||||
args = (host, port, 'XML-RPC', database_name, params[0], params[1],
|
||||
object_type, object_name, method) + params[2:]
|
||||
args = (host, port, 'XML-RPC', database_name, params[0],
|
||||
params[1], object_type, object_name, method) + \
|
||||
params[2:]
|
||||
res = dispatch(*args)
|
||||
return res
|
||||
except:
|
||||
|
||||
+13
-13
@@ -79,10 +79,10 @@ class PySocket:
|
||||
sock.settimeout(CONNECT_TIMEOUT)
|
||||
sock.connect((host, int(port)))
|
||||
if ssl:
|
||||
ssl_sock = ssl.wrap_socket(sock)
|
||||
ssl.wrap_socket(sock)
|
||||
self.ssl = True
|
||||
elif hasattr(socket, 'ssl'):
|
||||
ssl_sock = socket.ssl(sock)
|
||||
socket.ssl(sock)
|
||||
self.ssl = True
|
||||
except:
|
||||
pass
|
||||
@@ -131,12 +131,12 @@ class PySocket:
|
||||
msg = cPickle.dumps([msg, traceback], protocol=2)
|
||||
gzip_p = False
|
||||
if len(msg) > GZIP_THRESHOLD:
|
||||
buffer = StringIO.StringIO()
|
||||
output = gzip.GzipFile(mode='wb', fileobj=buffer)
|
||||
buf = StringIO.StringIO()
|
||||
output = gzip.GzipFile(mode='wb', fileobj=buf)
|
||||
output.write(msg)
|
||||
output.close()
|
||||
buffer.seek(0)
|
||||
msg = buffer.getvalue()
|
||||
buf.seek(0)
|
||||
msg = buf.getvalue()
|
||||
gzip_p = True
|
||||
size = len(msg)
|
||||
msg = str(size) + ' ' + (exception and "1" or "0") \
|
||||
@@ -155,7 +155,7 @@ class PySocket:
|
||||
|
||||
def receive(self):
|
||||
buf = self.buffer
|
||||
L = []
|
||||
buf_list = []
|
||||
size_remaining = MAX_LENGHT
|
||||
while size_remaining:
|
||||
chunk_size = min(size_remaining, 4096)
|
||||
@@ -165,13 +165,13 @@ class PySocket:
|
||||
chunk = self.sock.recv(chunk_size)
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
L.append(chunk)
|
||||
buf_list.append(chunk)
|
||||
size_remaining -= len(chunk)
|
||||
if ' ' in chunk:
|
||||
break
|
||||
if size_remaining < 0:
|
||||
raise RuntimeError, "socket connection broken"
|
||||
buf += ''.join(L)
|
||||
buf += ''.join(buf_list)
|
||||
size, msg = buf.split(' ', 1)
|
||||
size = int(size)
|
||||
if size > MAX_SIZE:
|
||||
@@ -186,8 +186,8 @@ class PySocket:
|
||||
raise RuntimeError, "socket connection broken"
|
||||
exception = msg[0] != "0"
|
||||
gzip_p = msg[1] != "0"
|
||||
L = [msg[2:]]
|
||||
size_remaining = size - len(L[0])
|
||||
buf_list = [msg[2:]]
|
||||
size_remaining = size - len(buf_list[0])
|
||||
while size_remaining:
|
||||
chunk_size = min(size_remaining, 4096)
|
||||
if self.ssl:
|
||||
@@ -196,9 +196,9 @@ class PySocket:
|
||||
chunk = self.sock.recv(chunk_size)
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
L.append(chunk)
|
||||
buf_list.append(chunk)
|
||||
size_remaining -= len(chunk)
|
||||
msg = ''.join(L)
|
||||
msg = ''.join(buf_list)
|
||||
if len(msg) > size:
|
||||
self.buffer = msg[size:]
|
||||
msg = msg[:size]
|
||||
|
||||
+22
-12
@@ -11,31 +11,31 @@ import datetime
|
||||
class PYSON(object):
|
||||
|
||||
def pyson(self):
|
||||
raise
|
||||
raise NotImplementedError
|
||||
|
||||
def types(self):
|
||||
raise
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def eval(dct, context):
|
||||
raise
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class PYSONEncoder(json.JSONEncoder):
|
||||
|
||||
def default(self, o):
|
||||
if isinstance(o, PYSON):
|
||||
return o.pyson()
|
||||
return super(PYSONEncoder, self).default(o)
|
||||
def default(self, obj):
|
||||
if isinstance(obj, PYSON):
|
||||
return obj.pyson()
|
||||
return super(PYSONEncoder, self).default(obj)
|
||||
|
||||
|
||||
class PYSONDecoder(json.JSONDecoder):
|
||||
|
||||
def __init__(self, context=None):
|
||||
self.__context = context or {}
|
||||
return super(PYSONDecoder, self).__init__(object_hook=self.object_hook)
|
||||
super(PYSONDecoder, self).__init__(object_hook=self._object_hook)
|
||||
|
||||
def object_hook(self, dct):
|
||||
def _object_hook(self, dct):
|
||||
if '__class__' in dct:
|
||||
klass = globals().get(dct['__class__'])
|
||||
if klass and hasattr(klass, 'eval'):
|
||||
@@ -46,6 +46,7 @@ class PYSONDecoder(json.JSONDecoder):
|
||||
class Eval(PYSON):
|
||||
|
||||
def __init__(self, value, default=''):
|
||||
super(Eval, self).__init__()
|
||||
self._value = value
|
||||
self._default = default
|
||||
|
||||
@@ -70,6 +71,7 @@ class Eval(PYSON):
|
||||
class Not(PYSON):
|
||||
|
||||
def __init__(self, value):
|
||||
super(Not, self).__init__()
|
||||
if isinstance(value, PYSON):
|
||||
assert value.types() == set([bool]), 'value must be boolean'
|
||||
else:
|
||||
@@ -93,6 +95,7 @@ class Not(PYSON):
|
||||
class Bool(PYSON):
|
||||
|
||||
def __init__(self, value):
|
||||
super(Bool, self).__init__()
|
||||
self._value = value
|
||||
|
||||
def pyson(self):
|
||||
@@ -112,6 +115,7 @@ class Bool(PYSON):
|
||||
class And(PYSON):
|
||||
|
||||
def __init__(self, *statements):
|
||||
super(And, self).__init__()
|
||||
for statement in statements:
|
||||
if isinstance(statement, PYSON):
|
||||
assert statement.types() == set([bool]), \
|
||||
@@ -151,6 +155,7 @@ class Or(And):
|
||||
class Equal(PYSON):
|
||||
|
||||
def __init__(self, statement1, statement2):
|
||||
super(Equal, self).__init__()
|
||||
if isinstance(statement1, PYSON):
|
||||
types1 = statement1.types()
|
||||
else:
|
||||
@@ -181,6 +186,7 @@ class Equal(PYSON):
|
||||
class Greater(PYSON):
|
||||
|
||||
def __init__(self, statement1, statement2, equal=False):
|
||||
super(Greater, self).__init__()
|
||||
for i in (statement1, statement2):
|
||||
if isinstance(i, PYSON):
|
||||
assert i.types().issubset(set([int, long, float])), \
|
||||
@@ -233,6 +239,7 @@ class Less(Greater):
|
||||
class If(PYSON):
|
||||
|
||||
def __init__(self, condition, then_statement, else_statement=None):
|
||||
super(If, self).__init__()
|
||||
if isinstance(condition, PYSON):
|
||||
assert condition.types() == set([bool]), 'condition must be boolean'
|
||||
else:
|
||||
@@ -276,6 +283,7 @@ class If(PYSON):
|
||||
class Get(PYSON):
|
||||
|
||||
def __init__(self, obj, key, default=''):
|
||||
super(Get, self).__init__()
|
||||
if isinstance(obj, PYSON):
|
||||
assert obj.types() == set([dict]), 'obj must be a dict'
|
||||
else:
|
||||
@@ -310,6 +318,7 @@ class Get(PYSON):
|
||||
class In(PYSON):
|
||||
|
||||
def __init__(self, key, obj):
|
||||
super(In, self).__init__()
|
||||
if isinstance(key, PYSON):
|
||||
assert key.types().issubset(set([str, int, long])), \
|
||||
'key must be a string or an integer or a long'
|
||||
@@ -347,6 +356,7 @@ class Date(PYSON):
|
||||
|
||||
def __init__(self, year=None, month=None, day=None,
|
||||
delta_years=0, delta_months=0, delta_days=0):
|
||||
super(Date, self).__init__()
|
||||
for i in (year, month, day, delta_years, delta_months, delta_days):
|
||||
if isinstance(i, PYSON):
|
||||
assert i.types().issubset(set([int, long, type(None)])), \
|
||||
@@ -388,8 +398,8 @@ class Date(PYSON):
|
||||
date = date.replace(year=year)
|
||||
if dct['dM']:
|
||||
month = date.month + dct['dM']
|
||||
year = date.year + month/12
|
||||
month = month%12
|
||||
year = date.year + month / 12
|
||||
month = month % 12
|
||||
date = date.replace(year=year, month=month)
|
||||
if dct['dd']:
|
||||
date += datetime.timedelta(days=dct['dd'])
|
||||
@@ -450,7 +460,7 @@ class DateTime(Date):
|
||||
if dct[i] is not None:
|
||||
replace[j] = dct[i]
|
||||
datetime_ = datetime_.replace(**replace)
|
||||
delta={}
|
||||
delta = {}
|
||||
for i, j in (('dh', 'hours'), ('dm', 'minutes'), ('ds', 'seconds'),
|
||||
('dms', 'microseconds')):
|
||||
if dct[i]:
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
from trytond.backend import Database
|
||||
from trytond.session import Session
|
||||
from trytond.pool import Pool
|
||||
from config import CONFIG
|
||||
from trytond.config import CONFIG
|
||||
import time
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ def check_super(passwd):
|
||||
def check(dbname, user, session):
|
||||
if user == 0:
|
||||
raise Exception('AccessDenied')
|
||||
result = False
|
||||
result = None
|
||||
now = time.time()
|
||||
timeout = int(CONFIG['session_timeout'])
|
||||
if _USER_CACHE.get(dbname, {}).has_key(user):
|
||||
@@ -82,7 +82,7 @@ def get_connections(dbname, user):
|
||||
now = time.time()
|
||||
timeout = int(CONFIG['session_timeout'])
|
||||
if _USER_CACHE.get(dbname, {}).has_key(int(user)):
|
||||
for i, session in enumerate(_USER_CACHE[dbname][int(user)]):
|
||||
for _, session in enumerate(_USER_CACHE[dbname][int(user)]):
|
||||
if abs(session.timestamp - now) < timeout:
|
||||
res += 1
|
||||
return res
|
||||
+8
-8
@@ -4,13 +4,13 @@
|
||||
%prog [options]
|
||||
"""
|
||||
import logging
|
||||
format='[%(asctime)s] %(levelname)s:%(name)s:%(message)s'
|
||||
datefmt='%a %b %d %H:%M:%S %Y'
|
||||
logging.basicConfig(level=logging.DEBUG, format=format, datefmt=datefmt)
|
||||
FORMAT = '[%(asctime)s] %(levelname)s:%(name)s:%(message)s'
|
||||
DATEFMT = '%a %b %d %H:%M:%S %Y'
|
||||
logging.basicConfig(level=logging.DEBUG, format=FORMAT, datefmt=DATEFMT)
|
||||
import logging.handlers
|
||||
import sys, os, signal
|
||||
import time
|
||||
from config import CONFIG
|
||||
from trytond.config import CONFIG
|
||||
from getpass import getpass
|
||||
try:
|
||||
import hashlib
|
||||
@@ -26,7 +26,6 @@ class TrytonServer(object):
|
||||
|
||||
def __init__(self):
|
||||
CONFIG.parse()
|
||||
from trytond.backend import Database
|
||||
|
||||
if CONFIG['logfile']:
|
||||
logf = CONFIG['logfile']
|
||||
@@ -39,10 +38,11 @@ class TrytonServer(object):
|
||||
logf, 'D', 1, 30)
|
||||
handler.rolloverAt -= diff
|
||||
except Exception, exception:
|
||||
sys.stderr.write("ERROR: couldn't create the logfile directory:" \
|
||||
sys.stderr.write(\
|
||||
"ERROR: couldn't create the logfile directory:" \
|
||||
+ str(exception))
|
||||
else:
|
||||
formatter = logging.Formatter(format, datefmt)
|
||||
formatter = logging.Formatter(FORMAT, DATEFMT)
|
||||
# tell the handler to use this format
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
@@ -69,7 +69,7 @@ class TrytonServer(object):
|
||||
def run(self):
|
||||
"Run the server and never return"
|
||||
from trytond.backend import Database
|
||||
from pool import Pool
|
||||
from trytond.pool import Pool
|
||||
from trytond.monitor import monitor
|
||||
|
||||
update = False
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import time
|
||||
|
||||
class Session(int):
|
||||
|
||||
def __init__(self, x):
|
||||
def __init__(self, value):
|
||||
super(Session, self).__init__()
|
||||
self.__data = {
|
||||
'session': base64.b64encode(os.urandom(32)),
|
||||
|
||||
+45
-36
@@ -2,19 +2,12 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
"Convert"
|
||||
import re
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
except ImportError:
|
||||
import StringIO
|
||||
import os.path
|
||||
from trytond.config import CONFIG
|
||||
from trytond.version import VERSION
|
||||
from trytond.tools import safe_eval
|
||||
import time
|
||||
from xml import sax
|
||||
from decimal import Decimal
|
||||
import datetime
|
||||
import time
|
||||
import logging
|
||||
import traceback
|
||||
import sys
|
||||
@@ -43,6 +36,7 @@ class MenuitemTagHandler:
|
||||
"""Taghandler for the tag <record> """
|
||||
def __init__(self, master_handler):
|
||||
self.mh = master_handler
|
||||
self.xml_id = None
|
||||
|
||||
def startElement(self, name, attributes):
|
||||
|
||||
@@ -72,7 +66,8 @@ class MenuitemTagHandler:
|
||||
"LEFT JOIN ir_action_act_window act ON (a.id = act.action) " \
|
||||
"LEFT JOIN ir_action_wizard wizard ON (a.id = wizard.action) " \
|
||||
"LEFT JOIN ir_action_url url ON (a.id = url.action) " \
|
||||
"LEFT JOIN ir_action_act_window_view wv on (act.id = wv.act_window) " \
|
||||
"LEFT JOIN ir_action_act_window_view wv ON " \
|
||||
"(act.id = wv.act_window) " \
|
||||
"LEFT JOIN ir_ui_view v on (v.id = wv.view) " \
|
||||
"WHERE report.id = %s " \
|
||||
"OR act.id = %s " \
|
||||
@@ -123,7 +118,7 @@ class MenuitemTagHandler:
|
||||
if not values.get('name'):
|
||||
if not action_name:
|
||||
raise Exception("Please provide at least a 'name' attributes "
|
||||
"or a 'action' attributes on the menuitem tags.")
|
||||
"or a 'action' attributes on the menuitem tags.")
|
||||
else:
|
||||
values['name'] = action_name
|
||||
|
||||
@@ -138,8 +133,7 @@ class MenuitemTagHandler:
|
||||
if name != "menuitem":
|
||||
return self
|
||||
else:
|
||||
res = self.mh.import_record(
|
||||
'ir.ui.menu', self.values, self.xml_id)
|
||||
self.mh.import_record( 'ir.ui.menu', self.values, self.xml_id)
|
||||
return None
|
||||
|
||||
def current_state(self):
|
||||
@@ -158,6 +152,11 @@ class RecordTagHandler:
|
||||
self.xml_ids = []
|
||||
self.model = None
|
||||
self.xml_id = None
|
||||
self.update = None
|
||||
self.values = None
|
||||
self.current_field = None
|
||||
self.cdata = None
|
||||
self.start_cdata = None
|
||||
|
||||
|
||||
def startElement(self, name, attributes):
|
||||
@@ -209,7 +208,9 @@ class RecordTagHandler:
|
||||
if not answer: return
|
||||
|
||||
if self.model._columns[field_name]._type == 'many2many':
|
||||
self.values[field_name] = [('set', [x['id'] for x in answer])]
|
||||
self.values[field_name] = [
|
||||
('set', [x['id'] for x in answer]),
|
||||
]
|
||||
|
||||
elif self.model._columns[field_name]._type == 'many2one':
|
||||
self.values[field_name] = answer[0]['id']
|
||||
@@ -226,7 +227,8 @@ class RecordTagHandler:
|
||||
self.values[field_name] = safe_eval(eval_attr, context)
|
||||
|
||||
else:
|
||||
raise Exception("Tags '%s' not supported inside tag record."% (name,))
|
||||
raise Exception("Tags '%s' not supported inside tag record." %
|
||||
(name,))
|
||||
|
||||
def characters(self, data):
|
||||
|
||||
@@ -255,7 +257,7 @@ class RecordTagHandler:
|
||||
"current_field expected to be set.")
|
||||
# Escape end cdata tag :
|
||||
if self.cdata in ('inside', 'start'):
|
||||
self.values[self.current_field] =\
|
||||
self.values[self.current_field] = \
|
||||
CDATA_END.sub('', self.values[self.current_field])
|
||||
self.cdata = 'done'
|
||||
|
||||
@@ -272,8 +274,7 @@ class RecordTagHandler:
|
||||
elif name == "record":
|
||||
if self.xml_id in self.xml_ids and not self.update:
|
||||
raise Exception('Duplicate id: "%s".' % (self.xml_id,))
|
||||
res = self.mh.import_record(
|
||||
self.model._name, self.values, self.xml_id)
|
||||
self.mh.import_record(self.model._name, self.values, self.xml_id)
|
||||
self.xml_ids.append(self.xml_id)
|
||||
return None
|
||||
else:
|
||||
@@ -393,6 +394,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
|
||||
def __init__(self, cursor, pool, module,):
|
||||
"Register known taghandlers, and managed tags."
|
||||
sax.handler.ContentHandler.__init__(self)
|
||||
|
||||
self.pool = pool
|
||||
self.cursor = cursor
|
||||
@@ -401,6 +403,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
self.modeldata_obj = pool.get('ir.model.data')
|
||||
self.fs2db = Fs2bdAccessor(cursor, self.user, self.modeldata_obj, pool)
|
||||
self.to_delete = self.populate_to_delete()
|
||||
self.noupdate = None
|
||||
|
||||
# Tag handlders are used to delegate the processing
|
||||
self.taghandlerlist = {
|
||||
@@ -410,7 +413,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
self.taghandler = None
|
||||
|
||||
# Managed tags are handled by the current class
|
||||
self.managedtags= ["data", "tryton"]
|
||||
self.managedtags = ["data", "tryton"]
|
||||
|
||||
# Connect to the sax api:
|
||||
self.sax_parser = sax.make_parser()
|
||||
@@ -455,7 +458,8 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
pass
|
||||
|
||||
else:
|
||||
logging.getLogger("convert").info("Tag "+ name + " not supported")
|
||||
logging.getLogger("convert").info( "Tag %s not supported" %
|
||||
name)
|
||||
return
|
||||
else:
|
||||
self.taghandler.startElement(name, attributes)
|
||||
@@ -597,7 +601,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
raise Exception("This record try to overwrite " \
|
||||
"data with the wrong model: %s (module: %s)" % (fs_id, module))
|
||||
|
||||
#Re-create object if it was deleted
|
||||
#Re-create record if it was deleted
|
||||
if not self.fs2db.get_browserecord(module, object_ref._name, db_id):
|
||||
db_id = object_ref.create(cursor, user, values,
|
||||
context={'module': module})
|
||||
@@ -605,9 +609,11 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
# reset_browsercord
|
||||
self.fs2db.reset_browsercord(module, object_ref._name, db_id)
|
||||
|
||||
object = self.fs2db.get_browserecord(module, object_ref._name, db_id)
|
||||
for table, field_name, field in object_ref._inherit_fields.values():
|
||||
inherit_db_ids[table] = object[field_name].id
|
||||
record = self.fs2db.get_browserecord(module, object_ref._name,
|
||||
db_id)
|
||||
for table, field_name, field in \
|
||||
object_ref._inherit_fields.values():
|
||||
inherit_db_ids[table] = record[field_name].id
|
||||
|
||||
#Add a translation record for field translatable
|
||||
for field_name in object_ref._columns.keys() + \
|
||||
@@ -677,7 +683,8 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
})
|
||||
self.fs2db.get(module, fs_id)["db_id"] = db_id
|
||||
|
||||
db_val = self.fs2db.get_browserecord(module, object_ref._name, db_id)
|
||||
db_val = self.fs2db.get_browserecord(module, object_ref._name,
|
||||
db_id)
|
||||
if not db_val:
|
||||
db_val = object_ref.browse(cursor, user, db_id)
|
||||
|
||||
@@ -737,10 +744,10 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
|
||||
|
||||
if not inherit_db_ids:
|
||||
object = object_ref.browse(cursor, user, db_id)
|
||||
record = object_ref.browse(cursor, user, db_id)
|
||||
for table, field_name, field in \
|
||||
object_ref._inherit_fields.values():
|
||||
inherit_db_ids[table] = object[field_name].id
|
||||
inherit_db_ids[table] = record[field_name].id
|
||||
if not inherit_mdata_ids:
|
||||
for table in inherit_db_ids.keys():
|
||||
data_id = self.modeldata_obj.search(cursor, user, [
|
||||
@@ -779,7 +786,8 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
cursor.execute('UPDATE ir_translation ' \
|
||||
'SET src = %s, module = %s ' \
|
||||
'WHERE id = %s',
|
||||
(to_update[field_name], module, trans_id))
|
||||
(to_update[field_name], module,
|
||||
trans_id))
|
||||
elif values.get(field_name):
|
||||
cursor.execute('INSERT INTO ir_translation ' \
|
||||
'(name, lang, type, src, res_id, ' \
|
||||
@@ -835,9 +843,9 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
context={'module': module})
|
||||
inherit_db_ids = {}
|
||||
|
||||
object = object_ref.browse(cursor, user, db_id)
|
||||
record = object_ref.browse(cursor, user, db_id)
|
||||
for table, field_name, field in object_ref._inherit_fields.values():
|
||||
inherit_db_ids[table] = object[field_name].id
|
||||
inherit_db_ids[table] = record[field_name].id
|
||||
|
||||
#Add a translation record for field translatable
|
||||
for field_name in object_ref._columns.keys() + \
|
||||
@@ -985,17 +993,17 @@ def post_import(cursor, pool, module, to_delete):
|
||||
model_obj.delete(cursor, user, db_id)
|
||||
mdata_delete.append(mdata_id)
|
||||
cursor.commit()
|
||||
except Exception, exception:
|
||||
except:
|
||||
cursor.rollback()
|
||||
tb_s = reduce(lambda x, y: x + y,
|
||||
traceback.format_exception(*sys.exc_info()))
|
||||
logging.getLogger("convert").error(
|
||||
'Could not delete id: %d of model %s\n' \
|
||||
'There should be some relation ' \
|
||||
'that points to this resource\n' \
|
||||
'You should manually fix this ' \
|
||||
'and restart --update=module\n' \
|
||||
'Exception: %s' % \
|
||||
'Could not delete id: %d of model %s\n'
|
||||
'There should be some relation '
|
||||
'that points to this resource\n'
|
||||
'You should manually fix this '
|
||||
'and restart --update=module\n'
|
||||
'Exception: %s' %
|
||||
(db_id, model, tb_s.decode('utf-8', 'ignore')))
|
||||
|
||||
transition_obj = pool.get('workflow.transition')
|
||||
@@ -1009,7 +1017,8 @@ def post_import(cursor, pool, module, to_delete):
|
||||
except:
|
||||
cursor.rollback()
|
||||
logging.getLogger("convert").error(
|
||||
'Could not delete id: %d of model workflow.transition'% (db_id,))
|
||||
'Could not delete id: %d of model workflow.transition' %
|
||||
(db_id,))
|
||||
|
||||
# Clean model_data:
|
||||
if mdata_delete:
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
#Copyright (c) 2002-2007 John D. Hunter; All Rights Reserved
|
||||
import time
|
||||
|
||||
def datetime_strftime(dt, fmt):
|
||||
def datetime_strftime(date, fmt):
|
||||
'''
|
||||
Allow datetime strftime formatting for years before 1900.
|
||||
See http://bugs.python.org/issue1777412
|
||||
'''
|
||||
if dt.year > 1900:
|
||||
return dt.strftime(fmt)
|
||||
if date.year > 1900:
|
||||
return date.strftime(fmt)
|
||||
|
||||
def _findall(text, substr):
|
||||
# Also finds overlaps
|
||||
@@ -23,7 +23,7 @@ def datetime_strftime(dt, fmt):
|
||||
i = j + 1
|
||||
return sites
|
||||
|
||||
year = dt.year
|
||||
year = date.year
|
||||
# For every non-leap year century, advance by
|
||||
# 6 years to get into the 28-year repeat cycle
|
||||
delta = 2000 - year
|
||||
@@ -31,20 +31,19 @@ def datetime_strftime(dt, fmt):
|
||||
year = year + off
|
||||
# Move to around the year 2000
|
||||
year = year + ((2000 - year) // 28) * 28
|
||||
timetuple = dt.timetuple()
|
||||
s1 = time.strftime(fmt, (year,) + timetuple[1:])
|
||||
sites1 = _findall(s1, str(year))
|
||||
timetuple = date.timetuple()
|
||||
string1 = time.strftime(fmt, (year,) + timetuple[1:])
|
||||
sites1 = _findall(string1, str(year))
|
||||
|
||||
s2 = time.strftime(fmt, (year + 28,) + timetuple[1:])
|
||||
sites2 = _findall(s2, str(year + 28))
|
||||
string2 = time.strftime(fmt, (year + 28,) + timetuple[1:])
|
||||
sites2 = _findall(string2, str(year + 28))
|
||||
|
||||
sites = []
|
||||
for site in sites1:
|
||||
if site in sites2:
|
||||
sites.append(site)
|
||||
|
||||
s = s1
|
||||
syear = "%4d" % (dt.year,)
|
||||
syear = "%4d" % (date.year,)
|
||||
for site in sites:
|
||||
s = s[:site] + syear + s[site+4:]
|
||||
return s
|
||||
string1 = string1[:site] + syear + string1[site+4:]
|
||||
return string1
|
||||
+56
-77
@@ -4,15 +4,13 @@
|
||||
"""
|
||||
Miscelleanous tools used by tryton
|
||||
"""
|
||||
import os, time, sys
|
||||
import os, time
|
||||
import inspect
|
||||
from trytond.config import CONFIG
|
||||
import socket
|
||||
import subprocess
|
||||
import zipfile
|
||||
from trytond.backend import Database
|
||||
from threading import Lock, local
|
||||
import logging
|
||||
import smtplib
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
@@ -20,11 +18,6 @@ except ImportError:
|
||||
import StringIO
|
||||
import dis
|
||||
import datetime
|
||||
try:
|
||||
import hashlib
|
||||
except ImportError:
|
||||
hashlib = None
|
||||
import md5
|
||||
|
||||
def find_in_path(name):
|
||||
if os.name == "nt":
|
||||
@@ -90,9 +83,9 @@ def file_open(name, mode="r", subdir='modules'):
|
||||
if subdir == 'modules':
|
||||
module_name = name.split(os.sep)[0]
|
||||
if module_name in EGG_MODULES:
|
||||
ep = EGG_MODULES[module_name]
|
||||
mod_path = os.path.join(ep.dist.location,
|
||||
*ep.module_name.split('.')[:-1])
|
||||
epoint = EGG_MODULES[module_name]
|
||||
mod_path = os.path.join(epoint.dist.location,
|
||||
*epoint.module_name.split('.')[:-1])
|
||||
name3 = os.path.join(mod_path, name)
|
||||
|
||||
if subdir:
|
||||
@@ -155,20 +148,6 @@ def get_smtp_server():
|
||||
|
||||
return smtp_server
|
||||
|
||||
def sms_send(user, password, api_id, text, to):
|
||||
"text must be latin-1 encoded"
|
||||
import urllib
|
||||
params = urllib.urlencode({
|
||||
'user': user,
|
||||
'password': password,
|
||||
'api_id': api_id,
|
||||
'text': text,
|
||||
'to':to,
|
||||
})
|
||||
#urllib.urlopen("http://api.clickatell.com/http/sendmsg", params)
|
||||
urllib.urlopen("http://196.7.150.220/http/sendmsg", params)
|
||||
return True
|
||||
|
||||
def find_language_context(args, kargs=None):
|
||||
if kargs is None:
|
||||
kargs = {}
|
||||
@@ -330,7 +309,8 @@ class Cache(object):
|
||||
cursor.execute('UPDATE ir_cache SET "timestamp" = %s '\
|
||||
'WHERE name = %s', (datetime.datetime.now(), name))
|
||||
else:
|
||||
cursor.execute('INSERT INTO ir_cache ("timestamp", "name") ' \
|
||||
cursor.execute('INSERT INTO ir_cache ' \
|
||||
'("timestamp", "name") ' \
|
||||
'VALUES (%s, %s)', (datetime.datetime.now(), name))
|
||||
Cache._resets[dbname].clear()
|
||||
finally:
|
||||
@@ -360,7 +340,7 @@ def memoize(maxsize):
|
||||
"""
|
||||
assert maxsize >= 4, "Memoize cannot work if maxsize is less than 4"
|
||||
|
||||
def wrap(f):
|
||||
def wrap(fct):
|
||||
cache = {}
|
||||
keys = [None for i in xrange(maxsize)]
|
||||
seg_size = maxsize // 4
|
||||
@@ -375,15 +355,15 @@ def memoize(maxsize):
|
||||
pos, res = res
|
||||
keys[pos] = None
|
||||
else:
|
||||
res = f(*args)
|
||||
res = fct(*args)
|
||||
|
||||
value = res
|
||||
for segment, p in enumerate(pointers):
|
||||
newkey = keys[p]
|
||||
keys[p] = key
|
||||
cache[key] = (p, value)
|
||||
for segment, pointer in enumerate(pointers):
|
||||
newkey = keys[pointer]
|
||||
keys[pointer] = key
|
||||
cache[key] = (pointer, value)
|
||||
|
||||
pointers[segment] = p + 1
|
||||
pointers[segment] = pointer + 1
|
||||
if pointers[segment] == max_pointers[segment]:
|
||||
pointers[segment] = segment * seg_size
|
||||
|
||||
@@ -394,8 +374,8 @@ def memoize(maxsize):
|
||||
|
||||
return res
|
||||
|
||||
wrapper.__doc__ = f.__doc__
|
||||
wrapper.__name__ = f.__name__
|
||||
wrapper.__doc__ = fct.__doc__
|
||||
wrapper.__name__ = fct.__name__
|
||||
|
||||
return wrapper
|
||||
return wrap
|
||||
@@ -419,103 +399,102 @@ def mod10r(number):
|
||||
|
||||
class LocalDict(local):
|
||||
|
||||
def __init__(self, dict=None):
|
||||
if dict is None:
|
||||
dict = {}
|
||||
self.dict = dict
|
||||
def __init__(self):
|
||||
super(LocalDict, self).__init__()
|
||||
self._dict = {}
|
||||
|
||||
def __str__(self):
|
||||
return str(self.dict)
|
||||
return str(self._dict)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.dict)
|
||||
return str(self._dict)
|
||||
|
||||
def clear(self):
|
||||
return self.dict.clear()
|
||||
return self._dict.clear()
|
||||
|
||||
def keys(self):
|
||||
return self.dict.keys()
|
||||
return self._dict.keys()
|
||||
|
||||
def __setitem__(self, i, y):
|
||||
self.dict.__setitem__(i, y)
|
||||
self._dict.__setitem__(i, y)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.dict.__getitem__(i)
|
||||
return self._dict.__getitem__(i)
|
||||
|
||||
def copy(self):
|
||||
return self.dict.copy()
|
||||
return self._dict.copy()
|
||||
|
||||
def iteritems(self):
|
||||
return self.dict.iteritems()
|
||||
return self._dict.iteritems()
|
||||
|
||||
def iterkeys(self):
|
||||
return self.dict.iterkeys()
|
||||
return self._dict.iterkeys()
|
||||
|
||||
def itervalues(self):
|
||||
return self.dict.itervalues()
|
||||
return self._dict.itervalues()
|
||||
|
||||
def pop(self, k, d=None):
|
||||
return self.dict.pop(k, d)
|
||||
return self._dict.pop(k, d)
|
||||
|
||||
def popitem(self):
|
||||
return self.dict.popitem()
|
||||
return self._dict.popitem()
|
||||
|
||||
def setdefault(self, k, d=None):
|
||||
return self.dict.setdefault(k, d)
|
||||
return self._dict.setdefault(k, d)
|
||||
|
||||
def update(self, E, **F):
|
||||
return self.dict.update(E, F)
|
||||
return self._dict.update(E, F)
|
||||
|
||||
def values(self):
|
||||
return self.dict.values()
|
||||
return self._dict.values()
|
||||
|
||||
def get(self, k, d=None):
|
||||
return self.dict.get(k, d)
|
||||
return self._dict.get(k, d)
|
||||
|
||||
def has_key(self, k):
|
||||
return self.dict.has_key(k)
|
||||
return self._dict.has_key(k)
|
||||
|
||||
def items(self):
|
||||
return self.dict.items()
|
||||
return self._dict.items()
|
||||
|
||||
def __cmp__(self, y):
|
||||
return self.dict.__cmp__(y)
|
||||
return self._dict.__cmp__(y)
|
||||
|
||||
def __contains__(self, k):
|
||||
return self.dict.__contains__(k)
|
||||
return self._dict.__contains__(k)
|
||||
|
||||
def __delitem__(self, y):
|
||||
return self.dict.__delitem__(y)
|
||||
return self._dict.__delitem__(y)
|
||||
|
||||
def __eq__(self, y):
|
||||
return self.dict.__eq__(y)
|
||||
return self._dict.__eq__(y)
|
||||
|
||||
def __ge__(self, y):
|
||||
return self.dict.__ge__(y)
|
||||
return self._dict.__ge__(y)
|
||||
|
||||
def __getitem__(self, y):
|
||||
return self.dict.__getitem__(y)
|
||||
return self._dict.__getitem__(y)
|
||||
|
||||
def __gt__(self, y):
|
||||
return self.dict.__gt__(y)
|
||||
return self._dict.__gt__(y)
|
||||
|
||||
def __hash__(self):
|
||||
return self.dict.__hash__()
|
||||
return self._dict.__hash__()
|
||||
|
||||
def __iter__(self):
|
||||
return self.dict.__iter__()
|
||||
return self._dict.__iter__()
|
||||
|
||||
def __le__(self, y):
|
||||
return self.dict.__le__(y)
|
||||
return self._dict.__le__(y)
|
||||
|
||||
def __len__(self):
|
||||
return self.dict.__len__()
|
||||
return self._dict.__len__()
|
||||
|
||||
def __lt__(self, y):
|
||||
return self.dict.__lt__(y)
|
||||
return self._dict.__lt__(y)
|
||||
|
||||
def __ne__(self, y):
|
||||
return self.dict.__ne__(y)
|
||||
return self._dict.__ne__(y)
|
||||
|
||||
def reduce_ids(field, ids):
|
||||
'''
|
||||
@@ -577,12 +556,12 @@ _ALLOWED_CODES = set(dis.opmap[x] for x in [
|
||||
|
||||
@memoize(1000)
|
||||
def _compile_source(source):
|
||||
c = compile(source, '', 'eval')
|
||||
comp = compile(source, '', 'eval')
|
||||
codes = []
|
||||
s = c.co_code
|
||||
co_code = comp.co_code
|
||||
i = 0
|
||||
while i < len(s):
|
||||
code = ord(s[i])
|
||||
while i < len(co_code):
|
||||
code = ord(co_code[i])
|
||||
codes.append(code)
|
||||
if code >= dis.HAVE_ARGUMENT:
|
||||
i += 3
|
||||
@@ -591,14 +570,14 @@ def _compile_source(source):
|
||||
for code in codes:
|
||||
if code not in _ALLOWED_CODES:
|
||||
raise ValueError('opcode %s not allowed' % dis.opname[code])
|
||||
return c
|
||||
return comp
|
||||
|
||||
def safe_eval(source, data=None):
|
||||
if '__subclasses__' in source:
|
||||
raise ValueError('__subclasses__ not allowed')
|
||||
|
||||
c = _compile_source(source)
|
||||
return eval(c, {'__builtins__': {
|
||||
comp = _compile_source(source)
|
||||
return eval(comp, {'__builtins__': {
|
||||
'True': True,
|
||||
'False': False,
|
||||
'str': str,
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from trytond.pool import Pool
|
||||
from trytond.model import ModelView
|
||||
from trytond.config import CONFIG
|
||||
from trytond.backend import DatabaseIntegrityError
|
||||
import sys
|
||||
import copy
|
||||
from xml import dom
|
||||
import traceback
|
||||
import logging
|
||||
from threading import Lock
|
||||
from random import randint
|
||||
from sys import maxint
|
||||
@@ -17,6 +10,7 @@ from sys import maxint
|
||||
class Wizard(object):
|
||||
_name = ""
|
||||
states = {}
|
||||
pool = None
|
||||
|
||||
def __new__(cls):
|
||||
Pool.register(cls, type='wizard')
|
||||
@@ -35,8 +29,8 @@ class Wizard(object):
|
||||
def init(self, cursor, module_name):
|
||||
for state in self.states.keys():
|
||||
if self.states[state]['result']['type'] == 'form':
|
||||
for i, button in enumerate(
|
||||
self.states[state]['result']['state']):
|
||||
for button in \
|
||||
self.states[state]['result']['state']:
|
||||
button_name = button[0]
|
||||
button_value = button[1]
|
||||
cursor.execute('SELECT id, name, src ' \
|
||||
@@ -50,8 +44,8 @@ class Wizard(object):
|
||||
res = cursor.dictfetchall()
|
||||
if not res:
|
||||
cursor.execute('INSERT INTO ir_translation ' \
|
||||
'(name, lang, type, src, value, module, fuzzy) ' \
|
||||
'VALUES (%s, %s, %s, %s, %s, %s, %s)',
|
||||
'(name, lang, type, src, value, module, fuzzy)'\
|
||||
' VALUES (%s, %s, %s, %s, %s, %s, %s)',
|
||||
(self._name + ',' + state + ',' + button_name,
|
||||
'en_US', 'wizard_button', button_value,
|
||||
'', module_name, False))
|
||||
|
||||
Reference in new issue
Block a user