Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(utils): use strcoll for sorting strings instead of strxfrm #14064

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions weblate/trans/tests/test_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@

from django.test import TestCase

import weblate.trans.util
from weblate.trans.util import sort_choices


class SortTest(TestCase):
def test_sort(self) -> None:
if not weblate.trans.util.USE_STRXFRM:
self.skipTest("strxfrm not available")
result = weblate.trans.util.sort_choices(
((2, "zkouška"), (3, "zkouzka"), (1, "zkouaka"))
)
result = sort_choices(((2, "zkouška"), (3, "zkouzka"), (1, "zkouaka")))

Check failure on line 14 in weblate/trans/tests/test_sort.py

View workflow job for this annotation

GitHub Actions / mypy

Argument 1 to "sort_choices" has incompatible type "tuple[tuple[int, str], tuple[int, str], tuple[int, str]]"; expected "list[tuple[str, str]]"
self.assertEqual([1, 2, 3], [x[0] for x in result])
23 changes: 5 additions & 18 deletions weblate/trans/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import re
import sys
from functools import cmp_to_key
from operator import itemgetter
from types import GeneratorType
from typing import TYPE_CHECKING, Any, TypeVar
Expand Down Expand Up @@ -36,7 +37,6 @@
from weblate.trans.models import Project, Translation, Unit

PLURAL_SEPARATOR = "\x1e\x1e"
USE_STRXFRM = False

PRIORITY_CHOICES = (
(60, gettext_lazy("Very high")),
Expand All @@ -51,21 +51,8 @@
r"([\u1100-\u11ff\u2e80-\u2fdf\u2ff0-\u9fff\ua960-\ua97f\uac00-\ud7ff\uf900-\ufaff\ufe30-\ufe4f\uff00-\uffef\U0001aff0-\U0001b16f\U0001f200-\U0001f2ff\U00020000-\U0003FFFF]+)"
)

# Initialize to sane Unicode locales for strxfrm
if locale.strxfrm("a") == "a":
try:
locale.setlocale(locale.LC_ALL, ("en_US", "UTF-8"))
except locale.Error:
USE_STRXFRM = False
else:
try:
locale.strxfrm("zkouška")
except OSError:
# Crashes on macOS 15, see
# https://github.com/python/cpython/issues/130567
USE_STRXFRM = False
else:
USE_STRXFRM = True
# Initialize to sane Unicode locales for strcoll
locale.setlocale(locale.LC_ALL, ("en_US", "UTF-8"))


def is_plural(text: str) -> bool:
Expand Down Expand Up @@ -284,9 +271,9 @@
"""Unicode aware sorting if available."""

def sort_strxfrm(item: T) -> str:
return locale.strxfrm(key(item))
return cmp_to_key(locale.strcoll)(key(item))

Check failure on line 274 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Incompatible return value type (got "SupportsAllComparisons", expected "str")

return sorted(choices, key=sort_strxfrm if USE_STRXFRM else key)
return sorted(choices, key=sort_strxfrm)


def sort_choices(choices: list[tuple[str, str]]) -> list[tuple[str, str]]:
Expand All @@ -306,7 +293,7 @@
or not url_has_allowed_host_and_scheme(next_url, allowed_hosts=None)
or not next_url.startswith("/")
):
return redirect(fallback)

Check failure on line 296 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Argument 1 to "redirect" has incompatible type "str | Model"; expected "Callable[..., Any] | str | SupportsGetAbsoluteUrl"
return HttpResponseRedirect(next_url)


Expand Down Expand Up @@ -336,8 +323,8 @@

# Remove any possible namespace
for child in xml:
if child.tag.startswith("{"):

Check failure on line 326 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Item "QName" of "str | bytes | bytearray | QName" has no attribute "startswith"

Check failure on line 326 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Argument 1 to "startswith" of "bytes" has incompatible type "str"; expected "Buffer | tuple[Buffer, ...]"

Check failure on line 326 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Argument 1 to "startswith" of "bytearray" has incompatible type "str"; expected "Buffer | tuple[Buffer, ...]"
child.tag = child.tag[child.tag.index("}") + 1 :]

Check failure on line 327 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Value of type "str | bytes | bytearray | QName" is not indexable

Check failure on line 327 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Item "QName" of "str | bytes | bytearray | QName" has no attribute "index"

Check failure on line 327 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Argument 1 to "index" of "bytes" has incompatible type "str"; expected "Buffer | SupportsIndex"

Check failure on line 327 in weblate/trans/util.py

View workflow job for this annotation

GitHub Actions / mypy

Argument 1 to "index" of "bytearray" has incompatible type "str"; expected "Buffer | SupportsIndex"
etree.cleanup_namespaces(xml)

# Convert to string
Expand Down
Loading