Buckets:
MisterAI/LocalAI_Demo_backends / cpu-diffusers.upgrade-tmp /venv /lib /python3.10 /site-packages /traitlets /config /configurable.py
| """A base class for objects that are configurable.""" | |
| # Copyright (c) IPython Development Team. | |
| # Distributed under the terms of the Modified BSD License. | |
| from __future__ import annotations | |
| import logging | |
| import typing as t | |
| from copy import deepcopy | |
| from textwrap import dedent | |
| from traitlets.traitlets import ( | |
| Any, | |
| Container, | |
| Dict, | |
| HasTraits, | |
| Instance, | |
| TraitType, | |
| default, | |
| observe, | |
| observe_compat, | |
| validate, | |
| ) | |
| from traitlets.utils import warnings | |
| from traitlets.utils.bunch import Bunch | |
| from traitlets.utils.text import indent, wrap_paragraphs | |
| from .loader import Config, DeferredConfig, LazyConfigValue, _is_section_key | |
| # ----------------------------------------------------------------------------- | |
| # Helper classes for Configurables | |
| # ----------------------------------------------------------------------------- | |
| if t.TYPE_CHECKING: | |
| LoggerType = t.Union[logging.Logger, logging.LoggerAdapter[t.Any]] | |
| else: | |
| LoggerType = t.Any | |
| class ConfigurableError(Exception): | |
| pass | |
| class MultipleInstanceError(ConfigurableError): | |
| pass | |
| # ----------------------------------------------------------------------------- | |
| # Configurable implementation | |
| # ----------------------------------------------------------------------------- | |
| class Configurable(HasTraits): | |
| config = Instance(Config, (), {}) | |
| parent = Instance("traitlets.config.configurable.Configurable", allow_none=True) | |
| def __init__(self, **kwargs: t.Any) -> None: | |
| """Create a configurable given a config config. | |
| Parameters | |
| ---------- | |
| config : Config | |
| If this is empty, default values are used. If config is a | |
| :class:`Config` instance, it will be used to configure the | |
| instance. | |
| parent : Configurable instance, optional | |
| The parent Configurable instance of this object. | |
| Notes | |
| ----- | |
| Subclasses of Configurable must call the :meth:`__init__` method of | |
| :class:`Configurable` *before* doing anything else and using | |
| :func:`super`:: | |
| class MyConfigurable(Configurable): | |
| def __init__(self, config=None): | |
| super(MyConfigurable, self).__init__(config=config) | |
| # Then any other code you need to finish initialization. | |
| This ensures that instances will be configured properly. | |
| """ | |
| parent = kwargs.pop("parent", None) | |
| if parent is not None: | |
| # config is implied from parent | |
| if kwargs.get("config", None) is None: | |
| kwargs["config"] = parent.config | |
| self.parent = parent | |
| config = kwargs.pop("config", None) | |
| # load kwarg traits, other than config | |
| super().__init__(**kwargs) | |
| # record traits set by config | |
| config_override_names = set() | |
| def notice_config_override(change: Bunch) -> None: | |
| """Record traits set by both config and kwargs. | |
| They will need to be overridden again after loading config. | |
| """ | |
| if change.name in kwargs: | |
| config_override_names.add(change.name) | |
| self.observe(notice_config_override) | |
| # load config | |
| if config is not None: | |
| # We used to deepcopy, but for now we are trying to just save | |
| # by reference. This *could* have side effects as all components | |
| # will share config. In fact, I did find such a side effect in | |
| # _config_changed below. If a config attribute value was a mutable type | |
| # all instances of a component were getting the same copy, effectively | |
| # making that a class attribute. | |
| # self.config = deepcopy(config) | |
| self.config = config | |
| else: | |
| # allow _config_default to return something | |
| self._load_config(self.config) | |
| self.unobserve(notice_config_override) | |
| for name in config_override_names: | |
| setattr(self, name, kwargs[name]) | |
| # ------------------------------------------------------------------------- | |
| # Static trait notifications | |
| # ------------------------------------------------------------------------- | |
| def section_names(cls) -> list[str]: | |
| """return section names as a list""" | |
| return [ | |
| c.__name__ | |
| for c in reversed(cls.__mro__) | |
| if issubclass(c, Configurable) and issubclass(cls, c) | |
| ] | |
| def _find_my_config(self, cfg: Config) -> t.Any: | |
| """extract my config from a global Config object | |
| will construct a Config object of only the config values that apply to me | |
| based on my mro(), as well as those of my parent(s) if they exist. | |
| If I am Bar and my parent is Foo, and their parent is Tim, | |
| this will return merge following config sections, in this order:: | |
| [Bar, Foo.Bar, Tim.Foo.Bar] | |
| With the last item being the highest priority. | |
| """ | |
| cfgs = [cfg] | |
| if self.parent: | |
| cfgs.append(self.parent._find_my_config(cfg)) | |
| my_config = Config() | |
| for c in cfgs: | |
| for sname in self.section_names(): | |
| # Don't do a blind getattr as that would cause the config to | |
| # dynamically create the section with name Class.__name__. | |
| if c._has_section(sname): | |
| my_config.merge(c[sname]) | |
| return my_config | |
| def _load_config( | |
| self, | |
| cfg: Config, | |
| section_names: list[str] | None = None, | |
| traits: dict[str, TraitType[t.Any, t.Any]] | None = None, | |
| ) -> None: | |
| """load traits from a Config object""" | |
| if traits is None: | |
| traits = self.traits(config=True) | |
| if section_names is None: | |
| section_names = self.section_names() | |
| my_config = self._find_my_config(cfg) | |
| # hold trait notifications until after all config has been loaded | |
| with self.hold_trait_notifications(): | |
| for name, config_value in my_config.items(): | |
| if name in traits: | |
| if isinstance(config_value, LazyConfigValue): | |
| # ConfigValue is a wrapper for using append / update on containers | |
| # without having to copy the initial value | |
| initial = getattr(self, name) | |
| config_value = config_value.get_value(initial) | |
| elif isinstance(config_value, DeferredConfig): | |
| # DeferredConfig tends to come from CLI/environment variables | |
| config_value = config_value.get_value(traits[name]) | |
| # We have to do a deepcopy here if we don't deepcopy the entire | |
| # config object. If we don't, a mutable config_value will be | |
| # shared by all instances, effectively making it a class attribute. | |
| setattr(self, name, deepcopy(config_value)) | |
| elif not _is_section_key(name) and not isinstance(config_value, Config): | |
| from difflib import get_close_matches | |
| if isinstance(self, LoggingConfigurable): | |
| assert self.log is not None | |
| warn = self.log.warning | |
| else: | |
| def warn(msg: t.Any) -> None: | |
| return warnings.warn(msg, UserWarning, stacklevel=9) | |
| matches = get_close_matches(name, traits) | |
| msg = f"Config option `{name}` not recognized by `{self.__class__.__name__}`." | |
| if len(matches) == 1: | |
| msg += f" Did you mean `{matches[0]}`?" | |
| elif len(matches) >= 1: | |
| msg += " Did you mean one of: `{matches}`?".format( | |
| matches=", ".join(sorted(matches)) | |
| ) | |
| warn(msg) | |
| def _config_changed(self, change: Bunch) -> None: | |
| """Update all the class traits having ``config=True`` in metadata. | |
| For any class trait with a ``config`` metadata attribute that is | |
| ``True``, we update the trait with the value of the corresponding | |
| config entry. | |
| """ | |
| # Get all traits with a config metadata entry that is True | |
| traits = self.traits(config=True) | |
| # We auto-load config section for this class as well as any parent | |
| # classes that are Configurable subclasses. This starts with Configurable | |
| # and works down the mro loading the config for each section. | |
| section_names = self.section_names() | |
| self._load_config(change.new, traits=traits, section_names=section_names) | |
| def update_config(self, config: Config) -> None: | |
| """Update config and load the new values""" | |
| # traitlets prior to 4.2 created a copy of self.config in order to trigger change events. | |
| # Some projects (IPython < 5) relied upon one side effect of this, | |
| # that self.config prior to update_config was not modified in-place. | |
| # For backward-compatibility, we must ensure that self.config | |
| # is a new object and not modified in-place, | |
| # but config consumers should not rely on this behavior. | |
| self.config = deepcopy(self.config) | |
| # load config | |
| self._load_config(config) | |
| # merge it into self.config | |
| self.config.merge(config) | |
| # TODO: trigger change event if/when dict-update change events take place | |
| # DO NOT trigger full trait-change | |
| def class_get_help(cls, inst: HasTraits | None = None) -> str: | |
| """Get the help string for this class in ReST format. | |
| If `inst` is given, its current trait values will be used in place of | |
| class defaults. | |
| """ | |
| assert inst is None or isinstance(inst, cls) | |
| final_help = [] | |
| base_classes = ", ".join(p.__name__ for p in cls.__bases__) | |
| final_help.append(f"{cls.__name__}({base_classes}) options") | |
| final_help.append(len(final_help[0]) * "-") | |
| for _, v in sorted(cls.class_traits(config=True).items()): | |
| help = cls.class_get_trait_help(v, inst) | |
| final_help.append(help) | |
| return "\n".join(final_help) | |
| def class_get_trait_help( | |
| cls, | |
| trait: TraitType[t.Any, t.Any], | |
| inst: HasTraits | None = None, | |
| helptext: str | None = None, | |
| ) -> str: | |
| """Get the helptext string for a single trait. | |
| :param inst: | |
| If given, its current trait values will be used in place of | |
| the class default. | |
| :param helptext: | |
| If not given, uses the `help` attribute of the current trait. | |
| """ | |
| assert inst is None or isinstance(inst, cls) | |
| lines = [] | |
| header = f"--{cls.__name__}.{trait.name}" | |
| if isinstance(trait, (Container, Dict)): | |
| multiplicity = trait.metadata.get("multiplicity", "append") | |
| if isinstance(trait, Dict): | |
| sample_value = "<key-1>=<value-1>" | |
| else: | |
| sample_value = "<%s-item-1>" % trait.__class__.__name__.lower() | |
| if multiplicity == "append": | |
| header = f"{header}={sample_value}..." | |
| else: | |
| header = f"{header} {sample_value}..." | |
| else: | |
| header = f"{header}=<{trait.__class__.__name__}>" | |
| # header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__) | |
| lines.append(header) | |
| if helptext is None: | |
| helptext = trait.help | |
| if helptext != "": | |
| helptext = "\n\n".join(wrap_paragraphs(helptext, 76)) | |
| lines.append(indent(helptext)) | |
| if "Enum" in trait.__class__.__name__: | |
| # include Enum choices | |
| lines.append(indent("Choices: %s" % trait.info())) | |
| if inst is not None: | |
| lines.append(indent(f"Current: {getattr(inst, trait.name or '')!r}")) | |
| else: | |
| try: | |
| dvr = trait.default_value_repr() | |
| except Exception: | |
| dvr = None # ignore defaults we can't construct | |
| if dvr is not None: | |
| if len(dvr) > 64: | |
| dvr = dvr[:61] + "..." | |
| lines.append(indent("Default: %s" % dvr)) | |
| return "\n".join(lines) | |
| def class_print_help(cls, inst: HasTraits | None = None) -> None: | |
| """Get the help string for a single trait and print it.""" | |
| print(cls.class_get_help(inst)) # noqa: T201 | |
| def _defining_class( | |
| cls, trait: TraitType[t.Any, t.Any], classes: t.Sequence[type[HasTraits]] | |
| ) -> type[Configurable]: | |
| """Get the class that defines a trait | |
| For reducing redundant help output in config files. | |
| Returns the current class if: | |
| - the trait is defined on this class, or | |
| - the class where it is defined would not be in the config file | |
| Parameters | |
| ---------- | |
| trait : Trait | |
| The trait to look for | |
| classes : list | |
| The list of other classes to consider for redundancy. | |
| Will return `cls` even if it is not defined on `cls` | |
| if the defining class is not in `classes`. | |
| """ | |
| defining_cls = cls | |
| assert trait.name is not None | |
| for parent in cls.mro(): | |
| if ( | |
| issubclass(parent, Configurable) | |
| and parent in classes | |
| and parent.class_own_traits(config=True).get(trait.name, None) is trait | |
| ): | |
| defining_cls = parent | |
| return defining_cls | |
| def class_config_section(cls, classes: t.Sequence[type[HasTraits]] | None = None) -> str: | |
| """Get the config section for this class. | |
| Parameters | |
| ---------- | |
| classes : list, optional | |
| The list of other classes in the config file. | |
| Used to reduce redundant information. | |
| """ | |
| def c(s: str) -> str: | |
| """return a commented, wrapped block.""" | |
| s = "\n\n".join(wrap_paragraphs(s, 78)) | |
| return "## " + s.replace("\n", "\n# ") | |
| # section header | |
| breaker = "#" + "-" * 78 | |
| parent_classes = ", ".join(p.__name__ for p in cls.__bases__ if issubclass(p, Configurable)) | |
| s = f"# {cls.__name__}({parent_classes}) configuration" | |
| lines = [breaker, s, breaker] | |
| # get the description trait | |
| desc = cls.class_traits().get("description") | |
| if desc: | |
| desc = desc.default_value | |
| if not desc: | |
| # no description from trait, use __doc__ | |
| desc = getattr(cls, "__doc__", "") # type:ignore[arg-type] | |
| if desc: | |
| lines.append(c(desc)) # type:ignore[arg-type] | |
| lines.append("") | |
| for name, trait in sorted(cls.class_traits(config=True).items()): | |
| default_repr = trait.default_value_repr() | |
| if classes: | |
| defining_class = cls._defining_class(trait, classes) | |
| else: | |
| defining_class = cls | |
| if defining_class is cls: | |
| # cls owns the trait, show full help | |
| if trait.help: | |
| lines.append(c(trait.help)) | |
| if "Enum" in type(trait).__name__: | |
| # include Enum choices | |
| lines.append("# Choices: %s" % trait.info()) | |
| lines.append("# Default: %s" % default_repr) | |
| else: | |
| # Trait appears multiple times and isn't defined here. | |
| # Truncate help to first line + "See also Original.trait" | |
| if trait.help: | |
| lines.append(c(trait.help.split("\n", 1)[0])) | |
| lines.append(f"# See also: {defining_class.__name__}.{name}") | |
| lines.append(f"# c.{cls.__name__}.{name} = {default_repr}") | |
| lines.append("") | |
| return "\n".join(lines) | |
| def class_config_rst_doc(cls) -> str: | |
| """Generate rST documentation for this class' config options. | |
| Excludes traits defined on parent classes. | |
| """ | |
| lines = [] | |
| classname = cls.__name__ | |
| for _, trait in sorted(cls.class_traits(config=True).items()): | |
| ttype = trait.__class__.__name__ | |
| if not trait.name: | |
| continue | |
| termline = classname + "." + trait.name | |
| # Choices or type | |
| if "Enum" in ttype: | |
| # include Enum choices | |
| termline += " : " + trait.info_rst() # type:ignore[attr-defined] | |
| else: | |
| termline += " : " + ttype | |
| lines.append(termline) | |
| # Default value | |
| try: | |
| dvr = trait.default_value_repr() | |
| except Exception: | |
| dvr = None # ignore defaults we can't construct | |
| if dvr is not None: | |
| if len(dvr) > 64: | |
| dvr = dvr[:61] + "..." | |
| # Double up backslashes, so they get to the rendered docs | |
| dvr = dvr.replace("\\n", "\\\\n") | |
| lines.append(indent("Default: ``%s``" % dvr)) | |
| lines.append("") | |
| help = trait.help or "No description" | |
| lines.append(indent(dedent(help))) | |
| # Blank line | |
| lines.append("") | |
| return "\n".join(lines) | |
| class LoggingConfigurable(Configurable): | |
| """A parent class for Configurables that log. | |
| Subclasses have a log trait, and the default behavior | |
| is to get the logger from the currently running Application. | |
| """ | |
| log = Any(help="Logger or LoggerAdapter instance", allow_none=False) | |
| def _validate_log(self, proposal: Bunch) -> LoggerType: | |
| if not isinstance(proposal.value, (logging.Logger, logging.LoggerAdapter)): | |
| # warn about unsupported type, but be lenient to allow for duck typing | |
| warnings.warn( | |
| f"{self.__class__.__name__}.log should be a Logger or LoggerAdapter," | |
| f" got {proposal.value}.", | |
| UserWarning, | |
| stacklevel=2, | |
| ) | |
| return t.cast(LoggerType, proposal.value) | |
| def _log_default(self) -> LoggerType: | |
| if isinstance(self.parent, LoggingConfigurable): | |
| assert self.parent is not None | |
| return t.cast(logging.Logger, self.parent.log) | |
| from traitlets import log | |
| return log.get_logger() | |
| def _get_log_handler(self) -> logging.Handler | None: | |
| """Return the default Handler | |
| Returns None if none can be found | |
| Deprecated, this now returns the first log handler which may or may | |
| not be the default one. | |
| """ | |
| if not self.log: | |
| return None | |
| logger: logging.Logger = ( | |
| self.log if isinstance(self.log, logging.Logger) else self.log.logger | |
| ) | |
| if not getattr(logger, "handlers", None): | |
| # no handlers attribute or empty handlers list | |
| return None | |
| return logger.handlers[0] | |
| CT = t.TypeVar("CT", bound="SingletonConfigurable") | |
| class SingletonConfigurable(LoggingConfigurable): | |
| """A configurable that only allows one instance. | |
| This class is for classes that should only have one instance of itself | |
| or *any* subclass. To create and retrieve such a class use the | |
| :meth:`SingletonConfigurable.instance` method. | |
| """ | |
| _instance = None | |
| def _walk_mro(cls) -> t.Generator[type[SingletonConfigurable], None, None]: | |
| """Walk the cls.mro() for parent classes that are also singletons | |
| For use in instance() | |
| """ | |
| for subclass in cls.mro(): | |
| if ( | |
| issubclass(cls, subclass) | |
| and issubclass(subclass, SingletonConfigurable) | |
| and subclass != SingletonConfigurable | |
| ): | |
| yield subclass | |
| def clear_instance(cls) -> None: | |
| """unset _instance for this class and singleton parents.""" | |
| if not cls.initialized(): | |
| return | |
| for subclass in cls._walk_mro(): | |
| if isinstance(subclass._instance, cls): | |
| # only clear instances that are instances | |
| # of the calling class | |
| subclass._instance = None # type:ignore[unreachable] | |
| def instance(cls: type[CT], *args: t.Any, **kwargs: t.Any) -> CT: | |
| """Returns a global instance of this class. | |
| This method create a new instance if none have previously been created | |
| and returns a previously created instance is one already exists. | |
| The arguments and keyword arguments passed to this method are passed | |
| on to the :meth:`__init__` method of the class upon instantiation. | |
| Examples | |
| -------- | |
| Create a singleton class using instance, and retrieve it:: | |
| >>> from traitlets.config.configurable import SingletonConfigurable | |
| >>> class Foo(SingletonConfigurable): pass | |
| >>> foo = Foo.instance() | |
| >>> foo == Foo.instance() | |
| True | |
| Create a subclass that is retrieved using the base class instance:: | |
| >>> class Bar(SingletonConfigurable): pass | |
| >>> class Bam(Bar): pass | |
| >>> bam = Bam.instance() | |
| >>> bam == Bar.instance() | |
| True | |
| """ | |
| # Create and save the instance | |
| if cls._instance is None: | |
| inst = cls(*args, **kwargs) | |
| # Now make sure that the instance will also be returned by | |
| # parent classes' _instance attribute. | |
| for subclass in cls._walk_mro(): | |
| subclass._instance = inst | |
| if isinstance(cls._instance, cls): | |
| return cls._instance | |
| else: | |
| raise MultipleInstanceError( | |
| f"An incompatible sibling of '{cls.__name__}' is already instantiated" | |
| f" as singleton: {type(cls._instance).__name__}" | |
| ) | |
| def initialized(cls) -> bool: | |
| """Has an instance been created?""" | |
| return hasattr(cls, "_instance") and cls._instance is not None | |
Xet Storage Details
- Size:
- 22.5 kB
- Xet hash:
- 07989bf376895f56f81b9ecfaf68893e3ba8d452882734669013633b3a7e981b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.