diff --git a/pydantic_extra_types/country.py b/pydantic_extra_types/country.py index 270b9bea..a6d26e2e 100644 --- a/pydantic_extra_types/country.py +++ b/pydantic_extra_types/country.py @@ -11,7 +11,7 @@ from pydantic_core import PydanticCustomError, core_schema try: - import pycountry # type: ignore[import] + import pycountry except ModuleNotFoundError: # pragma: no cover raise RuntimeError( 'The `country` module requires "pycountry" to be installed. You can install it with "pip install pycountry".' @@ -24,8 +24,6 @@ class CountryInfo: alpha3: str numeric_code: str short_name: str - # NOTE: Not all countries have an official name - official_name: str @lru_cache @@ -36,7 +34,6 @@ def _countries() -> list[CountryInfo]: alpha3=country.alpha_3, numeric_code=country.numeric, short_name=country.name, - official_name=getattr(country, 'official_name', ''), ) for country in pycountry.countries ] @@ -62,11 +59,6 @@ def _index_by_short_name() -> dict[str, CountryInfo]: return {country.short_name: country for country in _countries()} -@lru_cache -def _index_by_official_name() -> dict[str, CountryInfo]: - return {country.official_name: country for country in _countries() if country.official_name} - - class CountryAlpha2(str): """CountryAlpha2 parses country codes in the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format. @@ -123,12 +115,6 @@ def short_name(self) -> str: """The country short name.""" return _index_by_alpha2()[self].short_name - @property - def official_name(self) -> str: - """The country official name.""" - country = _index_by_alpha2()[self] - return country.official_name - class CountryAlpha3(str): """CountryAlpha3 parses country codes in the [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) @@ -187,12 +173,6 @@ def short_name(self) -> str: """The country short name.""" return _index_by_alpha3()[self].short_name - @property - def official_name(self) -> str: - """The country official name.""" - country = _index_by_alpha3()[self] - return country.official_name - class CountryNumericCode(str): """CountryNumericCode parses country codes in the @@ -251,12 +231,6 @@ def short_name(self) -> str: """The country short name.""" return _index_by_numeric_code()[self].short_name - @property - def official_name(self) -> str: - """The country official name.""" - country = _index_by_numeric_code()[self] - return country.official_name - class CountryShortName(str): """CountryShortName parses country codes in the short name format. @@ -305,63 +279,3 @@ def alpha3(self) -> str: def numeric_code(self) -> str: """The country code in the [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) format.""" return _index_by_short_name()[self].numeric_code - - @property - def official_name(self) -> str: - """The country official name.""" - country = _index_by_short_name()[self] - return country.official_name - - -class CountryOfficialName(str): - """CountryOfficialName parses country codes in the official name format. - - ```py - from pydantic import BaseModel - - from pydantic_extra_types.country import CountryOfficialName - - class Product(BaseModel): - made_in: CountryOfficialName - - product = Product(made_in="United States of America") - print(product) - #> made_in='United States of America' - ``` - """ - - @classmethod - def _validate(cls, __input_value: str, _: core_schema.ValidationInfo) -> CountryOfficialName: - if __input_value not in _index_by_official_name(): - raise PydanticCustomError('country_numeric_code', 'Invalid country official name') - return cls(__input_value) - - @classmethod - def __get_pydantic_core_schema__( - cls, source: type[Any], handler: GetCoreSchemaHandler - ) -> core_schema.AfterValidatorFunctionSchema: - return core_schema.with_info_after_validator_function( - cls._validate, - core_schema.str_schema(), - serialization=core_schema.to_string_ser_schema(), - ) - - @property - def alpha2(self) -> str: - """The country code in the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format.""" - return _index_by_official_name()[self].alpha2 - - @property - def alpha3(self) -> str: - """The country code in the [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) format.""" - return _index_by_official_name()[self].alpha3 - - @property - def numeric_code(self) -> str: - """The country code in the [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) format.""" - return _index_by_official_name()[self].numeric_code - - @property - def short_name(self) -> str: - """The country short name.""" - return _index_by_official_name()[self].short_name diff --git a/pyproject.toml b/pyproject.toml index 5bfea70a..cc51c1ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ dynamic = ['version'] [project.optional-dependencies] all = [ 'phonenumbers>=8,<9', - 'pycountry>=22,<23', + 'pycountry>=23,<24', 'python-ulid>=1,<2', ] diff --git a/tests/test_country_code.py b/tests/test_country_code.py index 686b7f7c..13bb85a0 100644 --- a/tests/test_country_code.py +++ b/tests/test_country_code.py @@ -8,12 +8,10 @@ CountryAlpha3, CountryInfo, CountryNumericCode, - CountryOfficialName, CountryShortName, _index_by_alpha2, _index_by_alpha3, _index_by_numeric_code, - _index_by_official_name, _index_by_short_name, ) @@ -52,25 +50,13 @@ class Product(BaseModel): return Product -@pytest.fixture(scope='module', name='ProductOfficialName') -def product_official_name_fixture(): - class Product(BaseModel): - made_in: CountryOfficialName - - return Product - - -@pytest.mark.parametrize( - 'alpha2, country_data', - [(alpha2, country_data) for alpha2, country_data in _index_by_alpha2().items()][:PARAMS_AMOUNT], -) +@pytest.mark.parametrize('alpha2, country_data', list(_index_by_alpha2().items())[:PARAMS_AMOUNT]) def test_valid_alpha2(alpha2: str, country_data: CountryInfo, ProductAlpha2): banana = ProductAlpha2(made_in=alpha2) assert banana.made_in == country_data.alpha2 assert banana.made_in.alpha3 == country_data.alpha3 assert banana.made_in.numeric_code == country_data.numeric_code assert banana.made_in.short_name == country_data.short_name - assert banana.made_in.official_name == country_data.official_name @pytest.mark.parametrize('alpha2', list(printable)) @@ -79,17 +65,13 @@ def test_invalid_alpha2(alpha2: str, ProductAlpha2): ProductAlpha2(made_in=alpha2) -@pytest.mark.parametrize( - 'alpha3, country_data', - [(alpha3, country_data) for alpha3, country_data in _index_by_alpha3().items()][:PARAMS_AMOUNT], -) +@pytest.mark.parametrize('alpha3, country_data', list(_index_by_alpha3().items())[:PARAMS_AMOUNT]) def test_valid_alpha3(alpha3: str, country_data: CountryInfo, ProductAlpha3): banana = ProductAlpha3(made_in=alpha3) assert banana.made_in == country_data.alpha3 assert banana.made_in.alpha2 == country_data.alpha2 assert banana.made_in.numeric_code == country_data.numeric_code assert banana.made_in.short_name == country_data.short_name - assert banana.made_in.official_name == country_data.official_name @pytest.mark.parametrize('alpha3', list(printable)) @@ -98,17 +80,13 @@ def test_invalid_alpha3(alpha3: str, ProductAlpha3): ProductAlpha3(made_in=alpha3) -@pytest.mark.parametrize( - 'short_name, country_data', - [(short_name, country_data) for short_name, country_data in _index_by_short_name().items()][:PARAMS_AMOUNT], -) +@pytest.mark.parametrize('short_name, country_data', list(_index_by_short_name().items())[:PARAMS_AMOUNT]) def test_valid_short_name(short_name: str, country_data: CountryInfo, ProductShortName): banana = ProductShortName(made_in=short_name) assert banana.made_in == country_data.short_name assert banana.made_in.alpha2 == country_data.alpha2 assert banana.made_in.alpha3 == country_data.alpha3 assert banana.made_in.numeric_code == country_data.numeric_code - assert banana.made_in.official_name == country_data.official_name @pytest.mark.parametrize('short_name', list(printable)) @@ -117,38 +95,13 @@ def test_invalid_short_name(short_name: str, ProductShortName): ProductShortName(made_in=short_name) -@pytest.mark.parametrize( - 'official_name, country_data', - [(official_name, country_data) for official_name, country_data in _index_by_official_name().items()][ - :PARAMS_AMOUNT - ], -) -def test_valid_official_name(official_name: str, country_data: CountryInfo, ProductOfficialName): - banana = ProductOfficialName(made_in=official_name) - assert banana.made_in == country_data.official_name - assert banana.made_in.alpha2 == country_data.alpha2 - assert banana.made_in.alpha3 == country_data.alpha3 - assert banana.made_in.short_name == country_data.short_name - assert banana.made_in.numeric_code == country_data.numeric_code - - -@pytest.mark.parametrize('official_name', list(printable)) -def test_invalid_official_name(official_name: str, ProductOfficialName): - with pytest.raises(ValidationError, match='Invalid country official name'): - ProductOfficialName(made_in=official_name) - - -@pytest.mark.parametrize( - 'numeric_code, country_data', - [(numeric_code, country_data) for numeric_code, country_data in _index_by_numeric_code().items()][:PARAMS_AMOUNT], -) +@pytest.mark.parametrize('numeric_code, country_data', list(_index_by_numeric_code().items())[:PARAMS_AMOUNT]) def test_valid_numeric_code(numeric_code: str, country_data: CountryInfo, ProductNumericCode): banana = ProductNumericCode(made_in=numeric_code) assert banana.made_in == country_data.numeric_code assert banana.made_in.alpha2 == country_data.alpha2 assert banana.made_in.alpha3 == country_data.alpha3 assert banana.made_in.short_name == country_data.short_name - assert banana.made_in.official_name == country_data.official_name @pytest.mark.parametrize('numeric_code', list(printable)) diff --git a/tests/test_json_schema.py b/tests/test_json_schema.py index ab38f67e..8508e87a 100644 --- a/tests/test_json_schema.py +++ b/tests/test_json_schema.py @@ -7,7 +7,6 @@ CountryAlpha2, CountryAlpha3, CountryNumericCode, - CountryOfficialName, CountryShortName, ) from pydantic_extra_types.isbn import ISBN @@ -71,15 +70,6 @@ 'type': 'object', }, ), - ( - CountryOfficialName, - { - 'properties': {'x': {'title': 'X', 'type': 'string'}}, - 'required': ['x'], - 'title': 'Model', - 'type': 'object', - }, - ), ( CountryShortName, {