Skip to content

Commit

Permalink
Merge pull request #74 from mirumee/update-package
Browse files Browse the repository at this point in the history
Update package
  • Loading branch information
michaljelonek authored Jun 5, 2023
2 parents fe88604 + ca24aa4 commit 78d26cc
Show file tree
Hide file tree
Showing 29 changed files with 701 additions and 496 deletions.
4 changes: 0 additions & 4 deletions .coveragerc

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Set up Python 3.9
- name: Set up Python 3.11
uses: actions/setup-python@v1
with:
python-version: 3.9
python-version: 3.11
- name: Install pypa/build
run: >-
python -m
Expand Down
44 changes: 38 additions & 6 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -24,11 +24,43 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python setup.py install
python -m pip install --upgrade pip
python -m pip install pytest pytest-cov mock
pip install wheel
pip install -e .[dev,test]
- run: mkdir coverage
- name: Test with pytest
run: |
pytest
pytest --cov
env:
COVERAGE_FILE: "coverage/.coverage.${{ matrix.python-version }}"
- name: Store coverage file
uses: actions/upload-artifact@v3
with:
name: coverage
path: coverage
- name: Linters
run: |
ruff check .
coverage:
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
with:
python-version: "3.11"
- name: Get coverage files
uses: actions/download-artifact@v3
with:
name: coverage
path: coverage
- run: pip install coverage[toml]
- run: ls -la coverage
- run: coverage combine coverage
- run: coverage report
- run: coverage xml
- uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
files: coverage.xml
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2010-2016, Mirumee Software
Copyright (c) 2010-2023, Mirumee Software
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
18 changes: 9 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Google i18n address
===========================================================================================

|codecov.io| |Circle CI| |PyPi downloads| |PyPi version| |PyPi pythons|
|codecov.io| |GH Actions| |PyPi downloads| |PyPi version| |PyPi pythons|

This package contains a copy of `Google's i18n
address <https://chromium-i18n.appspot.com/ssl-address>`_ metadata repository
Expand All @@ -19,7 +19,7 @@ Addresses validation

The ``normalize_address`` function checks the address and either returns its
canonical form (suitable for storage and use in addressing envelopes) or
raises an ``InvalidAddress`` exception that contains a list of errors.
raises an ``InvalidAddressError`` exception that contains a list of errors.


Address fields
Expand Down Expand Up @@ -49,10 +49,10 @@ Address validation with only country code:

