#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-# Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
+# Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
from functools import wraps
import cProfile
+from contextlib import contextmanager
import subprocess
import logging
import os
import sys
import threading
import time
+import werkzeug.utils
import zipfile
from collections import defaultdict, Mapping
from datetime import datetime
from config import config
from cache import *
+from .parse_version import parse_version
import openerp
# get_encodings, ustr and exception_to_unicode were originally from tools.misc.
raise Exception('Couldn\'t find %s' % name)
args2 = (prog,) + args
- return subprocess.call(args2)
+ with open(os.devnull) as dn:
+ return subprocess.call(args2, stdout=dn, stderr=subprocess.STDOUT)
def exec_pg_command_pipe(name, *args):
prog = find_pg_tool(name)
"""
return izip(xrange(len(l)-1, -1, -1), reversed(l))
+def topological_sort(elems):
+ """ Return a list of elements sorted so that their dependencies are listed
+ before them in the result.
+
+ :param elems: specifies the elements to sort with their dependencies; it is
+ a dictionary like `{element: dependencies}` where `dependencies` is a
+ collection of elements that must appear before `element`. The elements
+ of `dependencies` are not required to appear in `elems`; they will
+ simply not appear in the result.
+
+ :returns: a list with the keys of `elems` sorted according to their
+ specification.
+ """
+ # the algorithm is inspired by [Tarjan 1976],
+ # http://en.wikipedia.org/wiki/Topological_sorting#Algorithms
+ result = []
+ visited = set()
+
+ def visit(n):
+ if n not in visited:
+ visited.add(n)
+ if n in elems:
+ # first visit all dependencies of n, then append n to result
+ map(visit, elems[n])
+ result.append(n)
+
+ map(visit, elems)
+
+ return result
+
class UpdateableStr(local):
""" Class that stores an updateable string (used in wizards)
'fa_IR': u'Persian / فارس',
'fi_FI': u'Finnish / Suomi',
'fr_BE': u'French (BE) / Français (BE)',
+ 'fr_CA': u'French (CA) / Français (CA)',
'fr_CH': u'French (CH) / Français (CH)',
'fr_FR': u'French / Français',
'gl_ES': u'Galician / Galego',
return self._value
-def dumpstacks(sig, frame):
+def dumpstacks(sig=None, frame=None):
""" Signal handler: dump a stack trace for each existing thread."""
code = []
_logger.info("\n".join(code))
-
+class frozendict(dict):
+ """ An implementation of an immutable dictionary. """
+ def __delitem__(self, key):
+ raise NotImplementedError("'__delitem__' not supported on frozendict")
+ def __setitem__(self, key, val):
+ raise NotImplementedError("'__setitem__' not supported on frozendict")
+ def clear(self):
+ raise NotImplementedError("'clear' not supported on frozendict")
+ def pop(self, key, default=None):
+ raise NotImplementedError("'pop' not supported on frozendict")
+ def popitem(self):
+ raise NotImplementedError("'popitem' not supported on frozendict")
+ def setdefault(self, key, default=None):
+ raise NotImplementedError("'setdefault' not supported on frozendict")
+ def update(self, *args, **kwargs):
+ raise NotImplementedError("'update' not supported on frozendict")
+
+@contextmanager
+def ignore(*exc):
+ try:
+ yield
+ except exc:
+ pass
+
+# Avoid DeprecationWarning while still remaining compatible with werkzeug pre-0.9
+if parse_version(getattr(werkzeug, '__version__', '0.0')) < parse_version('0.9.0'):
+ def html_escape(text):
+ return werkzeug.utils.escape(text, quote=True)
+else:
+ def html_escape(text):
+ return werkzeug.utils.escape(text)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: