diff --git a/lingua_franca/__init__.py b/lingua_franca/__init__.py index 85ecb562..0404403c 100644 --- a/lingua_franca/__init__.py +++ b/lingua_franca/__init__.py @@ -2,3 +2,5 @@ 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 + +from lingua_franca import config diff --git a/lingua_franca/config.py b/lingua_franca/config.py new file mode 100644 index 00000000..06dc9677 --- /dev/null +++ b/lingua_franca/config.py @@ -0,0 +1 @@ +load_langs_on_demand = False diff --git a/lingua_franca/internal.py b/lingua_franca/internal.py index b947dd0d..b6fdee45 100644 --- a/lingua_franca/internal.py +++ b/lingua_franca/internal.py @@ -5,6 +5,8 @@ from sys import version from warnings import warn +from lingua_franca import config + _SUPPORTED_LANGUAGES = ("cs", "da", "de", "en", "es", "fr", "hu", "it", "nl", "pl", "pt", "sv") @@ -457,16 +459,14 @@ def is_error_type(_type): def localized_function_decorator(func): # Wrapper's logic def _call_localized_function(func, *args, **kwargs): + lang_code = None + load_langs_on_demand = config.load_langs_on_demand + unload_language_afterward = False func_signature = signature(func) func_params = list(func_signature.parameters) lang_param_index = func_params.index('lang') full_lang_code = None - # Momentarily assume we're not passing a lang code - lang_code = get_default_lang() - if not lang_code: - raise NoSuchModuleError("No language module loaded.") - # Check if we're passing a lang as a kwarg if 'lang' in kwargs.keys(): lang_param = kwargs['lang'] @@ -487,6 +487,15 @@ def _call_localized_function(func, *args, **kwargs): lang_code = args[lang_param_index] args = args[:lang_param_index] + args[lang_param_index+1:] + # Turns out, we aren't passing a lang code at all + lang_code = lang_code or get_default_lang() + if not lang_code: + if load_langs_on_demand: + raise NoSuchModuleError("No language module loaded " + "and none specified.") + else: + raise NoSuchModuleError("No language module loaded.") + if lang_code not in _SUPPORTED_LANGUAGES: try: tmp = lang_code @@ -528,9 +537,14 @@ def _call_localized_function(func, *args, **kwargs): raise NoSuchModuleError("Module lingua_franca." + _module_name + " not recognized") if lang_code not in _localized_functions[_module_name].keys(): - raise NoSuchModuleError(_module_name + " module of language '" + - lang_code + "' is not currently loaded.") - + if load_langs_on_demand: + load_language(lang_code) + unload_language_afterward = True + else: + raise NoSuchModuleError(_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. @@ -573,6 +587,8 @@ def _call_localized_function(func, *args, **kwargs): # Unload all the stuff we just assembled and imported del localized_func del _module + if unload_language_afterward: + unload_language(lang_code) return r_val # Actual wrapper diff --git a/test/test_localizer.py b/test/test_localizer.py index 4301b316..58b79772 100644 --- a/test/test_localizer.py +++ b/test/test_localizer.py @@ -104,6 +104,24 @@ def test_deprecate_positional_null_lang(self): 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 + 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 + # English should still be loaded, but not Spanish + self.assertEqual(lingua_franca.parse.extract_number("one", lang="en"), + 1) + with self.assertRaises(NoSuchModuleError): + lingua_franca.parse.extract_number("uno", lang="es") + unload_all_languages() + def test_load_language(self): lingua_franca.load_language('en')