| 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)
|
| +
|
|
|