def test_plural_form_property(self):
### tests/test_localedata.py
#
# Copyright (C) 2007-2011 Edgewall Software, 2013-2023 the Babel team
# All rights reserved.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

import os
import pickle
import random
import sys
import tempfile
import unittest
from operator import methodcaller

import pytest

from babel import Locale, UnknownLocaleError, localedata


class MergeResolveTestCase(unittest.TestCase):

    def test_merge_items(self):
        d = {1: 'foo', 3: 'baz'}
        localedata.merge(d, {1: 'Foo', 2: 'Bar'})
        assert d == {1: 'Foo', 2: 'Bar', 3: 'baz'}

    def test_merge_nested_dict(self):
        d1 = {'x': {'a': 1, 'b': 2, 'c': 3}}
        d2 = {'x': {'a': 1, 'b': 12, 'd': 14}}
        localedata.merge(d1, d2)
        assert d1 == {'x': {'a': 1, 'b': 12, 'c': 3, 'd': 14}}

    def test_merge_nested_dict_no_overlap(self):
        d1 = {'x': {'a': 1, 'b': 2}}
        d2 = {'y': {'a': 11, 'b': 12}}
        localedata.merge(d1, d2)
        assert d1 == {'x': {'a': 1, 'b': 2}, 'y': {'a': 11, 'b': 12}}

    def test_merge_with_alias_and_resolve(self):
        alias = localedata.Alias('x')
        d1 = {
            'x': {'a': 1, 'b': 2, 'c': 3},
            'y': alias,
        }
        d2 = {
            'x': {'a': 1, 'b': 12, 'd': 14},
            'y': {'b': 22, 'e': 25},
        }
        localedata.merge(d1, d2)
        assert d1 == {'x': {'a': 1, 'b': 12, 'c': 3, 'd': 14}, 'y': (alias, {'b': 22, 'e': 25})}
        d = localedata.LocaleDataDict(d1)
        assert dict(d.items()) == {'x': {'a': 1, 'b': 12, 'c': 3, 'd': 14}, 'y': {'a': 1, 'b': 22, 'c': 3, 'd': 14, 'e': 25}}


def test_load():
    assert localedata.load('en_US')['languages']['sv'] == 'Swedish'
    assert localedata.load('en_US') is localedata.load('en_US')


def test_merge():
    d = {1: 'foo', 3: 'baz'}
    localedata.merge(d, {1: 'Foo', 2: 'Bar'})
    assert d == {1: 'Foo', 2: 'Bar', 3: 'baz'}


def test_locale_identification():
    for locale in localedata.locale_identifiers():
        assert localedata.exists(locale)


def test_unique_ids():
    # Check all locale IDs are uniques.
    all_ids = localedata.locale_identifiers()
    assert len(all_ids) == len(set(all_ids))
    # Check locale IDs don't collide after lower-case normalization.
    lower_case_ids = list(map(methodcaller('lower'), all_ids))
    assert len(lower_case_ids) == len(set(lower_case_ids))


def test_mixedcased_locale():
    for locale in localedata.locale_identifiers():
        locale_id = ''.join([
            methodcaller(random.choice(['lower', 'upper']))(c) for c in locale])
        assert localedata.exists(locale_id)


def test_locale_argument_acceptance():
    # Testing None input.
    normalized_locale = localedata.normalize_locale(None)
    assert normalized_locale is None
    assert not localedata.exists(None)

    # Testing list input.
    normalized_locale = localedata.normalize_locale(['en_us', None])
    assert normalized_locale is None
    assert not localedata.exists(['en_us', None])


def test_locale_identifiers_cache(monkeypatch):
    original_listdir = localedata.os.listdir
    listdir_calls = []

    def listdir_spy(*args):
        rv = original_listdir(*args)
        listdir_calls.append((args, rv))
        return rv

    monkeypatch.setattr(localedata.os, 'listdir', listdir_spy)
    localedata.locale_identifiers.cache_clear()
    assert not listdir_calls
    l = localedata.locale_identifiers()
    assert len(listdir_calls) == 1
    assert localedata.locale_identifiers() is l
    assert len(listdir_calls) == 1
    localedata.locale_identifiers.cache_clear()
    assert localedata.locale_identifiers()
    assert len(listdir_calls) == 2


def test_locale_name_cleanup():
    """
    Test that locale identifiers are cleaned up to avoid directory traversal.
    """
    no_exist_name = os.path.join(tempfile.gettempdir(), "babel%d.dat" % random.randint(1, 99999))
    with open(no_exist_name, "wb") as f:
        pickle.dump({}, f)

    try:
        name = os.path.splitext(os.path.relpath(no_exist_name, localedata._dirname))[0]
    except ValueError:
        if sys.platform == "win32":
            pytest.skip("unable to form relpath")
        raise

    assert not localedata.exists(name)
    with pytest.raises(IOError):
        localedata.load(name)
    with pytest.raises(UnknownLocaleError):
        Locale(name)


@pytest.mark.skipif(sys.platform != "win32", reason="windows-only test")
def test_reserved_locale_names():
    for name in ("con", "aux", "nul", "prn", "com8", "lpt5"):
        with pytest.raises(ValueError):
            localedata.load(name)
        with pytest.raises(ValueError):
            Locale(name)
### tests/test_languages.py
from babel.languages import get_official_languages, get_territory_language_info


def test_official_languages():
    assert get_official_languages("FI") == ("fi", "sv")
    assert get_official_languages("SE") == ("sv",)
    assert get_official_languages("CH") == ("de", "fr", "it")
    assert get_official_languages("CH", de_facto=True) == ("de", "gsw", "fr", "it")
    assert get_official_languages("CH", regional=True) == ("de", "fr", "it", "rm")


def test_get_language_info():
    assert (
        set(get_territory_language_info("HU")) ==
        {"hu", "fr", "en", "de", "ro", "hr", "sk", "sl"}
    )
### tests/test_lists.py
import pytest

from babel import lists


def test_format_list():
    for list, locale, expected in [
        ([], 'en', ''),
        (['string'], 'en', 'string'),
        (['string1', 'string2'], 'en', 'string1 and string2'),
        (['string1', 'string2', 'string3'], 'en', 'string1, string2, and string3'),
        (['string1', 'string2', 'string3'], 'zh', 'string1、string2和string3'),
        (['string1', 'string2', 'string3', 'string4'], 'ne', 'string1,string2, string3 र string4'),
    ]:
        assert lists.format_list(list, locale=locale) == expected


def test_format_list_error():
    with pytest.raises(ValueError):
        lists.format_list(['a', 'b', 'c'], style='orange', locale='en')
### tests/test_plural.py
#
# Copyright (C) 2007-2011 Edgewall Software, 2013-2023 the Babel team
# All rights reserved.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.
import decimal
import unittest

import pytest

from babel import localedata, plural

EPSILON = decimal.Decimal("0.0001")


def test_plural_rule():
    rule = plural.PluralRule({'one': 'n is 1'})
    assert rule(1) == 'one'
    assert rule(2) == 'other'

    rule = plural.PluralRule({'one': 'n is 1'})
    assert rule.rules == {'one': 'n is 1'}


def test_plural_rule_operands_i():
    rule = plural.PluralRule({'one': 'i is 1'})
    assert rule(1.2) == 'one'
    assert rule(2) == 'other'


def test_plural_rule_operands_v():
    rule = plural.PluralRule({'one': 'v is 2'})
    assert rule(decimal.Decimal('1.20')) == 'one'
    assert rule(decimal.Decimal('1.2')) == 'other'
    assert rule(2) == 'other'


def test_plural_rule_operands_w():
    rule = plural.PluralRule({'one': 'w is 2'})
    assert rule(decimal.Decimal('1.23')) == 'one'
    assert rule(decimal.Decimal('1.20')) == 'other'
    assert rule(1.2) == 'other'


def test_plural_rule_operands_f():
    rule = plural.PluralRule({'one': 'f is 20'})
    assert rule(decimal.Decimal('1.23')) == 'other'
    assert rule(decimal.Decimal('1.20')) == 'one'
    assert rule(1.2) == 'other'


def test_plural_rule_operands_t():
    rule = plural.PluralRule({'one': 't = 5'})
    assert rule(decimal.Decimal('1.53')) == 'other'
    assert rule(decimal.Decimal('1.50')) == 'one'
    assert rule(1.5) == 'one'


def test_plural_other_is_ignored():
    rule = plural.PluralRule({'one': 'n is 1', 'other': '@integer 2'})
    assert rule(1) == 'one'


