Commit 4da88779 authored by Pierre Dittgen's avatar Pierre Dittgen
Browse files

merge requirements.txt

parent ff2ef427
...@@ -63,6 +63,10 @@ Validata extends frictionless, bringing additional checks (located in [custom-ch ...@@ -63,6 +63,10 @@ Validata extends frictionless, bringing additional checks (located in [custom-ch
- emit `opening-hours-value` error - emit `opening-hours-value` error
- `PhoneNumberValueError` checks that a value is a valid phone number
- emit `phone-number-value` error
- `SumColumnsValue` checks that a field contains the sum of some other fields - `SumColumnsValue` checks that a field contains the sum of some other fields
- emit `sum-columns-value` error - emit `sum-columns-value` error
......
...@@ -9,9 +9,9 @@ attrs==21.2.0 ...@@ -9,9 +9,9 @@ attrs==21.2.0
certifi==2021.5.30 certifi==2021.5.30
# via requests # via requests
chardet==4.0.0 chardet==4.0.0
# via frictionless # via
charset-normalizer==2.0.6 # frictionless
# via requests # requests
click==8.0.1 click==8.0.1
# via typer # via typer
colorama==0.4.4 colorama==0.4.4
...@@ -24,45 +24,47 @@ ezodf==0.3.2 ...@@ -24,45 +24,47 @@ ezodf==0.3.2
# via validata-core (setup.py) # via validata-core (setup.py)
frictionless[excel]==4.18.2 frictionless[excel]==4.18.2
# via validata-core (setup.py) # via validata-core (setup.py)
idna==3.2 idna==2.10
# via requests # via requests
importlib-resources==5.2.2 importlib-resources==5.2.2
# via validata-core (setup.py) # via validata-core (setup.py)
isodate==0.6.0 isodate==0.6.0
# via frictionless # via frictionless
jsonschema==4.0.1 jsonschema==3.2.0
# via frictionless # via frictionless
lxml==4.6.3 lxml==4.6.3
# via validata-core (setup.py) # via validata-core (setup.py)
marko==1.1.0 marko==1.1.0
# via frictionless # via frictionless
numpy==1.21.2 numpy==1.20.3
# via pandas # via pandas
opening-hours-py==0.5.2 opening-hours-py==0.5.2
# via validata-core (setup.py) # via validata-core (setup.py)
openpyxl==3.0.9 openpyxl==3.0.7
# via # via
# frictionless # frictionless
# validata-core (setup.py) # validata-core (setup.py)
pandas==1.3.3 pandas==1.2.4
# via tablib # via tablib
petl==1.7.4 petl==1.7.4
# via frictionless # via frictionless
pyrsistent==0.18.0 phonenumbers==8.12.34
# via validata-core (setup.py)
pyrsistent==0.17.3
# via jsonschema # via jsonschema
python-dateutil==2.8.2 python-dateutil==2.8.1
# via # via
# frictionless # frictionless
# pandas # pandas
python-slugify==5.0.2 python-slugify==5.0.2
# via frictionless # via frictionless
python-stdnum==1.17 python-stdnum==1.16
# via validata-core (setup.py) # via validata-core (setup.py)
pytz==2021.3 pytz==2021.1
# via pandas # via pandas
pyyaml==5.4.1 pyyaml==5.4.1
# via frictionless # via frictionless
requests==2.26.0 requests==2.25.1
# via # via
# frictionless # frictionless
# validata-core (setup.py) # validata-core (setup.py)
...@@ -75,6 +77,7 @@ simpleeval==0.9.10 ...@@ -75,6 +77,7 @@ simpleeval==0.9.10
six==1.16.0 six==1.16.0
# via # via
# isodate # isodate
# jsonschema
# python-dateutil # python-dateutil
# validators # validators
stringcase==1.2.0 stringcase==1.2.0
...@@ -87,7 +90,7 @@ toolz==0.11.1 ...@@ -87,7 +90,7 @@ toolz==0.11.1
# via validata-core (setup.py) # via validata-core (setup.py)
typer[all]==0.4.0 typer[all]==0.4.0
# via frictionless # via frictionless
urllib3==1.26.7 urllib3==1.26.4
# via requests # via requests
validators==0.18.2 validators==0.18.2
# via frictionless # via frictionless
...@@ -95,5 +98,8 @@ xlrd==2.0.1 ...@@ -95,5 +98,8 @@ xlrd==2.0.1
# via frictionless # via frictionless
xlwt==1.3.0 xlwt==1.3.0
# via frictionless # via frictionless
zipp==3.6.0 zipp==3.4.1
# via importlib-resources # via importlib-resources
# The following packages are considered to be unsafe in a requirements file:
# setuptools
...@@ -54,6 +54,7 @@ setup( ...@@ -54,6 +54,7 @@ setup(
"toolz", "toolz",
# for custom_checks # for custom_checks
"opening-hours-py", "opening-hours-py",
"phonenumbers",
"python-stdnum", "python-stdnum",
], ],
setup_requires=[ setup_requires=[
......
import pytest
from validata_core import validate
@pytest.fixture
def schema_phone_number():
return {
"$schema": "https://frictionlessdata.io/schemas/table-schema.json",
"fields": [
{
"name": "telephone",
"title": "Numéro de téléphone",
"type": "string",
},
],
"custom_checks": [
{"name": "phone-number-value", "params": {"column": "telephone"}}
],
}
# https://en.wikipedia.org/wiki/Fictitious_telephone_number#France
def test_valid_10digits_french_phone_number(schema_phone_number):
source = [["telephone"], ["02 61 91 13 45"]]
report = validate(source, schema_phone_number)
assert report.valid
def test_valid_10digits_french_phone_number_without_spaces(schema_phone_number):
source = [["telephone"], ["0261911345"]]
report = validate(source, schema_phone_number)
assert report.valid
def test_valid_10digits_french_phone_number_with_extra_spaces(schema_phone_number):
source = [["telephone"], [" 026 191 13 45 "]]
report = validate(source, schema_phone_number)
assert report.valid
def test_valid_international_phone_number(schema_phone_number):
source = [["telephone"], ["+33 2 61 91 13 45"]]
report = validate(source, schema_phone_number)
assert report.valid
def test_valid_french_short_phone_number(schema_phone_number):
source = [["telephone"], ["115"]]
report = validate(source, schema_phone_number)
assert report.valid
def test_invalid_legacy_french_phone_number(schema_phone_number):
source = [["telephone"], ["619 13 45"]]
report = validate(source, schema_phone_number)
assert not report.valid
...@@ -5,6 +5,7 @@ from .french_siret_value import FrenchSiretValue ...@@ -5,6 +5,7 @@ from .french_siret_value import FrenchSiretValue
from .missing_required_header import MissingRequiredHeader # noqa from .missing_required_header import MissingRequiredHeader # noqa
from .nomenclature_actes_value import NomenclatureActesValue from .nomenclature_actes_value import NomenclatureActesValue
from .opening_hours_value import OpeningHoursValue from .opening_hours_value import OpeningHoursValue
from .phone_number_value import PhoneNumberValue
from .sum_columns_value import SumColumnsValue from .sum_columns_value import SumColumnsValue
from .year_interval_value import YearIntervalValue from .year_interval_value import YearIntervalValue
...@@ -16,6 +17,7 @@ available_checks = { ...@@ -16,6 +17,7 @@ available_checks = {
"french-siret-value": FrenchSiretValue, "french-siret-value": FrenchSiretValue,
"nomenclature-actes-value": NomenclatureActesValue, "nomenclature-actes-value": NomenclatureActesValue,
"opening-hours-value": OpeningHoursValue, "opening-hours-value": OpeningHoursValue,
"phone-number-value": PhoneNumberValue,
"sum-columns-value": SumColumnsValue, "sum-columns-value": SumColumnsValue,
"year-interval-value": YearIntervalValue, "year-interval-value": YearIntervalValue,
} }
import phonenumbers
from frictionless import Check, errors
class PhoneNumberValueError(errors.CellError):
"""Custom error."""
code = "phone-number-value"
name = "Numéro de téléphone invalide"
tags = ["#body"]
template = "La valeur '{cell}' n'est pas un numéro de téléphone valide."
description = (
"Les numéros de téléphone acceptés sont les numéros français à 10 chiffres"
" (ex : `01 99 00 27 37`) ou au format international avec le préfixe du pays"
" (ex : `+33 1 99 00 27 37`). Les numéros courts (`115` par exemple) sont"
" également acceptés."
)
class PhoneNumberValue(Check):
"""Check phone number validity."""
possible_Errors = [PhoneNumberValueError] # type: ignore
def __init__(self, descriptor=None):
super().__init__(descriptor)
self.__column = self.get("column")
def validate_start(self):
if self.__column not in self.resource.schema.field_names:
note = f"La colonne {self.__column!r} est manquante."
yield errors.TaskError(note=note)
def validate_row(self, row):
cell_value = row[self.__column]
# Empty cell, don't check!
if not cell_value:
return
try:
phonenumbers.parse(cell_value, "FR")
except phonenumbers.NumberParseException:
try:
phonenumbers.parse(cell_value)
except phonenumbers.NumberParseException:
yield PhoneNumberValueError.from_row(
row, note="", field_name=self.__column
)
metadata_profile = { # type: ignore
"type": "object",
"required": ["column"],
"properties": {"column": {"type": "string"}},
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment