You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.8 KiB

6 months ago
import locale as pylocale
import logging
import sys
from importlib import import_module
from typing import Any, List, Optional, Tuple
from .config import AVAILABLE_LOCALES, DEFAULT_LOCALE, PROVIDERS
from .generator import Generator
from .utils.loading import list_module
logger = logging.getLogger(__name__)
# identify if python is being run in interactive mode. If so, disable logging.
inREPL = bool(getattr(sys, "ps1", False))
if inREPL:
logger.setLevel(logging.CRITICAL)
else:
logger.debug("Not in REPL -> leaving logger event level as is.")
class Factory:
@classmethod
def create(
cls,
locale: Optional[str] = None,
providers: Optional[List[str]] = None,
generator: Optional[Generator] = None,
includes: Optional[List[str]] = None,
# Should we use weightings (more realistic) or weight every element equally (faster)?
# By default, use weightings for backwards compatibility & realism
use_weighting: bool = True,
**config: Any,
) -> Generator:
if includes is None:
includes = []
# fix locale to package name
locale = locale.replace("-", "_") if locale else DEFAULT_LOCALE
locale = pylocale.normalize(locale).split(".")[0]
if locale not in AVAILABLE_LOCALES:
msg = f"Invalid configuration for faker locale `{locale}`"
raise AttributeError(msg)
config["locale"] = locale
config["use_weighting"] = use_weighting
providers = providers or PROVIDERS
providers += includes
faker = generator or Generator(**config)
for prov_name in providers:
if prov_name == "faker.providers":
continue
prov_cls, lang_found, _ = cls._find_provider_class(prov_name, locale)
provider = prov_cls(faker)
provider.__use_weighting__ = use_weighting
provider.__provider__ = prov_name
provider.__lang__ = lang_found
faker.add_provider(provider)
return faker
@classmethod
def _find_provider_class(
cls,
provider_path: str,
locale: Optional[str] = None,
) -> Tuple[Any, Optional[str], Optional[str]]:
provider_module = import_module(provider_path)
default_locale = getattr(provider_module, "default_locale", "")
if getattr(provider_module, "localized", False):
logger.debug(
"Looking for locale `%s` in provider `%s`.",
locale,
provider_module.__name__,
)
available_locales = list_module(provider_module)
if not locale or locale not in available_locales:
unavailable_locale = locale
locale = default_locale or DEFAULT_LOCALE
logger.debug(
"Specified locale `%s` is not available for "
"provider `%s`. Locale reset to `%s` for this "
"provider.",
unavailable_locale,
provider_module.__name__,
locale,
)
else:
logger.debug(
"Provider `%s` has been localized to `%s`.",
provider_module.__name__,
locale,
)
path = f"{provider_path}.{locale}"
provider_module = import_module(path)
else:
if locale:
logger.debug(
"Provider `%s` does not feature localization. "
"Specified locale `%s` is not utilized for this "
"provider.",
provider_module.__name__,
locale,
)
locale = default_locale = None
return provider_module.Provider, locale, default_locale # type: ignore