def test_to_javascript():
    assert (plural.to_javascript({'one': 'n is 1'})
            == "(function(n) { return (n == 1) ? 'one' : 'other'; })")


def test_to_python():
    func = plural.to_python({'one': 'n is 1', 'few': 'n in 2..4'})
    assert func(1) == 'one'
    assert func(3) == 'few'

    func = plural.to_python({'one': 'n in 1,11', 'few': 'n in 3..10,13..19'})
    assert func(11) == 'one'
    assert func(15) == 'few'


def test_to_gettext():
    assert (plural.to_gettext({'one': 'n is 1', 'two': 'n is 2'})
            == 'nplurals=3; plural=((n == 1) ? 0 : (n == 2) ? 1 : 2);')


def test_in_range_list():
    assert plural.in_range_list(1, [(1, 3)])
    assert plural.in_range_list(3, [(1, 3)])
    assert plural.in_range_list(3, [(1, 3), (5, 8)])
    assert not plural.in_range_list(1.2, [(1, 4)])
    assert not plural.in_range_list(10, [(1, 4)])
    assert not plural.in_range_list(10, [(1, 4), (6, 8)])


def test_within_range_list():
    assert plural.within_range_list(1, [(1, 3)])
    assert plural.within_range_list(1.0, [(1, 3)])
    assert plural.within_range_list(1.2, [(1, 4)])
    assert plural.within_range_list(8.8, [(1, 4), (7, 15)])
    assert not plural.within_range_list(10, [(1, 4)])
    assert not plural.within_range_list(10.5, [(1, 4), (20, 30)])


def test_cldr_modulo():
    assert plural.cldr_modulo(-3, 5) == -3
    assert plural.cldr_modulo(-3, -5) == -3
    assert plural.cldr_modulo(3, 5) == 3


def test_plural_within_rules():
    p = plural.PluralRule({'one': 'n is 1', 'few': 'n within 2,4,7..9'})
    assert repr(p) == "<PluralRule 'one: n is 1, few: n within 2,4,7..9'>"
    assert plural.to_javascript(p) == (
        "(function(n) { "
        "return ((n == 2) || (n == 4) || (n >= 7 && n <= 9))"
        " ? 'few' : (n == 1) ? 'one' : 'other'; })")
    assert plural.to_gettext(p) == (
        'nplurals=3; plural=(((n == 2) || (n == 4) || (n >= 7 && n <= 9))'
        ' ? 1 : (n == 1) ? 0 : 2);')
    assert p(0) == 'other'
    assert p(1) == 'one'
    assert p(2) == 'few'
    assert p(3) == 'other'
    assert p(4) == 'few'
    assert p(5) == 'other'
    assert p(6) == 'other'
    assert p(7) == 'few'
    assert p(8) == 'few'
    assert p(9) == 'few'


def test_locales_with_no_plural_rules_have_default():
    from babel import Locale
    pf = Locale.parse('ii').plural_form
    assert pf(1) == 'other'
    assert pf(2) == 'other'
    assert pf(15) == 'other'


WELL_FORMED_TOKEN_TESTS = (
    ("", []),
    (
        "n = 1",
        [
            ("value", "1"),
            ("symbol", "="),
            ("word", "n"),
        ],
    ),
    (
        "n = 1 @integer 1",
        [
            ("value", "1"),
            ("symbol", "="),
            ("word", "n"),
        ],
    ),
    (
        "n is 1",
        [
            ("value", "1"),
            ("word", "is"),
            ("word", "n"),
        ],
    ),
    (
        "n % 100 = 3..10",
        [
            ("value", "10"),
            ("ellipsis", ".."),
            ("value", "3"),
            ("symbol", "="),
            ("value", "100"),
            ("symbol", "%"),
            ("word", "n"),
        ],
    ),
)


@pytest.mark.parametrize('rule_text,tokens', WELL_FORMED_TOKEN_TESTS)
def test_tokenize_well_formed(rule_text, tokens):
    assert plural.tokenize_rule(rule_text) == tokens


MALFORMED_TOKEN_TESTS = (
    'a = 1', 'n ! 2',
)


@pytest.mark.parametrize('rule_text', MALFORMED_TOKEN_TESTS)
def test_tokenize_malformed(rule_text):
    with pytest.raises(plural.RuleError):
        plural.tokenize_rule(rule_text)


