diff options
author | Daniel Schadt <kingdread@gmx.de> | 2022-07-08 02:42:44 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2022-07-08 02:42:44 +0200 |
commit | bb6714e9d7468465f23bf0e163d06517de397dbe (patch) | |
tree | aaabb03f1e7f8f41259815e5f03fcca14ef124f2 | |
parent | 210650683ccbfa35da293cd1b43057a780349d91 (diff) | |
download | fietsboek-bb6714e9d7468465f23bf0e163d06517de397dbe.tar.gz fietsboek-bb6714e9d7468465f23bf0e163d06517de397dbe.tar.bz2 fietsboek-bb6714e9d7468465f23bf0e163d06517de397dbe.zip |
better loading in util.read_localized_resource
The other code kinda assumed that we can turn the resource path into a
package by replacing the slashes (path separators) with dots. That
turned out to not really work in the end, especially if the resource
subfolders don't have a __init__.py in there.
This uses the .files() API (available in Python 3.9 and backported in
importlib_resources) to better handle folders in the resources.
-rw-r--r-- | MANIFEST.in | 2 | ||||
-rw-r--r-- | fietsboek/util.py | 39 | ||||
-rw-r--r-- | setup.py | 1 |
3 files changed, 26 insertions, 16 deletions
diff --git a/MANIFEST.in b/MANIFEST.in index 0d8bb87..38898e6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,7 @@ include *.txt *.ini *.cfg *.rst recursive-include fietsboek *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2 recursive-include fietsboek/static * -recursive-include fietsboek/locale *.pot *.po *.mo +recursive-include fietsboek/locale *.pot *.po *.mo *.html recursive-include tests * recursive-exclude * __pycache__ recursive-exclude * *.py[co] diff --git a/fietsboek/util.py b/fietsboek/util.py index e24f96a..7ca0d62 100644 --- a/fietsboek/util.py +++ b/fietsboek/util.py @@ -2,8 +2,9 @@ import random import string import datetime -import importlib.resources +# Compat for Python < 3.9 +import importlib_resources import babel import markdown import bleach @@ -263,29 +264,37 @@ def check_password_constraints(password, repeat_password=None): raise ValueError(_("password_constraint.length")) -def read_localized_resource(locale_name, path): +def read_localized_resource(locale_name, path, raise_on_error=False): """Reads a localized resource. Localized resources are located in the ``fietsboek/locale/**`` directory. - Note that ``path`` may contain slashes, which are automatically replaced - with the right separators. + Note that ``path`` may contain slashes. If the resource could not be found, a placeholder string is returned instead. :param locale_name: Name of the locale. :type locale_name: str + :param raise_on_error: Raise an error instead of returning a placeholder. + :type raise_on_error: bool + :raises FileNotFoundError: If the path could not be found and + ``raise_on_error`` is ``True``. :return: The text content of the resource. :rtype: str """ - parts = path.split("/") - package = ".".join(parts[:-1]) - package = f"fietsboek.locale.{locale_name}.{package}" - try: - return importlib.resources.read_text(package, parts[-1]) - except (FileNotFoundError, ModuleNotFoundError, NotADirectoryError): - # Second chance: If the locale is a specific form of a more general - # locale, try the general locale as well. - if "_" in locale_name: - main_locale = locale_name.split("_", 1)[0] - return read_localized_resource(main_locale, path) + locales = [locale_name] + # Second chance: If the locale is a specific form of a more general + # locale, try the general locale as well. + if "_" in locale_name: + locales.append(locale_name.split("_", 1)[0]) + + for locale in locales: + locale_dir = importlib_resources.files('fietsboek') / 'locale' / locale + resource_path = locale_dir / path + try: + return resource_path.read_text() + except (FileNotFoundError, ModuleNotFoundError, NotADirectoryError): + pass + if raise_on_error: + raise FileNotFoundError(f"Resource {path!r} not found") + else: return f"{locale_name}:{path}" @@ -20,6 +20,7 @@ requires = [ 'SQLAlchemy', 'transaction', 'zope.sqlalchemy', + 'importlib_resources', 'Babel', 'cryptography', 'gpxpy', |