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

Sketch an implementation of I18N. #144

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/hamcrest/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from hamcrest.core.assert_that import assert_that
from hamcrest.core.core import *
from hamcrest.core.locale import set_locale, get_locale

__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
Expand Down
11 changes: 6 additions & 5 deletions src/hamcrest/core/assert_that.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import warnings
from typing import Optional, TypeVar, cast, overload

from hamcrest.core.locale import get_locale
from hamcrest.core.matcher import Matcher
from hamcrest.core.string_description import StringDescription
from hamcrest.core.localized_description import LocalizedDescription

__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
Expand Down Expand Up @@ -64,10 +65,10 @@ def assert_that(actual, matcher=None, reason=""):

def _assert_match(actual: T, matcher: Matcher[T], reason: str) -> None:
if not matcher.matches(actual):
description = StringDescription()
description.append_text(reason).append_text("\nExpected: ").append_description_of(
matcher
).append_text("\n but: ")
description = LocalizedDescription(locale=get_locale())
description.append_text(reason).append_text("\n") \
.append_text("Expected: ").append_description_of(matcher) \
.append_text("\n").append_text(" but: ")
matcher.describe_mismatch(actual, description)
description.append_text("\n")
raise AssertionError(description)
Expand Down
2 changes: 1 addition & 1 deletion src/hamcrest/core/base_matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from hamcrest.core.description import Description
from hamcrest.core.matcher import Matcher
from hamcrest.core.string_description import tostring
from hamcrest.core.localized_description import tostring

__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
Expand Down
41 changes: 41 additions & 0 deletions src/hamcrest/core/locale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
__author__ = "Majority Judgment"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"


_locale = "en_US"


def set_locale(new_locale):
global _locale # :(|)
_locale = new_locale


def get_locale():
global _locale # :(|)
return _locale


class LocaleLazyLoader(object):

# FIXME
# locales = dict()
locales = {
'fr_FR': {
'Butterfly': 'Papillon',
'ENGLISH DESCRIPTION': 'DESCRIPTION FRANÇAISE',

'Assertion failed': "Échec d'une assertion",
'Expected: ': 'Attendu⋅e: ',
' but: ': ' mais: ',
'was ': "obtenu⋅e ",
},
}

def get_locale_map(self, locale):
if locale not in self.locales:
self.locales[locale] = dict()
return self.locales[locale]


locale_loader = LocaleLazyLoader()
40 changes: 40 additions & 0 deletions src/hamcrest/core/localized_description.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from typing import Any, Iterable

from hamcrest.core.description import Description
from hamcrest.core.locale import get_locale, locale_loader
from hamcrest.core.selfdescribing import SelfDescribing
from hamcrest.core.string_description import StringDescription

__author__ = "Majority Judgment"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"


def tostring(selfdescribing: SelfDescribing) -> str:
"""Returns the description of a
:py:class:`~hamcrest.core.selfdescribing.SelfDescribing` object as a
localized string.

:param selfdescribing: The object to be described.
:returns: The description of the object.
"""
return str(LocalizedDescription().append_description_of(selfdescribing))


class LocalizedDescription(StringDescription):
"""Implementation of a localized :py:class:`~hamcrest.core.description.Description`
implementations.
"""

def __init__(self, locale=None) -> None:
super().__init__()
if locale is None:
locale = get_locale()
self.locale = locale
self.locale_map = locale_loader.get_locale_map(self.locale)

def append_text(self, text: str) -> Description:
if text in self.locale_map:
text = self.locale_map[text]
self.append(text)
return self
2 changes: 1 addition & 1 deletion src/hamcrest/library/integration/match_equality.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from hamcrest.core.helpers.wrap_matcher import wrap_matcher
from hamcrest.core.matcher import Matcher
from hamcrest.core.string_description import tostring
from hamcrest.core.localized_description import tostring

__author__ = "Chris Rose"
__copyright__ = "Copyright 2011 hamcrest.org"
Expand Down
6 changes: 3 additions & 3 deletions src/hamcrest/library/object/hasproperty.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from hamcrest.core.core.allof import AllOf
from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher as wrap_shortcut
from hamcrest.core.localized_description import LocalizedDescription
from hamcrest.core.matcher import Matcher
from hamcrest.core.string_description import StringDescription

__author__ = "Chris Rose"
__copyright__ = "Copyright 2011 hamcrest.org"
Expand Down Expand Up @@ -54,7 +54,7 @@ def describe_mismatch(self, item: object, mismatch_description: Description) ->
self.value_matcher.describe_mismatch(value, mismatch_description)

def __str__(self):
d = StringDescription()
d = LocalizedDescription()
self.describe_to(d)
return str(d)

Expand Down Expand Up @@ -178,7 +178,7 @@ def has_properties(*keys_valuematchers, **kv_args):
base_dict[key] = wrap_shortcut(value)

if len(base_dict) > 1:
description = StringDescription().append_text("an object with properties ")
description = LocalizedDescription().append_text("an object with properties ")
for i, (property_name, property_value_matcher) in enumerate(sorted(base_dict.items())):
description.append_description_of(property_name).append_text(
" matching "
Expand Down
61 changes: 61 additions & 0 deletions tests/hamcrest_unit_test/localized_description_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import re
import unittest
import pytest

from hamcrest.core.selfdescribing import SelfDescribing
from hamcrest.core.string_description import *
from hamcrest.core.localized_description import *


__author__ = "Majority Judgment"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"


class FakeSelfDescribing(SelfDescribing):
def describe_to(self, description):
description.append_text("ENGLISH DESCRIPTION")


class LocalizedDescriptionTest(unittest.TestCase):
def setUp(self):
self.description = LocalizedDescription(locale='fr_FR')

def testLetsSelfDescribingObjectDescribeItself(self):
self.description.append_description_of(FakeSelfDescribing())
self.assertEqual("DESCRIPTION FRANÇAISE", str(self.description))

def testNoL10nWhenDescribesStringInQuotes(self):
self.description.append_description_of("Butterfly")
self.assertEqual("'Butterfly'", str(self.description))

def testNoL10nWhenSelfDescribingObjectInAngleBrackets(self):
self.description.append_description_of(42)
self.assertEqual("<42>", str(self.description))

def testShouldNotAddAngleBracketsIfObjectDescriptionAlreadyHasThem(self):
self.description.append_description_of(object())
expected = re.compile("<object object at 0x[0-9a-fA-F]+>")
self.assertTrue(expected.match(str(self.description)))

def testDescribeUnicodeStringAsUnicode(self):
self.description.append_description_of("\u05d0")
self.assertEqual("'\u05d0'", str(self.description))


# below is a set of things that should append without error to string
# descriptions
@pytest.mark.parametrize("valid_input", (b"bytes", "unicode"))
def test_description_append_valid_input(valid_input):
desc = LocalizedDescription()
desc.append(valid_input)
str(desc)


def test_description_append_invalid_input():
desc = LocalizedDescription()
desc.append(chr(239))


if __name__ == "__main__":
unittest.main()