factory.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. # coding=utf-8
  2. from __future__ import unicode_literals
  3. from __future__ import absolute_import
  4. from importlib import import_module
  5. import locale as pylocale
  6. import logging
  7. import sys
  8. from faker import Generator
  9. from faker.config import DEFAULT_LOCALE, PROVIDERS, AVAILABLE_LOCALES
  10. from faker.utils.loading import list_module
  11. logger = logging.getLogger(__name__)
  12. # identify if python is being run in interactive mode. If so, disable logging.
  13. inREPL = bool(getattr(sys, 'ps1', False))
  14. if inREPL:
  15. logger.setLevel(logging.CRITICAL)
  16. else:
  17. logger.debug('Not in REPL -> leaving logger event level as is.')
  18. class Factory(object):
  19. @classmethod
  20. def create(
  21. cls,
  22. locale=None,
  23. providers=None,
  24. generator=None,
  25. includes=None,
  26. **config):
  27. if includes is None:
  28. includes = []
  29. # fix locale to package name
  30. locale = locale.replace('-', '_') if locale else DEFAULT_LOCALE
  31. locale = pylocale.normalize(locale).split('.')[0]
  32. if locale not in AVAILABLE_LOCALES:
  33. msg = 'Invalid configuration for faker locale `{0}`'.format(locale)
  34. raise AttributeError(msg)
  35. config['locale'] = locale
  36. providers = providers or PROVIDERS
  37. providers += includes
  38. faker = generator or Generator(**config)
  39. for prov_name in providers:
  40. if prov_name == 'faker.providers':
  41. continue
  42. prov_cls, lang_found = cls._get_provider_class(prov_name, locale)
  43. provider = prov_cls(faker)
  44. provider.__provider__ = prov_name
  45. provider.__lang__ = lang_found
  46. faker.add_provider(provider)
  47. return faker
  48. @classmethod
  49. def _get_provider_class(cls, provider, locale=''):
  50. provider_class = cls._find_provider_class(provider, locale)
  51. if provider_class:
  52. return provider_class, locale
  53. if locale and locale != DEFAULT_LOCALE:
  54. # fallback to default locale
  55. provider_class = cls._find_provider_class(provider, DEFAULT_LOCALE)
  56. if provider_class:
  57. return provider_class, DEFAULT_LOCALE
  58. # fallback to no locale
  59. provider_class = cls._find_provider_class(provider)
  60. if provider_class:
  61. return provider_class, None
  62. msg = 'Unable to find provider `{0}` with locale `{1}`'.format(
  63. provider, locale)
  64. raise ValueError(msg)
  65. @classmethod
  66. def _find_provider_class(cls, provider_path, locale=None):
  67. provider_module = import_module(provider_path)
  68. if getattr(provider_module, 'localized', False):
  69. logger.debug('Looking for locale `{}` in provider `{}`.'.format(
  70. locale, provider_module.__name__))
  71. available_locales = list_module(provider_module)
  72. if not locale or locale not in available_locales:
  73. unavailable_locale = locale
  74. locale = getattr(
  75. provider_module, 'default_locale', DEFAULT_LOCALE)
  76. logger.debug('Specified locale `{}` is not available for '
  77. 'provider `{}`. Locale reset to `{}` for this '
  78. 'provider.'.format(unavailable_locale,
  79. provider_module.__name__,
  80. locale)
  81. )
  82. else:
  83. logger.debug('Provider `{}` has been localized to `{}`.'.format(
  84. provider_module.__name__, locale))
  85. path = "{provider_path}.{locale}".format(
  86. provider_path=provider_path,
  87. locale=locale,
  88. )
  89. provider_module = import_module(path)
  90. else:
  91. logger.debug('Provider `{}` does not feature localization. '
  92. 'Specified locale `{}` is not utilized for this '
  93. 'provider.'.format(
  94. provider_module.__name__, locale)
  95. )
  96. if locale is not None:
  97. provider_module = import_module(provider_path)
  98. return provider_module.Provider