From dd5211ffa5ae09d8fd0cd43728a25da26dd6fe78 Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Sun, 26 Feb 2023 14:38:47 -0500 Subject: [PATCH] more bulletproofing --- apprise/AppriseLocale.py | 36 ++++++++++++++++++++++-------------- test/test_locale.py | 26 +++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/apprise/AppriseLocale.py b/apprise/AppriseLocale.py index 851547ca66..11862162dd 100644 --- a/apprise/AppriseLocale.py +++ b/apprise/AppriseLocale.py @@ -96,18 +96,12 @@ def __init__(self, language=None): # We're done return - # Add default language - if self.lang: - self.add(self.lang) - - else: + # Add language + if not (self.lang and self.add(self.lang)): # Fall back to our default self.add(self._default_language) - self.lang = self._default_language - logger.debug('Language set to %s', self.lang) - - def add(self, lang): + def add(self, lang, set_default=True): """ Add a language to our list """ @@ -122,13 +116,26 @@ def add(self, lang): # the global namespace only self.__fn_map = getattr(self._gtobjs[lang], self._fn) - except IOError as e: - # This occurs if we can't access/load our translations - logger.debug('IOError: %s' % str(e)) + except FileNotFoundError: + # The translation directory does not exist + logger.debug( + 'Could not load translation path: %s', + join(self._locale_dir, lang)) + + # Fallback + if None not in self._gtobjs: + self._gtobjs[None] = gettext + self.__fn_map = getattr(self._gtobjs[None], self._fn) + if set_default: + self.lang = None return False logger.trace('Loaded language %s', lang) + if set_default: + logger.debug('Language set to %s', self.lang) + self.lang = self._default_language + return True @contextlib.contextmanager @@ -150,9 +157,10 @@ def lang_at(self, lang, mapto=_fn): # Tidy the language lang = AppriseLocale.detect_language(lang, detect_fallback=False) - if lang not in self._gtobjs and not self.add(lang): + if lang not in self._gtobjs and not self.add(lang, set_default=False): if self._default_language not in self._gtobjs \ - and not self.add(self._default_language): + and not self.add(self._default_language, + set_default=False): # Do Nothing yield None diff --git a/test/test_locale.py b/test/test_locale.py index 04c7a790e3..2c5e3a6a5e 100644 --- a/test/test_locale.py +++ b/test/test_locale.py @@ -83,7 +83,7 @@ def test_apprise_locale_gettext_translations(mock_gettext_trans): """ - mock_gettext_trans.side_effect = IOError() + mock_gettext_trans.side_effect = FileNotFoundError() # This throws internally but we handle it gracefully al = AppriseLocale.AppriseLocale() @@ -107,6 +107,10 @@ def test_apprise_locale_gettext_lang_at(): # This throws internally but we handle it gracefully al = AppriseLocale.AppriseLocale() + # Edge Cases + assert al.add('en', set_default=False) is True + assert al.add('en', set_default=True) is True + with al.lang_at('en'): # functions still behave as normal pass @@ -126,6 +130,26 @@ def test_apprise_locale_gettext_lang_at(): # functions still behave as normal assert callable(_) + # Test our initialization when our fallback is a language we do + # not have. This is only done to test edge cases when for whatever + # reason the person who set up apprise does not have the languages + # installed. + fallback = AppriseLocale.AppriseLocale._default_language + with environ('LANG', 'LANGUAGE', 'LC_ALL', 'LC_CTYPE', LANG="en_CA"): + AppriseLocale.AppriseLocale._default_language = 'zz' + al = AppriseLocale.AppriseLocale() + assert al.gettext('test') == 'test' + + # Test case with set_default set to False (so we're still set to 'zz') + assert al.add('zy', set_default=False) is False + assert al.gettext('test') == 'test' + + al.add('ab', set_default=True) + assert al.gettext('test') == 'test' + + assert al.add('zy', set_default=False) is False + AppriseLocale.AppriseLocale._default_language = fallback + @pytest.mark.skipif( 'gettext' not in sys.modules, reason="Requires gettext")