class TestNextTokenTestCase(unittest.TestCase):

    def test_empty(self):
        assert not plural.test_next_token([], '')

    def test_type_ok_and_no_value(self):
        assert plural.test_next_token([('word', 'and')], 'word')

    def test_type_ok_and_not_value(self):
        assert not plural.test_next_token([('word', 'and')], 'word', 'or')

    def test_type_ok_and_value_ok(self):
        assert plural.test_next_token([('word', 'and')], 'word', 'and')

    def test_type_not_ok_and_value_ok(self):
        assert not plural.test_next_token([('abc', 'and')], 'word', 'and')


def make_range_list(*values):
    ranges = []
    for v in values:
        if isinstance(v, int):
            val_node = plural.value_node(v)
            ranges.append((val_node, val_node))
        else:
            assert isinstance(v, tuple)
            ranges.append((plural.value_node(v[0]),
                           plural.value_node(v[1])))
    return plural.range_list_node(ranges)


class PluralRuleParserTestCase(unittest.TestCase):

    def setUp(self):
        self.n = plural.ident_node('n')

    def n_eq(self, v):
        return 'relation', ('in', self.n, make_range_list(v))

    def test_error_when_unexpected_end(self):
        with pytest.raises(plural.RuleError):
            plural._Parser('n =')

    def test_eq_relation(self):
        assert plural._Parser('n = 1').ast == self.n_eq(1)

    def test_in_range_relation(self):
        assert plural._Parser('n = 2..4').ast == \
            ('relation', ('in', self.n, make_range_list((2, 4))))

    def test_negate(self):
        assert plural._Parser('n != 1').ast == plural.negate(self.n_eq(1))

    def test_or(self):
        assert plural._Parser('n = 1 or n = 2').ast ==\
            ('or', (self.n_eq(1), self.n_eq(2)))

    def test_and(self):
        assert plural._Parser('n = 1 and n = 2').ast ==\
            ('and', (self.n_eq(1), self.n_eq(2)))
### tests/test_numbers.py
#
# Copyright (C) 2007-2011 Edgewall Software, 2013-2023 the Babel team
# All rights reserved.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

import decimal
import unittest
from datetime import date

import pytest

from babel import localedata, numbers
from babel.numbers import (
    UnknownCurrencyError,
    get_currency_precision,
    get_currency_unit_pattern,
    get_decimal_precision,
    is_currency,
    list_currencies,
    normalize_currency,
    validate_currency,
)


class FormatDecimalTestCase(unittest.TestCase):

    def test_patterns(self):
        assert numbers.format_decimal(12345, '##0', locale='en_US') == '12345'
  <response clipped><NOTE>Due to the max output limit, only part of the full response has been shown to you.</NOTE>e) across 0:00
    ("en_US", time(5), "night1"),  # (from, before) across 0:00
    ("en_US", time(6), "morning1"),  # (from, before)
    ("agq", time(10), "am"),  # no periods defined
    ("agq", time(22), "pm"),  # no periods defined
    ("am", time(14), "afternoon1"),  # (before, after)
])
def test_day_period_rules(locale, time, expected_period_id):
    assert dates.get_period_id(time, locale=locale) == expected_period_id
### tests/test_support.py
#
# Copyright (C) 2007-2011 Edgewall Software, 2013-2023 the Babel team
# All rights reserved.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

import datetime
import inspect
import os
import shutil
import sys
import tempfile
import unittest
from decimal import Decimal
from io import BytesIO

import pytest

from babel import support
from babel.messages import Catalog
from babel.messages.mofile import write_mo

SKIP_LGETTEXT = sys.version_info >= (3, 8)


@pytest.mark.usefixtures("os_environ")
class TranslationsTestCase(unittest.TestCase):

    def setUp(self):
        # Use a locale which won't fail to run the tests
        os.environ['LANG'] = 'en_US.UTF-8'
        messages1 = [
            ('foo', {'string': 'Voh'}),
            ('foo', {'string': 'VohCTX', 'context': 'foo'}),
            (('foo1', 'foos1'), {'string': ('Voh1', 'Vohs1')}),
            (('foo1', 'foos1'), {'string': ('VohCTX1', 'VohsCTX1'), 'context': 'foo'}),
        ]
        messages2 = [
            ('foo', {'string': 'VohD'}),
            ('foo', {'string': 'VohCTXD', 'context': 'foo'}),
            (('foo1', 'foos1'), {'string': ('VohD1', 'VohsD1')}),
            (('foo1', 'foos1'), {'string': ('VohCTXD1', 'VohsCTXD1'), 'context': 'foo'}),
        ]
        catalog1 = Catalog(locale='en_GB', domain='messages')
        catalog2 = Catalog(locale='en_GB', domain='messages1')
        for ids, kwargs in messages1:
            catalog1.add(ids, **kwargs)
        for ids, kwargs in messages2:
            catalog2.add(ids, **kwargs)
        catalog1_fp = BytesIO()
        catalog2_fp = BytesIO()
        write_mo(catalog1_fp, catalog1)
        catalog1_fp.seek(0)
        write_mo(catalog2_fp, catalog2)
        catalog2_fp.seek(0)
        translations1 = support.Translations(catalog1_fp)
        translations2 = support.Translations(catalog2_fp, domain='messages1')
        self.translations = translations1.add(translations2, merge=False)

    def assertEqualTypeToo(self, expected, result):
        assert expected == result
        assert type(expected) == type(result), f"instance types do not match: {type(expected)!r}!={type(result)!r}"

    def test_pgettext(self):
        self.assertEqualTypeToo('Voh', self.translations.gettext('foo'))
        self.assertEqualTypeToo('VohCTX', self.translations.pgettext('foo',
                                                                     'foo'))

    def test_upgettext(self):
        self.assertEqualTypeToo('Voh', self.translations.ugettext('foo'))
        self.assertEqualTypeToo('VohCTX', self.translations.upgettext('foo',
                                                                      'foo'))

    @pytest.mark.skipif(SKIP_LGETTEXT, reason="lgettext is deprecated")
    def test_lpgettext(self):
        self.assertEqualTypeToo(b'Voh', self.translations.lgettext('foo'))
        self.assertEqualTypeToo(b'VohCTX', self.translations.lpgettext('foo',
                                                                       'foo'))

    def test_npgettext(self):
        self.assertEqualTypeToo('Voh1',
                                self.translations.ngettext('foo1', 'foos1', 1))
        self.assertEqualTypeToo('Vohs1',
                                self.translations.ngettext('foo1', 'foos1', 2))
        self.assertEqualTypeToo('VohCTX1',
                                self.translations.npgettext('foo', 'foo1',
                                                            'foos1', 1))
        self.assertEqualTypeToo('VohsCTX1',
                                self.translations.npgettext('foo', 'foo1',
                                                            'foos1', 2))

    def test_unpgettext(self):
        self.assertEqualTypeToo('Voh1',
                                self.translations.ungettext('foo1', 'foos1', 1))
        self.assertEqualTypeToo('Vohs1',
                                self.translations.ungettext('foo1', 'foos1', 2))
        self.assertEqualTypeToo('VohCTX1',
                                self.translations.unpgettext('foo', 'foo1',
                                                             'foos1', 1))
        self.assertEqualTypeToo('VohsCTX1',
                                self.translations.unpgettext('foo', 'foo1',
                                                             'foos1', 2))

    @pytest.mark.skipif(SKIP_LGETTEXT, reason="lgettext is deprecated")
    def test_lnpgettext(self):
        self.assertEqualTypeToo(b'Voh1',
                                self.translations.lngettext('foo1', 'foos1', 1))
        self.assertEqualTypeToo(b'Vohs1',
                                self.translations.lngettext('foo1', 'foos1', 2))
        self.assertEqualTypeToo(b'VohCTX1',
                                self.translations.lnpgettext('foo', 'foo1',
                                                             'foos1', 1))
        self.assertEqualTypeToo(b'VohsCTX1',
                                self.translations.lnpgettext('foo', 'foo1',
                                                             'foos1', 2))

    def test_dpgettext(self):
        self.assertEqualTypeToo(
            'VohD', self.translations.dgettext('messages1', 'foo'))
        self.assertEqualTypeToo(
            'VohCTXD', self.translations.dpgettext('messages1', 'foo', 'foo'))

    def test_dupgettext(self):
        self.assertEqualTypeToo(
            'VohD', self.translations.dugettext('messages1', 'foo'))
        self.assertEqualTypeToo(
            'VohCTXD', self.translations.dupgettext('messages1', 'foo', 'foo'))

    @pytest.mark.skipif(SKIP_LGETTEXT, reason="lgettext is deprecated")
    def test_ldpgettext(self):
        self.assertEqualTypeToo(
            b'VohD', self.translations.ldgettext('messages1', 'foo'))
        self.assertEqualTypeToo(
            b'VohCTXD', self.translations.ldpgettext('messages1', 'foo', 'foo'))

    def test_dnpgettext(self):
        self.assertEqualTypeToo(
            'VohD1', self.translations.dngettext('messages1', 'foo1', 'foos1', 1))
        self.assertEqualTypeToo(
            'VohsD1', self.translations.dngettext('messages1', 'foo1', 'foos1', 2))
        self.assertEqualTypeToo(
            'VohCTXD1', self.translations.dnpgettext('messages1', 'foo', 'foo1',
                                                     'foos1', 1))
        self.assertEqualTypeToo(
            'VohsCTXD1', self.translations.dnpgettext('messages1', 'foo', 'foo1',
                                                      'foos1', 2))

    def test_dunpgettext(self):
        self.assertEqualTypeToo(
            'VohD1', self.translations.dungettext('messages1', 'foo1', 'foos1', 1))
        self.assertEqualTypeToo(
            'VohsD1', self.translations.dungettext('messages1', 'foo1', 'foos1', 2))
        self.assertEqualTypeToo(
            'VohCTXD1', self.translations.dunpgettext('messages1', 'foo', 'foo1',
                                                      'foos1', 1))
        self.assertEqualTypeToo(
            'VohsCTXD1', self.translations.dunpgettext('messages1', 'foo', 'foo1',
                                                       'foos1', 2))

    @pytest.mark.skipif(SKIP_LGETTEXT, reason="lgettext is deprecated")
    def test_ldnpgettext(self):
        self.assertEqualTypeToo(
            b'VohD1', self.translations.ldngettext('messages1', 'foo1', 'foos1', 1))
        self.assertEqualTypeToo(
            b'VohsD1', self.translations.ldngettext('messages1', 'foo1', 'foos1', 2))
        self.assertEqualTypeToo(
            b'VohCTXD1', self.translations.ldnpgettext('messages1', 'foo', 'foo1',
                                                       'foos1', 1))
        self.assertEqualTypeToo(
            b'VohsCTXD1', self.translations.ldnpgettext('messages1', 'foo', 'foo1',
                                                        'foos1', 2))

    def test_load(self):
        tempdir = tempfile.mkdtemp()
        try:
            messages_dir = os.path.join(tempdir, 'fr', 'LC_MESSAGES')
            os.makedirs(messages_dir)
            catalog = Catalog(locale='fr', domain='messages')
            catalog.add('foo', 'bar')
            with open(os.path.join(messages_dir, 'messages.mo'), 'wb') as f:
                write_mo(f, catalog)

            translations = support.Translations.load(tempdir, locales=('fr',), domain='messages')
            assert translations.gettext('foo') == 'bar'
        finally:
            shutil.rmtree(tempdir)


class NullTranslationsTestCase(unittest.TestCase):

    def setUp(self):
        fp = BytesIO()
        write_mo(fp, Catalog(locale='de'))
        fp.seek(0)
        self.translations = support.Translations(fp=fp)
        self.null_translations = support.NullTranslations(fp=fp)

    def method_names(self):
        names = [name for name in dir(self.translations) if 'gettext' in name]
        if SKIP_LGETTEXT:
            # Remove deprecated l*gettext functions
            names = [name for name in names if not name.startswith('l')]
        return names

    def test_same_methods(self):
        for name in self.method_names():
            if not hasattr(self.null_translations, name):
                self.fail(f"NullTranslations does not provide method {name!r}")

    def test_method_signature_compatibility(self):
        for name in self.method_names():
            translations_method = getattr(self.translations, name)
            null_method = getattr(self.null_translations, name)
            assert inspect.getfullargspec(translations_method) == inspect.getfullargspec(null_method)

    def test_same_return_values(self):
        data = {
            'message': 'foo', 'domain': 'domain', 'context': 'tests',
            'singular': 'bar', 'plural': 'baz', 'num': 1,
            'msgid1': 'bar', 'msgid2': 'baz', 'n': 1,
        }
        for name in self.method_names():
            method = getattr(self.translations, name)
            null_method = getattr(self.null_translations, name)
            signature = inspect.getfullargspec(method)
            parameter_names = [name for name in signature.args if name != 'self']
            values = [data[name] for name in parameter_names]
            assert method(*values) == null_method(*values)


