[MERGE] cleaned some imports, removed some code for older python versions.

bzr revid: vmt@openerp.com-20120118160305-ucennaoqehjuut1z
This commit is contained in:
Vo Minh Thu 2012-01-18 17:03:05 +01:00
commit 418739cf3e
18 changed files with 33 additions and 666 deletions

View File

@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import ast
import copy
import logging

View File

@ -34,7 +34,6 @@ from osv import osv
from osv import fields
from openerp.tools.translate import _
from openerp.tools import html2text
from openerp.tools.func import wraps
import openerp.tools as tools
# ustr was originally from tools.misc.

View File

@ -13,17 +13,17 @@
2. Try simple literal definition to verify it works with literal_eval
-
!python {model: ir.model}: |
from tools.safe_eval import literal_eval
import ast
expected = (1, {"a": 9}, (True, False, None))
actual = literal_eval('(1, {"a": 9}, (True, False, None))')
actual = ast.literal_eval('(1, {"a": 9}, (True, False, None))')
assert actual == expected, "Simple python expressions are not working with literal_eval"
-
3. Try arithmetic expression in literal_eval to verify it does not work
-
!python {model: ir.model}: |
from tools.safe_eval import literal_eval
import ast
try:
literal_eval('(1, {"a": 2*9}, (True, False, None))')
ast.literal_eval('(1, {"a": 2*9}, (True, False, None))')
assert False, "literal_eval should not accept arithmetic expressions"
except ValueError:
pass
@ -31,9 +31,9 @@
4. Try forbidden expressions in literal_eval to verify they are not allowed
-
!python {model: ir.model}: |
from tools.safe_eval import literal_eval
import ast
try:
literal_eval('{"a": True.__class__}')
ast.literal_eval('{"a": True.__class__}')
assert False, "literal_eval should accept only literals"
except ValueError:
pass

View File

@ -30,7 +30,6 @@ import socket
import sys
import threading
import time
import traceback
import types
from pprint import pformat

View File

@ -46,7 +46,7 @@ import openerp.netsvc as netsvc
import openerp.tools as tools
from openerp.tools.translate import _
from openerp.tools import float_round, float_repr
import json
import simplejson
def _symbol_set(symb):
if symb == None or symb == False:
@ -1324,10 +1324,10 @@ class serialized(_column):
"""
def _symbol_set_struct(val):
return json.dumps(val)
return simplejson.dumps(val)
def _symbol_get_struct(self, val):
return json.loads(val or '{}')
return simplejson.loads(val or '{}')
_prefetch = False
_type = 'serialized'

View File

@ -21,6 +21,7 @@
#.apidoc title: Objects Services (OSV)
from functools import wraps
import logging
from psycopg2 import IntegrityError, errorcodes
@ -29,7 +30,6 @@ import openerp
import openerp.netsvc as netsvc
import openerp.pooler as pooler
import openerp.sql_db as sql_db
from openerp.tools.func import wraps
from openerp.tools.translate import translate
from openerp.osv.orm import MetaModel, Model, TransientModel, AbstractModel
import openerp.exceptions

View File

@ -39,21 +39,17 @@
static HTTP, DAV or other.
"""
from websrv_lib import *
import openerp.netsvc as netsvc
import errno
import threading
import openerp.tools as tools
import base64
import posixpath
import urllib
import os
import select
import socket
import xmlrpclib
import logging
from SimpleXMLRPCServer import SimpleXMLRPCDispatcher
from websrv_lib import *
import openerp.netsvc as netsvc
import openerp.tools as tools
try:
import fcntl
except ImportError:

View File

@ -39,6 +39,7 @@ import openerp.sql_db as sql_db
import openerp.tools as tools
import openerp.modules
import openerp.exceptions
from openerp.service import http_server
#.apidoc title: Exported Service methods
#.apidoc module-mods: member-order: bysource

View File

@ -32,9 +32,6 @@
usable in other projects, too.
"""
import socket
import base64
import errno
import SocketServer
from BaseHTTPServer import *
from SimpleHTTPServer import SimpleHTTPRequestHandler

View File

@ -35,14 +35,13 @@ See also: the `pooler` module
__all__ = ['db_connect', 'close_db']
from threading import currentThread
from functools import wraps
import logging
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE,\
ISOLATION_LEVEL_REPEATABLE_READ
from psycopg2.psycopg1 import cursor as psycopg1cursor
from psycopg2.pool import PoolError
import psycopg2.extensions
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_REPEATABLE_READ
from psycopg2.pool import PoolError
from psycopg2.psycopg1 import cursor as psycopg1cursor
from threading import currentThread
import warnings
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
@ -67,7 +66,7 @@ psycopg2.extensions.register_type(psycopg2.extensions.new_type((700, 701, 1700,)
import tools
from tools.func import wraps, frame_codeinfo
from tools.func import frame_codeinfo
from datetime import datetime as mdt
from datetime import timedelta
import threading
@ -423,7 +422,7 @@ class ConnectionPool(object):
try:
result = psycopg2.connect(dsn=dsn, connection_factory=PsycoConnection)
except psycopg2.Error, e:
except psycopg2.Error:
self.__logger.exception('Connection to the database failed')
raise
self._connections.append((result, True))

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import os
import time
import unittest2
import xmlrpclib
import openerp

View File

@ -7,11 +7,8 @@
# > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \
# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence
# This assume an existing database.
import os
import psycopg2
import time
import unittest2
import xmlrpclib
import openerp
import common

View File

@ -6,7 +6,6 @@
# OPENERP_DATABASE=yy nosetests tests/test_xmlrpc.py
# > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \
# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_xmlrpc
import os
import time
import unittest2
import xmlrpclib

View File

@ -1,441 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
"""
FROM Python 2.5
Generic (shallow and deep) copying operations.
Interface summary:
import copy
x = copy.copy(y) # make a shallow copy of y
x = copy.deepcopy(y) # make a deep copy of y
For module specific errors, copy.Error is raised.
The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances).
- A shallow copy constructs a new compound object and then (to the
extent possible) inserts *the same objects* into it that the
original contains.
- A deep copy constructs a new compound object and then, recursively,
inserts *copies* into it of the objects found in the original.
Two problems often exist with deep copy operations that don't exist
with shallow copy operations:
a) recursive objects (compound objects that, directly or indirectly,
contain a reference to themselves) may cause a recursive loop
b) because deep copy copies *everything* it may copy too much, e.g.
administrative data structures that should be shared even between
copies
Python's deep copy operation avoids these problems by:
a) keeping a table of objects already copied during the current
copying pass
b) letting user-defined classes override the copying operation or the
set of components copied
This version does not copy types like module, class, function, method,
nor stack trace, stack frame, nor file, socket, window, nor array, nor
any similar types.
Classes can use the same interfaces to control copying that they use
to control pickling: they can define methods called __getinitargs__(),
__getstate__() and __setstate__(). See the documentation for module
"pickle" for information on these methods.
"""
import types
from copy_reg import dispatch_table
class Error(Exception):
pass
error = Error # backward compatibility
try:
from org.python.core import PyStringMap
except ImportError:
PyStringMap = None
__all__ = ["Error", "copy", "deepcopy"]
def copy(x):
"""Shallow copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
cls = type(x)
copier = _copy_dispatch.get(cls)
if copier:
return copier(x)
copier = getattr(cls, "__copy__", None)
if copier:
return copier(x)
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
rv = reductor(2)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error("un(shallow)copyable object of type %s" % cls)
return _reconstruct(x, rv, 0)
_copy_dispatch = d = {}
def _copy_immutable(x):
return x
for t in (type(None), int, long, float, bool, str, tuple,
frozenset, type, xrange, types.ClassType,
types.BuiltinFunctionType,
types.FunctionType):
d[t] = _copy_immutable
for name in ("ComplexType", "UnicodeType", "CodeType"):
t = getattr(types, name, None)
if t is not None:
d[t] = _copy_immutable
def _copy_with_constructor(x):
return type(x)(x)
for t in (list, dict, set):
d[t] = _copy_with_constructor
def _copy_with_copy_method(x):
return x.copy()
if PyStringMap is not None:
d[PyStringMap] = _copy_with_copy_method
def _copy_inst(x):
if hasattr(x, '__copy__'):
return x.__copy__()
if hasattr(x, '__getinitargs__'):
args = x.__getinitargs__()
y = x.__class__(*args)
else:
y = _EmptyClass()
y.__class__ = x.__class__
if hasattr(x, '__getstate__'):
state = x.__getstate__()
else:
state = x.__dict__
if hasattr(y, '__setstate__'):
y.__setstate__(state)
else:
y.__dict__.update(state)
return y
d[types.InstanceType] = _copy_inst
del d
def deepcopy(x, memo=None, _nil=None):
"""Deep copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
if memo is None:
memo = {}
if _nil is None:
_nil = {}
d = id(x)
y = memo.get(d, _nil)
if y is not _nil:
return y
cls = type(x)
copier = _deepcopy_dispatch.get(cls)
if copier:
y = copier(x, memo)
else:
try:
issc = issubclass(cls, type)
except TypeError: # cls is not a class (old Boost; see SF #502085)
issc = 0
if issc:
y = _deepcopy_atomic(x, memo)
else:
copier = getattr(x, "__deepcopy__", None)
if copier:
y = copier(memo)
else:
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
rv = reductor(2)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error(
"un(deep)copyable object of type %s" % cls)
y = _reconstruct(x, rv, 1, memo)
memo[d] = y
_keep_alive(x, memo) # Make sure x lives at least as long as d
return y
_deepcopy_dispatch = d = {}
def _deepcopy_atomic(x, memo):
return x
d[type(None)] = _deepcopy_atomic
d[int] = _deepcopy_atomic
d[long] = _deepcopy_atomic
d[float] = _deepcopy_atomic
d[bool] = _deepcopy_atomic
try:
d[complex] = _deepcopy_atomic
except NameError:
pass
d[str] = _deepcopy_atomic
try:
d[unicode] = _deepcopy_atomic
except NameError:
pass
try:
d[types.CodeType] = _deepcopy_atomic
except AttributeError:
pass
d[type] = _deepcopy_atomic
d[xrange] = _deepcopy_atomic
d[types.ClassType] = _deepcopy_atomic
d[types.BuiltinFunctionType] = _deepcopy_atomic
d[types.FunctionType] = _deepcopy_atomic
def _deepcopy_list(x, memo):
y = []
memo[id(x)] = y
for a in x:
y.append(deepcopy(a, memo))
return y
d[list] = _deepcopy_list
def _deepcopy_tuple(x, memo):
y = []
for a in x:
y.append(deepcopy(a, memo))
d = id(x)
try:
return memo[d]
except KeyError:
pass
for i in range(len(x)):
if x[i] is not y[i]:
y = tuple(y)
break
else:
y = x
memo[d] = y
return y
d[tuple] = _deepcopy_tuple
def _deepcopy_dict(x, memo):
y = {}
memo[id(x)] = y
for key, value in x.iteritems():
y[deepcopy(key, memo)] = deepcopy(value, memo)
return y
d[dict] = _deepcopy_dict
if PyStringMap is not None:
d[PyStringMap] = _deepcopy_dict
def _keep_alive(x, memo):
"""Keeps a reference to the object x in the memo.
Because we remember objects by their id, we have
to assure that possibly temporary objects are kept
alive by referencing them.
We store a reference at the id of the memo, which should
normally not be used unless someone tries to deepcopy
the memo itself...
"""
try:
memo[id(memo)].append(x)
except KeyError:
# aha, this is the first one :-)
memo[id(memo)]=[x]
def _deepcopy_inst(x, memo):
if hasattr(x, '__deepcopy__'):
return x.__deepcopy__(memo)
if hasattr(x, '__getinitargs__'):
args = x.__getinitargs__()
args = deepcopy(args, memo)
y = x.__class__(*args)
else:
y = _EmptyClass()
y.__class__ = x.__class__
memo[id(x)] = y
if hasattr(x, '__getstate__'):
state = x.__getstate__()
else:
state = x.__dict__
state = deepcopy(state, memo)
if hasattr(y, '__setstate__'):
y.__setstate__(state)
else:
y.__dict__.update(state)
return y
d[types.InstanceType] = _deepcopy_inst
def _reconstruct(x, info, deep, memo=None):
if isinstance(info, str):
return x
assert isinstance(info, tuple)
if memo is None:
memo = {}
n = len(info)
assert n in (2, 3, 4, 5)
callable, args = info[:2]
if n > 2:
state = info[2]
else:
state = {}
if n > 3:
listiter = info[3]
else:
listiter = None
if n > 4:
dictiter = info[4]
else:
dictiter = None
if deep:
args = deepcopy(args, memo)
y = callable(*args)
memo[id(x)] = y
if listiter is not None:
for item in listiter:
if deep:
item = deepcopy(item, memo)
y.append(item)
if dictiter is not None:
for key, value in dictiter:
if deep:
key = deepcopy(key, memo)
value = deepcopy(value, memo)
y[key] = value
if state:
if deep:
state = deepcopy(state, memo)
if hasattr(y, '__setstate__'):
y.__setstate__(state)
else:
if isinstance(state, tuple) and len(state) == 2:
state, slotstate = state
else:
slotstate = None
if state is not None:
y.__dict__.update(state)
if slotstate is not None:
for key, value in slotstate.iteritems():
setattr(y, key, value)
return y
del d
del types
# Helper for instance creation without calling __init__
class _EmptyClass:
pass
def _test():
l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
{'abc': 'ABC'}, (), [], {}]
l1 = copy(l)
print l1==l
l1 = map(copy, l)
print l1==l
l1 = deepcopy(l)
print l1==l
class C:
def __init__(self, arg=None):
self.a = 1
self.arg = arg
if __name__ == '__main__':
import sys
file = sys.argv[0]
else:
file = __file__
self.fp = open(file)
self.fp.close()
def __getstate__(self):
return {'a': self.a, 'arg': self.arg}
def __setstate__(self, state):
for key, value in state.iteritems():
setattr(self, key, value)
def __deepcopy__(self, memo=None):
new = self.__class__(deepcopy(self.arg, memo))
new.a = self.a
return new
c = C('argument sketch')
l.append(c)
l2 = copy(l)
print l == l2
print l
print l2
l2 = deepcopy(l)
print l == l2
print l
print l2
l.append({l[1]: l, 'xyz': l[2]})
l3 = copy(l)
import repr
print map(repr.repr, l)
print map(repr.repr, l1)
print map(repr.repr, l2)
print map(repr.repr, l3)
l3 = deepcopy(l)
import repr
print map(repr.repr, l)
print map(repr.repr, l1)
print map(repr.repr, l2)
print map(repr.repr, l3)
if __name__ == '__main__':
_test()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -20,68 +20,10 @@
#
##############################################################################
__all__ = ['partial', 'wraps', 'update_wrapper', 'synchronized']
try:
from functools import partial, wraps, update_wrapper
except ImportError:
# The functools module doesn't exist in python < 2.5
# Code taken from python 2.5
# http://svn.python.org/view/python/tags/r254/Lib/functools.py?view=markup
def partial(fun, *args, **kwargs):
""" Partial implementation
See: http://svn.python.org/view/python/tags/r254/Lib/functools.py
"""
def _partial(*args2, **kwargs2):
return fun(*(args+args2), **dict(kwargs, **kwargs2))
return _partial
### --- code from python 2.5
# update_wrapper() and wraps() are tools to help write
# wrapper functions that can handle naive introspection
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Update a wrapper function to look like the wrapped function
wrapper is the function to be updated
wrapped is the original function
assigned is a tuple naming the attributes assigned directly
from the wrapped function to the wrapper function (defaults to
functools.WRAPPER_ASSIGNMENTS)
updated is a tuple naming the attributes off the wrapper that
are updated with the corresponding attribute from the wrapped
function (defaults to functools.WRAPPER_UPDATES)
"""
for attr in assigned:
setattr(wrapper, attr, getattr(wrapped, attr))
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
# Return the wrapper so this can be used as a decorator via partial()
return wrapper
def wraps(wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Decorator factory to apply update_wrapper() to a wrapper function
Returns a decorator that invokes update_wrapper() with the decorated
function as the wrapper argument and the arguments to wraps() as the
remaining arguments. Default arguments are as for update_wrapper().
This is a convenience function to simplify applying partial() to
update_wrapper().
"""
return partial(update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated)
__all__ = ['synchronized']
from functools import wraps
from inspect import getsourcefile
def synchronized(lock_attr='_lock'):
def decorator(func):
@ -96,10 +38,6 @@ def synchronized(lock_attr='_lock'):
return wrapper
return decorator
from inspect import getsourcefile
def frame_codeinfo(fframe, back=0):
""" Return a (filename, line) pair for a previous frame .
@return (filename, lineno) where lineno is either int or string==''

View File

@ -26,6 +26,7 @@
Miscelleanous tools used by OpenERP.
"""
from functools import wraps
import inspect
import subprocess
import logging
@ -50,10 +51,7 @@ from email import Encoders
from itertools import islice, izip
from lxml import etree
from which import which
if sys.version_info[:2] < (2, 4):
from threadinglocal import local
else:
from threading import local
from threading import local
try:
from html2text import html2text
except ImportError:
@ -547,28 +545,6 @@ class currency(float):
def to_xml(s):
return s.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')
# to be compatible with python 2.4
import __builtin__
if not hasattr(__builtin__, 'all'):
def all(iterable):
for element in iterable:
if not element:
return False
return True
__builtin__.all = all
del all
if not hasattr(__builtin__, 'any'):
def any(iterable):
for element in iterable:
if element:
return True
return False
__builtin__.any = any
del any
def get_iso_codes(lang):
if lang.find('_') != -1:
if lang.split('_')[0] == lang.split('_')[1].lower():
@ -715,8 +691,6 @@ def human_size(sz):
return "%0.2f %s" % (s, units[i])
def logged(f):
from func import wraps
@wraps(f)
def wrapper(*args, **kwargs):
from pprint import pformat
@ -742,8 +716,6 @@ class profile(object):
self.fname = fname
def __call__(self, f):
from func import wraps
@wraps(f)
def wrapper(*args, **kwargs):
class profile_wrapper(object):
@ -759,40 +731,6 @@ class profile(object):
return wrapper
def debug(what):
"""
This method allow you to debug your code without print
Example:
>>> def func_foo(bar)
... baz = bar
... debug(baz)
... qnx = (baz, bar)
... debug(qnx)
...
>>> func_foo(42)
This will output on the logger:
[Wed Dec 25 00:00:00 2008] DEBUG:func_foo:baz = 42
[Wed Dec 25 00:00:00 2008] DEBUG:func_foo:qnx = (42, 42)
To view the DEBUG lines in the logger you must start the server with the option
--log-level=debug
"""
warnings.warn("The tools.debug() method is deprecated, please use logging.",
DeprecationWarning, stacklevel=2)
from inspect import stack
from pprint import pformat
st = stack()[1]
param = re.split("debug *\((.+)\)", st[4][0].strip())[1].strip()
while param.count(')') > param.count('('): param = param[:param.rfind(')')]
what = pformat(what)
if param != what:
what = "%s = %s" % (param, what)
logging.getLogger(st[3]).debug(what)
__icons_list = ['STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
'STOCK_CANCEL', 'STOCK_CDROM', 'STOCK_CLEAR', 'STOCK_CLOSE', 'STOCK_COLOR_PICKER',
'STOCK_CONNECT', 'STOCK_CONVERT', 'STOCK_COPY', 'STOCK_CUT', 'STOCK_DELETE',
@ -1200,4 +1138,4 @@ class UnquoteEvalContext(defaultdict):
def __missing__(self, key):
return unquote(key)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -30,14 +30,13 @@ condition/math builtins.
# - http://code.activestate.com/recipes/286134/
# - safe_eval in lp:~xrg/openobject-server/optimize-5.0
# - safe_eval in tryton http://hg.tryton.org/hgwebdir.cgi/trytond/rev/bbb5f73319ad
# - python 2.6's ast.literal_eval
from opcode import HAVE_ARGUMENT, opmap, opname
from types import CodeType
import logging
import os
__all__ = ['test_expr', 'literal_eval', 'safe_eval', 'const_eval', 'ext_eval' ]
__all__ = ['test_expr', 'safe_eval', 'const_eval', 'ext_eval' ]
# The time module is usually already provided in the safe_eval environment
# but some code, e.g. datetime.datetime.now() (Windows/Python 2.5.2, bug
@ -161,61 +160,6 @@ def expr_eval(expr):
c = test_expr(expr, _EXPR_OPCODES)
return eval(c)
# Port of Python 2.6's ast.literal_eval for use under Python 2.5
SAFE_CONSTANTS = {'None': None, 'True': True, 'False': False}
try:
# first, try importing directly
from ast import literal_eval
except ImportError:
import _ast as ast
def _convert(node):
if isinstance(node, ast.Str):
return node.s
elif isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.Tuple):
return tuple(map(_convert, node.elts))
elif isinstance(node, ast.List):
return list(map(_convert, node.elts))
elif isinstance(node, ast.Dict):
return dict((_convert(k), _convert(v)) for k, v
in zip(node.keys, node.values))
elif isinstance(node, ast.Name):
if node.id in SAFE_CONSTANTS:
return SAFE_CONSTANTS[node.id]
raise ValueError('malformed or disallowed expression')
def parse(expr, filename='<unknown>', mode='eval'):
"""parse(source[, filename], mode]] -> code object
Parse an expression into an AST node.
Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST).
"""
return compile(expr, filename, mode, ast.PyCF_ONLY_AST)
def literal_eval(node_or_string):
"""literal_eval(expression) -> value
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the
following Python literal structures: strings, numbers, tuples,
lists, dicts, booleans, and None.
>>> literal_eval('[1,True,"spam"]')
[1, True, 'spam']
>>> literal_eval('1+3')
Traceback (most recent call last):
...
ValueError: malformed or disallowed expression
"""
if isinstance(node_or_string, basestring):
node_or_string = parse(node_or_string)
if isinstance(node_or_string, ast.Expression):
node_or_string = node_or_string.body
return _convert(node_or_string)
def _import(name, globals=None, locals=None, fromlist=None, level=-1):
if globals is None:
globals = {}

View File

@ -19,8 +19,9 @@
#
##############################################################################
import copy
import openerp.netsvc as netsvc
from openerp.tools import copy
from openerp.tools.misc import UpdateableStr, UpdateableDict
from openerp.tools.translate import translate
from lxml import etree