summaryrefslogtreecommitdiff
path: root/bin/tools
diff options
context:
space:
mode:
authorP. Christeas <p_christ@hol.gr>2009-01-31 12:08:04 +0200
committerP. Christeas <p_christ@hol.gr>2009-01-31 12:08:04 +0200
commitb69c19fbb2a56de017f466c76d06addd968c96ce (patch)
tree18fd5664613588c2901a5ede849592ddba2b3e9d /bin/tools
parentf84b1e90e73969887f9e1ae6e43548c3d853c7e8 (diff)
parent27240361ca5ead2597ae8f0c63043bab0e969001 (diff)
Merge branch 'master' of openobject-server into mdv-gpl3-py26
Conflicts: bin/netsvc.py bin/tools/translate.py bzr revid: p_christ@hol.gr-20090131100804-pu97gelwjh1flk3h
Diffstat (limited to 'bin/tools')
-rw-r--r--bin/tools/__init__.py1
-rw-r--r--bin/tools/config.py70
-rw-r--r--bin/tools/copy.py416
-rw-r--r--bin/tools/translate.py14
4 files changed, 490 insertions, 11 deletions
diff --git a/bin/tools/__init__.py b/bin/tools/__init__.py
index ad693e14aa1..f188864820d 100644
--- a/bin/tools/__init__.py
+++ b/bin/tools/__init__.py
@@ -19,6 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
+import copy
from config import *
from misc import *
from convert import *
diff --git a/bin/tools/config.py b/bin/tools/config.py
index fc5659d03bc..d79a997561c 100644
--- a/bin/tools/config.py
+++ b/bin/tools/config.py
@@ -180,9 +180,19 @@ class configmanager(object):
(opt, args) = parser.parse_args()
- assert not (bool(opt.syslog) and bool(opt.logfile)), "the syslog and logfile options are exclusive"
- assert not (opt.translate_in and (not opt.language or not opt.db_name)), "the i18n-import option cannot be used without the language (-l) and the database (-d) options"
- assert not (opt.translate_out and (not opt.db_name)), "the i18n-export option cannot be used without the database (-d) option"
+ def die(cond, msg):
+ if cond:
+ print msg
+ sys.exit(1)
+
+ die(bool(opt.syslog) and bool(opt.logfile),
+ "the syslog and logfile options are exclusive")
+
+ die(opt.translate_in and (not opt.language or not opt.db_name),
+ "the i18n-import option cannot be used without the language (-l) and the database (-d) options")
+
+ die(opt.translate_out and (not opt.db_name),
+ "the i18n-export option cannot be used without the database (-d) option")
# place/search the config file on Win32 near the server installation
# (../etc from the server)
@@ -246,10 +256,62 @@ class configmanager(object):
self.options['pg_path'] = opt.pg_path
if self.options.get('language', False):
- assert len(self.options['language'])<=5, 'ERROR: The Lang name must take max 5 chars, Eg: -lfr_BE'
+ if len(self.options['language']) <= 5:
+ raise Exception('ERROR: The Lang name must take max 5 chars, Eg: -lfr_BE')
+
+ if not self.options['db_user']:
+ try:
+ import getpass
+ self.options['db_user'] = getpass.getuser()
+ except:
+ self.options['db_user'] = None
+
+ die(not self.options['db_user'], 'ERROR: No user specified for the connection to the database')
+
+ if self.options['db_password']:
+ if sys.platform == 'win32' and not self.options['db_host']:
+ self.options['db_host'] = 'localhost'
+ if self.options['db_host']:
+ self._generate_pgpassfile()
+
if opt.save:
self.save()
+ def _generate_pgpassfile(self):
+ """
+ Generate the pgpass file with the parameters from the command line (db_host, db_user,
+ db_password)
+
+ Used because pg_dump and pg_restore can not accept the password on the command line.
+ """
+ is_win32 = sys.platform == 'win32'
+ if is_win32:
+ filename = os.path.join(os.environ['APPDATA'], 'pgpass.conf')
+ else:
+ filename = os.path.join(os.environ['HOME'], '.pgpass')
+
+ text_to_add = "%(db_host)s:*:*:%(db_user)s:%(db_password)s" % self.options
+
+ if os.path.exists(filename):
+ content = [x.strip() for x in file(filename, 'r').readlines()]
+ if text_to_add in content:
+ return
+
+ fp = file(filename, 'a+')
+ fp.write(text_to_add + "\n")
+ fp.close()
+
+ if is_win32:
+ import _winreg
+ x=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
+ y = _winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", 0,_winreg.KEY_ALL_ACCESS)
+ _winreg.SetValueEx(y,"PGPASSFILE", 0, _winreg.REG_EXPAND_SZ, filename )
+ _winreg.CloseKey(y)
+ _winreg.CloseKey(x)
+ else:
+ import stat
+ os.chmod(filename, stat.S_IRUSR + stat.S_IWUSR)
+
def _check_addons_path(self, option, opt, value, parser):
res = os.path.abspath(os.path.expanduser(value))
if not os.path.exists(res):
diff --git a/bin/tools/copy.py b/bin/tools/copy.py
new file mode 100644
index 00000000000..e301b710976
--- /dev/null
+++ b/bin/tools/copy.py
@@ -0,0 +1,416 @@
+"""
+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=[]):
+ """Deep copy operation on arbitrary Python objects.
+
+ See the module's __doc__ string for more info.
+ """
+
+ if memo is None:
+ memo = {}
+
+ 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()
diff --git a/bin/tools/translate.py b/bin/tools/translate.py
index 24f606f3550..224f26bec71 100644
--- a/bin/tools/translate.py
+++ b/bin/tools/translate.py
@@ -478,7 +478,7 @@ def trans_generate(lang, modules, dbname=None):
push_translation(module, report_type, name, 0, t)
except IOError, xml.dom.expatbuilder.expat.ExpatError:
if fname:
- logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't export translation for report %s %s %s" % (name, report_type, fname))
+ logger.notifyChannel("i18n", netsvc.LOG_ERROR, "couldn't export translation for report %s %s %s" % (name, report_type, fname))
for constraint in pool.get(model)._constraints:
msg = constraint[1]
@@ -540,14 +540,13 @@ def trans_load(db_name, filename, lang, strict=False, verbose=True):
return r
except IOError:
if verbose:
- logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,))
+ logger.notifyChannel("i18n", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,))
return None
def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=None, verbose=True):
logger = netsvc.Logger()
if verbose:
- logger.notifyChannel("init", netsvc.LOG_INFO,
- 'loading translation file for language %s' % (lang))
+ logger.notifyChannel("i18n", netsvc.LOG_INFO, 'loading translation file for language %s' % (lang))
pool = pooler.get_pool(db_name)
lang_obj = pool.get('res.lang')
trans_obj = pool.get('ir.translation')
@@ -617,8 +616,9 @@ def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=
langs = lang_obj.read(cr, uid, lang_ids)
ls = map(lambda x: (x['code'],x['name']), langs)
- fileobj.seek(0)
+ # now, the serious things: we read the language file
+ fileobj.seek(0)
if fileformat == 'csv':
reader = csv.reader(fileobj, quotechar='"', delimiter=',')
# read the first line of the file (it contains columns titles)
@@ -701,11 +701,11 @@ def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=
cr.commit()
cr.close()
if verbose:
- logger.notifyChannel("init", netsvc.LOG_INFO,
+ logger.notifyChannel("i18n", netsvc.LOG_INFO,
"translation file loaded succesfully")
except IOError:
filename = '[lang: %s][format: %s]' % (lang or 'new', fileformat)
- logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,))
+ logger.notifyChannel("i18n", netsvc.LOG_ERROR, "couldn't read translation file %s" % (filename,))
cr.commit()
cr.close()
except: