def deprecated(self, msg, *args, **kwargs): """Call this method when a deprecated feature is used. If the system is configured for fatal deprecations then the message is logged at the 'critical' level and :class:`DeprecatedConfig` will be raised. Otherwise, the message will be logged (once) at the 'warn' level. :raises: :class:`DeprecatedConfig` if the system is configured for fatal deprecations. """ stdmsg = _("Deprecated: %s") % msg if CONF.fatal_deprecations: self.critical(stdmsg, *args, **kwargs) raise DeprecatedConfig(msg=stdmsg) # Using a list because a tuple with dict can't be stored in a set. sent_args = self._deprecated_messages_sent.setdefault(msg, list()) if args in sent_args: # Already logged this message, so don't log it again. return sent_args.append(args) self.warn(stdmsg, *args, **kwargs)
def bool_from_string(subject, strict=False, default=False): """Interpret a string as a boolean. A case-insensitive match is performed such that strings matching 't', 'true', 'on', 'y', 'yes', or '1' are considered True and, when `strict=False`, anything else returns the value specified by 'default'. Useful for JSON-decoded stuff and config file parsing. If `strict=True`, unrecognized values, including None, will raise a ValueError which is useful when parsing values passed in from an API call. Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. """ if not isinstance(subject, six.string_types): subject = six.text_type(subject) lowered = subject.strip().lower() if lowered in TRUE_STRINGS: return True elif lowered in FALSE_STRINGS: return False elif strict: acceptable = ', '.join( "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) msg = _("Unrecognized value '%(val)s', acceptable values are:" " %(acceptable)s") % {'val': subject, 'acceptable': acceptable} raise ValueError(msg) else: return default
def string_to_bytes(text, unit_system='IEC', return_int=False): """Converts a string into an float representation of bytes. The units supported for IEC :: Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it) KB, KiB, MB, MiB, GB, GiB, TB, TiB The units supported for SI :: kb(it), Mb(it), Gb(it), Tb(it) kB, MB, GB, TB Note that the SI unit system does not support capital letter 'K' :param text: String input for bytes size conversion. :param unit_system: Unit system for byte size conversion. :param return_int: If True, returns integer representation of text in bytes. (default: decimal) :returns: Numerical representation of text in bytes. :raises ValueError: If text has an invalid value. """ try: base, reg_ex = UNIT_SYSTEM_INFO[unit_system] except KeyError: msg = _('Invalid unit system: "%s"') % unit_system raise ValueError(msg) match = reg_ex.match(text) if match: magnitude = float(match.group(1)) unit_prefix = match.group(2) if match.group(3) in ['b', 'bit']: magnitude /= 8 else: msg = _('Invalid string format: %s') % text raise ValueError(msg) if not unit_prefix: res = magnitude else: res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix]) if return_int: return int(math.ceil(res)) return res
class LogConfigError(Exception): message = _('Error loading logging config %(log_config)s: %(err_msg)s') def __init__(self, log_config, err_msg): self.log_config = log_config self.err_msg = err_msg def __str__(self): return self.message % dict(log_config=self.log_config, err_msg=self.err_msg)
def _find_facility_from_conf(): facility_names = logging.handlers.SysLogHandler.facility_names facility = getattr(logging.handlers.SysLogHandler, CONF.syslog_log_facility, None) if facility is None and CONF.syslog_log_facility in facility_names: facility = facility_names.get(CONF.syslog_log_facility) if facility is None: valid_facilities = facility_names.keys() consts = [ 'LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON', 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS', 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP', 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3', 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7' ] valid_facilities.extend(consts) raise TypeError( _('syslog facility must be one of: %s') % ', '.join("'%s'" % fac for fac in valid_facilities)) return facility
class deprecated(object): """A decorator to mark callables as deprecated. This decorator logs a deprecation message when the callable it decorates is used. The message will include the release where the callable was deprecated, the release where it may be removed and possibly an optional replacement. Examples: 1. Specifying the required deprecated release >>> @deprecated(as_of=deprecated.ICEHOUSE) ... def a(): pass 2. Specifying a replacement: >>> @deprecated(as_of=deprecated.ICEHOUSE, in_favor_of='f()') ... def b(): pass 3. Specifying the release where the functionality may be removed: >>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=+1) ... def c(): pass 4. Specifying the deprecated functionality will not be removed: >>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=0) ... def d(): pass 5. Specifying a replacement, deprecated functionality will not be removed: >>> @deprecated(as_of=deprecated.ICEHOUSE, in_favor_of='f()', remove_in=0) ... def e(): pass """ # NOTE(morganfainberg): Bexar is used for unit test purposes, it is # expected we maintain a gap between Bexar and Folsom in this list. BEXAR = 'B' FOLSOM = 'F' GRIZZLY = 'G' HAVANA = 'H' ICEHOUSE = 'I' JUNO = 'J' KILO = 'K' _RELEASES = { # NOTE(morganfainberg): Bexar is used for unit test purposes, it is # expected we maintain a gap between Bexar and Folsom in this list. 'B': 'Bexar', 'F': 'Folsom', 'G': 'Grizzly', 'H': 'Havana', 'I': 'Icehouse', 'J': 'Juno', 'K': 'Kilo', } _deprecated_msg_with_alternative = _( '%(what)s is deprecated as of %(as_of)s in favor of ' '%(in_favor_of)s and may be removed in %(remove_in)s.') _deprecated_msg_no_alternative = _( '%(what)s is deprecated as of %(as_of)s and may be ' 'removed in %(remove_in)s. It will not be superseded.') _deprecated_msg_with_alternative_no_removal = _( '%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s.') _deprecated_msg_with_no_alternative_no_removal = _( '%(what)s is deprecated as of %(as_of)s. It will not be superseded.') def __init__(self, as_of, in_favor_of=None, remove_in=2, what=None): """Initialize decorator :param as_of: the release deprecating the callable. Constants are define in this class for convenience. :param in_favor_of: the replacement for the callable (optional) :param remove_in: an integer specifying how many releases to wait before removing (default: 2) :param what: name of the thing being deprecated (default: the callable's name) """ self.as_of = as_of self.in_favor_of = in_favor_of self.remove_in = remove_in self.what = what def __call__(self, func_or_cls): if not self.what: self.what = func_or_cls.__name__ + '()' msg, details = self._build_message() if inspect.isfunction(func_or_cls): @six.wraps(func_or_cls) def wrapped(*args, **kwargs): LOG.deprecated(msg, details) return func_or_cls(*args, **kwargs) return wrapped elif inspect.isclass(func_or_cls): orig_init = func_or_cls.__init__ # TODO(tsufiev): change `functools` module to `six` as # soon as six 1.7.4 (with fix for passing `assigned` # argument to underlying `functools.wraps`) is released # and added to the tempest_lib-incubator requrements @functools.wraps(orig_init, assigned=('__name__', '__doc__')) def new_init(self, *args, **kwargs): LOG.deprecated(msg, details) orig_init(self, *args, **kwargs) func_or_cls.__init__ = new_init return func_or_cls else: raise TypeError('deprecated can be used only with functions or ' 'classes') def _get_safe_to_remove_release(self, release): # TODO(dstanek): this method will have to be reimplemented once # when we get to the X release because once we get to the Y # release, what is Y+2? new_release = chr(ord(release) + self.remove_in) if new_release in self._RELEASES: return self._RELEASES[new_release] else: return new_release def _build_message(self): details = dict(what=self.what, as_of=self._RELEASES[self.as_of], remove_in=self._get_safe_to_remove_release(self.as_of)) if self.in_favor_of: details['in_favor_of'] = self.in_favor_of if self.remove_in > 0: msg = self._deprecated_msg_with_alternative else: # There are no plans to remove this function, but it is # now deprecated. msg = self._deprecated_msg_with_alternative_no_removal else: if self.remove_in > 0: msg = self._deprecated_msg_no_alternative else: # There are no plans to remove this function, but it is # now deprecated. msg = self._deprecated_msg_with_no_alternative_no_removal return msg, details
class DeprecatedConfig(Exception): message = _("Fatal call to deprecated config: %(msg)s") def __init__(self, msg): super(Exception, self).__init__(self.message % dict(msg=msg))