.. code:: python
>>> from i18naddress import InvalidAddress, normalize_address
>>> from i18naddress import InvalidAddressError, normalize_address
>>> try:
... address = normalize_address({'country_code': 'US'})
... except InvalidAddress as e:
... except InvalidAddressError as e:
... print(e.errors)
...
{'city': 'required',
Expand Down Expand Up @@ -84,15 +84,15 @@ Postal code/zip code validation example:

.. code:: python
>>> from i18naddress import InvalidAddress, normalize_address
>>> from i18naddress import InvalidAddressError, normalize_address
>>> try:
... address = normalize_address({
... 'country_code': 'US',
... 'country_area': 'California',
... 'city': 'Mountain View',
... 'postal_code': '74043',
... 'street_address': '1600 Amphitheatre Pkwy'})
... except InvalidAddress as e:
... except InvalidAddressError as e:
... print(e.errors)
...
{'postal_code': 'invalid'}
Expand Down Expand Up @@ -278,7 +278,7 @@ Django forms will return only required address fields in ``form.cleaned_data`` d
from django import forms
from i18naddress import InvalidAddress, normalize_address, get_validation_rules
from i18naddress import InvalidAddressError, normalize_address, get_validation_rules
class AddressForm(forms.Form):
Expand Down Expand Up @@ -323,8 +323,8 @@ Django forms will return only required address fields in ``form.cleaned_data`` d

.. |codecov.io| image:: https://img.shields.io/codecov/c/github/mirumee/google-i18n-address.svg
:target: https://codecov.io/github/mirumee/google-i18n-address?branch=master
.. |Circle CI| image:: https://img.shields.io/circleci/project/mirumee/google-i18n-address.svg
:target: https://circleci.com/gh/mirumee/google-i18n-address/tree/master
.. |GH Actions| image:: https://github.com/mirumee/google-i18n-address/actions/workflows/python-package.yml/badge.svg?branch=master
:target: https://github.com/mirumee/google-i18n-address/actions?query=branch%3Amaster+
.. |PyPi downloads| image:: https://img.shields.io/pypi/dm/google-i18n-address.svg
:target: https://pypi.python.org/pypi/google-i18n-address
.. |PyPi pythons| image:: https://img.shields.io/pypi/pyversions/google-i18n-address.svg
Expand Down
83 changes: 36 additions & 47 deletions i18naddress/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
from __future__ import unicode_literals

import io
import json
import os
import re
Expand All @@ -26,7 +23,7 @@

def load_validation_data(country_code="all"):
if not VALID_COUNTRY_CODE.match(country_code):
raise ValueError("%r is not a valid country code" % (country_code,))
raise ValueError(f"{country_code!r} is not a valid country code")
country_code = country_code.lower()
try:
# VALIDATION_DATA_PATH may have '%' symbols
Expand All @@ -37,12 +34,12 @@ def load_validation_data(country_code="all"):
path = os.path.join(VALIDATION_DATA_DIR, "%s.json" % country_code)

if not os.path.exists(path):
raise ValueError("%r is not a valid country code" % (country_code,))
with io.open(path, encoding="utf-8") as data:
raise ValueError(f"{country_code!r} is not a valid country code")
with open(path, encoding="utf-8") as data:
return json.load(data)


class ValidationRules(object):
class ValidationRules:
__slots__ = [
"country_code",
"country_name",
Expand Down Expand Up @@ -104,24 +101,23 @@ def __init__(
def __repr__(self):
return (
"ValidationRules("
"country_code=%r, "
"country_name=%r, "
"address_format=%r, "
"address_latin_format=%r, "
"allowed_fields=%r, "
"required_fields=%r, "
"upper_fields=%r, "
"country_area_type=%r, "
"country_area_choices=%r, "
"city_type=%r, "
"city_choices=%r, "
"city_area_type=%r, "
"city_area_choices=%r, "
"postal_code_type=%r, "
"postal_code_matchers=%r, "
"postal_code_examples=%r, "
"postal_code_prefix=%r)"
% (
"country_code={!r}, "
"country_name={!r}, "
"address_format={!r}, "
"address_latin_format={!r}, "
"allowed_fields={!r}, "
"required_fields={!r}, "
"upper_fields={!r}, "
"country_area_type={!r}, "
"country_area_choices={!r}, "
"city_type={!r}, "
"city_choices={!r}, "
"city_area_type={!r}, "
"city_area_choices={!r}, "
"postal_code_type={!r}, "
"postal_code_matchers={!r}, "
"postal_code_examples={!r}, "
"postal_code_prefix={!r})".format(
self.country_code,
self.country_name,
self.address_format,
Expand Down Expand Up @@ -178,7 +174,7 @@ def _make_choices(rules, translated=False):
def _compact_choices(choices):
value_map = OrderedDict()
for key, value in choices:
if not key in value_map:
if key not in value_map:
value_map[key] = set()
value_map[key].add(value)
return [
Expand All @@ -202,7 +198,7 @@ def _load_country_data(country_code):
if country_code:
country_code = country_code.upper()
if country_code.lower() == "zz":
raise ValueError("%r is not a valid country code" % (country_code,))
raise ValueError(f"{country_code!r} is not a valid country code")
database = load_validation_data(country_code.lower())
country_data.update(database[country_code])
return country_data, database
Expand Down Expand Up @@ -253,9 +249,7 @@ def get_validation_rules(address):
if is_default_language:
localized_country_data = database[country_code]
else:
localized_country_data = database[
"%s--%s" % (country_code, language)
]
localized_country_data = database[f"{country_code}--{language}"]
localized_country_area_choices = _make_choices(localized_country_data)
country_area_choices += localized_country_area_choices
existing_choice = country_area is not None
Expand All @@ -265,12 +259,10 @@ def get_validation_rules(address):
if matched_country_area:
# third level of data is for cities
if is_default_language:
country_area_data = database[
"%s/%s" % (country_code, country_area)
]
country_area_data = database[f"{country_code}/{country_area}"]
else:
country_area_data = database[
"%s/%s--%s" % (country_code, country_area, language)
f"{country_code}/{country_area}--{language}"
]
if not existing_choice:
if "zip" in country_area_data:
Expand All @@ -290,12 +282,11 @@ def get_validation_rules(address):
# fourth level of data is for dependent sublocalities
if is_default_language:
city_data = database[
"%s/%s/%s" % (country_code, country_area, city)
f"{country_code}/{country_area}/{city}"
]
else:
city_data = database[
"%s/%s/%s--%s"
% (country_code, country_area, city, language)
f"{country_code}/{country_area}/{city}--{language}"
]
if not existing_choice:
if "zip" in city_data:
Expand All @@ -314,13 +305,11 @@ def get_validation_rules(address):
if matched_city_area:
if is_default_language:
city_area_data = database[
"%s/%s/%s/%s"
% (country_code, country_area, city, city_area)
f"{country_code}/{country_area}/{city}/{city_area}"
]
else:
city_area_data = database[
"%s/%s/%s/%s--%s"
% (
"{}/{}/{}/{}--{}".format(
country_code,
country_area,
city,
Expand Down Expand Up @@ -362,9 +351,9 @@ def get_validation_rules(address):
)


class InvalidAddress(ValueError):
class InvalidAddressError(ValueError):
def __init__(self, message, errors):
super(InvalidAddress, self).__init__(message)
super().__init__(message)
self.errors = errors


Expand Down Expand Up @@ -418,7 +407,7 @@ def normalize_address(address):
_normalize_field("street_address", rules, cleaned_data, [], errors)
_normalize_field("sorting_code", rules, cleaned_data, [], errors)
if errors:
raise InvalidAddress("Invalid address", errors)
raise InvalidAddressError("Invalid address", errors)
return cleaned_data


Expand Down Expand Up @@ -482,21 +471,21 @@ def latinize_address(address, normalized=False):
if country_code:
country_area = address["country_area"]
if country_area:
key = "%s/%s" % (country_code, country_area)
key = f"{country_code}/{country_area}"
country_area_data = database.get(key)
if country_area_data:
cleaned_data["country_area"] = country_area_data.get(
"lname", country_area_data.get("name", country_area)
)
city = address["city"]
key = "%s/%s/%s" % (country_code, country_area, city)
key = f"{country_code}/{country_area}/{city}"
city_data = database.get(key)
if city_data:
cleaned_data["city"] = city_data.get(
"lname", city_data.get("name", city)
)
city_area = address["city_area"]
key = "%s/%s/%s/%s" % (country_code, country_area, city, city_area)
key = f"{country_code}/{country_area}/{city}/{city_area}"
city_area_data = database.get(key)
if city_area_data:
cleaned_data["city_area"] = city_area_data.get(
Expand Down
2 changes: 1 addition & 1 deletion i18naddress/data/all.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion i18naddress/data/bh.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"BH": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/BH", "key": "BH", "name": "BAHRAIN", "zip": "(?:\\d|1[0-2])\\d{2}", "zipex": "317"}}
{"BH": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/BH", "key": "BH", "name": "BAHRAIN", "zip": "(?:^|\\b)(?:1[0-2]|[1-9])\\d{2}(?:$|\\b)", "zipex": "317"}}
2 changes: 1 addition & 1 deletion i18naddress/data/cl.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion i18naddress/data/cn.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion i18naddress/data/co.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"CO": {"fmt": "%N%n%O%n%A%n%C, %S, %Z", "id": "data/CO", "key": "CO", "name": "COLOMBIA", "posturl": "http://www.codigopostal.gov.co/", "require": "AS", "state_name_type": "department", "zip": "\\d{6}", "zipex": "111221,130001,760011"}}
{"CO": {"fmt": "%N%n%O%n%A%n%D%n%C, %S, %Z", "id": "data/CO", "key": "CO", "lang": "es", "languages": "es", "name": "COLOMBIA", "posturl": "http://www.codigopostal.gov.co/", "require": "AS", "state_name_type": "department", "sub_isoids": "AMA~ANT~ARA~ATL~DC~BOL~BOY~CAL~CAQ~CAS~CAU~CES~CHO~COR~CUN~GUA~GUV~HUI~LAG~MAG~MET~NAR~NSA~PUT~QUI~RIS~SAP~SAN~SUC~TOL~VAC~VAU~VID", "sub_keys": "Amazonas~Antioquia~Arauca~Atlántico~Bogotá~Bolívar~Boyacá~Caldas~Caquetá~Casanare~Cauca~Cesar~Chocó~Córdoba~Cundinamarca~Guainía~Guaviare~Huila~La Guajira~Magdalena~Meta~Nariño~Norte de Santander~Putumayo~Quindío~Risaralda~San Andrés y Providencia~Santander~Sucre~Tolima~Valle del Cauca~Vaupés~Vichada", "zip": "\\d{6}", "zipex": "111221,130001,760011"}, "CO/Amazonas": {"id": "data/CO/Amazonas", "isoid": "AMA", "key": "Amazonas", "lang": "es"}, "CO/Antioquia": {"id": "data/CO/Antioquia", "isoid": "ANT", "key": "Antioquia", "lang": "es"}, "CO/Arauca": {"id": "data/CO/Arauca", "isoid": "ARA", "key": "Arauca", "lang": "es"}, "CO/Atlántico": {"id": "data/CO/Atlántico", "isoid": "ATL", "key": "Atlántico", "lang": "es"}, "CO/Bogotá": {"id": "data/CO/Bogotá", "isoid": "DC", "key": "Bogotá", "lang": "es"}, "CO/Bolívar": {"id": "data/CO/Bolívar", "isoid": "BOL", "key": "Bolívar", "lang": "es"}, "CO/Boyacá": {"id": "data/CO/Boyacá", "isoid": "BOY", "key": "Boyacá", "lang": "es"}, "CO/Caldas": {"id": "data/CO/Caldas", "isoid": "CAL", "key": "Caldas", "lang": "es"}, "CO/Caquetá": {"id": "data/CO/Caquetá", "isoid": "CAQ", "key": "Caquetá", "lang": "es"}, "CO/Casanare": {"id": "data/CO/Casanare", "isoid": "CAS", "key": "Casanare", "lang": "es"}, "CO/Cauca": {"id": "data/CO/Cauca", "isoid": "CAU", "key": "Cauca", "lang": "es"}, "CO/Cesar": {"id": "data/CO/Cesar", "isoid": "CES", "key": "Cesar", "lang": "es"}, "CO/Chocó": {"id": "data/CO/Chocó", "isoid": "CHO", "key": "Chocó", "lang": "es"}, "CO/Cundinamarca": {"id": "data/CO/Cundinamarca", "isoid": "CUN", "key": "Cundinamarca", "lang": "es"}, "CO/Córdoba": {"id": "data/CO/Córdoba", "isoid": "COR", "key": "Córdoba", "lang": "es"}, "CO/Guainía": {"id": "data/CO/Guainía", "isoid": "GUA", "key": "Guainía", "lang": "es"}, "CO/Guaviare": {"id": "data/CO/Guaviare", "isoid": "GUV", "key": "Guaviare", "lang": "es"}, "CO/Huila": {"id": "data/CO/Huila", "isoid": "HUI", "key": "Huila", "lang": "es"}, "CO/La Guajira": {"id": "data/CO/La Guajira", "isoid": "LAG", "key": "La Guajira", "lang": "es"}, "CO/Magdalena": {"id": "data/CO/Magdalena", "isoid": "MAG", "key": "Magdalena", "lang": "es"}, "CO/Meta": {"id": "data/CO/Meta", "isoid": "MET", "key": "Meta", "lang": "es"}, "CO/Nariño": {"id": "data/CO/Nariño", "isoid": "NAR", "key": "Nariño", "lang": "es"}, "CO/Norte de Santander": {"id": "data/CO/Norte de Santander", "isoid": "NSA", "key": "Norte de Santander", "lang": "es"}, "CO/Putumayo": {"id": "data/CO/Putumayo", "isoid": "PUT", "key": "Putumayo", "lang": "es"}, "CO/Quindío": {"id": "data/CO/Quindío", "isoid": "QUI", "key": "Quindío", "lang": "es"}, "CO/Risaralda": {"id": "data/CO/Risaralda", "isoid": "RIS", "key": "Risaralda", "lang": "es"}, "CO/San Andrés y Providencia": {"id": "data/CO/San Andrés y Providencia", "isoid": "SAP", "key": "San Andrés y Providencia", "lang": "es"}, "CO/Santander": {"id": "data/CO/Santander", "isoid": "SAN", "key": "Santander", "lang": "es"}, "CO/Sucre": {"id": "data/CO/Sucre", "isoid": "SUC", "key": "Sucre", "lang": "es"}, "CO/Tolima": {"id": "data/CO/Tolima", "isoid": "TOL", "key": "Tolima", "lang": "es"}, "CO/Valle del Cauca": {"id": "data/CO/Valle del Cauca", "isoid": "VAC", "key": "Valle del Cauca", "lang": "es"}, "CO/Vaupés": {"id": "data/CO/Vaupés", "isoid": "VAU", "key": "Vaupés", "lang": "es"}, "CO/Vichada": {"id": "data/CO/Vichada", "isoid": "VID", "key": "Vichada", "lang": "es"}}
2 changes: 1 addition & 1 deletion i18naddress/data/ee.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"EE": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/EE", "key": "EE", "name": "ESTONIA", "posturl": "https://www.omniva.ee/era/sihtnumbrite_otsing", "require": "ACZ", "zip": "\\d{5}", "zipex": "69501,11212"}}
{"EE": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/EE", "key": "EE", "name": "ESTONIA", "posturl": "https://www.omniva.ee/era/sihtnumbrite_otsing", "require": "ACZ", "zip": "\\d{5}", "zipex": "69501,11212"}}
2 changes: 1 addition & 1 deletion i18naddress/data/es.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion i18naddress/data/kr.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion i18naddress/data/lt.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"LT": {"fmt": "%O%n%N%n%A%nLT-%Z %C", "id": "data/LT", "key": "LT", "name": "LITHUANIA", "postprefix": "LT-", "posturl": "http://www.post.lt/lt/?id=316", "require": "ACZ", "zip": "\\d{5}", "zipex": "04340,03500"}}
{"LT": {"fmt": "%O%n%N%n%A%nLT-%Z %C %S", "id": "data/LT", "key": "LT", "name": "LITHUANIA", "postprefix": "LT-", "posturl": "http://www.post.lt/lt/?id=316", "require": "ACZ", "zip": "\\d{5}", "zipex": "04340,03500"}}
2 changes: 1 addition & 1 deletion i18naddress/data/lv.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"LV": {"fmt": "%N%n%O%n%A%n%C, %Z", "id": "data/LV", "key": "LV", "name": "LATVIA", "posturl": "http://www.pasts.lv/lv/uzzinas/nodalas/", "require": "ACZ", "zip": "LV-\\d{4}", "zipex": "LV-1073,LV-1000"}}
{"LV": {"fmt": "%N%n%O%n%A%n%S%n%C, %Z", "id": "data/LV", "key": "LV", "name": "LATVIA", "posturl": "http://www.pasts.lv/lv/uzzinas/nodalas/", "require": "ACZ", "zip": "LV-\\d{4}", "zipex": "LV-1073,LV-1000"}}
Loading

0 comments on commit 78d26cc

Please sign in to comment.