class LazyProxyTestCase(unittest.TestCase):

    def test_proxy_caches_result_of_function_call(self):
        self.counter = 0

        def add_one():
            self.counter += 1
            return self.counter
        proxy = support.LazyProxy(add_one)
        assert proxy.value == 1
        assert proxy.value == 1

    def test_can_disable_proxy_cache(self):
        self.counter = 0

        def add_one():
            self.counter += 1
            return self.counter
        proxy = support.LazyProxy(add_one, enable_cache=False)
        assert proxy.value == 1
        assert proxy.value == 2

    def test_can_copy_proxy(self):
        from copy import copy
### tests/test_util.py
#
# Copyright (C) 2007-2011 Edgewall Software, 2013-2023 the Babel team
# All rights reserved.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

import __future__

import unittest
from io import BytesIO

import pytest

from babel import util
from babel.util import parse_future_flags


class _FF:
    division = __future__.division.compiler_flag
    print_function = __future__.print_function.compiler_flag
    with_statement = __future__.with_statement.compiler_flag
    unicode_literals = __future__.unicode_literals.compiler_flag


def test_distinct():
    assert list(util.distinct([1, 2, 1, 3, 4, 4])) == [1, 2, 3, 4]
    assert list(util.distinct('foobar')) == ['f', 'o', 'b', 'a', 'r']


def test_pathmatch():
    assert util.pathmatch('**.py', 'bar.py')
    assert util.pathmatch('**.py', 'foo/bar/baz.py')
    assert not util.pathmatch('**.py', 'templates/index.html')
    assert util.pathmatch('**/templates/*.html', 'templates/index.html')
    assert not util.pathmatch('**/templates/*.html', 'templates/foo/bar.html')
    assert util.pathmatch('^foo/**.py', 'foo/bar/baz/blah.py')
    assert not util.pathmatch('^foo/**.py', 'blah/foo/bar/baz.py')
    assert util.pathmatch('./foo/**.py', 'foo/bar/baz/blah.py')
    assert util.pathmatch('./blah.py', 'blah.py')
    assert not util.pathmatch('./foo/**.py', 'blah/foo/bar/baz.py')


class FixedOffsetTimezoneTestCase(unittest.TestCase):

    def test_zone_negative_offset(self):
        assert util.FixedOffsetTimezone(-60).zone == 'Etc/GMT-60'

    def test_zone_zero_offset(self):
        assert util.FixedOffsetTimezone(0).zone == 'Etc/GMT+0'

    def test_zone_positive_offset(self):
        assert util.FixedOffsetTimezone(330).zone == 'Etc/GMT+330'


def parse_encoding(s):
    return util.parse_encoding(BytesIO(s.encode('utf-8')))


def test_parse_encoding_defined():
    assert parse_encoding('# coding: utf-8') == 'utf-8'


def test_parse_encoding_undefined():
    assert parse_encoding('') is None


def test_parse_encoding_non_ascii():
    assert parse_encoding('K\xf6ln') is None


@pytest.mark.parametrize('source, result', [
    ('''
from __future__ import print_function,
    division, with_statement,
    unicode_literals
''', _FF.print_function | _FF.division | _FF.with_statement | _FF.unicode_literals),
    ('''
from __future__ import print_function, division
print('hello')
''', _FF.print_function | _FF.division),
    ('''
from __future__ import print_function, division, unknown,,,,,
print 'hello'
''', _FF.print_function | _FF.division),
    ('''
from __future__ import (
    print_function,
    division)
''', _FF.print_function | _FF.division),
    ('''
from __future__ import \\
    print_function, \\
    division
''', _FF.print_function | _FF.division),
])
def test_parse_future(source, result):
    fp = BytesIO(source.encode('latin-1'))
    flags = parse_future_flags(fp)
    assert flags == result
[The command completed with exit code 0.]
[Current working directory: /workspace/babel]
[Python interpreter: /usr/bin/python]
[Command finished with exit code 0]