diff --git a/.gitignore b/.gitignore index 632a9568..38c7f46a 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,4 @@ venv.bak/ .vscode/ vscode/ *.code-workspace +.vscode-* \ No newline at end of file diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 00000000..d8bd1ec5 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,3 @@ +[MESSAGES CONTROL] + +disable=C0103,C0114,C0115,C0116,W0613 \ No newline at end of file diff --git a/lingua_franca/__init__.py b/lingua_franca/__init__.py index 0404403c..acfaf302 100644 --- a/lingua_franca/__init__.py +++ b/lingua_franca/__init__.py @@ -1,6 +1,15 @@ -from .internal import get_default_lang, set_default_lang, get_default_loc, \ - get_active_langs, _set_active_langs, get_primary_lang_code, \ - get_full_lang_code, resolve_resource_file, load_language, \ - load_languages, unload_language, unload_languages, get_supported_langs +### DO NOT CHANGE THIS IMPORT ORDER ### +from .internal import get_active_langs, get_supported_locs, \ + get_full_lang_code, get_supported_langs, get_default_loc, \ + get_primary_lang_code -from lingua_franca import config +from .configuration import Config + +### END OF IMPORT ORDER ### + +from .internal import get_default_lang, set_default_lang, \ + _set_active_langs, resolve_resource_file, \ + load_language, load_languages, unload_language, unload_languages + + +config = Config() diff --git a/lingua_franca/bracket_expansion.py b/lingua_franca/bracket_expansion.py index 2998e7af..2205dbef 100644 --- a/lingua_franca/bracket_expansion.py +++ b/lingua_franca/bracket_expansion.py @@ -172,4 +172,4 @@ def _expand_tree(self, tree): def expand_parentheses(self): tree = self._parse() - return self._expand_tree(tree) \ No newline at end of file + return self._expand_tree(tree) diff --git a/lingua_franca/config.py b/lingua_franca/config.py deleted file mode 100644 index 06dc9677..00000000 --- a/lingua_franca/config.py +++ /dev/null @@ -1 +0,0 @@ -load_langs_on_demand = False diff --git a/lingua_franca/configuration.py b/lingua_franca/configuration.py new file mode 100644 index 00000000..b738d6f2 --- /dev/null +++ b/lingua_franca/configuration.py @@ -0,0 +1,122 @@ +import json + +from lingua_franca import get_active_langs, get_supported_locs, \ + get_supported_langs, get_primary_lang_code, get_full_lang_code, \ + get_default_loc +from lingua_franca.internal import resolve_resource_file + +default_global_values = \ + { + 'load_langs_on_demand': False + } + + +class LangConfig(dict): + def __init__(self, lang_code): + super().__init__() + if lang_code not in get_supported_locs(): + # DO NOT catch UnsupportedLanguageError! + # If this fails, we want to crash. This can *only* result from + # someone trying to override sanity checks upstairs. There are no + # circumstances under which this should fail and allow the program + # to continue. + lang_code = get_full_lang_code(lang_code) + + resource_file = resolve_resource_file(f'text/{lang_code}/config.json') + try: + with open(resource_file, 'r', encoding='utf-8') as i_file: + default_values = json.load(i_file) + for k in default_values: + self[k] = default_values[k] + except (FileNotFoundError, TypeError): + pass + + +class Config(dict): + def __init__(self): + super().__init__() + self['global'] = dict(default_global_values) + for lang in get_active_langs(): + self.load_lang(lang) + + def load_lang(self, lang): + if all((lang not in get_supported_locs(), + lang in get_supported_langs())): + if lang not in self.keys(): + self[lang] = {} + self[lang]['universal'] = LangConfig(lang) + + full_loc = get_full_lang_code(lang) + else: + full_loc = lang + lang = get_primary_lang_code(lang) + + self[lang][full_loc] = LangConfig(full_loc) + + def _find_setting(self, setting=None, lang=''): + if setting is None: + raise ValueError("lingua_franca.config requires " + "a setting parameter!") + + setting_available_in = [] + possible_locs = [] + + while True: + if setting in self['global']: + setting_available_in.append('global') + if lang == 'global': + break + + lang = lang or get_default_loc() + + if lang in get_supported_langs(): + possible_locs.append((lang, 'universal')) + possible_locs.append((lang, get_full_lang_code(lang))) + + if lang in get_supported_locs(): + primary_lang_code = get_primary_lang_code(lang) + possible_locs.append((primary_lang_code, 'universal')) + possible_locs.append( + (primary_lang_code, get_default_loc(primary_lang_code))) + possible_locs.append((primary_lang_code, lang)) + + for place in possible_locs: + if setting in self[place[0]][place[1]]: + setting_available_in.append(place) + + break + try: + return setting_available_in[-1] + except IndexError: + return None + + def get(self, setting=None, lang=''): + if lang != 'global': + if all((lang, + get_primary_lang_code(lang) not in get_active_langs())): + raise ModuleNotFoundError(f"{lang} is not currently loaded") + + try: + setting_location = self._find_setting(setting, lang) + + if setting_location == 'global': + return self['global'][setting] + return self[setting_location[0]][setting_location[1]][setting] + + except TypeError: + return None + + def set(self, setting=None, value=None, lang='global'): + if lang == 'global': + if setting in self['global']: + self['global'][setting] = value + return + + setting_location = self._find_setting(setting, lang if lang != + 'global' else get_default_loc()) + if all((setting_location, setting_location != 'global')): + self[setting_location[0]][setting_location[1]][setting] = value + return + + raise KeyError( + f"{setting} is not available as a setting for language: '{lang}'") diff --git a/lingua_franca/format.py b/lingua_franca/format.py index d4f195c4..7060eb86 100755 --- a/lingua_franca/format.py +++ b/lingua_franca/format.py @@ -21,6 +21,7 @@ from warnings import warn from os.path import join +from lingua_franca import config from lingua_franca.bracket_expansion import SentenceTreeParser from lingua_franca.internal import localized_function, \ @@ -28,7 +29,7 @@ get_full_lang_code, get_default_lang, get_default_loc, \ is_supported_full_lang, _raise_unsupported_language, \ UnsupportedLanguageError, NoneLangWarning, InvalidLangWarning, \ - FunctionNotLocalizedError + FunctionNotLocalizedError, ConfigVar _REGISTERED_FUNCTIONS = ("nice_number", @@ -241,7 +242,7 @@ def year_format(self, dt, lang, bc): 'res/text')) -@localized_function(run_own_code_on=[UnsupportedLanguageError]) +@localized_function(run_own_code_on=[UnsupportedLanguageError, TypeError]) def nice_number(number, lang='', speech=True, denominators=None): """Format a float to human readable functions @@ -255,12 +256,23 @@ def nice_number(number, lang='', speech=True, denominators=None): Returns: (str): The formatted string. """ + args = locals() + if denominators: + try: + denominators.__iter__ + except (AttributeError, TypeError): + try: + args[denominators] = range(*denominators) + except TypeError: + raise ValueError("nice_number(denominators) must be " + "iterable, or a valid param for range()") + nice_number(**args) return str(number) @localized_function() -def nice_time(dt, lang='', speech=True, use_24hour=False, - use_ampm=False, variant=None): +def nice_time(dt, lang='', speech=True, use_24hour=ConfigVar, + use_ampm=ConfigVar, variant=ConfigVar): """ Format a time to a comfortable human format @@ -281,7 +293,7 @@ def nice_time(dt, lang='', speech=True, use_24hour=False, @localized_function() -def pronounce_number(number, lang='', places=2, short_scale=True, +def pronounce_number(number, lang='', places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -321,8 +333,8 @@ def nice_date(dt, lang='', now=None): return date_time_format.date_format(dt, full_code, now) -def nice_date_time(dt, lang='', now=None, use_24hour=False, - use_ampm=False): +def nice_date_time(dt, lang='', now=None, use_24hour=ConfigVar, + use_ampm=ConfigVar): """ Format a datetime to a pronounceable date and time @@ -346,6 +358,11 @@ def nice_date_time(dt, lang='', now=None, use_24hour=False, full_code = get_full_lang_code(lang) date_time_format.cache(full_code) + if use_24hour is ConfigVar: + use_24hour = config.get(setting='use_24hour', lang=full_code) + if use_ampm is ConfigVar: + use_ampm = config.get(setting='use_ampm', lang=full_code) + return date_time_format.date_time_format(dt, full_code, now, use_24hour, use_ampm) diff --git a/lingua_franca/internal.py b/lingua_franca/internal.py index 27ca74bf..f2df6b26 100644 --- a/lingua_franca/internal.py +++ b/lingua_franca/internal.py @@ -5,8 +5,6 @@ from sys import version from warnings import warn -from lingua_franca import config - _SUPPORTED_LANGUAGES = ("ca", "cs", "da", "de", "en", "es", "fr", "hu", "it", "nl", "pl", "pt", "sl", "sv") @@ -31,10 +29,11 @@ 'sl': 'sl-si', 'sv': 'sv-se', 'tr': 'tr-tr'} - +__default_full_codes = dict(_DEFAULT_FULL_LANG_CODES) __default_lang = None __active_lang_code = None __loaded_langs = [] +__loaded_locs = [] _localized_functions = {} @@ -54,6 +53,13 @@ class FunctionNotLocalizedError(NotImplementedError): pass +class ConfigVar(): + name: str + + def __init__(self, name: str): + self.name = name + + NoneLangWarning = \ DeprecationWarning("Lingua Franca is dropping support" " for 'lang=None' as an explicit" @@ -89,14 +95,30 @@ def get_supported_langs(): return _SUPPORTED_LANGUAGES +def get_supported_locs(): + """ + Returns: + list(str) + """ + return _SUPPORTED_FULL_LOCALIZATIONS + + def get_active_langs(): - """ Get the list of currently-loaded language codes + """ Get the list of currently-loaded languages Returns: list(str) """ return __loaded_langs +def get_active_locs(): + """ Get the list of currently-loaded languages + + Returns: + list(str) + """ + return __loaded_locs + def _set_active_langs(langs=None, override_default=True): """ Set the list of languages to load. @@ -118,15 +140,24 @@ def _set_active_langs(langs=None, override_default=True): if not isinstance(langs, list): raise(TypeError("lingua_franca.internal._set_active_langs expects" " 'str' or 'list'")) - global __loaded_langs, __default_lang + global __loaded_langs, __default_lang, __active_lang_code __loaded_langs = list(dict.fromkeys(langs)) if __default_lang: if override_default or get_primary_lang_code(__default_lang) \ not in __loaded_langs: - if len(__loaded_langs): + if len(__loaded_langs) > 0: set_default_lang(get_full_lang_code(__loaded_langs[0])) else: __default_lang = None + + if not __default_lang: + __active_lang_code = None + elif __active_lang_code is not None: + if get_primary_lang_code(__active_lang_code) != __default_lang: + __cur_default = __default_full_codes[__default_lang] + __active_lang_code = __cur_default if __cur_default in __loaded_locs \ + else _DEFAULT_FULL_LANG_CODES[__default_lang] + _refresh_function_dict() @@ -172,17 +203,32 @@ def load_language(lang): whether 'primary' or 'full') Case-insensitive. """ + from lingua_franca import config if not isinstance(lang, str): raise TypeError("lingua_franca.load_language expects 'str' " "(got " + type(lang) + ")") + loc = None if lang not in _SUPPORTED_LANGUAGES: if lang in _SUPPORTED_FULL_LOCALIZATIONS: + loc = lang lang = get_primary_lang_code(lang) + if lang not in __loaded_langs: __loaded_langs.append(lang) if not __default_lang: - set_default_lang(lang) - _set_active_langs(__loaded_langs) + set_default_lang(loc or lang) + else: + _set_active_langs(__loaded_langs, override_default=False) + if lang not in config.keys(): + config.load_lang(lang) + default_loc = get_default_loc(lang) + if default_loc not in __loaded_locs: + __loaded_locs.append(default_loc) + if all((loc, loc != default_loc)): + set_default_loc(lang, loc) + if all((loc, loc not in config[lang].keys())): + config.load_lang(loc) + __loaded_locs.append(loc) def load_languages(langs): @@ -207,9 +253,36 @@ def unload_language(lang): Args: lang (str): language code to unload """ + from lingua_franca import config + + lang = lang.lower() + # if passed full lang code, unload that locale + if lang in __loaded_locs: + loc = lang + lang = get_primary_lang_code(loc) + + __loaded_locs.remove(loc) + if loc in config[lang]: + config[lang].pop(loc) + + only_remaining_loc_of_this_lang = True + for _loc in __loaded_locs: + if get_primary_lang_code(_loc) == lang: + only_remaining_loc_of_this_lang = False + set_default_loc(lang, _loc) + + if not only_remaining_loc_of_this_lang: + return + else: + locales = [_loc for _loc in __loaded_locs + if get_primary_lang_code(_loc) == lang] + for _loc in locales: + unload_language(_loc) + # unload the whole language if lang in __loaded_langs: __loaded_langs.remove(lang) _set_active_langs(__loaded_langs) + config.pop(lang) def unload_languages(langs): @@ -220,8 +293,7 @@ def unload_languages(langs): langs (list[str]) """ for lang in langs: - __loaded_langs.remove(lang) - _set_active_langs(__loaded_langs) + unload_language(lang) def get_default_lang(): @@ -239,7 +311,7 @@ def get_default_lang(): return __default_lang -def get_default_loc(): +def get_default_loc(lang=''): """ Return the current, localized BCP-47 language code, such as 'en-US' or 'es-ES'. For the default language *family* - which is passed to most parsers and formatters - call `get_default_lang` @@ -247,10 +319,15 @@ def get_default_loc(): The 'localized' portion conforms to ISO 3166-1 alpha-2 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 """ - return __active_lang_code + if not lang: + return __active_lang_code + elif lang.lower() not in _SUPPORTED_LANGUAGES: + + raise UnsupportedLanguageError(lang) + return __default_full_codes[lang.lower()] -def set_default_lang(lang_code): +def set_default_lang(lang_code=''): """ Set the active BCP-47 language code to be used in formatting/parsing Will choose a default localization if passed a primary language family (ex: `set_default_lang("en")` will default to "en-US") @@ -272,22 +349,52 @@ def set_default_lang(lang_code): else: __default_lang = primary_lang_code + if primary_lang_code != lang_code: + if primary_lang_code not in __loaded_langs: + load_language(primary_lang_code) + if lang_code not in __loaded_locs: + load_language(lang_code) + else: + load_language(lang_code) + # make sure the default language is loaded. # also make sure the default language is at the front. # position doesn't matter here, but it clarifies things while debugging. - if __default_lang in __loaded_langs: - __loaded_langs.remove(__default_lang) + if __default_lang not in __loaded_langs: + load_language(__default_lang) + + __loaded_langs.remove(__default_lang) __loaded_langs.insert(0, __default_lang) _refresh_function_dict() if is_supported_full_lang(lang_code): - __active_lang_code = lang_code - else: - __active_lang_code = get_full_lang_code(__default_lang) + set_default_loc(get_primary_lang_code(lang_code), lang_code) + elif lang_code: + set_default_loc(lang_code, get_full_lang_code(lang_code)) -# TODO remove this when invalid lang codes are removed (currently deprecated) +def set_default_loc(lang: str = None, loc: str = None): + if not loc: + raise ValueError("set_default_loc expects a BCP-47 lang code") + if not lang: + lang = get_default_lang() + lang = lang.lower() + loc = loc.lower() + if lang not in _SUPPORTED_LANGUAGES or \ + loc not in _SUPPORTED_FULL_LOCALIZATIONS: + raise UnsupportedLanguageError(f"{lang} - {loc}") + + if get_primary_lang_code(loc) != lang: + raise ValueError(f"Localization '{loc}'' does not correspond to " + "language '{lang}'") + + __default_full_codes[lang] = loc + if lang == get_default_lang(): + global __active_lang_code + __active_lang_code = loc + +# TODO remove this when invalid lang codes are removed (currently deprecated) def get_primary_lang_code(lang=''): if not lang: if lang is None: @@ -366,9 +473,14 @@ def __get_full_lang_code_deprecation_warning(lang=''): Returns: str: A full language code, such as "en-us" or "de-de" """ - if lang is None: - return __active_lang_code.lower() - elif not isinstance(lang, str): + if not lang: + if lang is None: + warn(NoneLangWarning) + if __active_lang_code: + return __active_lang_code.lower() + raise ModuleNotFoundError("No language module loaded!") + + if not isinstance(lang, str): raise TypeError("get_full_lang_code expects str, " "got {}".format(type(lang))) if lang.lower() in _SUPPORTED_FULL_LOCALIZATIONS: @@ -379,7 +491,7 @@ def __get_full_lang_code_deprecation_warning(lang=''): raise UnsupportedLanguageError(lang) -def localized_function(run_own_code_on=[type(None)]): +def localized_function(run_own_code_on=[type(None)], config_vars=[]): """ Decorator which finds localized functions, and calls them, from signatures defined in the top-level modules. See lingua_franca.format or .parse for @@ -419,7 +531,6 @@ def nice_number(number, lang='', speech=True, denominators=None): be run. Calls to the wrapped function will be passed to the appropriate, localized function. - """ # Make sure everything in run_own_code_on is an Error or None BadTypeError = \ @@ -445,11 +556,14 @@ def is_error_type(_type): raise BadTypeError # Begin wrapper + def localized_function_decorator(func): # Wrapper's logic def _call_localized_function(func, *args, **kwargs): + from lingua_franca import config + lang_code = None - load_langs_on_demand = config.load_langs_on_demand + load_langs_on_demand = config.get('load_langs_on_demand') unload_language_afterward = False func_signature = signature(func) func_params = list(func_signature.parameters) @@ -459,7 +573,7 @@ def _call_localized_function(func, *args, **kwargs): # Check if we're passing a lang as a kwarg if 'lang' in kwargs.keys(): lang_param = kwargs['lang'] - if lang_param == None: + if lang_param is None: warn(NoneLangWarning) lang_code = get_default_lang() else: @@ -468,12 +582,14 @@ def _call_localized_function(func, *args, **kwargs): # Check if we're passing a lang as a positional arg elif lang_param_index < len(args): lang_param = args[lang_param_index] - if lang_param == None: + if lang_param is None: warn(NoneLangWarning) lang_code = get_default_lang() elif lang_param in _SUPPORTED_LANGUAGES or \ lang_param in _SUPPORTED_FULL_LOCALIZATIONS: lang_code = args[lang_param_index] + else: + lang_code = lang_param args = args[:lang_param_index] + args[lang_param_index+1:] # Turns out, we aren't passing a lang code at all @@ -509,12 +625,17 @@ def _call_localized_function(func, *args, **kwargs): lang_code = get_default_lang() full_lang_code = get_full_lang_code() __use_tmp = False + # if the lang code is still invalid, abort directly if lang_code not in _SUPPORTED_LANGUAGES: - _raise_unsupported_language(lang_code) + raise UnsupportedLanguageError(lang_param) if __use_tmp: full_lang_code = tmp + if full_lang_code not in __loaded_locs: + if load_langs_on_demand: + load_language(full_lang_code) else: - full_lang_code = get_full_lang_code(lang_code) + full_lang_code = get_full_lang_code(lang_code) if lang_code \ + not in _SUPPORTED_FULL_LOCALIZATIONS else lang_code # Here comes the ugly business. _module_name = func.__module__.split('.')[-1] @@ -525,15 +646,22 @@ def _call_localized_function(func, *args, **kwargs): if _module_name not in _localized_functions.keys(): raise ModuleNotFoundError("Module lingua_franca." + _module_name + " not recognized") - if lang_code not in _localized_functions[_module_name].keys(): + + # Check if language/loc loaded, handle load_langs_on_demand + load_full = full_lang_code not in get_active_locs() + load_primary = lang_code not in get_active_langs() + if load_full or load_primary: if load_langs_on_demand: - load_language(lang_code) + old_langs = __loaded_langs + __loaded_locs + load_language(full_lang_code) unload_language_afterward = True else: - raise ModuleNotFoundError(_module_name + + if not load_full: + raise ModuleNotFoundError(_module_name + " module of language '" + lang_code + "' is not currently loaded.") + func_name = func.__name__.split('.')[-1] # At some point in the past, both the module and the language # were imported/loaded, respectively. @@ -546,7 +674,14 @@ def _call_localized_function(func, *args, **kwargs): # If we didn't find a localized function to correspond with # the wrapped function, we cached NotImplementedError in its # place. - loc_signature = _localized_functions[_module_name][lang_code][func_name] + try: + loc_signature = \ + _localized_functions[_module_name][lang_code][func_name] + except KeyError: + raise ModuleNotFoundError(_module_name + + " module of language '" + + lang_code + + "' is not currently loaded.") if isinstance(loc_signature, type(NotImplementedError())): raise loc_signature @@ -565,6 +700,15 @@ def _call_localized_function(func, *args, **kwargs): del kwargs['lang'] args = tuple(arg for arg in list(args) if arg not in (lang_code, full_lang_code)) + # Now let's substitute any values that are supposed to come from + # lingua_franca.config + for kwarg in loc_signature.parameters: + if all((kwarg not in kwargs, + len(args) < + list(loc_signature.parameters).index(kwarg) + 1)): + config_var = config.get(kwarg, full_lang_code) + if config_var is not None: + kwargs[kwarg] = config_var # Now we call the function, ignoring any kwargs from the # wrapped function that aren't in the localized function. @@ -577,7 +721,10 @@ def _call_localized_function(func, *args, **kwargs): del localized_func del _module if unload_language_afterward: - unload_language(lang_code) + unload_language(full_lang_code) + unload_also = [language for language in \ + __loaded_langs + __loaded_locs if language not in old_langs] + unload_languages(unload_also) return r_val # Actual wrapper @@ -719,7 +866,7 @@ def resolve_resource_file(res_name, data_dir=None): return None # Resource cannot be resolved -def lookup_variant(mappings, key="variant"): +def lookup_variant(mappings, key="variant", config_name=None): """function decorator maps strings to Enums expected by language specific functions mappings can be used to translate values read from configuration files @@ -744,12 +891,25 @@ def lang_variant_function_decorator(func): @wraps(func) def call_function(*args, **kwargs): - if key in kwargs and isinstance(kwargs[key], str): - if kwargs[key] in mappings: - kwargs[key] = mappings[kwargs[key]] + from lingua_franca import config + get_from_config = False + if key not in kwargs: + get_from_config = True if config_name else False + elif isinstance(kwargs[key], ConfigVar): + get_from_config = True + if get_from_config: + if 'lang' in kwargs: + lang = kwargs['lang'] else: - raise ValueError("Unknown variant, mapping does not " - "exist for {v}".format(v=key)) + lang = get_default_loc() + kwargs[key] = config.get((config_name if config_name else key), lang) + if key in kwargs: + if isinstance(kwargs[key], str): + if kwargs[key] in mappings: + kwargs[key] = mappings[kwargs[key]] + else: + raise ValueError("Unknown variant, mapping does not " + "exist for {v}".format(v=key)) return func(*args, **kwargs) return call_function diff --git a/lingua_franca/lang/__init__.py b/lingua_franca/lang/__init__.py index a82a87d3..086a6fb7 100644 --- a/lingua_franca/lang/__init__.py +++ b/lingua_franca/lang/__init__.py @@ -44,7 +44,7 @@ def set_active_lang(lang_code): set_default_lang(lang_code=lang_code) -def get_primary_lang_code(lang=None): +def get_primary_lang_code(lang=''): """ Get the primary language code Args: @@ -58,7 +58,7 @@ def get_primary_lang_code(lang=None): return gplc(lang=lang) -def get_full_lang_code(lang=None): +def get_full_lang_code(lang=''): """ Get the full language code Args: diff --git a/lingua_franca/lang/format_ca.py b/lingua_franca/lang/format_ca.py index b3dc265c..ef9f0c62 100644 --- a/lingua_franca/lang/format_ca.py +++ b/lingua_franca/lang/format_ca.py @@ -14,10 +14,11 @@ # limitations under the License. # +from lingua_franca import config from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_ca import _FRACTION_STRING_CA, \ _NUM_STRING_CA -from lingua_franca.internal import lookup_variant +from lingua_franca.internal import lookup_variant, ConfigVar from enum import IntEnum @@ -133,9 +134,11 @@ def pronounce_number_ca(number, places=2): "bell": TimeVariantCA.BELL, "full_bell": TimeVariantCA.FULL_BELL, "spanish": TimeVariantCA.SPANISH_LIKE -}) -def nice_time_ca(dt, speech=True, use_24hour=False, use_ampm=False, - variant=None): + }, + key="variant", + config_name="time_variant") +def nice_time_ca(dt, speech=True, use_24hour=ConfigVar, use_ampm=False, + variant=ConfigVar): """ Format a time to a comfortable human format For example, generate 'cinc trenta' for speech or '5:30' for diff --git a/lingua_franca/lang/format_cs.py b/lingua_franca/lang/format_cs.py index 841a9693..8711d4c3 100644 --- a/lingua_franca/lang/format_cs.py +++ b/lingua_franca/lang/format_cs.py @@ -15,6 +15,8 @@ # limitations under the License. # +from lingua_franca.internal import ConfigVar + from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_cs import _NUM_STRING_CS, \ _FRACTION_STRING_CS, _LONG_SCALE_CS, _SHORT_SCALE_CS, _SHORT_ORDINAL_CS, _LONG_ORDINAL_CS @@ -68,7 +70,7 @@ def nice_number_cs(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_cs(number, places=2, short_scale=True, scientific=False, +def pronounce_number_cs(number, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -305,7 +307,7 @@ def _long_scale(n): return result -def nice_time_cs(dt, speech=True, use_24hour=True, use_ampm=False): +def nice_time_cs(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format For example, generate 'five thirty' for speech or '5:30' for diff --git a/lingua_franca/lang/format_da.py b/lingua_franca/lang/format_da.py index f1ccdcc1..0b57230e 100644 --- a/lingua_franca/lang/format_da.py +++ b/lingua_franca/lang/format_da.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_da import _EXTRA_SPACE_DA, \ @@ -59,7 +60,7 @@ def nice_number_da(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_da(number, places=2, short_scale=True, scientific=False, +def pronounce_number_da(number, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -214,7 +215,7 @@ def pronounce_ordinal_da(number): return pronounce_number_da(number) + "ende" -def nice_time_da(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_da(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format diff --git a/lingua_franca/lang/format_de.py b/lingua_franca/lang/format_de.py index 9f6c7455..1a15c2e7 100644 --- a/lingua_franca/lang/format_de.py +++ b/lingua_franca/lang/format_de.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_de import _EXTRA_SPACE_DE, \ @@ -58,7 +59,7 @@ def nice_number_de(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_de(number, places=2, short_scale=True, scientific=False, +def pronounce_number_de(number, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -207,7 +208,7 @@ def pronounce_ordinal_de(number): return pronounce_number_de(number) + "ste" -def nice_time_de(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_de(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format For example, generate 'five thirty' for speech or '5:30' for diff --git a/lingua_franca/lang/format_en.py b/lingua_franca/lang/format_en.py index c2911fe8..52b49839 100644 --- a/lingua_franca/lang/format_en.py +++ b/lingua_franca/lang/format_en.py @@ -14,12 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_en import _NUM_STRING_EN, \ _FRACTION_STRING_EN, _LONG_SCALE_EN, _SHORT_SCALE_EN, _SHORT_ORDINAL_EN, _LONG_ORDINAL_EN + def nice_number_en(number, speech=True, denominators=range(1, 21)): """ English helper for nice_number @@ -65,7 +67,7 @@ def nice_number_en(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_en(number, places=2, short_scale=True, scientific=False, +def pronounce_number_en(number, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -302,7 +304,7 @@ def _long_scale(n): return result -def nice_time_en(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_en(dt, speech=True, use_24hour=ConfigVar, use_ampm=ConfigVar): """ Format a time to a comfortable human format For example, generate 'five thirty' for speech or '5:30' for diff --git a/lingua_franca/lang/format_es.py b/lingua_franca/lang/format_es.py index a224af57..c72e7c27 100644 --- a/lingua_franca/lang/format_es.py +++ b/lingua_franca/lang/format_es.py @@ -17,6 +17,8 @@ Format functions for castillian (es-es) """ +from lingua_franca.internal import ConfigVar + from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_es import _NUM_STRING_ES, \ _FRACTION_STRING_ES @@ -153,7 +155,7 @@ def pronounce_number_es(number, places=2): return result -def nice_time_es(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_es(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format diff --git a/lingua_franca/lang/format_fr.py b/lingua_franca/lang/format_fr.py index 5eea39c3..0365818c 100644 --- a/lingua_franca/lang/format_fr.py +++ b/lingua_franca/lang/format_fr.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar + from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_fr import _NUM_STRING_FR, \ _FRACTION_STRING_FR @@ -150,7 +152,7 @@ def pronounce_number_fr(number, places=2): return result -def nice_time_fr(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_fr(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format diff --git a/lingua_franca/lang/format_hu.py b/lingua_franca/lang/format_hu.py index f12a1843..02218a5f 100644 --- a/lingua_franca/lang/format_hu.py +++ b/lingua_franca/lang/format_hu.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_hu import _NUM_POWERS_OF_TEN, \ @@ -74,7 +75,7 @@ def nice_number_hu(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_hu(number, places=2, short_scale=True, scientific=False, +def pronounce_number_hu(number, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -230,7 +231,7 @@ def pronounce_ordinal_hu(number): return root + "edik" if vtype == 1 else root + "adik" -def nice_time_hu(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_hu(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format diff --git a/lingua_franca/lang/format_it.py b/lingua_franca/lang/format_it.py index 52cf4e11..daed230e 100644 --- a/lingua_franca/lang/format_it.py +++ b/lingua_franca/lang/format_it.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_it import _NUM_STRING_IT, \ @@ -76,7 +77,7 @@ def nice_number_it(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_it(number, places=2, short_scale=False, scientific=False): +def pronounce_number_it(number, places=2, short_scale=ConfigVar, scientific=False): """ Convert a number to it's spoken equivalent adapted to italian fron en version @@ -237,7 +238,7 @@ def _long_scale(n): return result -def nice_time_it(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_it(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format adapted to italian fron en version diff --git a/lingua_franca/lang/format_nl.py b/lingua_franca/lang/format_nl.py index cba2110d..a71e20aa 100644 --- a/lingua_franca/lang/format_nl.py +++ b/lingua_franca/lang/format_nl.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from .format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_nl import _NUM_POWERS_OF_TEN, \ @@ -58,7 +59,7 @@ def nice_number_nl(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_nl(number, places=2, short_scale=True, scientific=False, +def pronounce_number_nl(number, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -202,7 +203,7 @@ def pronounce_ordinal_nl(number): return pronounce_number_nl(number) + "ste" -def nice_time_nl(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_nl(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format diff --git a/lingua_franca/lang/format_pl.py b/lingua_franca/lang/format_pl.py index 483a0fc8..8be62d37 100644 --- a/lingua_franca/lang/format_pl.py +++ b/lingua_franca/lang/format_pl.py @@ -18,7 +18,7 @@ from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_pl import _NUM_STRING_PL, \ _FRACTION_STRING_PL, _SHORT_SCALE_PL, _SHORT_ORDINAL_PL, _ALT_ORDINALS_PL -from lingua_franca.internal import FunctionNotLocalizedError +from lingua_franca.internal import FunctionNotLocalizedError, ConfigVar def nice_number_pl(number, speech=True, denominators=range(1, 21)): @@ -61,7 +61,7 @@ def nice_number_pl(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_pl(num, places=2, short_scale=True, scientific=False, +def pronounce_number_pl(num, places=2, short_scale=ConfigVar, scientific=False, ordinals=False, scientific_run=False): """ Convert a number to it's spoken equivalent @@ -232,7 +232,7 @@ def _split_by(n, split=1000): return result -def nice_time_pl(dt, speech=True, use_24hour=True, use_ampm=False): +def nice_time_pl(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format For example, generate 'five thirty' for speech or '5:30' for diff --git a/lingua_franca/lang/format_pt.py b/lingua_franca/lang/format_pt.py index 7c8107ed..da2069c3 100644 --- a/lingua_franca/lang/format_pt.py +++ b/lingua_franca/lang/format_pt.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from lingua_franca.lang.format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_pt import _FRACTION_STRING_PT, \ @@ -115,7 +116,7 @@ def pronounce_number_pt(number, places=2): return result -def nice_time_pt(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_pt(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format For example, generate 'cinco treinta' for speech or '5:30' for diff --git a/lingua_franca/lang/format_sl.py b/lingua_franca/lang/format_sl.py index 6a48802d..5316c527 100644 --- a/lingua_franca/lang/format_sl.py +++ b/lingua_franca/lang/format_sl.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from lingua_franca.lang.common_data_sl import _NUM_STRING_SL, \ _FRACTION_STRING_SL, _LONG_SCALE_SL, _SHORT_SCALE_SL, _SHORT_ORDINAL_SL @@ -67,7 +68,7 @@ def nice_number_sl(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_sl(num, places=2, short_scale=True, scientific=False, +def pronounce_number_sl(num, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -332,7 +333,7 @@ def _long_scale(n): return result -def nice_time_sl(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_sl(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format For example, generate 'pet trideset' for speech or '5:30' for diff --git a/lingua_franca/lang/format_sv.py b/lingua_franca/lang/format_sv.py index 260f03b1..3bac1eb6 100644 --- a/lingua_franca/lang/format_sv.py +++ b/lingua_franca/lang/format_sv.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from lingua_franca.internal import ConfigVar from .format_common import convert_to_mixed_fraction from lingua_franca.lang.common_data_sv import _EXTRA_SPACE_SV, \ @@ -64,7 +65,7 @@ def nice_number_sv(number, speech=True, denominators=range(1, 21)): return return_string -def pronounce_number_sv(number, places=2, short_scale=True, scientific=False, +def pronounce_number_sv(number, places=2, short_scale=ConfigVar, scientific=False, ordinals=False): """ Convert a number to it's spoken equivalent @@ -219,7 +220,7 @@ def pronounce_ordinal_sv(number): return result -def nice_time_sv(dt, speech=True, use_24hour=False, use_ampm=False): +def nice_time_sv(dt, speech=True, use_24hour=ConfigVar, use_ampm=False): """ Format a time to a comfortable human format diff --git a/lingua_franca/lang/parse_ca.py b/lingua_franca/lang/parse_ca.py index 87cfa4a0..766d780c 100644 --- a/lingua_franca/lang/parse_ca.py +++ b/lingua_franca/lang/parse_ca.py @@ -27,13 +27,13 @@ _FEMALE_DETERMINANTS_CA, _FEMALE_ENDINGS_CA, \ _MALE_DETERMINANTS_CA, _MALE_ENDINGS_CA, _GENDERS_CA, \ _TENS_CA, _AFTER_TENS_CA, _HUNDREDS_CA, _BEFORE_HUNDREDS_CA -from lingua_franca.internal import resolve_resource_file +from lingua_franca.internal import resolve_resource_file, ConfigVar from lingua_franca.lang.parse_common import Normalizer import json import re -def is_fractional_ca(input_str, short_scale=True): +def is_fractional_ca(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. @@ -90,7 +90,7 @@ def is_fractional_ca(input_str, short_scale=True): return False -def extract_number_ca(text, short_scale=True, ordinals=False): +def extract_number_ca(text, short_scale=ConfigVar, ordinals=False): """ This function prepares the given text for parsing by making numbers consistent, getting rid of contractions, etc. diff --git a/lingua_franca/lang/parse_cs.py b/lingua_franca/lang/parse_cs.py index 0541cbfd..b791122e 100644 --- a/lingua_franca/lang/parse_cs.py +++ b/lingua_franca/lang/parse_cs.py @@ -27,6 +27,7 @@ import re import json from lingua_franca import resolve_resource_file +from lingua_franca.internal import ConfigVar from lingua_franca.time import now_local @@ -82,7 +83,7 @@ def generate_plurals_cs(originals): _STRING_LONG_ORDINAL_CS = invert_dict(_LONG_ORDINAL_CS) -def _convert_words_to_numbers_cs(text, short_scale=True, ordinals=False): +def _convert_words_to_numbers_cs(text, short_scale=ConfigVar, ordinals=False): """ Convert words in a string into their equivalent numbers. Args: @@ -118,7 +119,7 @@ def _convert_words_to_numbers_cs(text, short_scale=True, ordinals=False): return ' '.join(results) -def _extract_numbers_with_text_cs(tokens, short_scale=True, +def _extract_numbers_with_text_cs(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ Extract all numbers from a list of Tokens, with the words that @@ -160,7 +161,7 @@ def _extract_numbers_with_text_cs(tokens, short_scale=True, return results -def _extract_number_with_text_cs(tokens, short_scale=True, +def _extract_number_with_text_cs(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ This function extracts a number from a list of Tokens. @@ -184,7 +185,7 @@ def _extract_number_with_text_cs(tokens, short_scale=True, def _extract_number_with_text_cs_helper(tokens, - short_scale=True, ordinals=False, + short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ Helper for _extract_number_with_text_en. @@ -579,7 +580,7 @@ def _initialize_number_data(short_scale): return multiplies, string_num_ordinal_cs, string_num_scale_cs -def extract_number_cs(text, short_scale=True, ordinals=False): +def extract_number_cs(text, short_scale=ConfigVar, ordinals=False): """ This function extracts a number from a text string, handles pronunciations in long scale and short scale @@ -1533,7 +1534,7 @@ def date_found(): return [extractedDate, resultStr] -def isFractional_cs(input_str, short_scale=True): +def isFractional_cs(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. @@ -1559,7 +1560,7 @@ def isFractional_cs(input_str, short_scale=True): return False -def extract_numbers_cs(text, short_scale=True, ordinals=False): +def extract_numbers_cs(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. diff --git a/lingua_franca/lang/parse_da.py b/lingua_franca/lang/parse_da.py index c6dc4353..433ea47b 100644 --- a/lingua_franca/lang/parse_da.py +++ b/lingua_franca/lang/parse_da.py @@ -15,13 +15,15 @@ # from datetime import datetime from dateutil.relativedelta import relativedelta + from lingua_franca.lang.parse_common import is_numeric, look_for_fractions, \ extract_numbers_generic, Normalizer from lingua_franca.lang.common_data_da import _DA_NUMBERS from lingua_franca.lang.format_da import pronounce_number_da +from lingua_franca.internal import ConfigVar -def extract_number_da(text, short_scale=True, ordinals=False): +def extract_number_da(text, short_scale=ConfigVar, ordinals=False): """ This function prepares the given text for parsing by making numbers consistent, getting rid of contractions, etc. @@ -768,7 +770,7 @@ def date_found(): return [extractedDate, resultStr] -def is_fractional_da(input_str, short_scale=True): +def is_fractional_da(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. @@ -864,7 +866,7 @@ def normalize_da(text, remove_articles=True): return normalized[1:] # strip the initial space -def extract_numbers_da(text, short_scale=True, ordinals=False): +def extract_numbers_da(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. diff --git a/lingua_franca/lang/parse_de.py b/lingua_franca/lang/parse_de.py index 5f7f7b32..193c4b26 100644 --- a/lingua_franca/lang/parse_de.py +++ b/lingua_franca/lang/parse_de.py @@ -21,6 +21,8 @@ from lingua_franca.lang.common_data_de import _DE_NUMBERS from lingua_franca.lang.format_de import pronounce_number_de +from lingua_franca.internal import ConfigVar + de_numbers = { 'null': 0, 'ein': 1, @@ -141,7 +143,7 @@ def repl(match): return (duration, text) -def extract_number_de(text, short_scale=True, ordinals=False): +def extract_number_de(text, short_scale=ConfigVar, ordinals=False): """ This function prepares the given text for parsing by making numbers consistent, getting rid of contractions, etc. @@ -894,7 +896,7 @@ def date_found(): return [extractedDate, resultStr] -def is_fractional_de(input_str, short_scale=True): +def is_fractional_de(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. @@ -997,7 +999,7 @@ def normalize_de(text, remove_articles=True): return normalized[1:] # strip the initial space -def extract_numbers_de(text, short_scale=True, ordinals=False): +def extract_numbers_de(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. diff --git a/lingua_franca/lang/parse_en.py b/lingua_franca/lang/parse_en.py index 4b0feb4c..ed15baa3 100644 --- a/lingua_franca/lang/parse_en.py +++ b/lingua_franca/lang/parse_en.py @@ -28,10 +28,10 @@ import re import json -from lingua_franca.internal import resolve_resource_file +from lingua_franca.internal import resolve_resource_file, ConfigVar -def _convert_words_to_numbers_en(text, short_scale=True, ordinals=False): +def _convert_words_to_numbers_en(text, short_scale=ConfigVar, ordinals=False): """ Convert words in a string into their equivalent numbers. Args: @@ -66,7 +66,7 @@ def _convert_words_to_numbers_en(text, short_scale=True, ordinals=False): return ' '.join(results) -def _extract_numbers_with_text_en(tokens, short_scale=True, +def _extract_numbers_with_text_en(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ Extract all numbers from a list of Tokens, with the words that @@ -108,7 +108,7 @@ def _extract_numbers_with_text_en(tokens, short_scale=True, return results -def _extract_number_with_text_en(tokens, short_scale=True, +def _extract_number_with_text_en(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ This function extracts a number from a list of Tokens. @@ -132,7 +132,7 @@ def _extract_number_with_text_en(tokens, short_scale=True, def _extract_number_with_text_en_helper(tokens, - short_scale=True, ordinals=False, + short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ Helper for _extract_number_with_text_en. @@ -529,7 +529,7 @@ def _initialize_number_data_en(short_scale, speech=True): return multiplies, string_num_ordinal_en, string_num_scale_en -def extract_number_en(text, short_scale=True, ordinals=False): +def extract_number_en(text, short_scale=ConfigVar, ordinals=False): """ This function extracts a number from a text string, handles pronunciations in long scale and short scale @@ -1420,7 +1420,7 @@ def date_found(): return [extractedDate, resultStr] -def is_fractional_en(input_str, short_scale=True, spoken=True): +def is_fractional_en(input_str, short_scale=ConfigVar, spoken=True): """ This function takes the given text and checks if it is a fraction. @@ -1450,7 +1450,7 @@ def is_fractional_en(input_str, short_scale=True, spoken=True): return False -def extract_numbers_en(text, short_scale=True, ordinals=False): +def extract_numbers_en(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. @@ -1477,6 +1477,6 @@ def numbers_to_digits(self, utterance): return _convert_words_to_numbers_en(utterance, ordinals=None) -def normalize_en(text, remove_articles=True): +def normalize_en(text, remove_articles=ConfigVar): """ English string normalization """ return EnglishNormalizer().normalize(text, remove_articles) diff --git a/lingua_franca/lang/parse_es.py b/lingua_franca/lang/parse_es.py index bd0ef0d2..d42295ed 100644 --- a/lingua_franca/lang/parse_es.py +++ b/lingua_franca/lang/parse_es.py @@ -20,8 +20,10 @@ from lingua_franca.lang.parse_common import * from lingua_franca.lang.common_data_es import _ARTICLES_ES, _STRING_NUM_ES +from lingua_franca.internal import ConfigVar -def is_fractional_es(input_str, short_scale=True): + +def is_fractional_es(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. @@ -55,7 +57,7 @@ def is_fractional_es(input_str, short_scale=True): return False -def extract_number_es(text, short_scale=True, ordinals=False): +def extract_number_es(text, short_scale=ConfigVar, ordinals=False): """ This function prepares the given text for parsing by making numbers consistent, getting rid of contractions, etc. @@ -267,7 +269,7 @@ def es_number(i): return es_number(i) -def extract_numbers_es(text, short_scale=True, ordinals=False): +def extract_numbers_es(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. diff --git a/lingua_franca/lang/parse_fr.py b/lingua_franca/lang/parse_fr.py index 895990f5..7f344a8a 100644 --- a/lingua_franca/lang/parse_fr.py +++ b/lingua_franca/lang/parse_fr.py @@ -22,6 +22,8 @@ from lingua_franca.lang.common_data_fr import _ARTICLES_FR, _NUMBERS_FR, \ _ORDINAL_ENDINGS_FR +from lingua_franca.internal import ConfigVar + def extract_duration_fr(text): """ Convert an french phrase into a number of seconds @@ -366,7 +368,7 @@ def _number_ordinal_fr(words, i): return None -def extract_number_fr(text, short_scale=True, ordinals=False): +def extract_number_fr(text, short_scale=ConfigVar, ordinals=False): """Takes in a string and extracts a number. Args: text (str): the string to extract a number from @@ -991,7 +993,7 @@ def date_found(): return [extractedDate, resultStr] -def is_fractional_fr(input_str, short_scale=True): +def is_fractional_fr(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. Args: @@ -1061,7 +1063,7 @@ def normalize_fr(text, remove_articles=True): return normalized[1:] # strip the initial space -def extract_numbers_fr(text, short_scale=True, ordinals=False): +def extract_numbers_fr(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. diff --git a/lingua_franca/lang/parse_hu.py b/lingua_franca/lang/parse_hu.py index ba4f523b..4e8f1049 100644 --- a/lingua_franca/lang/parse_hu.py +++ b/lingua_franca/lang/parse_hu.py @@ -16,6 +16,7 @@ from datetime import datetime, timedelta from lingua_franca.lang.parse_common import Normalizer +from lingua_franca.internal import ConfigVar class HungarianNormalizer(Normalizer): """ TODO implement language specific normalizer""" diff --git a/lingua_franca/lang/parse_it.py b/lingua_franca/lang/parse_it.py index ed05dd0b..5a444b99 100644 --- a/lingua_franca/lang/parse_it.py +++ b/lingua_franca/lang/parse_it.py @@ -28,8 +28,9 @@ from lingua_franca.lang.common_data_it import _SHORT_ORDINAL_STRING_IT, \ _ARTICLES_IT, _LONG_ORDINAL_STRING_IT, _STRING_NUM_IT +from lingua_franca.internal import ConfigVar -def is_fractional_it(input_str, short_scale=False): +def is_fractional_it(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. Updated to italian from en version 18.8.9 @@ -223,7 +224,7 @@ def _extract_number_long_it(word): return value -def extract_number_it(text, short_scale=False, ordinals=False): +def extract_number_it(text, short_scale=ConfigVar, ordinals=False): """ This function extracts a number from a text string, handles pronunciations in long scale and short scale @@ -1147,7 +1148,7 @@ def get_gender_it(word, context=""): return gender -def extract_numbers_it(text, short_scale=False, ordinals=False): +def extract_numbers_it(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. diff --git a/lingua_franca/lang/parse_nl.py b/lingua_franca/lang/parse_nl.py index 79a1f4be..fdd482a9 100644 --- a/lingua_franca/lang/parse_nl.py +++ b/lingua_franca/lang/parse_nl.py @@ -26,8 +26,9 @@ _STRING_SHORT_ORDINAL_NL, _SUMS_NL import re +from lingua_franca.internal import ConfigVar -def _convert_words_to_numbers_nl(text, short_scale=True, ordinals=False): +def _convert_words_to_numbers_nl(text, short_scale=ConfigVar, ordinals=False): """Convert words in a string into their equivalent numbers. Args: text str: @@ -61,7 +62,7 @@ def _convert_words_to_numbers_nl(text, short_scale=True, ordinals=False): return ' '.join(results) -def _extract_numbers_with_text_nl(tokens, short_scale=True, +def _extract_numbers_with_text_nl(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """Extract all numbers from a list of _Tokens, with the representing words. @@ -100,7 +101,7 @@ def _extract_numbers_with_text_nl(tokens, short_scale=True, return results -def _extract_number_with_text_nl(tokens, short_scale=True, +def _extract_number_with_text_nl(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """This function extracts a number from a list of _Tokens. @@ -122,7 +123,7 @@ def _extract_number_with_text_nl(tokens, short_scale=True, def _extract_number_with_text_nl_helper(tokens, - short_scale=True, ordinals=False, + short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """Helper for _extract_number_with_text_nl. @@ -413,7 +414,7 @@ def _initialize_number_data_nl(short_scale): return multiplies, string_num_ordinal_nl, string_num_scale_nl -def extract_number_nl(text, short_scale=True, ordinals=False): +def extract_number_nl(text, short_scale=ConfigVar, ordinals=False): """Extract a number from a text string The function handles pronunciations in long scale and short scale @@ -1268,7 +1269,7 @@ def date_found(): return [extractedDate, resultStr] -def is_fractional_nl(input_str, short_scale=True): +def is_fractional_nl(input_str, short_scale=ConfigVar): """This function takes the given text and checks if it is a fraction. Args: @@ -1292,7 +1293,7 @@ def is_fractional_nl(input_str, short_scale=True): return False -def extract_numbers_nl(text, short_scale=True, ordinals=False): +def extract_numbers_nl(text, short_scale=ConfigVar, ordinals=False): """Takes in a string and extracts a list of numbers. Args: diff --git a/lingua_franca/lang/parse_pl.py b/lingua_franca/lang/parse_pl.py index e8df170b..ad9fca9e 100644 --- a/lingua_franca/lang/parse_pl.py +++ b/lingua_franca/lang/parse_pl.py @@ -26,6 +26,7 @@ import re +from lingua_franca.internal import ConfigVar def generate_plurals_pl(originals): """ @@ -109,7 +110,7 @@ def generate_fractions_pl(fractions): _REV_FRACTITONS = generate_fractions_pl(invert_dict(_FRACTION_STRING_PL)) -def _convert_words_to_numbers_pl(text, short_scale=True, ordinals=False): +def _convert_words_to_numbers_pl(text, short_scale=ConfigVar, ordinals=False): """ Convert words in a string into their equivalent numbers. Args: @@ -145,7 +146,7 @@ def _convert_words_to_numbers_pl(text, short_scale=True, ordinals=False): return ' '.join(results) -def _extract_numbers_with_text_pl(tokens, short_scale=True, +def _extract_numbers_with_text_pl(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ Extract all numbers from a list of Tokens, with the words that @@ -187,7 +188,7 @@ def _extract_numbers_with_text_pl(tokens, short_scale=True, return results -def _extract_number_with_text_pl(tokens, short_scale=True, +def _extract_number_with_text_pl(tokens, short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ This function extracts a number from a list of Tokens. @@ -209,7 +210,7 @@ def _extract_number_with_text_pl(tokens, short_scale=True, def _extract_number_with_text_pl_helper(tokens, - short_scale=True, ordinals=False, + short_scale=ConfigVar, ordinals=False, fractional_numbers=True): """ Helper for _extract_number_with_text_en. @@ -576,7 +577,7 @@ def _initialize_number_data(short_scale): return multiplies, _STRING_SHORT_ORDINAL_PL, string_num_scale -def extract_number_pl(text, short_scale=True, ordinals=False): +def extract_number_pl(text, short_scale=ConfigVar, ordinals=False): """ This function extracts a number from a text string, handles pronunciations in long scale and short scale @@ -1314,7 +1315,7 @@ def date_found(): return [extractedDate, resultStr] -def isFractional_pl(input_str, short_scale=True): +def isFractional_pl(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. @@ -1332,7 +1333,7 @@ def isFractional_pl(input_str, short_scale=True): return False -def extract_numbers_pl(text, short_scale=True, ordinals=False): +def extract_numbers_pl(text, short_scale=ConfigVar, ordinals=False): """ Takes in a string and extracts a list of numbers. diff --git a/lingua_franca/lang/parse_pt.py b/lingua_franca/lang/parse_pt.py index a17ab107..875dcea7 100644 --- a/lingua_franca/lang/parse_pt.py +++ b/lingua_franca/lang/parse_pt.py @@ -26,13 +26,13 @@ from lingua_franca.lang.common_data_pt import _NUMBERS_PT, \ _FEMALE_DETERMINANTS_PT, _FEMALE_ENDINGS_PT, \ _MALE_DETERMINANTS_PT, _MALE_ENDINGS_PT, _GENDERS_PT -from lingua_franca.internal import resolve_resource_file +from lingua_franca.internal import resolve_resource_file, ConfigVar from lingua_franca.lang.parse_common import Normalizer import json import re -def is_fractional_pt(input_str, short_scale=True): +def is_fractional_pt(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. @@ -66,7 +66,7 @@ def is_fractional_pt(input_str, short_scale=True): return False -def extract_number_pt(text, short_scale=True, ordinals=False): +def extract_number_pt(text, short_scale=ConfigVar, ordinals=False): """ This function prepares the given text for parsing by making numbers consistent, getting rid of contractions, etc. diff --git a/lingua_franca/lang/parse_sv.py b/lingua_franca/lang/parse_sv.py index 8d66c63f..a075a3d4 100644 --- a/lingua_franca/lang/parse_sv.py +++ b/lingua_franca/lang/parse_sv.py @@ -16,9 +16,9 @@ from datetime import datetime from dateutil.relativedelta import relativedelta from .parse_common import is_numeric, look_for_fractions, Normalizer +from lingua_franca.internal import ConfigVar - -def extract_number_sv(text, short_scale=True, ordinals=False): +def extract_number_sv(text, short_scale=ConfigVar, ordinals=False): """ This function prepares the given text for parsing by making numbers consistent, getting rid of contractions, etc. @@ -725,7 +725,7 @@ def date_found(): return [extractedDate, resultStr] -def is_fractional_sv(input_str, short_scale=True): +def is_fractional_sv(input_str, short_scale=ConfigVar): """ This function takes the given text and checks if it is a fraction. diff --git a/lingua_franca/parse.py b/lingua_franca/parse.py index ac7732a8..240c0adc 100644 --- a/lingua_franca/parse.py +++ b/lingua_franca/parse.py @@ -15,11 +15,8 @@ # from difflib import SequenceMatcher -from warnings import warn -from lingua_franca.time import now_local from lingua_franca.internal import populate_localized_function_dict, \ - get_active_langs, get_full_lang_code, get_primary_lang_code, \ - get_default_lang, localized_function, _raise_unsupported_language + get_active_langs, ConfigVar, localized_function _REGISTERED_FUNCTIONS = ("extract_numbers", "extract_number", @@ -67,12 +64,14 @@ def match_one(query, choices): if isinstance(choices, dict): return (choices[best[0]], best[1]) - else: - return best + return best @localized_function() -def extract_numbers(text, short_scale=True, ordinals=False, lang=''): +def extract_numbers(text: str, + short_scale: bool = ConfigVar, + ordinals: bool = ConfigVar, + lang: str = ''): """ Takes in a string and extracts a list of numbers. @@ -90,7 +89,10 @@ def extract_numbers(text, short_scale=True, ordinals=False, lang=''): @localized_function() -def extract_number(text, short_scale=True, ordinals=False, lang=''): +def extract_number(text: str, + short_scale: bool = ConfigVar, + ordinals: bool = ConfigVar, + lang: str = ''): """Takes in a string and extracts a number. Args: @@ -191,7 +193,7 @@ def extract_datetime(text, anchorDate=None, lang='', default_time=None): @localized_function() -def normalize(text, lang='', remove_articles=True): +def normalize(text, lang='', remove_articles=ConfigVar): """Prepare a string for parsing This function prepares the given text for parsing by making @@ -227,7 +229,7 @@ def get_gender(word, context="", lang=''): @localized_function() -def is_fractional(input_str, short_scale=True, lang=''): +def is_fractional(input_str, short_scale=ConfigVar, lang=''): """ This function takes the given text and checks if it is a fraction. Used by most of the number exractors. diff --git a/lingua_franca/res/text/ca-es/config.json b/lingua_franca/res/text/ca-es/config.json new file mode 100644 index 00000000..c4c8d865 --- /dev/null +++ b/lingua_franca/res/text/ca-es/config.json @@ -0,0 +1,7 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false, + "time_variant": "default" +} \ No newline at end of file diff --git a/lingua_franca/res/text/cs-cz/config.json b/lingua_franca/res/text/cs-cz/config.json new file mode 100644 index 00000000..72e5387f --- /dev/null +++ b/lingua_franca/res/text/cs-cz/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": true, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/da-dk/config.json b/lingua_franca/res/text/da-dk/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/da-dk/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/de-de/config.json b/lingua_franca/res/text/de-de/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/de-de/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/en-au/config.json b/lingua_franca/res/text/en-au/config.json new file mode 100644 index 00000000..d3e5b728 --- /dev/null +++ b/lingua_franca/res/text/en-au/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": false, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/en-us/config.json b/lingua_franca/res/text/en-us/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/en-us/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/es-es/config.json b/lingua_franca/res/text/es-es/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/es-es/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/fr-fr/config.json b/lingua_franca/res/text/fr-fr/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/fr-fr/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/hu-hu/config.json b/lingua_franca/res/text/hu-hu/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/hu-hu/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/it-it/config.json b/lingua_franca/res/text/it-it/config.json new file mode 100644 index 00000000..d3e5b728 --- /dev/null +++ b/lingua_franca/res/text/it-it/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": false, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/nl-nl/config.json b/lingua_franca/res/text/nl-nl/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/nl-nl/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/pl-pl/config.json b/lingua_franca/res/text/pl-pl/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/pl-pl/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/pt-pt/config.json b/lingua_franca/res/text/pt-pt/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/pt-pt/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/ru-ru/config.json b/lingua_franca/res/text/ru-ru/config.json new file mode 100644 index 00000000..d3e5b728 --- /dev/null +++ b/lingua_franca/res/text/ru-ru/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": false, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/sl-si/config.json b/lingua_franca/res/text/sl-si/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/sl-si/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/sv-se/config.json b/lingua_franca/res/text/sv-se/config.json new file mode 100644 index 00000000..e204bcf7 --- /dev/null +++ b/lingua_franca/res/text/sv-se/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": true, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/lingua_franca/res/text/tr-tr/config.json b/lingua_franca/res/text/tr-tr/config.json new file mode 100644 index 00000000..d3e5b728 --- /dev/null +++ b/lingua_franca/res/text/tr-tr/config.json @@ -0,0 +1,6 @@ +{ + "short_scale": false, + "remove_articles": true, + "use_24hour": false, + "use_ampm": false +} \ No newline at end of file diff --git a/project-structure.md b/project-structure.md index eda6d2d5..b89125a8 100644 --- a/project-structure.md +++ b/project-structure.md @@ -17,6 +17,7 @@ ├─ res/ (fully localized data, 'en-us' vs 'en-au' and etc.) │ ├─ text/ │ │ ├─ / + | | | ├─ config.json (locale-specific settings) │ │ │ ├─ date_time.json │ │ │ ├─ common words @@ -27,6 +28,9 @@ Ensure that all supported languages are registered in `lingua_franca.internal.py`, in the list `_SUPPORTED_LANGUAGES`. +All locales must have a `config.json` in their resource folder. This can be copied and pasted +from a similar locale, if Lingua Franca has already been localized in the same or a similar language, but must contain all of the settings present in that language's localized functions (see below.) + ## Localizing functions If you are localizing an existing top-level function, there is no need to alter the top-level @@ -63,12 +67,28 @@ What you must do: - Name function arguments exactly as they are named in the top-level modules - You do not need to implement all arguments, but you must name them identically - All arguments must be keyword arguments (except the primary arguments) + - If an argument's default value should be read from `config`, rather than hardcoded, set its + default value to the *data type* `ConfigVar` (see below) - If you need to add new arguments, feel free, but MAKE SURE you add the argument to the top-level function, as a keyword arg. This is the only time you should need to modify the top-level functions while localizing. Ensure that any new arguments are at the end of the function signatures, both in the top-level function, and in your localized function. +If a function argument's default value should be read from config, it should be set +to the *data type* `ConfigVar` (not an instance.) For example, here is `parse.extract_number()`'s +top-level signature: + +```python3 + def extract_number(text: str, + short_scale: bool = ConfigVar, + ordinals: bool = ConfigVar, + lang: str = '') +``` + +Again, take care to ensure that these arguments default to the data type `ConfigVar`, rather +than an instance of `ConfigVar`. + ## Adding new functions Ensure that all functions which will have localized versions are registered in their module's diff --git a/setup.py b/setup.py index 57253d24..da51a390 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def required(requirements_file): setup( name='lingua_franca', - version='0.3.1', + version='0.4.0a1', packages=['lingua_franca', 'lingua_franca.lang'], url='https://github.com/MycroftAI/lingua-franca', license='Apache2.0', diff --git a/test/test_localizer.py b/test/test_localizer.py index 44efcff6..32557290 100644 --- a/test/test_localizer.py +++ b/test/test_localizer.py @@ -1,12 +1,11 @@ import unittest -from sys import version - import lingua_franca import lingua_franca.parse import lingua_franca.format -from lingua_franca.internal import localized_function, _SUPPORTED_LANGUAGES +from lingua_franca.internal import localized_function, _SUPPORTED_LANGUAGES, \ + unload_languages def unload_all_languages(): @@ -14,7 +13,7 @@ def unload_all_languages(): your test util to run them in order. Sadly, spamming this function is easier and probably less onerous for most devs. """ - lingua_franca._set_active_langs([]) + unload_languages(_SUPPORTED_LANGUAGES) def setUpModule(): @@ -100,14 +99,13 @@ class TestLanguageLoading(unittest.TestCase): def test_load_on_demand(self): unload_all_languages() - lingua_franca.load_language("en") - lingua_franca.config.load_langs_on_demand = True + lingua_franca.load_language("en-us") + lingua_franca.config.set(setting='load_langs_on_demand', value=True) self.assertEqual(lingua_franca.parse.extract_number("one", lang="en"), 1) self.assertEqual(lingua_franca.parse.extract_number("uno", lang="es"), 1) - - lingua_franca.config.load_langs_on_demand = False + lingua_franca.config.set(setting='load_langs_on_demand', value=False) # English should still be loaded, but not Spanish self.assertEqual(lingua_franca.parse.extract_number("one", lang="en"), 1) @@ -134,8 +132,6 @@ def test_load_language(self): unload_all_languages() def test_auto_default_language(self): - lingua_franca.load_language('en') - # Load two languages, ensure first is default lingua_franca.load_languages(['en', 'es']) self.assertEqual(lingua_franca.get_default_lang(), 'en') diff --git a/test/test_parse.py b/test/test_parse.py index bc309138..5f322893 100644 --- a/test/test_parse.py +++ b/test/test_parse.py @@ -29,8 +29,8 @@ def setUpModule(): # TODO spin off English tests - load_language('en') - set_default_lang('en') + # load_language('en-us') + set_default_lang('en-us') def tearDownModule(): diff --git a/test/test_parse_da.py b/test/test_parse_da.py index 8d9de64d..2f31e343 100644 --- a/test/test_parse_da.py +++ b/test/test_parse_da.py @@ -16,7 +16,8 @@ import unittest from datetime import datetime, time -from lingua_franca import load_language, unload_language, set_default_lang +from lingua_franca import load_language, unload_language, set_default_lang, \ + get_active_langs, config from lingua_franca.parse import extract_datetime from lingua_franca.parse import extract_number from lingua_franca.parse import normalize @@ -170,6 +171,8 @@ def testExtract(text, expected_date, expected_leftover): def test_extractdatetime_no_time(self): """Check that None is returned if no time is found in sentence.""" + if 'da' not in get_active_langs(): + raise(ValueError(f"{get_active_langs()}")) with self.assertWarns(UserWarning): self.assertEqual(extract_datetime('ingen tid', lang='da-da'), None) diff --git a/test/test_parse_nl.py b/test/test_parse_nl.py index cff8c1c2..af29ebd1 100644 --- a/test/test_parse_nl.py +++ b/test/test_parse_nl.py @@ -34,6 +34,9 @@ def tearDownModule(): class TestParsing(unittest.TestCase): + def setUpClass(): + load_language('nl-nl') + set_default_lang('nl-nl') def test_articles(self): self.assertEqual( normalize("dit is de test", LANG, remove_articles=True),