['a'] >>> :type string: str or unicode :param string: a csv line :type sep: str or unicode :param sep: field separator, default to the comma (',') :rtype: str or unicode :return: the unquoted string (or the input string if it wasn't quoted) """ return [word.strip() for word in string.split(sep) if word.strip()] get_csv = callable_deprecated("get_csv is deprecated, use splitstrip")( splitstrip) def split_url_or_path(url_or_path): """return the latest component of a string containing either an url of the form <scheme>://<path> or a local file system path """ if "://" in url_or_path: return url_or_path.rstrip("/").rsplit("/", 1) return osp.split(url_or_path.rstrip(osp.sep)) def text_to_dict(text): """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.
return sep.join(result) def norm_read(path): """Return the content of the file with normalized line feeds. :type path: str :param path: path to the file to read :rtype: str :return: the content of the file with normalized line feeds """ return open(path, "U").read() norm_read = callable_deprecated("use \"open(path, 'U').read()\"")(norm_read) def norm_open(path): """Return a stream for a file with content with normalized line feeds. :type path: str :param path: path to the file to open :rtype: file or StringIO :return: the opened file with normalized line feeds """ return open(path, "U") norm_open = callable_deprecated("use \"open(path, 'U')\"")(norm_open)
while begin < end: yield begin begin = next_month(begin, incmonth) else: incr = get_step(begin, incday or 1) while begin < end: yield begin begin += incr # makes py datetime usable ##################################################### ONEDAY: timedelta = timedelta(days=1) ONEWEEK: timedelta = timedelta(days=7) strptime = callable_deprecated("Use strptime from datetime.datetime instead")( datetime.strptime) def strptime_time(value, format="%H:%M"): return time(*time_strptime(value, format)[3:6]) def todate(somedate: date) -> date: """return a date from a date (leaving unchanged) or a datetime""" if isinstance(somedate, datetime): return date(somedate.year, somedate.month, somedate.day) assert isinstance(somedate, (date, DateTimeType)), repr(somedate) return somedate def totime(somedate):
# See also http://bugs.python.org/issue11776 if sys.version_info[0] == 3: def method_type(callable, instance, klass): # api change. klass is no more considered return types.MethodType(callable, instance) else: # alias types otherwise method_type = types.MethodType # Pythons 2 and 3 differ on where to get StringIO if sys.version_info < (3, 0): from cStringIO import StringIO FileIO = file # noqa BytesIO = StringIO reload = reload # noqa else: from io import StringIO, FileIO # noqa from imp import reload # noqa from logilab.common.deprecation import callable_deprecated # noqa # Other projects import these from here, keep providing them for # backwards compat any = callable_deprecated('use builtin "any"')(any) all = callable_deprecated('use builtin "all"')(all)
from unittest2 import SkipTest except ImportError: raise ImportError("You have to install python-unittest2 to use %s" % __name__) else: # mypy: Name 'unittest' already defined (possibly by an import) # compat import unittest as unittest # type: ignore from unittest import SkipTest __all__ = ["unittest_main", "find_tests", "nocoverage", "pause_trace"] DEFAULT_PREFIXES = ("test", "regrtest", "smoketest", "unittest", "func", "validation") is_generator = callable_deprecated( "[lgc 0.63] use inspect.isgeneratorfunction")(isgeneratorfunction) # used by unittest to count the number of relevant levels in the traceback __unittest = 1 @callable_deprecated( "with_tempdir is deprecated, use tempfile.TemporaryDirectory.") def with_tempdir(callable: Callable) -> Callable: """A decorator ensuring no temporary file left when the function return Work only for temporary file created with the tempfile module""" if isgeneratorfunction(callable): def proxy(*args: Any, **kwargs: Any) -> Iterator[Union[Iterator, Iterator[str]]]: old_tmpdir = tempfile.gettempdir()
class OptionsProviderMixIn(object): """Mixin to provide options to an OptionsManager""" # those attributes should be overridden priority = -1 name = "default" options: Tuple = () level = 0 def __init__(self) -> None: self.config = optik_ext.Values() for option_tuple in self.options: try: option, optdict = option_tuple except ValueError: raise Exception("Bad option: %s" % str(option_tuple)) if isinstance(optdict.get("default"), Method): optdict["default"].bind(self) elif isinstance(optdict.get("callback"), Method): optdict["callback"].bind(self) self.load_defaults() def load_defaults(self) -> None: """initialize the provider using default values""" for opt, optdict in self.options: action = optdict.get("action") if action != "callback": # callback action have no default default = self.option_default(opt, optdict) if default is REQUIRED: continue self.set_option(opt, default, action, optdict) def option_default(self, opt, optdict=None): """return the default value for an option""" if optdict is None: optdict = self.get_option_def(opt) default = optdict.get("default") if callable(default): default = default() return default def option_attrname(self, opt, optdict=None): """get the config attribute corresponding to opt""" if optdict is None: optdict = self.get_option_def(opt) return optdict.get("dest", opt.replace("-", "_")) option_name = callable_deprecated( "[0.60] OptionsProviderMixIn.option_name() was renamed to option_attrname()" )(option_attrname) def option_value(self, opt): """get the current value for the given option""" return getattr(self.config, self.option_attrname(opt), None) def set_option(self, opt, value, action=None, optdict=None): """method called to set an option (registered in the options list)""" if optdict is None: optdict = self.get_option_def(opt) if value is not None: value = _validate(value, optdict, opt) if action is None: action = optdict.get("action", "store") if optdict.get("type") == "named": # XXX need specific handling optname = self.option_attrname(opt, optdict) currentvalue = getattr(self.config, optname, None) if currentvalue: currentvalue.update(value) value = currentvalue if action == "store": setattr(self.config, self.option_attrname(opt, optdict), value) elif action in ("store_true", "count"): setattr(self.config, self.option_attrname(opt, optdict), 0) elif action == "store_false": setattr(self.config, self.option_attrname(opt, optdict), 1) elif action == "append": opt = self.option_attrname(opt, optdict) _list = getattr(self.config, opt, None) if _list is None: if isinstance(value, (list, tuple)): _list = value elif value is not None: _list = [] _list.append(value) setattr(self.config, opt, _list) elif isinstance(_list, tuple): setattr(self.config, opt, _list + (value, )) else: _list.append(value) elif action == "callback": optdict["callback"](None, opt, value, None) else: raise UnsupportedAction(action) def input_option(self, option, optdict, inputlevel=99): default = self.option_default(option, optdict) if default is REQUIRED: defaultstr = "(required): " elif optdict.get("level", 0) > inputlevel: return elif optdict["type"] == "password" or default is None: defaultstr = ": " else: defaultstr = "(default: %s): " % format_option_value( optdict, default) print(":%s:" % option) print(optdict.get("help") or option) inputfunc = INPUT_FUNCTIONS[optdict["type"]] value = inputfunc(optdict, defaultstr) while default is REQUIRED and not value: print("please specify a value") value = inputfunc(optdict, "%s: " % option) if value is None and default is not None: value = default self.set_option(option, value, optdict=optdict) def get_option_def(self, opt): """return the dictionary defining an option given it's name""" assert self.options for option in self.options: if option[0] == opt: return option[1] # mypy: Argument 2 to "OptionError" has incompatible type "str"; expected "Option" # seems to be working? raise OptionError("no such option %s in section %r" % (opt, self.name), opt) # type: ignore def all_options(self): """return an iterator on available options for this provider option are actually described by a 3-uple: (section, option name, option dictionary) """ for section, options in self.options_by_section(): if section is None: if self.name is None: continue section = self.name.upper() for option, optiondict, value in options: yield section, option, optiondict def options_by_section(self) -> Iterator[Any]: """return an iterator on options grouped by section (section, [list of (optname, optdict, optvalue)]) """ sections: Dict[str, List[Tuple[str, Dict[str, Any], Any]]] = {} for optname, optdict in self.options: sections.setdefault(optdict.get("group"), []).append( (optname, optdict, self.option_value(optname))) if None in sections: # mypy: No overload variant of "pop" of "MutableMapping" matches argument type "None" # it actually works yield None, sections.pop(None) # type: ignore for section, options in sorted(sections.items()): yield section.upper(), options def options_and_values(self, options=None): if options is None: options = self.options for optname, optdict in options: yield (optname, optdict, self.option_value(optname))
def _validate(value: Union[List[str], int, str], optdict: Dict[str, Any], name: str = "") -> Union[List[str], int, str]: """return a validated value for an option according to its type optional argument name is only used for error message formatting """ try: _type = optdict["type"] except KeyError: # FIXME return value return _call_validator(_type, optdict, name, value) convert = callable_deprecated("[0.60] convert() was renamed _validate()")( _validate) # format and output functions ################################################## def comment(string): """return string as a comment""" lines = [line.strip() for line in string.splitlines()] return "# " + ("%s# " % os.linesep).join(lines) def format_time(value): if not value: return "0" if value != int(value): return "%.2fs" % value