Source code for mimesis.providers.generic
"""Provides all at one."""
import inspect
import typing as t
from mimesis.locales import Locale
from mimesis.providers.base import (
BaseDataProvider,
BaseProvider,
ProviderRegistry,
)
from mimesis.types import MissingSeed, Seed
__all__ = ["Generic"]
[docs]
class Generic(BaseProvider):
"""Class which contain all providers at one."""
[docs]
def __init__(
self,
locale: Locale = Locale.DEFAULT,
seed: Seed = MissingSeed,
) -> None:
"""Initialize attributes lazily."""
super().__init__(seed=seed)
self.locale = locale
for name, provider_cls in ProviderRegistry.get_all().items():
if provider_cls is Generic:
continue
if issubclass(provider_cls, BaseDataProvider):
setattr(self, f"_{name}", provider_cls)
elif issubclass(provider_cls, BaseProvider):
setattr(self, name, provider_cls(seed=self.seed))
def __getattr__(self, attrname: str) -> t.Any:
"""Get attribute without an underscore.
:param attrname: Attribute name.
:return: An attribute.
"""
attribute = object.__getattribute__(self, "_" + attrname)
if attribute and callable(attribute):
self.__dict__[attrname] = attribute(
self.locale,
self.seed,
)
return self.__dict__[attrname]
return None
def __dir__(self) -> list[str]:
"""Available data providers.
:return: List of attributes.
"""
attributes = []
exclude = list(BaseProvider().__dict__.keys())
# Exclude locale explicitly because
# it is not a provider.
exclude.append("locale")
for attr in self.__dict__:
if attr not in exclude:
if attr.startswith("_"):
attribute = attr.replace("_", "", 1)
attributes.append(attribute)
else:
attributes.append(attr)
return attributes
[docs]
def reseed(self, seed: Seed = MissingSeed) -> None:
"""Reseed the internal random generator.
Overrides method `BaseProvider.reseed()`.
:param seed: Seed for random.
:return: None.
"""
# Make sure to reseed the random generator on Generic itself.
super().reseed(seed)
for attr in self.__dir__():
try:
provider = getattr(self, attr)
provider.reseed(seed)
except AttributeError:
continue
[docs]
def add_provider(self, cls: t.Type[BaseProvider], **kwargs: t.Any) -> None:
"""Adds a custom provider to a Generic() object.
:param cls: Custom provider.
:param kwargs: Keyword arguments for provider.
:raises TypeError: if cls is Generic, if cls is not
class or is not a subclass of BaseProvider.
:return: Absolutely none.
"""
if inspect.isclass(cls):
if not issubclass(cls, BaseProvider):
raise TypeError(
"The provider must be a "
"subclass of mimesis.providers.BaseProvider"
)
try:
name = cls.Meta.name
except AttributeError:
name = cls.__name__.lower()
# Enforce the same seed is used across all providers.
kwargs.pop("seed", None)
instance = cls(seed=self.seed, **kwargs)
if isinstance(instance, Generic):
raise TypeError("Cannot add Generic instance to itself.")
setattr(self, name, instance)
else:
raise TypeError("The provider must be a class")
[docs]
def add_providers(self, *providers: t.Type[BaseProvider]) -> None:
"""Adds multiple custom providers to a Generic() object.
This method is a convenience method for adding multiple providers
at once. It is equivalent to calling :meth:`add_provider` for each
provider in the list of providers.
Example:
>>> from mimesis import Generic
>>> from myproviders import ProviderA, ProviderB
>>> g = Generic()
>>> g.add_providers(ProviderA, ProviderB)
>>> g.providera.never()
>>> g.providerb.gonna()
If you want to pass keyword arguments to the providers, you can
do so by using :meth:`add_provider` instead.
:param providers: Custom providers.
:return: None
"""
for provider in providers:
self.add_provider(provider)
def __iadd__(self, other: t.Type[BaseProvider]) -> "Generic":
"""Adds a custom provider to a Generic() object.
:param other: Custom provider.
:return: None
:raises TypeError: if cls is not class or is not a subclass
of BaseProvider.
"""
self.add_provider(other)
return self
def __str__(self) -> str:
"""Human-readable representation of locale."""
return f"{self.__class__.__name__} <{self.locale}>"