logilab.common package¶
Subpackages¶
- logilab.common.ureports package
- Submodules
- logilab.common.ureports.docbook_writer module
DocbookWriter
DocbookWriter.begin_format()
DocbookWriter.end_format()
DocbookWriter.visit_link()
DocbookWriter.visit_list()
DocbookWriter.visit_paragraph()
DocbookWriter.visit_section()
DocbookWriter.visit_span()
DocbookWriter.visit_table()
DocbookWriter.visit_text()
DocbookWriter.visit_title()
DocbookWriter.visit_verbatimtext()
- logilab.common.ureports.html_writer module
HTMLWriter
HTMLWriter.begin_format()
HTMLWriter.end_format()
HTMLWriter.handle_attrs()
HTMLWriter.visit_link()
HTMLWriter.visit_list()
HTMLWriter.visit_paragraph()
HTMLWriter.visit_section()
HTMLWriter.visit_span()
HTMLWriter.visit_table()
HTMLWriter.visit_text()
HTMLWriter.visit_title()
HTMLWriter.visit_verbatimtext()
- logilab.common.ureports.nodes module
- logilab.common.ureports.text_writer module
TextWriter
TextWriter.begin_format()
TextWriter.default_table()
TextWriter.field_table()
TextWriter.visit_link()
TextWriter.visit_list()
TextWriter.visit_paragraph()
TextWriter.visit_section()
TextWriter.visit_span()
TextWriter.visit_table()
TextWriter.visit_text()
TextWriter.visit_title()
TextWriter.visit_verbatimtext()
- Module contents
Submodules¶
logilab.common.cache module¶
Cache module, with a least recently used algorithm for the management of the deletion of entries.
- class logilab.common.cache.Cache(size: int = 100)[source]¶
Bases:
dict
A dictionary like cache.
- inv:
len(self._usage) <= self.size len(self.data) <= self.size
- clear() None. Remove all items from D. ¶
- pop(k[, d]) v, remove specified key and return the corresponding value. ¶
If key is not found, d is returned if given, otherwise KeyError is raised
- popitem() (k, v), remove and return some (key, value) pair as a [source]¶
2-tuple; but raise KeyError if D is empty.
logilab.common.changelog module¶
Manipulation of upstream change log files.
The upstream change log files format handled is simpler than the one often used such as those generated by the default Emacs changelog mode.
Sample ChangeLog format:
Change log for project Yoo
==========================
--
* add a new functionality
2002-02-01 -- 0.1.1
* fix bug #435454
* fix bug #434356
2002-01-01 -- 0.1
* initial release
There is 3 entries in this change log, one for each released version and one for the next version (i.e. the current entry). Each entry contains a set of messages corresponding to changes done in this release. All the non empty lines before the first entry are considered as the change log title.
- class logilab.common.changelog.ChangeLog(changelog_file: str, title: str = '')[source]¶
Bases:
object
object representation of a whole ChangeLog file
- add_entry(entry: ChangeLogEntry) None [source]¶
add a new entry to the change log
- entry_class¶
alias of
ChangeLogEntry
- class logilab.common.changelog.ChangeLogEntry(date: Optional[str] = None, version: Optional[str] = None, **kwargs: Any)[source]¶
Bases:
object
a change log entry, i.e. a set of messages associated to a version and its release date
- exception logilab.common.changelog.EntryNotFound[source]¶
Bases:
Exception
raised when we are unable to find a given entry
logilab.common.clcommands module¶
Helper functions to support command line tools providing more than one command.
e.g called as “tool command [options] args…” where <options> and <args> are command’specific
- exception logilab.common.clcommands.BadCommandUsage[source]¶
Bases:
Exception
Raised when an unknown command is used or when a command is not correctly used (bad options, too much / missing arguments…).
Trigger display of command usage.
- class logilab.common.clcommands.Command(logger)[source]¶
Bases:
Configuration
Base class for command line commands.
Class attributes:
name, the name of the command
min_args, minimum number of arguments, None if unspecified
max_args, maximum number of arguments, None if unspecified
arguments, string describing arguments, used in command usage
hidden, boolean flag telling if the command should be hidden, e.g. does not appear in help’s commands list
options, options list, as allowed by :mod:configuration
- arguments = ''¶
- main_run(args, rcfile=None)[source]¶
Run the command and return status 0 if everything went fine.
If
CommandError
is raised by the underlying command, simply log the error and return status 2.Any other exceptions, including
BadCommandUsage
will be propagated.
- max_args = None¶
- min_args = None¶
- name = ''¶
- exception logilab.common.clcommands.CommandError[source]¶
Bases:
Exception
Raised when a command can’t be processed and we want to display it and exit, without traceback nor usage displayed.
- class logilab.common.clcommands.CommandLine(pgm=None, doc=None, copyright=None, version=None, rcfile=None, logthreshold=40, check_duplicated_command=True)[source]¶
Bases:
dict
Usage:
>>> LDI = cli.CommandLine('ldi', doc='Logilab debian installer', version=version, rcfile=RCFILE) >>> LDI.register(MyCommandClass) >>> LDI.register(MyOtherCommandClass) >>> LDI.run(sys.argv[1:])
Arguments:
pgm, the program name, default to basename(sys.argv[0])
doc, a short description of the command line tool
copyright, additional doc string that will be appended to the generated doc
version, version number of string of the tool. If specified, global –version option will be available.
rcfile, path to a configuration file. If specified, global –C/–rc-file option will be available? self.rcfile = rcfile
logger, logger to propagate to commands, default to logging.getLogger(self.pgm))
- run(args)[source]¶
main command line access point: * init logging * handle global options (-h/–help, –version, -C/–rc-file) * check command * run command
Terminate by
SystemExit
logilab.common.compat module¶
Wrappers around some builtins introduced in python 2.3, 2.4 and 2.5, making them available in for earlier versions of python.
See another compatibility snippets from other projects:
lib2to3.fixes
coverage.backward
unittest2.compatibility
logilab.common.configuration module¶
Classes to handle advanced configuration in simple to complex applications.
Allows to load the configuration from a file or from command line options, to generate a sample configuration file or to display program’s usage. Fills the gap between optik/optparse and ConfigParser by adding data types (which are also available as a standalone optik extension in the optik_ext module).
Quick start: simplest usage¶
- class logilab.common.configuration.Configuration(config_file=None, options=None, name=None, usage=None, doc=None, version=None)[source]¶
Bases:
ConfigurationMixIn
class for simple configurations which don’t need the manager / providers model and prefer delegation to inheritance
configuration values are accessible through a dict like interface
- class logilab.common.configuration.ConfigurationMixIn(*args: Any, **kwargs: Any)[source]¶
Bases:
OptionsManagerMixIn
,OptionsProviderMixIn
basic mixin for simple configurations which don’t need the manager / providers model
- class logilab.common.configuration.OptionsManager2ConfigurationAdapter(provider)[source]¶
Bases:
object
Adapt an option manager to behave like a logilab.common.configuration.Configuration instance
- class logilab.common.configuration.OptionsManagerMixIn(usage: Optional[str], config_file: Optional[Any] = None, version: Optional[Any] = None, quiet: int = 0)[source]¶
Bases:
object
MixIn to handle a configuration from both a configuration file and command line options
- add_help_section(title: str, description: str, level: int = 0) None [source]¶
add a dummy option section for help purpose
- add_optik_option(provider: ConfigurationMixIn, optikcontainer: Union[OptionParser, OptionGroup], opt: str, optdict: Dict[str, Any]) None [source]¶
- add_option_group(group_name: str, doc: Optional[str], options: Union[List[Tuple[str, Dict[str, Any]]], List[Tuple[str, Dict[str, str]]]], provider: ConfigurationMixIn) None [source]¶
add an option group including the listed options
- cb_set_provider_option(option: Option, opt: str, value: Union[List[str], int, str], parser: OptionParser) None [source]¶
optik callback for option setting
- generate_config(stream: Optional[Union[StringIO, TextIOWrapper]] = None, skipsections: Tuple[()] = (), encoding: Optional[Any] = None, header_message: Optional[str] = None) None [source]¶
write a configuration file according to the current configuration into the given stream or stdout
- generate_manpage(pkginfo: attrdict, section: int = 1, stream: Optional[StringIO] = None) None [source]¶
write a man page for the current configuration into the given stream or stdout
- global_set_option(opt: str, value: Union[List[str], int, str]) None [source]¶
set option on the correct option provider
- input_config(onlysection=None, inputlevel=0, stream=None)[source]¶
interactively get configuration values by asking to the user and generate a configuration file
- load_command_line_configuration(args: Optional[List[str]] = None) List[str] [source]¶
override configuration according to command line parameters
return additional arguments
- load_config_file() None [source]¶
dispatch values previously read from a configuration file to each options provider)
- load_configuration(**kwargs: Any) None [source]¶
override configuration according to given parameters
- load_file_configuration(config_file: Optional[str] = None) None [source]¶
load the configuration from file
- optik_option(provider: ConfigurationMixIn, opt: str, optdict: Dict[str, Any]) Tuple[List[str], Dict[str, Any]] [source]¶
get our personal option definition and return a suitable form for use with optik/optparse
- read_config_file(config_file: Optional[str] = None) None [source]¶
read the configuration file but do not load it (i.e. dispatching values to each options provider)
- register_options_provider(provider: ConfigurationMixIn, own_group: bool = True) None [source]¶
register an options provider
- class logilab.common.configuration.OptionsProviderMixIn[source]¶
Bases:
object
Mixin to provide options to an OptionsManager
- all_options()[source]¶
return an iterator on available options for this provider option are actually described by a 3-uple: (section, option name, option dictionary)
- level = 0¶
- name = 'default'¶
- options_by_section() Iterator[Any] [source]¶
return an iterator on options grouped by section
(section, [list of (optname, optdict, optvalue)])
- priority = -1¶
logilab.common.daemon module¶
A daemonize function (for Unices)
logilab.common.date module¶
Date manipulation helper functions.
- logilab.common.date.add_days_worked(start: date, days: int) date [source]¶
adds date but try to only take days worked into account
- logilab.common.date.date_range(begin: date, end: date, incday: Optional[Any] = None, incmonth: Optional[bool] = None) Generator[date, Any, None] [source]¶
yields each date between begin and end
- Parameters:
begin – the start date
end – the end date
incr – the step to use to iterate over dates. Default is one day.
include – None (means no exclusion) or a function taking a date as parameter, and returning True if the date should be included.
When using mx datetime, you should NOT use incmonth argument, use instead oneDay, oneHour, oneMinute, oneSecond, oneWeek or endOfMonth (to enumerate months) as incday argument
- logilab.common.date.datefactory(year: int, month: int, day: int, sampledate: Union[date, datetime]) Union[date, datetime] [source]¶
- logilab.common.date.datetime_to_seconds(date)[source]¶
return the number of seconds since the begining of the day for that date
- logilab.common.date.days_between(start: Union[date, datetime], end: Union[date, datetime]) int [source]¶
- logilab.common.date.get_national_holidays(begin: Union[date, datetime], end: Union[date, datetime]) Union[List[date], List[datetime]] [source]¶
return french national days off between begin and end
- logilab.common.date.nb_open_days(start: Union[date, datetime], end: Union[date, datetime]) int [source]¶
- logilab.common.date.str2date(datestr: str, sampledate: Union[date, datetime]) Union[date, datetime] [source]¶
- logilab.common.date.timedelta_to_seconds(delta)[source]¶
return the time delta as a fraction of days
- logilab.common.date.todate(somedate: date) date [source]¶
return a date from a date (leaving unchanged) or a datetime
- logilab.common.date.todatetime(somedate)[source]¶
return a date from a date (leaving unchanged) or a datetime
- logilab.common.date.totime(somedate)[source]¶
return a time from a time (leaving unchanged), date or datetime
logilab.common.debugger module¶
Customized version of pdb’s default debugger.
sets up a history file
uses ipython if available to colorize lines of code
overrides list command to search for current block instead of using 5 lines of context
- class logilab.common.debugger.Debugger(tcbk=None)[source]¶
Bases:
Pdb
custom debugger
sets up a history file
uses ipython if available to colorize lines of code
overrides list command to search for current block instead of using 5 lines of context
- attr_matches(text, namespace)[source]¶
implementation coming from rlcompleter.Completer.attr_matches Compute matches when text contains a dot.
Assuming the text is of the form NAME.NAME….[NAME], and is evaluatable in self.namespace, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. (For class instances, class members are also considered.)
WARNING: this can still invoke arbitrary C code, if an object with a __getattr__ hook is evaluated.
- complete_p(text, line, begin_idx, end_idx)[source]¶
provide variable names completion for the
p
command
- do_l(arg)¶
overrides default list command to display the surrounding block instead of 5 lines of context
- do_list(arg)[source]¶
overrides default list command to display the surrounding block instead of 5 lines of context
- do_o(arg)¶
opens source file corresponding to the current stack level
- logilab.common.debugger.colorize(source, start_lineno, curlineno)[source]¶
fallback colorize function
logilab.common.decorators module¶
A few useful function/method decorators.
- logilab.common.decorators.cached(callableobj: None = None, keyarg: Optional[int] = None, **kwargs: Any) Callable[[_T], _T] [source]¶
- logilab.common.decorators.cached(callableobj: _T = None, keyarg: Optional[int] = None, **kwargs: Any) _T
Simple decorator to cache result of method call.
- class logilab.common.decorators.cached_decorator(cacheattr: Optional[str] = None, keyarg: Optional[int] = None)[source]¶
Bases:
object
- class logilab.common.decorators.classproperty(get)[source]¶
Bases:
object
this is a simple property-like class but for class attributes.
- logilab.common.decorators.clear_cache(obj, funcname)[source]¶
Clear a cache handled by the
cached()
decorator. If ‘x’ class has @cached on its method foo, type>>> clear_cache(x, 'foo')
to purge this method’s cache on the instance.
- logilab.common.decorators.copy_cache(obj, funcname, cacheobj)[source]¶
Copy cache for <funcname> from cacheobj to obj.
- class logilab.common.decorators.iclassmethod(func)[source]¶
Bases:
object
Descriptor for method which should be available as class method if called on the class or instance method if called on an instance.
- logilab.common.decorators.locked(acquire, release)[source]¶
Decorator taking two methods to acquire/release a lock as argument, returning a decorator function which will call the inner method after having called acquire(self) et will call release(self) afterwards.
- logilab.common.decorators.monkeypatch(klass: type, methodname: Optional[str] = None) Callable [source]¶
Decorator extending class with the decorated callable. This is basically a syntactic sugar vs class assignment.
>>> class A: ... pass >>> @monkeypatch(A) ... def meth(self): ... return 12 ... >>> a = A() >>> a.meth() 12 >>> @monkeypatch(A, 'foo') ... def meth(self): ... return 12 ... >>> a.foo() 12
logilab.common.deprecation module¶
Deprecation utilities.
- class logilab.common.deprecation.DeprecationWarningKind(value)[source]¶
Bases:
Enum
An enumeration.
- ARGUMENT = 'argument'¶
- ATTRIBUTE = 'attribute'¶
- CALLABLE = 'callable'¶
- CLASS = 'class'¶
- MODULE = 'module'¶
- class logilab.common.deprecation.DeprecationWarningOperation(value)[source]¶
Bases:
Enum
An enumeration.
- DEPRECATED = 'deprecated'¶
- MOVED = 'moved'¶
- REMOVED = 'removed'¶
- RENAMED = 'renamed'¶
- class logilab.common.deprecation.DeprecationWrapper(proxied: Any, msg: Optional[str] = None, version: Optional[str] = None)[source]¶
Bases:
object
proxy to print a warning on access to any attribute of the wrapped object
- class logilab.common.deprecation.FakeDistribution(*args, **kwargs)[source]¶
Bases:
Distribution
see https://github.com/python/importlib_metadata/blob/main/CHANGES.rst#v600
- exception logilab.common.deprecation.StructuredDeprecationWarning(reason: str, package: Optional[str] = None, version: Optional[str] = None)[source]¶
Bases:
DeprecationWarning
Base class for all structured DeprecationWarning Mostly used with isinstance
- exception logilab.common.deprecation.TargetDeprecatedDeprecationWarning(reason: str, kind: DeprecationWarningKind, package: Optional[str] = None, version: Optional[str] = None)[source]¶
Bases:
StructuredDeprecationWarning
- exception logilab.common.deprecation.TargetMovedDeprecationWarning(reason: str, kind: DeprecationWarningKind, old_name: str, new_name: str, old_module: str, new_module: str, package: Optional[str] = None, version: Optional[str] = None)[source]¶
Bases:
StructuredDeprecationWarning
- exception logilab.common.deprecation.TargetRemovedDeprecationWarning(reason: str, kind: DeprecationWarningKind, name: str, package: Optional[str] = None, version: Optional[str] = None)[source]¶
Bases:
StructuredDeprecationWarning
- exception logilab.common.deprecation.TargetRenamedDeprecationWarning(reason: str, kind: DeprecationWarningKind, old_name: str, new_name: str, package: Optional[str] = None, version: Optional[str] = None)[source]¶
Bases:
StructuredDeprecationWarning
- logilab.common.deprecation.argument_removed(old_argument_name: str, version: Optional[str] = None) Callable [source]¶
callable decorator to allow getting backward compatibility for renamed keyword arguments.
>>> @argument_removed("old") ... def some_function(new): ... return new >>> some_function(old=42) sample.py:15: DeprecationWarning: argument old of callable some_function has been renamed and is deprecated, use keyword argument new instead some_function(old=42) 42
- logilab.common.deprecation.argument_renamed(old_name: str, new_name: str, version: Optional[str] = None) Callable [source]¶
callable decorator to allow getting backward compatibility for renamed keyword arguments.
>>> @argument_renamed(old_name="old", new_name="new") ... def some_function(new): ... return new >>> some_function(old=42) sample.py:15: DeprecationWarning: argument old of callable some_function has been renamed and is deprecated, use keyword argument new instead some_function(old=42) 42
- logilab.common.deprecation.attribute_renamed(old_name: str, new_name: str, version: Optional[str] = None) Callable [source]¶
class decorator to allow getting backward compatibility for renamed attributes.
>>> @attribute_renamed(old_name="old", new_name="new") ... class SomeClass: ... def __init__(self): ... self.new = 42
>>> some_class = SomeClass() >>> print(some_class.old) sample.py:15: DeprecationWarning: SomeClass.old has been renamed and is deprecated, use SomeClass.new instead print(some_class.old) 42 >>> some_class.old = 43 sample.py:16: DeprecationWarning: SomeClass.old has been renamed and is deprecated, use SomeClass.new instead some_class.old = 43 >>> some_class.old == some_class.new True
- logilab.common.deprecation.callable_deprecated(reason: Optional[str] = None, version: Optional[str] = None, stacklevel: int = 2) Callable [source]¶
Display a deprecation message only if the version is older than the compatible version.
- logilab.common.deprecation.callable_moved(module_name: str, object_name: str, version: Optional[str] = None, stacklevel: int = 2, new_name: Optional[str] = None) Callable [source]¶
use to tell that a callable has been moved to a new module.
It returns a callable wrapper, so that when its called a warning is printed telling where the object can be found, import is done (and not before) and the actual object is called.
NOTE: the usage is somewhat limited on classes since it will fail if the wrapper is use in a class ancestors list, use the class_moved function instead (which has no lazy import feature though).
- logilab.common.deprecation.callable_renamed(old_name: str, new_function: Callable, version: Optional[str] = None) Callable [source]¶
use to tell that a callable has been renamed.
It returns a callable wrapper, so that when its called a warning is printed telling what is the object new name.
>>> old_function = renamed('old_function', new_function) >>> old_function() sample.py:57: DeprecationWarning: old_function has been renamed and is deprecated, uses new_function instead old_function() >>>
- logilab.common.deprecation.class_deprecated¶
alias of
_class_deprecated
- logilab.common.deprecation.class_moved(new_class: type, old_name: Optional[str] = None, message: Optional[str] = None, version: Optional[str] = None) type [source]¶
nice wrapper around class_renamed when a class has been moved into another module
- logilab.common.deprecation.class_renamed(old_name: str, new_class: type, message: ~typing.Optional[str] = None, version: ~typing.Optional[str] = None, module_name: ~typing.Optional[str] = None, deprecated_warning_class=<class 'logilab.common.deprecation.TargetRenamedDeprecationWarning'>, deprecated_warning_kwargs=None) type [source]¶
automatically creates a class which fires a DeprecationWarning when instantiated.
>>> Set = class_renamed('Set', set, 'Set is now replaced by set') >>> s = Set() sample.py:57: DeprecationWarning: Set is now replaced by set s = Set() >>>
- logilab.common.deprecation.lazy_wraps(wrapped: Callable) Callable [source]¶
This is the equivalent of the @wraps decorator of functools except it won’t try to grabs attributes of the targeted function on decoration but on access.
This is needed because of logilab.common.modutils.LazyObject.
Indeed: if you try to decorate a LazyObject with @wraps, wraps will try to access attributes of LazyObject and this will trigger the attempt to import the module decorated by LazyObject which you don’t want to do when you just want to mark this LazyObject has been a deprecated objet that you only wants to trigger if the user try to use it.
Usage: like @wraps()
>>> @lazy_wraps(function) >>> def wrapper(*args, **kwargs): ...
- logilab.common.deprecation.send_warning(reason: str, deprecation_class: Type[DeprecationWarning], deprecation_class_kwargs: Dict[str, Any], version: Optional[str] = None, stacklevel: int = 2, module_name: Optional[str] = None) None [source]¶
Display a deprecation message only if the version is older than the compatible version.
logilab.common.fileutils module¶
File and file-path manipulation utilities.
- group path manipulation:
first_level_directory, relative_path, is_binary,get_by_ext, remove_dead_links
- group file manipulation:
norm_read, norm_open, lines, stream_lines, lines,write_open_mode, ensure_fs_mode, export
- sort:
path manipulation, file manipulation
- class logilab.common.fileutils.ProtectedFile(filepath: str, mode: str)[source]¶
Bases:
FileIO
A special file-object class that automatically does a ‘chmod +w’ when needed.
XXX: for now, the way it is done allows ‘normal file-objects’ to be created during the ProtectedFile object lifetime. One way to circumvent this would be to chmod / unchmod on each write operation.
One other way would be to :
catch the IOError in the __init__
if IOError, then create a StringIO object
each write operation writes in this StringIO object
on close()/del(), write/append the StringIO content to the file and do the chmod only once
- exception logilab.common.fileutils.UnresolvableError[source]¶
Bases:
Exception
Exception raised by relative path when it’s unable to compute relative path between two paths.
- logilab.common.fileutils.ensure_fs_mode(filepath, desired_mode=128)[source]¶
Check that the given file has the given mode(s) set, else try to set it.
- logilab.common.fileutils.export(from_dir: str, to_dir: str, blacklist: Tuple[str, str, str, str, str, str, str, str] = ('CVS', '.svn', '.hg', '.git', '.tox', 'debian', 'dist', 'build'), ignore_ext: Tuple[str, str, str, str, str, str] = ('.pyc', '.pyo', '.elc', '~', '.swp', '.orig'), verbose: int = 0) None [source]¶
Make a mirror of from_dir in to_dir, omitting directories and files listed in the black list or ending with one of the given extensions.
- Parameters:
from_dir (str) – directory to export
to_dir (str) – destination directory
blacklist (list or tuple) – list of files or directories to ignore, default to the content of BASE_BLACKLIST
ignore_ext (list or tuple) – list of extensions to ignore, default to the content of IGNORED_EXTENSIONS
verbose (bool) – flag indicating whether information about exported files should be printed to stderr, default to False
- logilab.common.fileutils.first_level_directory(path: str) str [source]¶
Return the first level directory of a path.
>>> first_level_directory('home/syt/work') 'home' >>> first_level_directory('/home/syt/work') '/' >>> first_level_directory('work') 'work' >>>
- logilab.common.fileutils.is_binary(filename: str) int [source]¶
Return true if filename may be a binary file, according to it’s extension.
- logilab.common.fileutils.lines(path: str, comments: Optional[str] = None) List[str] [source]¶
Return a list of non empty lines in the file located at path.
- Parameters:
- Return type:
- Returns:
a list of stripped line in the file, without empty and commented lines
- Warning:
at some point this function will probably return an iterator
- logilab.common.fileutils.relative_path(from_file, to_file)[source]¶
Try to get a relative path from from_file to to_file (path will be absolute if to_file is an absolute file). This function is useful to create link in from_file to to_file. This typical use case is used in this function description.
If both files are relative, they’re expected to be relative to the same directory.
>>> relative_path( from_file='toto/index.html', to_file='index.html') '../index.html' >>> relative_path( from_file='index.html', to_file='toto/index.html') 'toto/index.html' >>> relative_path( from_file='tutu/index.html', to_file='toto/index.html') '../toto/index.html' >>> relative_path( from_file='toto/index.html', to_file='/index.html') '/index.html' >>> relative_path( from_file='/toto/index.html', to_file='/index.html') '../index.html' >>> relative_path( from_file='/toto/index.html', to_file='/toto/summary.html') 'summary.html' >>> relative_path( from_file='index.html', to_file='index.html') '' >>> relative_path( from_file='/index.html', to_file='toto/index.html') Traceback (most recent call last): File "<string>", line 1, in ? File "<stdin>", line 37, in relative_path UnresolvableError >>> relative_path( from_file='/index.html', to_file='/index.html') '' >>>
- Parameters:
- Raises:
UnresolvableError – if it has been unable to guess a correct path
- Return type:
- Returns:
the relative path of to_file from from_file
- logilab.common.fileutils.remove_dead_links(directory, verbose=0)[source]¶
Recursively traverse directory and remove all dead links.
- logilab.common.fileutils.stream_lines(stream: TextIOWrapper, comments: Optional[str] = None) List[str] [source]¶
Return a list of non empty lines in the given stream.
- Parameters:
stream (object implementing 'xreadlines' or 'readlines') – file like object
comments (str or None) – optional string which can be used to comment a line in the file (i.e. lines starting with this string won’t be returned)
- Return type:
- Returns:
a list of stripped line in the file, without empty and commented lines
- Warning:
at some point this function will probably return an iterator
logilab.common.graph module¶
Graph manipulation utilities.
(dot generation adapted from pypy/translator/tool/make_dot.py)
- class logilab.common.graph.DotBackend(graphname, rankdir=None, size=None, ratio=None, charset='utf-8', renderer='dot', additionnal_param={})[source]¶
Bases:
object
Dot File backend.
- emit_edge(name1, name2, **props)[source]¶
emit an edge from <name1> to <name2>. edge properties: see http://www.graphviz.org/doc/info/attrs.html
- emit_node(name, **props)[source]¶
emit a node with given properties. node properties: see http://www.graphviz.org/doc/info/attrs.html
- generate(outputfile=None, dotfile=None, mapfile=None)[source]¶
Generates a graph file.
- Parameters:
outputfile – filename and path [defaults to graphname.png]
dotfile – filename and path [defaults to graphname.dot]
- Return type:
- Returns:
a path to the generated file
- property source¶
returns self._source
- logilab.common.graph.get_cycles(graph_dict: Dict[V, List[V]], vertices: Optional[Iterable] = None) List[List] [source]¶
given a dictionary representing an ordered graph (i.e. key are vertices and values is a list of destination vertices representing edges), return a list of detected cycles
- logilab.common.graph.has_path(graph_dict: Dict[str, List[str]], fromnode: str, tonode: str, path: Optional[List[str]] = None) Optional[List[str]] [source]¶
generic function taking a simple graph definition as a dictionary, with node has key associated to a list of nodes directly reachable from it.
Return None if no path exists to go from fromnode to tonode, else the first path found (as a list including the destination node at last)
- logilab.common.graph.ordered_nodes(graph: Dict[V, List[V]]) Tuple[V, ...] [source]¶
takes a dependency graph dict as arguments and return an ordered tuple of nodes starting with nodes without dependencies and up to the outermost node.
If there is some cycle in the graph,
UnorderableGraph
will be raised.Also the given graph dict will be emptied.
logilab.common.interface module¶
Bases class for interfaces to provide ‘light’ interface handling.
- TODO:
_ implements a check method which check that an object implements the interface _ Attribute objects
This module requires at least python 2.2
logilab.common.logging_ext module¶
Extends the logging module from the standard library.
- class logilab.common.logging_ext.ColorFormatter(fmt=None, datefmt=None, colors=None)[source]¶
Bases:
Formatter
A color Formatter for the logging standard module.
By default, colorize CRITICAL and ERROR in red, WARNING in orange, INFO in green and DEBUG in yellow.
self.colors is customizable via the ‘color’ constructor argument (dictionary).
self.colorfilters is a list of functions that get the LogRecord and return a color name or None.
- format(record)[source]¶
Format the specified record as text.
The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.
- logilab.common.logging_ext.get_formatter(logformat='%(asctime)s - (%(name)s) %(levelname)s: %(message)s', logdateformat='%Y-%m-%d %H:%M:%S')[source]¶
- logilab.common.logging_ext.get_handler(debug=False, syslog=False, logfile=None, rotation_parameters=None)[source]¶
get an apropriate handler according to given parameters
- logilab.common.logging_ext.init_log(debug=False, syslog=False, logthreshold=None, logfile=None, logformat='%(asctime)s - (%(name)s) %(levelname)s: %(message)s', logdateformat='%Y-%m-%d %H:%M:%S', fmt=None, rotation_parameters=None, handler=None)[source]¶
init the log service
- logilab.common.logging_ext.set_color_formatter(logger=None, **kw)[source]¶
Install a color formatter on the ‘logger’. If not given, it will defaults to the default logger.
Any additional keyword will be passed as-is to the ColorFormatter constructor.
logilab.common.modutils module¶
Python modules manipulation utility functions.
- class logilab.common.modutils.LazyObject(module, obj)[source]¶
Bases:
object
This class allows to lazyly declare a object (most likely only a callable according to the code) from a module without importing it.
The import will be triggered when the user tries to access attributes of the object/callable or call it.
Trying to set or delete attributes of the wrapped object/callable will not works as expected.
- logilab.common.modutils.clean_sys_modules(names)[source]¶
remove submodules starting with name from names from sys.modules
- logilab.common.modutils.cleanup_sys_modules(directories)[source]¶
remove submodules of directories from sys.modules
- logilab.common.modutils.get_module_files(src_directory: str, blacklist: Sequence[str] = ('CVS', '.svn', '.hg', '.git', '.tox', 'debian', 'dist', 'build')) List[str] [source]¶
given a package directory return a list of all available python module’s files in the package and its subpackages
- Parameters:
- Return type:
- Returns:
the list of all available python module’s files in the package and its subpackages
logilab.common.optik_ext module¶
Add an abstraction level to transparently import optik classes from optparse (python >= 2.3) or the optik package.
It also defines three new types for optik/optparse command line parser :
regexp argument of this type will be converted using re.compile
csv argument of this type will be converted using split(‘,’)
yn argument of this type will be true if ‘y’ or ‘yes’, false if ‘n’ or ‘no’
named argument of this type are in the form <NAME>=<VALUE> or <NAME>:<VALUE>
password argument of this type wont be converted but this is used by other tools such as interactive prompt for configuration to double check value and use an invisible field
multiple_choice same as default “choice” type but multiple choices allowed
file argument of this type wont be converted but checked that the given file exists
color argument of this type wont be converted but checked its either a named color or a color specified using hexadecimal notation (preceded by a #)
time argument of this type will be converted to a float value in seconds according to time units (ms, s, min, h, d)
bytes argument of this type will be converted to a float value in bytes according to byte units (b, kb, mb, gb, tb)
- class logilab.common.optik_ext.Option(*opts: str, **attrs: Any)[source]¶
Bases:
Option
override optik.Option to add some new option types
- ATTRS = ['action', 'type', 'dest', 'default', 'nargs', 'const', 'choices', 'callback', 'callback_args', 'callback_kwargs', 'help', 'metavar', 'hide', 'level']¶
- TYPES = ('string', 'int', 'long', 'float', 'complex', 'choice', 'regexp', 'csv', 'yn', 'named', 'password', 'multiple_choice', 'file', 'color', 'time', 'bytes')¶
- TYPE_CHECKER = {'bytes': <function check_bytes>, 'choice': <function check_choice>, 'color': <function check_color>, 'complex': <function check_builtin>, 'csv': <function check_csv>, 'file': <function check_file>, 'float': <function check_builtin>, 'int': <function check_builtin>, 'long': <function check_builtin>, 'multiple_choice': <function check_csv>, 'named': <function check_named>, 'password': <function check_password>, 'regexp': <function check_regexp>, 'time': <function check_time>, 'yn': <function check_yn>}¶
- class logilab.common.optik_ext.OptionGroup(parser, title, description=None)[source]¶
Bases:
OptionContainer
- level = 0¶
- class logilab.common.optik_ext.OptionParser(option_class: type = <class 'logilab.common.optik_ext.Option'>, *args: ~typing.Any, **kwargs: ~typing.Any)[source]¶
Bases:
OptionParser
override optik.OptionParser to use our Option class
logilab.common.optparser module¶
logilab.common.proc module¶
module providing: * process information (linux specific: rely on /proc) * a class for resource control (memory / time / cpu time)
This module doesn’t work on windows platforms (only tested on linux)
- organization:
Logilab
- exception logilab.common.proc.LineageMemoryError[source]¶
Bases:
ResourceError
Error raised when the total amount of memory used by a process and it’s child is reached
- limit = 'Lineage total Memory'¶
- class logilab.common.proc.MemorySentinel(interval, memory_limit, gpid=None)[source]¶
Bases:
Thread
A class checking a process don’t use too much memory in a separated daemonic thread
- class logilab.common.proc.ProcInfo(pid)[source]¶
Bases:
Node
provide access to process information found in /proc
- class logilab.common.proc.ResourceController(max_cpu_time=None, max_time=None, max_memory=None, max_reprieve=60)[source]¶
Bases:
object
- exception logilab.common.proc.ResourceError[source]¶
Bases:
Exception
Error raise when resource limit is reached
- limit = 'Unknown Resource Limit'¶
- exception logilab.common.proc.TimeoutError[source]¶
Bases:
ResourceError
Error raised when the process is running for to much time
- limit = 'Real Time'¶
- exception logilab.common.proc.XCPUError[source]¶
Bases:
ResourceError
Error raised when CPU Time limit is reached
- limit = 'CPU Time'¶
logilab.common.pytest module¶
logilab.common.registry module¶
This module provides bases for predicates dispatching (the pattern in use here is similar to what’s refered as multi-dispatch or predicate-dispatch in the literature, though a bit different since the idea is to select across different implementation ‘e.g. classes), not to dispatch a message to a function or method. It contains the following classes:
RegistryStore
, the top level object which loads implementation objects and stores them into registries. You’ll usually use it to access registries and their contained objects;Registry
, the base class which contains objects semantically grouped (for instance, sharing a same API, hence the ‘implementation’ name). You’ll use it to select the proper implementation according to a context. Notice you may use registries on their own without using the store.
Note
implementation objects are usually designed to be accessed through the registry and not by direct instantiation, besides to use it as base classe.
The selection procedure is delegated to a selector, which is responsible for scoring the object according to some context. At the end of the selection, if an implementation has been found, an instance of this class is returned. A selector is built from one or more predicates combined together using AND, OR, NOT operators (actually &, | and ~). You’ll thus find some base classes to build predicates:
Predicate
, the abstract base predicate classAndPredicate
,OrPredicate
,NotPredicate
, which you shouldn’t have to use directly. You’ll use &, | and ‘~’ operators between predicates directly
You’ll eventually find one concrete predicate: yes
- class logilab.common.registry.RegistryStore(debugmode: bool = False)[source]¶
This class is responsible for loading objects and storing them in their registry which is created on the fly as needed.
It handles dynamic registration of objects and provides a convenient api to access them. To be recognized as an object that should be stored into one of the store’s registry (
Registry
), an object must provide the following attributes, used control how they interact with the registry:__registries__
list of registry names (string like ‘views’, ‘templates’…) into which the object should be registered
__regid__
object identifier in the registry (string like ‘main’, ‘primary’, ‘folder_box’)
__select__
the object predicate selectors
Moreover, the
__abstract__
attribute may be set to True to indicate that an object is abstract and should not be registered (such inherited attributes not considered).Note
When using the store to load objects dynamically, you always have to use super() to get the methods and attributes of the superclasses, and not use the class identifier. If not, you’ll get into trouble at reload time.
For example, instead of writing:
class Thing(Parent): __regid__ = 'athing' __select__ = yes() def f(self, arg1): Parent.f(self, arg1)
You must write:
class Thing(Parent): __regid__ = 'athing' __select__ = yes() def f(self, arg1): super(Thing, self).f(arg1)
Controlling object registration¶
Dynamic loading is triggered by calling the
register_modnames()
method, given a list of modules names to inspect.For each module, by default, all compatible objects are registered automatically. However if some objects come as replacement of other objects, or have to be included only if some condition is met, you’ll have to define a registration_callback(vreg) function in the module and explicitly register all objects in this module, using the api defined below.
- register_all(objects: Iterable, modname: str, butclasses: Sequence = ()) None [source]¶
register registrable objects into objects.
Registrable objects are properly configured subclasses of
RegistrableObject
. Objects which are not defined in the module modname or which are in butclasses won’t be registered.Typical usage is:
store.register_all(globals().values(), __name__, (ClassIWantToRegisterExplicitly,))
So you get partially automatic registration, keeping manual registration for some object (to use
register_and_replace()
for instance).
- register_and_replace(obj, replaced, registryname=None)[source]¶
register obj object into registryname or obj.__registries__ if not specified. If found, the replaced object will be unregistered first (else a warning will be issued as it is generally unexpected).
- register(obj: Any, registryname: Optional[Any] = None, oid: Optional[Any] = None, clear: bool = False) None [source]¶
register obj implementation into registryname or obj.__registries__ if not specified, with identifier oid or obj.__regid__ if not specified.
If clear is true, all objects with the same identifier will be previously unregistered.
- unregister(obj, registryname=None)[source]¶
unregister obj object from the registry registryname or obj.__registries__ if not specified.
Note
Once the function registration_callback(vreg) is implemented in a module, all the objects from this module have to be explicitly registered as it disables the automatic object registration.
Examples:
def registration_callback(store): # register everything in the module except BabarClass store.register_all(globals().values(), __name__, (BabarClass,)) # conditionally register BabarClass if 'babar_relation' in store.schema: store.register(BabarClass)
In this example, we register all application object classes defined in the module except BabarClass. This class is then registered only if the ‘babar_relation’ relation type is defined in the instance schema.
def registration_callback(store): store.register(Elephant) # replace Babar by Celeste store.register_and_replace(Celeste, Babar)
In this example, we explicitly register classes one by one:
the Elephant class
the Celeste to replace Babar
If at some point we register a new appobject class in this module, it won’t be registered at all without modification to the registration_callback implementation. The first example will register it though, thanks to the call to the register_all method.
Controlling registry instantiation¶
The REGISTRY_FACTORY class dictionary allows to specify which class should be instantiated for a given registry name. The class associated to None key will be the class used when there is no specific class for a name.
- class logilab.common.registry.Registry(debugmode: bool)[source]¶
The registry store a set of implementations associated to identifier:
to each identifier are associated a list of implementations
to select an implementation of a given identifier, you should use one of the
select()
orselect_or_none()
methodto select a list of implementations for a context, you should use the
possible_objects()
methoddictionary like access to an identifier will return the bare list of implementations for this identifier.
To be usable in a registry, the only requirement is to have a __select__ attribute.
At the end of the registration process, the
__registered__()
method is called on each registered object which have them, given the registry in which it’s registered as argument.Registration methods:
- register(obj: Any, oid: Optional[Any] = None, clear: bool = False) None [source]¶
base method to add an object in the registry
Selection methods:
- select(_Registry__oid, *args, **kwargs)[source]¶
return the most specific object among those with the given oid according to the given context.
raise
ObjectNotFound
if there are no object with id oid in this registryraise
NoSelectableObject
if no object can be selected
- select_or_none(_Registry__oid, *args, **kwargs)[source]¶
return the most specific object among those with the given oid according to the given context, or None if no object applies.
- possible_objects(*args, **kwargs)[source]¶
return an iterator on possible objects in this registry for the given context
- object_by_id(oid, *args, **kwargs)[source]¶
return object with the oid identifier. Only one object is expected to be found.
raise
ObjectNotFound
if there are no object with id oid in this registryraise
AssertionError
if there is more than one object there
Predicates¶
- class logilab.common.registry.Predicate[source]¶
base class for selector classes providing implementation for operators
&
,|
and~
This class is only here to give access to binary operators, the selector logic itself should be implemented in the
__call__()
method. Notice it should usually accept any arbitrary arguments (the context), though that may vary depending on your usage of the registry.a selector is called to help choosing the correct object for a particular context by returning a score (int) telling how well the implementation given as first argument fit to the given context.
0 score means that the class doesn’t apply.
- logilab.common.registry.objectify_predicate(selector_func: Callable) Any [source]¶
Most of the time, a simple score function is enough to build a selector. The
objectify_predicate()
decorator turn it into a proper selector class:@objectify_predicate def one(cls, req, rset=None, **kwargs): return 1 class MyView(View): __select__ = View.__select__ & one()
- class logilab.common.registry.yes(score: float = 0.5)[source]¶
Return the score given as parameter, with a default score of 0.5 so any other selector take precedence.
Usually used for objects which can be selected whatever the context, or also sometimes to add arbitrary points to a score.
Take care, yes(0) could be named ‘no’…
Debugging¶
- class logilab.common.registry.traced_selection(traced='all')[source]¶
Typical usage is :
>>> from logilab.common.registry import traced_selection >>> with traced_selection(): ... # some code in which you want to debug selectors ... # for all objects
This will yield lines like this in the logs:
selector one_line_rset returned 0 for <class 'elephant.Babar'>
You can also give to
traced_selection
the identifiers of objects on which you want to debug selection (‘oid1’ and ‘oid2’ in the example above).>>> with traced_selection( ('regid1', 'regid2') ): ... # some code in which you want to debug selectors ... # for objects with __regid__ 'regid1' and 'regid2'
A potentially useful point to set up such a tracing function is the logilab.common.registry.Registry.select method body.
Exceptions¶
- class logilab.common.registry.RegistryNotFound[source]¶
Raised when an unknown registry is requested.
This is usually a programming/typo error.
- class logilab.common.registry.AndPredicate(*selectors: Any)[source]¶
Bases:
MultiPredicate
and-chained selectors
- class logilab.common.registry.MultiPredicate(*selectors: Any)[source]¶
Bases:
Predicate
base class for compound selector classes
- exception logilab.common.registry.NoSelectableObject(args, kwargs, objects)[source]¶
Bases:
RegistryException
Raised when no object is selectable for a given context.
- exception logilab.common.registry.ObjectNotFound[source]¶
Bases:
RegistryException
Raised when an unregistered object is requested.
This may be a programming/typo or a misconfiguration error.
- class logilab.common.registry.OrPredicate(*selectors: Any)[source]¶
Bases:
MultiPredicate
or-chained selectors
- class logilab.common.registry.Predicate[source]¶
Bases:
object
base class for selector classes providing implementation for operators
&
,|
and~
This class is only here to give access to binary operators, the selector logic itself should be implemented in the
__call__()
method. Notice it should usually accept any arbitrary arguments (the context), though that may vary depending on your usage of the registry.a selector is called to help choosing the correct object for a particular context by returning a score (int) telling how well the implementation given as first argument fit to the given context.
0 score means that the class doesn’t apply.
- property func_name¶
- class logilab.common.registry.RegistrableInstance(*args, **kwargs)[source]¶
Bases:
RegistrableObject
Inherit this class if you want instances of the classes to be automatically registered.
- class logilab.common.registry.RegistrableObject[source]¶
Bases:
object
This is the base class for registrable objects which are selected according to a context.
__registry__
name of the registry for this object (string like ‘views’, ‘templates’…). You may want to define __registries__ directly if your object should be registered in several registries.
__regid__
object’s identifier in the registry (string like ‘main’, ‘primary’, ‘folder_box’)
__select__
class’selector
Moreover, the __abstract__ attribute may be set to True to indicate that a class is abstract and should not be registered.
You don’t have to inherit from this class to put it in a registry (having __regid__ and __select__ is enough), though this is needed for classes that should be automatically registered.
- class logilab.common.registry.Registry(debugmode: bool)[source]¶
Bases:
dict
The registry store a set of implementations associated to identifier:
to each identifier are associated a list of implementations
to select an implementation of a given identifier, you should use one of the
select()
orselect_or_none()
methodto select a list of implementations for a context, you should use the
possible_objects()
methoddictionary like access to an identifier will return the bare list of implementations for this identifier.
To be usable in a registry, the only requirement is to have a __select__ attribute.
At the end of the registration process, the
__registered__()
method is called on each registered object which have them, given the registry in which it’s registered as argument.Registration methods:
- register(obj: Any, oid: Optional[Any] = None, clear: bool = False) None [source]¶
base method to add an object in the registry
Selection methods:
- select(_Registry__oid, *args, **kwargs)[source]¶
return the most specific object among those with the given oid according to the given context.
raise
ObjectNotFound
if there are no object with id oid in this registryraise
NoSelectableObject
if no object can be selected
- select_or_none(_Registry__oid, *args, **kwargs)[source]¶
return the most specific object among those with the given oid according to the given context, or None if no object applies.
- possible_objects(*args, **kwargs)[source]¶
return an iterator on possible objects in this registry for the given context
- object_by_id(oid, *args, **kwargs)[source]¶
return object with the oid identifier. Only one object is expected to be found.
raise
ObjectNotFound
if there are no object with id oid in this registryraise
AssertionError
if there is more than one object there
- add_select_best_listener(listener)[source]¶
Add a listener to the list of one parameters callables (function/method) that will be called everytime the selection Registry._select_best is done and they will recieve a dict of the following form:
{"all_objects": [], "end_score": 0, "winners": [], "winner": None or winner, "self": self, "args": args, "kwargs": kwargs, }
- critical(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘CRITICAL’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.critical(“Houston, we have a %s”, “major disaster”, exc_info=1)
- debug(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘DEBUG’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.debug(“Houston, we have a %s”, “thorny problem”, exc_info=1)
- error(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘ERROR’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.error(“Houston, we have a %s”, “major problem”, exc_info=1)
- exception(msg, *args, exc_info=True, **kwargs)¶
Convenience method for logging an ERROR with exception information.
- info(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘INFO’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.info(“Houston, we have a %s”, “interesting problem”, exc_info=1)
- initialization_completed() None [source]¶
call method __registered__() on registered objects when the callback is defined
- object_by_id(oid, *args, **kwargs)[source]¶
return object with the oid identifier. Only one object is expected to be found.
raise
ObjectNotFound
if there are no object with id oid in this registryraise
AssertionError
if there is more than one object there
- classmethod objid(obj: Any) str [source]¶
returns a unique identifier for an object stored in the registry
- classmethod objname(obj: Any) str [source]¶
returns a readable name for an object stored in the registry
- possible_objects(*args, **kwargs)[source]¶
return an iterator on possible objects in this registry for the given context
- register(obj: Any, oid: Optional[Any] = None, clear: bool = False) None [source]¶
base method to add an object in the registry
- select(_Registry__oid, *args, **kwargs)[source]¶
return the most specific object among those with the given oid according to the given context.
raise
ObjectNotFound
if there are no object with id oid in this registryraise
NoSelectableObject
if no object can be selected
- select_or_none(_Registry__oid, *args, **kwargs)[source]¶
return the most specific object among those with the given oid according to the given context, or None if no object applies.
- selected(winner, args, kwargs)[source]¶
override here if for instance you don’t want “instanciation”
- warning(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘WARNING’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.warning(“Houston, we have a %s”, “bit of a problem”, exc_info=1)
- exception logilab.common.registry.RegistryException[source]¶
Bases:
Exception
Base class for registry exception.
- exception logilab.common.registry.RegistryNotFound[source]¶
Bases:
RegistryException
Raised when an unknown registry is requested.
This is usually a programming/typo error.
- class logilab.common.registry.RegistryStore(debugmode: bool = False)[source]¶
Bases:
dict
This class is responsible for loading objects and storing them in their registry which is created on the fly as needed.
It handles dynamic registration of objects and provides a convenient api to access them. To be recognized as an object that should be stored into one of the store’s registry (
Registry
), an object must provide the following attributes, used control how they interact with the registry:__registries__
list of registry names (string like ‘views’, ‘templates’…) into which the object should be registered
__regid__
object identifier in the registry (string like ‘main’, ‘primary’, ‘folder_box’)
__select__
the object predicate selectors
Moreover, the
__abstract__
attribute may be set to True to indicate that an object is abstract and should not be registered (such inherited attributes not considered).Note
When using the store to load objects dynamically, you always have to use super() to get the methods and attributes of the superclasses, and not use the class identifier. If not, you’ll get into trouble at reload time.
For example, instead of writing:
class Thing(Parent): __regid__ = 'athing' __select__ = yes() def f(self, arg1): Parent.f(self, arg1)
You must write:
class Thing(Parent): __regid__ = 'athing' __select__ = yes() def f(self, arg1): super(Thing, self).f(arg1)
Controlling object registration¶
Dynamic loading is triggered by calling the
register_modnames()
method, given a list of modules names to inspect.For each module, by default, all compatible objects are registered automatically. However if some objects come as replacement of other objects, or have to be included only if some condition is met, you’ll have to define a registration_callback(vreg) function in the module and explicitly register all objects in this module, using the api defined below.
- register_all(objects: Iterable, modname: str, butclasses: Sequence = ()) None [source]¶
register registrable objects into objects.
Registrable objects are properly configured subclasses of
RegistrableObject
. Objects which are not defined in the module modname or which are in butclasses won’t be registered.Typical usage is:
store.register_all(globals().values(), __name__, (ClassIWantToRegisterExplicitly,))
So you get partially automatic registration, keeping manual registration for some object (to use
register_and_replace()
for instance).
- register_and_replace(obj, replaced, registryname=None)[source]¶
register obj object into registryname or obj.__registries__ if not specified. If found, the replaced object will be unregistered first (else a warning will be issued as it is generally unexpected).
- register(obj: Any, registryname: Optional[Any] = None, oid: Optional[Any] = None, clear: bool = False) None [source]¶
register obj implementation into registryname or obj.__registries__ if not specified, with identifier oid or obj.__regid__ if not specified.
If clear is true, all objects with the same identifier will be previously unregistered.
- unregister(obj, registryname=None)[source]¶
unregister obj object from the registry registryname or obj.__registries__ if not specified.
Note
Once the function registration_callback(vreg) is implemented in a module, all the objects from this module have to be explicitly registered as it disables the automatic object registration.
Examples:
def registration_callback(store): # register everything in the module except BabarClass store.register_all(globals().values(), __name__, (BabarClass,)) # conditionally register BabarClass if 'babar_relation' in store.schema: store.register(BabarClass)
In this example, we register all application object classes defined in the module except BabarClass. This class is then registered only if the ‘babar_relation’ relation type is defined in the instance schema.
def registration_callback(store): store.register(Elephant) # replace Babar by Celeste store.register_and_replace(Celeste, Babar)
In this example, we explicitly register classes one by one:
the Elephant class
the Celeste to replace Babar
If at some point we register a new appobject class in this module, it won’t be registered at all without modification to the registration_callback implementation. The first example will register it though, thanks to the call to the register_all method.
Controlling registry instantiation¶
The REGISTRY_FACTORY class dictionary allows to specify which class should be instantiated for a given registry name. The class associated to None key will be the class used when there is no specific class for a name.
- REGISTRY_FACTORY: Dict[Union[None, str], type] = {None: <class 'logilab.common.registry.Registry'>}¶
- critical(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘CRITICAL’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.critical(“Houston, we have a %s”, “major disaster”, exc_info=1)
- debug(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘DEBUG’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.debug(“Houston, we have a %s”, “thorny problem”, exc_info=1)
- error(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘ERROR’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.error(“Houston, we have a %s”, “major problem”, exc_info=1)
- exception(msg, *args, exc_info=True, **kwargs)¶
Convenience method for logging an ERROR with exception information.
- info(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘INFO’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.info(“Houston, we have a %s”, “interesting problem”, exc_info=1)
- init_registration(path: List[str], extrapath: Optional[Any] = None) List[Tuple[str, str]] [source]¶
reset registry and walk down path to return list of (path, name) file modules to be loaded
- classmethod is_registrable(obj: Any) bool [source]¶
ensure obj should be registered
as arbitrary stuff may be registered, do a lot of check and warn about weird cases (think to dumb proxy objects)
- is_reload_needed(path)[source]¶
return True if something module changed and the registry should be reloaded
- load_file(filepath: str, modname: str) None [source]¶
load registrable objects (if any) from a python file
- load_module(module: module) None [source]¶
Automatically handle module objects registration.
Instances are registered as soon as they are hashable and have the following attributes:
__regid__ (a string)
__select__ (a callable)
__registries__ (a tuple/list of string)
For classes this is a bit more complicated :
first ensure parent classes are already registered
class with __abstract__ == True in their local dictionary are skipped
object class needs to have registries and identifier properly set to a non empty string to be registered.
- register(obj: Any, registryname: Optional[Any] = None, oid: Optional[Any] = None, clear: bool = False) None [source]¶
register obj implementation into registryname or obj.__registries__ if not specified, with identifier oid or obj.__regid__ if not specified.
If clear is true, all objects with the same identifier will be previously unregistered.
- register_all(objects: Iterable, modname: str, butclasses: Sequence = ()) None [source]¶
register registrable objects into objects.
Registrable objects are properly configured subclasses of
RegistrableObject
. Objects which are not defined in the module modname or which are in butclasses won’t be registered.Typical usage is:
store.register_all(globals().values(), __name__, (ClassIWantToRegisterExplicitly,))
So you get partially automatic registration, keeping manual registration for some object (to use
register_and_replace()
for instance).
- register_and_replace(obj, replaced, registryname=None)[source]¶
register obj object into registryname or obj.__registries__ if not specified. If found, the replaced object will be unregistered first (else a warning will be issued as it is generally unexpected).
- registry_class(regid: str) type [source]¶
return existing registry named regid or use factory to create one and return it
- setdefault(regid: str) Registry [source]¶
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- unregister(obj, registryname=None)[source]¶
unregister obj object from the registry registryname or obj.__registries__ if not specified.
- warning(msg, *args, **kwargs)¶
Log ‘msg % args’ with severity ‘WARNING’.
To pass exception information, use the keyword argument exc_info with a true value, e.g.
logger.warning(“Houston, we have a %s”, “bit of a problem”, exc_info=1)
- exception logilab.common.registry.SelectAmbiguity[source]¶
Bases:
RegistryException
Raised when several objects compete at selection time with an equal score.
- logilab.common.registry.obj_registries(cls: Any, registryname: Optional[Any] = None) Tuple[str] [source]¶
return a tuple of registry names (see __registries__)
- logilab.common.registry.objectify_predicate(selector_func: Callable) Any [source]¶
Most of the time, a simple score function is enough to build a selector. The
objectify_predicate()
decorator turn it into a proper selector class:@objectify_predicate def one(cls, req, rset=None, **kwargs): return 1 class MyView(View): __select__ = View.__select__ & one()
- class logilab.common.registry.traced_selection(traced='all')[source]¶
Bases:
object
Typical usage is :
>>> from logilab.common.registry import traced_selection >>> with traced_selection(): ... # some code in which you want to debug selectors ... # for all objects
This will yield lines like this in the logs:
selector one_line_rset returned 0 for <class 'elephant.Babar'>
You can also give to
traced_selection
the identifiers of objects on which you want to debug selection (‘oid1’ and ‘oid2’ in the example above).>>> with traced_selection( ('regid1', 'regid2') ): ... # some code in which you want to debug selectors ... # for objects with __regid__ 'regid1' and 'regid2'
A potentially useful point to set up such a tracing function is the logilab.common.registry.Registry.select method body.
- class logilab.common.registry.yes(score: float = 0.5)[source]¶
Bases:
Predicate
Return the score given as parameter, with a default score of 0.5 so any other selector take precedence.
Usually used for objects which can be selected whatever the context, or also sometimes to add arbitrary points to a score.
Take care, yes(0) could be named ‘no’…
logilab.common.shellutils module¶
shell/term utilities, useful to write some python scripts instead of shell scripts.
- class logilab.common.shellutils.ProgressBar(nbops: int, size: int = 20, stream: ~_io.StringIO = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>, title: str = '')[source]¶
Bases:
object
A simple text progression bar.
- property text¶
- class logilab.common.shellutils.RawInput(input_function: Optional[Callable] = None, printer: Optional[Callable] = None, **kwargs: Any)[source]¶
Bases:
object
- logilab.common.shellutils.chown(path, login=None, group=None)[source]¶
Same as os.chown function but accepting user login or group name as argument. If login or group is omitted, it’s left unchanged.
Note: you must own the file to chown it (or be root). Otherwise OSError is raised.
- logilab.common.shellutils.find(directory: str, exts: Union[Tuple[str, ...], str], exclude: bool = False, blacklist: Tuple[str, ...] = ('CVS', '.svn', '.hg', '.git', '.tox', 'debian', 'dist', 'build')) List[str] [source]¶
Recursively find files ending with the given extensions from the directory.
- Parameters:
directory (str) – directory where the search should start
exts (basestring or list or tuple) – extensions or lists or extensions to search
exts – if this argument is True, returning files NOT ending with the given extensions
blacklist (list or tuple) – optional list of files or directory to ignore, default to the value of logilab.common.STD_BLACKLIST
- Return type:
- Returns:
the list of all matching files
- logilab.common.shellutils.generate_password(length=8, vocab='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')[source]¶
dumb password generation function
- logilab.common.shellutils.getlogin()[source]¶
avoid using os.getlogin() because of strange tty / stdin problems (man 3 getlogin) Another solution would be to use $LOGNAME, $USER or $USERNAME
- logilab.common.shellutils.globfind(directory: str, pattern: str, blacklist: Tuple[str, str, str, str, str, str, str, str] = ('CVS', '.svn', '.hg', '.git', '.tox', 'debian', 'dist', 'build')) Iterator[str] [source]¶
Recursively finds files matching glob pattern under directory.
This is an alternative to logilab.common.shellutils.find.
- Parameters:
- Return type:
iterator
- Returns:
iterator over the list of all matching files
- logilab.common.shellutils.mv(source, destination, _action=<function move>)[source]¶
A shell-like mv, supporting wildcards.
logilab.common.sphinx_ext module¶
logilab.common.sphinxutils module¶
Sphinx utils
ModuleGenerator: Generate a file that lists all the modules of a list of packages in order to pull all the docstring. This should not be used in a makefile to systematically generate sphinx documentation!
Typical usage:
>>> from logilab.common.sphinxutils import ModuleGenerator
>>> mgen = ModuleGenerator('logilab common', '/home/adim/src/logilab/common')
>>> mgen.generate('api_logilab_common.rst', exclude_dirs=('test',))
- class logilab.common.sphinxutils.ModuleGenerator(project_title, code_dir)[source]¶
Bases:
object
- class_def = '\n\n.. autoclass:: %s\n :members: %s\n\n'¶
- file_header = '.. -*- coding: utf-8 -*-\n\n%s\n'¶
- generate(dest_file, exclude_dirs=('CVS', '.svn', '.hg', '.git', '.tox', 'debian', 'dist', 'build'))[source]¶
make the module file
- module_def = '\n:mod:`%s`\n=======%s\n\n.. automodule:: %s\n :members: %s\n'¶
logilab.common.table module¶
Table management module.
- class logilab.common.table.DocbookRenderer(**properties: Any)[source]¶
Bases:
TableCellRenderer
Defines how to render a cell for a docboook table
- define_col_header(col_index: int, table_style: TableStyle) str [source]¶
Computes the colspec element according to the style
- class logilab.common.table.DocbookTableWriter(stream: StringIO, table: Table, style: Optional[Any], **properties: Any)[source]¶
Bases:
TableWriter
Defines an implementation of TableWriter to write a table in Docbook
- class logilab.common.table.Table(default_value: int = 0, col_names: Optional[List[str]] = None, row_names: Optional[Any] = None)[source]¶
Bases:
object
Table defines a data table with column and row names. inv:
len(self.data) <= len(self.row_names) forall(self.data, lambda x: len(x) <= len(self.col_names))
- append_column(col_data: range, col_name: str) None [source]¶
Appends the ‘col_index’ column pre:
type(col_data) == types.ListType len(col_data) == len(self.row_names)
- append_row(row_data: Union[List[Union[float, str]], List[int]], row_name: Optional[str] = None) int [source]¶
Appends a row to the table pre:
type(row_data) == types.ListType len(row_data) == len(self.col_names)
- apply_stylesheet(stylesheet: TableStyleSheet) None [source]¶
Applies the stylesheet to this table
- create_columns(col_names: List[str]) None [source]¶
Appends col_names to the list of existing columns
- delete_column(index: int) List[int] [source]¶
Deletes the ‘index’ column in the table, and returns it. Raises an IndexError if index is out of range
- delete_column_by_id(col_id: str) None [source]¶
Deletes the ‘col_id’ col in the table. Raises a KeyError if col_id was not found.
- delete_row(index: int) List[str] [source]¶
Deletes the ‘index’ row in the table, and returns it. Raises an IndexError if index is out of range
- delete_row_by_id(row_id: str) None [source]¶
Deletes the ‘row_id’ row in the table. Raises a KeyError if row_id was not found.
- groupby(colname: str, *others: str) Union[Dict[str, Dict[str, Table]], Dict[str, Table]] [source]¶
builds indexes of data :returns: nested dictionaries pointing to actual rows
- insert_column(index: int, col_data: range, col_name: str) None [source]¶
Appends col_data before ‘index’ in the table. To make ‘insert’ behave like ‘list.insert’, inserting in an out of range index will insert col_data to the end of the list pre:
type(col_data) == types.ListType len(col_data) == len(self.row_names)
- insert_row(index: int, row_data: List[str], row_name: Optional[str] = None) None [source]¶
Appends row_data before ‘index’ in the table. To make ‘insert’ behave like ‘list.insert’, inserting in an out of range index will insert row_data to the end of the list pre:
type(row_data) == types.ListType len(row_data) == len(self.col_names)
- set_cell(row_index: int, col_index: int, data: int) None [source]¶
sets value of cell ‘row_indew’, ‘col_index’ to data
- set_cell_by_ids(row_id: str, col_id: str, data: Union[int, str]) None [source]¶
sets value of cell mapped by row_id and col_id to data Raises a KeyError if row_id or col_id are not found in the table
- set_column(col_index: int, col_data: Union[List[int], range]) None [source]¶
sets the ‘col_index’ column pre:
type(col_data) == types.ListType len(col_data) == len(self.row_names)
- set_column_by_id(col_id: str, col_data: Union[List[int], range]) None [source]¶
sets the ‘col_id’ column pre:
type(col_data) == types.ListType len(col_data) == len(self.col_names)
Raises a KeyError if col_id is not found
- set_row(row_index: int, row_data: Union[List[float], List[int], List[str]]) None [source]¶
sets the ‘row_index’ row pre:
type(row_data) == types.ListType len(row_data) == len(self.col_names)
- set_row_by_id(row_id: str, row_data: List[str]) None [source]¶
sets the ‘row_id’ column pre:
type(row_data) == types.ListType len(row_data) == len(self.row_names)
Raises a KeyError if row_id is not found
- sort_by_column_id(col_id: str, method: str = 'asc') None [source]¶
Sorts the table (in-place) according to data stored in col_id
- class logilab.common.table.TableCellRenderer(**properties: Any)[source]¶
Bases:
object
Defines a simple text renderer
- render_cell(cell_coord: Tuple[int, int], table: Table, table_style: TableStyle) Union[str, int] [source]¶
Renders the cell at ‘cell_coord’ in the table, using table_style
- class logilab.common.table.TableStyle(table: Table)[source]¶
Bases:
object
Defines a table’s style
- get_alignment_by_index(col_index: int) str [source]¶
Allors to get the alignment according to the column index rather than using the column’s id. BE CAREFUL : the ‘0’ column is the ‘__row_column__’ one !
- get_size_by_index(col_index: int) str [source]¶
Allows to get the size according to the column index rather than using the column’s id. BE CAREFUL : the ‘0’ column is the ‘__row_column__’ one !
- get_unit_by_index(col_index: int) str [source]¶
Allors to get the unit according to the column index rather than using the column’s id. BE CAREFUL : the ‘0’ column is the ‘__row_column__’ one !
- set_alignment(value: str, col_id: str) None [source]¶
sets the alignment of the specified col_id to value
- set_alignment_by_index(value: str, col_index: int) None [source]¶
Allows to set the alignment according to the column index rather than using the column’s id. BE CAREFUL : the ‘0’ column is the ‘__row_column__’ one !
- set_size_by_index(value: str, col_index: int) None [source]¶
Allows to set the size according to the column index rather than using the column’s id. BE CAREFUL : the ‘0’ column is the ‘__row_column__’ one !
- set_unit_by_index(value: str, col_index: int) None [source]¶
Allows to set the unit according to the column index rather than using the column’s id. BE CAREFUL : the ‘0’ column is the ‘__row_column__’ one ! (Note that in the ‘unit’ case, you shouldn’t have to set a unit for the 1st column (the __row__column__ one))
- class logilab.common.table.TableStyleSheet(rules: Optional[List[str]] = None)[source]¶
Bases:
object
A simple Table stylesheet Rules are expressions where cells are defined by the row_index and col_index separated by an underscore (‘_’). For example, suppose you want to say that the (2,5) cell must be the sum of its two preceding cells in the row, you would create the following rule
2_5 = 2_3 + 2_4
You can also use all the math.* operations you want. For example:
2_5 = sqrt(2_3**2 + 2_4**2)
- add_colavg_rule(dest_cell: Tuple[int, int], col_index: int, start_row: int, end_row: int) None [source]¶
Creates and adds a rule to make the col average (from start_row to end_row) dest_cell is a tuple of two elements (x,y) of the destination cell No check is done for indexes ranges. pre:
start_row >= 0 end_row > start_row
- add_colsum_rule(dest_cell: Tuple[int, int], col_index: int, start_row: int, end_row: int) None [source]¶
Creates and adds a rule to sum over the col at col_index from start_row to end_row. dest_cell is a tuple of two elements (x,y) of the destination cell No check is done for indexes ranges. pre:
start_row >= 0 end_row > start_row
- add_rowavg_rule(dest_cell: Tuple[int, int], row_index: int, start_col: int, end_col: int) None [source]¶
Creates and adds a rule to make the row average (from start_col to end_col) dest_cell is a tuple of two elements (x,y) of the destination cell No check is done for indexes ranges. pre:
start_col >= 0 end_col > start_col
- add_rowsum_rule(dest_cell: Tuple[int, int], row_index: int, start_col: int, end_col: int) None [source]¶
Creates and adds a rule to sum over the row at row_index from start_col to end_col. dest_cell is a tuple of two elements (x,y) of the destination cell No check is done for indexes ranges. pre:
start_col >= 0 end_col > start_col
logilab.common.tasksqueue module¶
Prioritized tasks queue
logilab.common.testlib module¶
Run tests.
This will find all modules whose name match a given prefix in the test directory, and run them. Various command line options provide additional facilities.
Command line options:
- -v
verbose – run tests in verbose mode with output to stdout
- -q
quiet – don’t print anything except if a test fails
- -t
testdir – directory where the tests will be found
- -x
exclude – add a test to exclude
- -p
profile – profiled execution
- -d
dbc – enable design-by-contract
- -m
match – only run test matching the tag pattern which follow
If no non-option arguments are present, prefixes used are ‘test’, ‘regrtest’, ‘smoketest’ and ‘unittest’.
- logilab.common.testlib.find_tests(testdir, prefixes=('test', 'regrtest', 'smoketest', 'unittest', 'func', 'validation'), suffix='.py', excludes=(), remove_suffix=True)[source]¶
Return a list of all applicable test modules.
- logilab.common.testlib.nocoverage(func: Callable) Callable [source]¶
Function decorator that pauses tracing functions
- logilab.common.testlib.pause_trace(trace: Optional[Callable] = None) Iterator ¶
A context manager that temporary replaces the trace function
- logilab.common.testlib.unittest_main¶
alias of
TestProgram
logilab.common.textutils module¶
Some text manipulation utility functions.
- group text formatting:
normalize_text, normalize_paragraph, pretty_match,unquote, colorize_ansi
- group text manipulation:
searchall, splitstrip
- sort:
text formatting, text manipulation
- type ANSI_STYLES:
dict(str)
- var ANSI_STYLES:
dictionary mapping style identifier to ANSI terminal code
- type ANSI_COLORS:
dict(str)
- var ANSI_COLORS:
dictionary mapping color identifier to ANSI terminal code
- type ANSI_PREFIX:
str
- var ANSI_PREFIX:
ANSI terminal code notifying the start of an ANSI escape sequence
- type ANSI_END:
str
- var ANSI_END:
ANSI terminal code notifying the end of an ANSI escape sequence
- type ANSI_RESET:
str
- var ANSI_RESET:
ANSI terminal code resetting format defined by a previous ANSI escape sequence
- logilab.common.textutils.apply_units(string: str, units: ~typing.Dict[str, int], inter: ~typing.Union[~typing.Callable, None, type] = None, final: type = <class 'float'>, blank_reg: ~re.Pattern = re.compile('(\\s|,)+'), value_reg: ~re.Pattern = re.compile('(?P<value>-?(([0-9]+\\.[0-9]*)|((0x?)?[0-9]+)))(?P<unit>[a-zA-Z]+)?')) Union[float, int] [source]¶
Parse the string applying the units defined in units (e.g.: “1.5m”,{‘m’,60} -> 80).
- Parameters:
string (str or unicode) – the string to parse
units (dict (or any object with __getitem__ using basestring key)) – a dict mapping a unit string repr to its value
inter (type) – used to parse every intermediate value (need __sum__)
blank_reg (regexp) – should match every blank char to ignore.
value_reg (regexp with "value" and optional "unit" group) – match a value and it’s unit into the
- logilab.common.textutils.colorize_ansi(msg: str, color: Optional[str] = None, style: Optional[str] = None) str [source]¶
colorize message by wrapping it with ansi escape codes
- logilab.common.textutils.diff_colorize_ansi(lines, out=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>, style={'add': 'green', 'remove': 'red', 'separator': 'cyan'})[source]¶
- logilab.common.textutils.normalize_paragraph(text: str, line_len: int = 80, indent: str = '') str [source]¶
normalize a text to display it with a maximum line size and optionally arbitrary indentation. Line jumps are normalized. The indentation string may be used top insert a comment mark for instance.
- Parameters:
- Return type:
str or unicode
- Returns:
the input text normalized to fit on lines with a maximized size inferior to line_len, and optionally prefixed by an indentation string
- logilab.common.textutils.normalize_rest_paragraph(text: str, line_len: int = 80, indent: str = '') str [source]¶
normalize a ReST text to display it with a maximum line size and optionally arbitrary indentation. Line jumps are normalized. The indentation string may be used top insert a comment mark for instance.
- Parameters:
- Return type:
str or unicode
- Returns:
the input text normalized to fit on lines with a maximized size inferior to line_len, and optionally prefixed by an indentation string
- logilab.common.textutils.normalize_text(text: str, line_len: int = 80, indent: str = '', rest: bool = False) str [source]¶
normalize a text to display it with a maximum line size and optionally arbitrary indentation. Line jumps are normalized but blank lines are kept. The indentation string may be used to insert a comment (#) or a quoting (>) mark for instance.
- Parameters:
- Return type:
str or unicode
- Returns:
the input text normalized to fit on lines with a maximized size inferior to line_len, and optionally prefixed by an indentation string
- logilab.common.textutils.pretty_match(match: Match, string: str, underline_char: str = '^') str [source]¶
return a string with the match location underlined:
>>> import re >>> print(pretty_match(re.search('mange', 'il mange du bacon'), 'il mange du bacon')) il mange du bacon ^^^^^ >>>
- Parameters:
match (_sre.SRE_match) – object returned by re.match, re.search or re.finditer
string (str or unicode) – the string on which the regular expression has been applied to obtain the match object
underline_char (str or unicode) – character to use to underline the matched section, default to the carret ‘^’
- Return type:
str or unicode
- Returns:
the original string with an inserted line to underline the match location
- logilab.common.textutils.split_url_or_path(url_or_path)[source]¶
return the latest component of a string containing either an url of the form <scheme>://<path> or a local file system path
- logilab.common.textutils.splitstrip(string: str, sep: str = ',') List[str] [source]¶
return a list of stripped string by splitting the string given as argument on sep (‘,’ by default). Empty string are discarded.
>>> splitstrip('a, b, c , 4,,') ['a', 'b', 'c', '4'] >>> splitstrip('a') ['a'] >>>
- logilab.common.textutils.splittext(text: str, line_len: int) Tuple[str, str] [source]¶
split the given text on space according to the given max line size
return a 2-uple: * a line <= line_len if possible * the rest of the text which has to be reported on another line
- logilab.common.textutils.text_to_dict(text)[source]¶
parse multilines text containing simple ‘key=value’ lines and return a dict of {‘key’: ‘value’}. When the same key is encountered multiple time, value is turned into a list containing all values.
>>> d = text_to_dict('''multiple=1 ... multiple= 2 ... single =3 ... ''') >>> d['single'] '3' >>> d['multiple'] ['1', '2']
- logilab.common.textutils.unormalize(ustring: str, substitute: Optional[str] = None) str [source]¶
replace diacritical characters with their corresponding ascii characters
Convert the unicode string to its long normalized form (unicode character will be transform into several characters) and keep the first one only. The normal form KD (NFKD) will apply the compatibility decomposition, i.e. replace all compatibility characters with their equivalents.
- Parameters:
substitute (str) – replacement character to use if decomposition fails
- See:
Another project about ASCII transliterations of Unicode text http://pypi.python.org/pypi/Unidecode
logilab.common.tree module¶
Base class to represent a tree structure.
- class logilab.common.tree.BinaryNode(lhs=None, rhs=None)[source]¶
Bases:
VNode
a binary node (i.e. only two children
- class logilab.common.tree.Node(nid: Optional[str] = None)[source]¶
Bases:
object
a basic tree node, characterized by an id
- exception logilab.common.tree.NodeNotFound[source]¶
Bases:
Exception
raised when a node has not been found
- class logilab.common.tree.PostfixedDepthFirstIterator(node: Node, filter_func: Optional[Any] = None)[source]¶
Bases:
FilteredIterator
a postfixed depth first iterator, designed to be used with visitors
- class logilab.common.tree.PrefixedDepthFirstIterator(node: Node, filter_func: Optional[Any] = None)[source]¶
Bases:
FilteredIterator
a prefixed depth first iterator, designed to be used with visitors
- class logilab.common.tree.VNode(nid: Optional[str] = None)[source]¶
Bases:
Node
,VisitedMixIn
a visitable node
logilab.common.umessage module¶
Unicode email support (extends email from stdlib)
- class logilab.common.umessage.UMessage(message: Message)[source]¶
Bases:
object
Encapsulates an email.Message instance and returns only unicode objects.
- date(alternative_source=False, return_str=False)[source]¶
return a datetime object for the email’s date or None if no date is set or if it can’t be parsed
- get_payload(index: Optional[Any] = None, decode: bool = False) Union[str, UMessage, List[UMessage]] [source]¶
logilab.common.urllib2ext module¶
logilab.common.vcgutils module¶
Functions to generate files readable with Georg Sander’s vcg (Visualization of Compiler Graphs).
You can download vcg at http://rw4.cs.uni-sb.de/~sander/html/gshome.html Note that vcg exists as a debian package.
See vcg’s documentation for explanation about the different values that maybe used for the functions parameters.
logilab.common.visitor module¶
A generic visitor abstract implementation.
- class logilab.common.visitor.FilteredIterator(node: Node, list_func: Callable, filter_func: Optional[Any] = None)[source]¶
Bases:
object
- class logilab.common.visitor.VisitedMixIn[source]¶
Bases:
object
Visited interface allow node visitors to use the node
logilab.common.xmlutils module¶
XML utilities.
This module contains useful functions for parsing and using XML data. For the moment, there is only one function that can parse the data inside a processing instruction and return a Python dictionary.
- logilab.common.xmlutils.parse_pi_data(pi_data: str) Dict[str, Optional[str]] [source]¶
Utility function that parses the data contained in an XML processing instruction and returns a dictionary of keywords and their associated values (most of the time, the processing instructions contain data like
keyword="value"
, if a keyword is not associated to a value, for examplekeyword
, it will be associated toNone
).- Parameters:
pi_data (unicode) – data contained in an XML processing instruction.
- Returns:
Dictionary of the keywords (Unicode strings) associated to their values (Unicode strings) as they were defined in the data.
- Return type:
Module contents¶
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
- class logilab.common.attrdict[source]¶
Bases:
dict
A dictionary for which keys are also accessible as attributes.
- logilab.common.flatten(iterable, tr_func=None, results=None)[source]¶
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.
- Return type:
>>> flatten([1, [2, 3]]) [1, 2, 3]