Skip to content

Commit

Permalink
Fix gettext return type, re-extract Babel strings
Browse files Browse the repository at this point in the history
`lazy_gettext` (aliased as `__`) returns `LazyString`, which is not compatible with `str` and causes downstream type errors. Since it's meant to ducktype a string and works in _almost_ all situations (notable exception: `json.dumps`), we re-cast `__` to claim it returns a `str`.
  • Loading branch information
jace committed Dec 14, 2023
1 parent 1e6d678 commit ac1a823
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 246 deletions.
4 changes: 2 additions & 2 deletions babel.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[python: **.py]
[html-jinja2: **/templates/**.html.jinja2]
extensions=jinja2.ext.autoescape,jinja2.ext.do
[jinja2: **/templates/**.html.jinja2]
extensions=jinja2.ext.do
[javascript-jinja2: **/templates/js/**.js.jinja2]
encoding = utf-8
extract_messages=_,gettext,ngettext
8 changes: 7 additions & 1 deletion src/baseframe/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Baseframe init."""

from flask_babel import gettext as _, lazy_gettext as __
from typing import Callable, cast

from flask_babel import gettext, lazy_gettext

from ._version import __version__, __version_info__
from .assets import Version, assets
Expand All @@ -13,6 +15,10 @@

from . import forms # isort:skip

# Pretend these return str, not Any or LazyString
_ = cast(Callable[..., str], gettext)
__ = cast(Callable[..., str], lazy_gettext)

# TODO: baseframe_js and baseframe_css are defined in deprecated.py
# and pending removal after an audit of all apps
__all__ = [ # noqa: F405
Expand Down
8 changes: 4 additions & 4 deletions src/baseframe/extensions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Standard extensions to add to the Flask app."""
# pyright: reportMissingImports = false

import os.path
import typing as t
from datetime import tzinfo
from typing import cast

from flask import current_app, request
from flask_babel import Babel, Domain
Expand All @@ -24,8 +26,6 @@
line_profile = None

__all__ = [
'_',
'__',
'asset_cache',
'babel',
'baseframe_translations',
Expand All @@ -52,8 +52,8 @@
baseframe_translations = Domain(
os.path.join(os.path.dirname(__file__), 'translations'), domain='baseframe'
)
_ = baseframe_translations.gettext
__ = baseframe_translations.lazy_gettext
_ = cast(t.Callable[..., str], baseframe_translations.gettext)
__ = cast(t.Callable[..., str], baseframe_translations.lazy_gettext)


def get_user_locale() -> str:
Expand Down
19 changes: 10 additions & 9 deletions src/baseframe/forms/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from collections import namedtuple
from decimal import Decimal
from fractions import Fraction
from typing import Any, cast
from urllib.parse import urljoin, urlparse

import dns.resolver
Expand Down Expand Up @@ -219,12 +220,12 @@ def __call__(self, form: WTForm, field: WTField) -> None:
raise ValidationError(self.message.format(**d))

def compare(self, value: t.Any, other: t.Any) -> bool:
raise NotImplementedError(_("Subclasses must define ``compare``"))
raise NotImplementedError("Subclasses must define ``compare``")


class GreaterThan(_Comparison):
"""
Validate field.data > otherfield.data.
Validate ``field.data > otherfield.data``.
:param fieldname:
The name of the other field to compare to.
Expand All @@ -242,7 +243,7 @@ def compare(self, value: t.Any, other: t.Any) -> bool:

class GreaterThanEqualTo(_Comparison):
"""
Validate field.data >= otherfield.data.
Validate ``field.data >= otherfield.data``.
:param fieldname:
The name of the other field to compare to.
Expand All @@ -260,7 +261,7 @@ def compare(self, value: t.Any, other: t.Any) -> bool:

class LesserThan(_Comparison):
"""
Validate field.data < otherfield.data.
Validate ``field.data < otherfield.data``.
:param fieldname:
The name of the other field to compare to.
Expand All @@ -278,7 +279,7 @@ def compare(self, value: t.Any, other: t.Any) -> bool:

class LesserThanEqualTo(_Comparison):
"""
Validate field.data <= otherfield.data.
Validate ``field.data <= otherfield.data``.
:param fieldname:
The name of the other field to compare to.
Expand All @@ -296,7 +297,7 @@ def compare(self, value: t.Any, other: t.Any) -> bool:

class NotEqualTo(_Comparison):
"""
Validate field.data != otherfield.data.
Validate ``field.data != otherfield.data``.
:param fieldname:
The name of the other field to compare to.
Expand Down Expand Up @@ -428,7 +429,7 @@ class ValidUrl:
"""

user_agent = (
"Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Hasgeek/linkchecker"
'Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Hasgeek/linkchecker'
)

default_message = __("The URL “{url}” is not valid or is currently inaccessible")
Expand Down Expand Up @@ -500,7 +501,7 @@ def check_url(

cache_key = 'linkchecker/' + md5sum(url)
try:
cache_check = asset_cache.get(cache_key)
cache_check = cast(Any, asset_cache.get(cache_key))
except ValueError: # Possible error from a broken pickle
cache_check = None
# Read from cache, but assume cache may be broken since Flask-Cache stores data
Expand All @@ -509,7 +510,7 @@ def check_url(
rurl = cache_check.get('url')
code = cache_check.get('code')
else:
rurl = None # rurl is the response URL after following redirects
rurl = None # `rurl` is the response URL after following redirects
code = None

# TODO: Also honour the robots.txt protocol and stay off URLs that aren't meant
Expand Down
Loading

0 comments on commit ac1a823

Please sign in to comment.