[IMP] tools.safe_eval_qweb: methods intended to provide more restricted alternatives...
[odoo/odoo.git] / openerp / tools / misc.py
index 47a2ae4..bdbb4d1 100644 (file)
@@ -3,7 +3,7 @@
 #
 #    OpenERP, Open Source Management Solution
 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-#    Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
+#    Copyright (C) 2010-2013 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
@@ -20,7 +20,6 @@
 #
 ##############################################################################
 
-#.apidoc title: Utilities: tools.misc
 
 """
 Miscellaneous tools used by OpenERP.
@@ -36,9 +35,9 @@ import sys
 import threading
 import time
 import zipfile
-from collections import defaultdict
+from collections import defaultdict, Mapping
 from datetime import datetime
-from itertools import islice, izip
+from itertools import islice, izip, groupby
 from lxml import etree
 from which import which
 from threading import local
@@ -139,6 +138,7 @@ def file_open(name, mode="r", subdir='addons', pathinfo=False):
         # Is it below 'addons_path' or 'root_path'?
         name = os.path.normcase(os.path.normpath(name))
         for root in adps + [rtp]:
+            root = os.path.normcase(os.path.normpath(root)) + os.sep
             if name.startswith(root):
                 base = root.rstrip(os.sep)
                 name = name[len(base) + 1:]
@@ -272,18 +272,6 @@ def reverse_enumerate(l):
     """
     return izip(xrange(len(l)-1, -1, -1), reversed(l))
 
-#----------------------------------------------------------
-# SMS
-#----------------------------------------------------------
-# text must be latin-1 encoded
-def sms_send(user, password, api_id, text, to):
-    import urllib
-    url = "http://api.urlsms.com/SendSMS.aspx"
-    #url = "http://196.7.150.220/http/sendmsg"
-    params = urllib.urlencode({'UserID': user, 'Password': password, 'SenderID': api_id, 'MsgText': text, 'RecipientMobileNo':to})
-    urllib.urlopen(url+"?"+params)
-    # FIXME: Use the logger if there is an error
-    return True
 
 class UpdateableStr(local):
     """ Class that stores an updateable string (used in wizards)
@@ -433,6 +421,7 @@ def get_iso_codes(lang):
 
 ALL_LANGUAGES = {
         'ab_RU': u'Abkhazian / аҧсуа',
+        'am_ET': u'Amharic / አምሃርኛ',
         'ar_SY': u'Arabic / الْعَرَبيّة',
         'bg_BG': u'Bulgarian / български език',
         'bs_BS': u'Bosnian / bosanski jezik',
@@ -643,21 +632,6 @@ def icons(*a, **kw):
     global __icons_list
     return [(x, x) for x in __icons_list ]
 
-def extract_zip_file(zip_file, outdirectory):
-    zf = zipfile.ZipFile(zip_file, 'r')
-    out = outdirectory
-    for path in zf.namelist():
-        tgt = os.path.join(out, path)
-        tgtdir = os.path.dirname(tgt)
-        if not os.path.exists(tgtdir):
-            os.makedirs(tgtdir)
-
-        if not tgt.endswith(os.sep):
-            fp = open(tgt, 'wb')
-            fp.write(zf.read(path))
-            fp.close()
-    zf.close()
-
 def detect_ip_addr():
     """Try a very crude method to figure out a valid external
        IP or hostname for the current machine. Don't rely on this
@@ -1074,4 +1048,50 @@ class CountingStream(object):
             raise StopIteration()
         return val
 
+def stripped_sys_argv(*strip_args):
+    """Return sys.argv with some arguments stripped, suitable for reexecution or subprocesses"""
+    strip_args = sorted(set(strip_args) | set(['-s', '--save', '-d', '--database', '-u', '--update', '-i', '--init']))
+    assert all(config.parser.has_option(s) for s in strip_args)
+    takes_value = dict((s, config.parser.get_option(s).takes_value()) for s in strip_args)
+
+    longs, shorts = list(tuple(y) for _, y in groupby(strip_args, lambda x: x.startswith('--')))
+    longs_eq = tuple(l + '=' for l in longs if takes_value[l])
+
+    args = sys.argv[:]
+
+    def strip(args, i):
+        return args[i].startswith(shorts) \
+            or args[i].startswith(longs_eq) or (args[i] in longs) \
+            or (i >= 1 and (args[i - 1] in strip_args) and takes_value[args[i - 1]])
+
+    return [x for i, x in enumerate(args) if not strip(args, i)]
+
+class ConstantMapping(Mapping):
+    """
+    An immutable mapping returning the provided value for every single key.
+
+    Useful for default value to methods
+    """
+    __slots__ = ['_value']
+    def __init__(self, val):
+        self._value = val
+
+    def __len__(self):
+        """
+        defaultdict updates its length for each individually requested key, is
+        that really useful?
+        """
+        return 0
+
+    def __iter__(self):
+        """
+        same as len, defaultdict udpates its iterable keyset with each key
+        requested, is there a point for this?
+        """
+        return iter([])
+
+    def __getitem__(self, item):
+        return self._value
+
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: