Index: third_party/logilab/common/__init__.py |
diff --git a/third_party/logilab/common/__init__.py b/third_party/logilab/common/__init__.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8d063e2cb98a712d32e7d9bf376e95c85ec90897 |
--- /dev/null |
+++ b/third_party/logilab/common/__init__.py |
@@ -0,0 +1,171 @@ |
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
+# |
+# This file is part of logilab-common. |
+# |
+# logilab-common is free software: you can redistribute it and/or modify it under |
+# the terms of the GNU Lesser General Public License as published by the Free |
+# Software Foundation, either version 2.1 of the License, or (at your option) any |
+# later version. |
+# |
+# logilab-common 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 Lesser General Public License for more |
+# details. |
+# |
+# You should have received a copy of the GNU Lesser General Public License along |
+# with logilab-common. If not, see <http://www.gnu.org/licenses/>. |
+"""Logilab common library (aka Logilab's extension to the standard library). |
+ |
+:type STD_BLACKLIST: tuple |
+:var STD_BLACKLIST: directories ignored by default by the functions in |
+ this package which have to recurse into directories |
+ |
+:type IGNORED_EXTENSIONS: tuple |
+:var IGNORED_EXTENSIONS: file extensions that may usually be ignored |
+""" |
+__docformat__ = "restructuredtext en" |
+from logilab.common.__pkginfo__ import version as __version__ |
+ |
+STD_BLACKLIST = ('CVS', '.svn', '.hg', 'debian', 'dist', 'build') |
+ |
+IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~', '.swp', '.orig') |
+ |
+# set this to False if you've mx DateTime installed but you don't want your db |
+# adapter to use it (should be set before you got a connection) |
+USE_MX_DATETIME = True |
+ |
+ |
+class attrdict(dict): |
+ """A dictionary for which keys are also accessible as attributes.""" |
+ def __getattr__(self, attr): |
+ try: |
+ return self[attr] |
+ except KeyError: |
+ raise AttributeError(attr) |
+ |
+class dictattr(dict): |
+ def __init__(self, proxy): |
+ self.__proxy = proxy |
+ |
+ def __getitem__(self, attr): |
+ try: |
+ return getattr(self.__proxy, attr) |
+ except AttributeError: |
+ raise KeyError(attr) |
+ |
+class nullobject(object): |
+ def __repr__(self): |
+ return '<nullobject>' |
+ def __nonzero__(self): |
+ return False |
+ |
+class tempattr(object): |
+ def __init__(self, obj, attr, value): |
+ self.obj = obj |
+ self.attr = attr |
+ self.value = value |
+ |
+ def __enter__(self): |
+ self.oldvalue = getattr(self.obj, self.attr) |
+ setattr(self.obj, self.attr, self.value) |
+ return self.obj |
+ |
+ def __exit__(self, exctype, value, traceback): |
+ setattr(self.obj, self.attr, self.oldvalue) |
+ |
+ |
+ |
+# flatten ----- |
+# XXX move in a specific module and use yield instead |
+# do not mix flatten and translate |
+# |
+# def iterable(obj): |
+# try: iter(obj) |
+# except: return False |
+# return True |
+# |
+# def is_string_like(obj): |
+# try: obj +'' |
+# except (TypeError, ValueError): return False |
+# return True |
+# |
+#def is_scalar(obj): |
+# return is_string_like(obj) or not iterable(obj) |
+# |
+#def flatten(seq): |
+# for item in seq: |
+# if is_scalar(item): |
+# yield item |
+# else: |
+# for subitem in flatten(item): |
+# yield subitem |
+ |
+def flatten(iterable, tr_func=None, results=None): |
+ """Flatten a list of list with any level. |
+ |
+ If tr_func is not None, it should be a one argument function that'll be called |
+ on each final element. |
+ |
+ :rtype: list |
+ |
+ >>> flatten([1, [2, 3]]) |
+ [1, 2, 3] |
+ """ |
+ if results is None: |
+ results = [] |
+ for val in iterable: |
+ if isinstance(val, (list, tuple)): |
+ flatten(val, tr_func, results) |
+ elif tr_func is None: |
+ results.append(val) |
+ else: |
+ results.append(tr_func(val)) |
+ return results |
+ |
+ |
+# XXX is function below still used ? |
+ |
+def make_domains(lists): |
+ """ |
+ Given a list of lists, return a list of domain for each list to produce all |
+ combinations of possibles values. |
+ |
+ :rtype: list |
+ |
+ Example: |
+ |
+ >>> make_domains(['a', 'b'], ['c','d', 'e']) |
+ [['a', 'b', 'a', 'b', 'a', 'b'], ['c', 'c', 'd', 'd', 'e', 'e']] |
+ """ |
+ domains = [] |
+ for iterable in lists: |
+ new_domain = iterable[:] |
+ for i in range(len(domains)): |
+ domains[i] = domains[i]*len(iterable) |
+ if domains: |
+ missing = (len(domains[0]) - len(iterable)) / len(iterable) |
+ i = 0 |
+ for j in range(len(iterable)): |
+ value = iterable[j] |
+ for dummy in range(missing): |
+ new_domain.insert(i, value) |
+ i += 1 |
+ i += 1 |
+ domains.append(new_domain) |
+ return domains |
+ |
+ |
+# private stuff ################################################################ |
+ |
+def _handle_blacklist(blacklist, dirnames, filenames): |
+ """remove files/directories in the black list |
+ |
+ dirnames/filenames are usually from os.walk |
+ """ |
+ for norecurs in blacklist: |
+ if norecurs in dirnames: |
+ dirnames.remove(norecurs) |
+ elif norecurs in filenames: |
+ filenames.remove(norecurs) |
+ |