Source code for dateparser.languages.loader

from collections import OrderedDict
from copy import deepcopy
from importlib import import_module
from itertools import zip_longest

import regex as re

from ..data import language_locale_dict, language_order
from .locale import Locale

LOCALE_SPLIT_PATTERN = re.compile(r"-(?=[A-Z0-9]+$)")


def _isvalidlocale(locale):
    language = LOCALE_SPLIT_PATTERN.split(locale)[0]
    if language not in language_order:
        return False
    else:
        locales_list = language_locale_dict[language]
        if locale == language or locale in locales_list:
            return True
        else:
            return False


def _filter_valid_locales(locales):
    return [locale for locale in locales if _isvalidlocale(locale)]


def _construct_locales(languages, region):
    if region:
        possible_locales = [language + "-" + region for language in languages]
        locales = _filter_valid_locales(possible_locales)
    else:
        locales = languages
    return locales


[docs] class LocaleDataLoader: """Class that handles loading of locale instances.""" _loaded_languages = {} _loaded_locales = {}
[docs] def get_locale_map( self, languages=None, locales=None, region=None, use_given_order=False, allow_conflicting_locales=False, ): """ Get an ordered mapping with locale codes as keys and corresponding locale instances as values. :param languages: A list of language codes, e.g. ['en', 'es', 'zh-Hant']. If locales are not given, languages and region are used to construct locales to load. :type languages: list :param locales: A list of codes of locales which are to be loaded, e.g. ['fr-PF', 'qu-EC', 'af-NA'] :type locales: list :param region: A region code, e.g. 'IN', '001', 'NE'. If locales are not given, languages and region are used to construct locales to load. :type region: str :param use_given_order: If True, the returned mapping is ordered in the order locales are given. :type use_given_order: bool :param allow_conflicting_locales: if True, locales with same language and different region can be loaded. :type allow_conflicting_locales: bool :return: ordered locale code to locale instance mapping """ return OrderedDict( self._load_data( languages=languages, locales=locales, region=region, use_given_order=use_given_order, allow_conflicting_locales=allow_conflicting_locales, ) )
[docs] def get_locales( self, languages=None, locales=None, region=None, use_given_order=False, allow_conflicting_locales=False, ): """ Yield locale instances. :param languages: A list of language codes, e.g. ['en', 'es', 'zh-Hant']. If locales are not given, languages and region are used to construct locales to load. :type languages: list :param locales: A list of codes of locales which are to be loaded, e.g. ['fr-PF', 'qu-EC', 'af-NA'] :type locales: list :param region: A region code, e.g. 'IN', '001', 'NE'. If locales are not given, languages and region are used to construct locales to load. :type region: str :param use_given_order: If True, the returned mapping is ordered in the order locales are given. :type use_given_order: bool :param allow_conflicting_locales: if True, locales with same language and different region can be loaded. :type allow_conflicting_locales: bool :yield: locale instances """ for _, locale in self._load_data( languages=languages, locales=locales, region=region, use_given_order=use_given_order, allow_conflicting_locales=allow_conflicting_locales, ): yield locale
[docs] def get_locale(self, shortname): """ Get a locale instance. :param shortname: A locale code, e.g. 'fr-PF', 'qu-EC', 'af-NA'. :type shortname: str :return: locale instance """ return list(self.get_locales(locales=[shortname]))[0]
def _load_data( self, languages=None, locales=None, region=None, use_given_order=False, allow_conflicting_locales=False, ): locale_dict = OrderedDict() if locales: invalid_locales = [] for locale in locales: lang_reg = LOCALE_SPLIT_PATTERN.split(locale) if len(lang_reg) == 1: lang_reg.append("") locale_dict[locale] = tuple(lang_reg) if not _isvalidlocale(locale): invalid_locales.append(locale) if invalid_locales: raise ValueError( "Unknown locale(s): %s" % ", ".join(map(repr, invalid_locales)) ) if not allow_conflicting_locales: if len(set(locales)) > len({t[0] for t in locale_dict.values()}): raise ValueError( "Locales should not have same language and different region" ) else: if languages is None: languages = language_order unsupported_languages = set(languages) - set(language_order) if unsupported_languages: raise ValueError( "Unknown language(s): %s" % ", ".join(map(repr, unsupported_languages)) ) if region is None: region = "" locales = _construct_locales(languages, region) locale_dict.update( zip_longest( locales, tuple(zip_longest(languages, [], fillvalue=region)) ) ) if not use_given_order: locale_dict = OrderedDict( sorted(locale_dict.items(), key=lambda x: language_order.index(x[1][0])) ) for shortname, lang_reg in locale_dict.items(): if shortname not in self._loaded_locales: lang, reg = lang_reg if lang in self._loaded_languages: locale = Locale( shortname, language_info=deepcopy(self._loaded_languages[lang]) ) self._loaded_locales[shortname] = locale else: language_info = getattr( import_module("dateparser.data.date_translation_data." + lang), "info", ) locale = Locale(shortname, language_info=deepcopy(language_info)) self._loaded_languages[lang] = language_info self._loaded_locales[shortname] = locale yield shortname, self._loaded_locales[shortname]
default_loader = LocaleDataLoader()