From bc3cd919482360b01a4eec17be83c582d0c3ac98 Mon Sep 17 00:00:00 2001 From: sarrabah Date: Thu, 23 Jan 2025 17:20:37 +0100 Subject: [PATCH 1/9] Delete new_geo method --- src/frformat/formats/canton.py | 2 +- src/frformat/formats/code_commune_insee.py | 2 +- src/frformat/formats/code_pays.py | 4 +- src/frformat/formats/code_region.py | 4 +- src/frformat/formats/commune.py | 2 +- src/frformat/formats/departement.py | 2 +- src/frformat/formats/numero_departement.py | 2 +- src/frformat/formats/pays.py | 2 +- src/frformat/formats/region.py | 2 +- src/frformat/set_format.py | 73 ++++++------------- ...r_with_cog.py => test_insee_geo_format.py} | 12 ++- 11 files changed, 43 insertions(+), 64 deletions(-) rename src/tests/{test_geo_fr_with_cog.py => test_insee_geo_format.py} (95%) diff --git a/src/frformat/formats/canton.py b/src/frformat/formats/canton.py index e456e6f..520466d 100644 --- a/src/frformat/formats/canton.py +++ b/src/frformat/formats/canton.py @@ -10,4 +10,4 @@ canton_versioned_data.add_version(Millesime.M2023, CANTON_COG_2023) canton_versioned_data.add_version(Millesime.M2024, CANTON_COG_2024) -Canton = set_format.new_geo("Canton", name, description, canton_versioned_data) +Canton = set_format.new("Canton", name, description, canton_versioned_data) diff --git a/src/frformat/formats/code_commune_insee.py b/src/frformat/formats/code_commune_insee.py index 036d117..4aa6858 100644 --- a/src/frformat/formats/code_commune_insee.py +++ b/src/frformat/formats/code_commune_insee.py @@ -17,6 +17,6 @@ Millesime.M2024, CODES_COMMUNES_INSEE_COG_2024 ) -CodeCommuneInsee = set_format.new_geo( +CodeCommuneInsee = set_format.new( "CodeCommuneInsee", name, description, code_commune_insee_versioned_data ) diff --git a/src/frformat/formats/code_pays.py b/src/frformat/formats/code_pays.py index 5044a07..80f3964 100644 --- a/src/frformat/formats/code_pays.py +++ b/src/frformat/formats/code_pays.py @@ -15,7 +15,7 @@ code_pays_IS02_versioned_data.add_version(Millesime.M2023, CODES_PAYS_ISO2_COG_2023) code_pays_IS02_versioned_data.add_version(Millesime.M2024, CODES_PAYS_ISO2_COG_2024) -CodePaysISO2 = set_format.new_geo( +CodePaysISO2 = set_format.new( "CodePaysISO2", name, description, code_pays_IS02_versioned_data ) @@ -27,6 +27,6 @@ code_pays_IS03_versioned_data.add_version(Millesime.M2023, CODES_PAYS_ISO3_COG_2023) code_pays_IS03_versioned_data.add_version(Millesime.M2024, CODES_PAYS_ISO3_COG_2024) -CodePaysISO3 = set_format.new_geo( +CodePaysISO3 = set_format.new( "CodePaysISO3", name, description, code_pays_IS03_versioned_data ) diff --git a/src/frformat/formats/code_region.py b/src/frformat/formats/code_region.py index 4d960ac..7f5b6f5 100644 --- a/src/frformat/formats/code_region.py +++ b/src/frformat/formats/code_region.py @@ -34,6 +34,4 @@ code_region_versioned_data.add_version(Millesime.M2023, CODES_REGIONS_COG_2023) code_region_versioned_data.add_version(Millesime.M2024, CODES_REGIONS_COG_2024) -CodeRegion = set_format.new_geo( - "CodeRegion", name, description, code_region_versioned_data -) +CodeRegion = set_format.new("CodeRegion", name, description, code_region_versioned_data) diff --git a/src/frformat/formats/commune.py b/src/frformat/formats/commune.py index f85587f..048c80a 100644 --- a/src/frformat/formats/commune.py +++ b/src/frformat/formats/commune.py @@ -13,4 +13,4 @@ commune_versioned_data.add_version(Millesime.M2023, COMMUNES_COG_2023) commune_versioned_data.add_version(Millesime.M2024, COMMUNES_COG_2024) -Commune = set_format.new_geo("Commune", name, description, commune_versioned_data) +Commune = set_format.new("Commune", name, description, commune_versioned_data) diff --git a/src/frformat/formats/departement.py b/src/frformat/formats/departement.py index c276302..697d255 100644 --- a/src/frformat/formats/departement.py +++ b/src/frformat/formats/departement.py @@ -13,6 +13,6 @@ departement_versioned_data.add_version(Millesime.M2023, DEPARTEMENTS_COG_2023) departement_versioned_data.add_version(Millesime.M2024, DEPARTEMENTS_COG_2024) -Departement = set_format.new_geo( +Departement = set_format.new( "Departement", name, description, departement_versioned_data ) diff --git a/src/frformat/formats/numero_departement.py b/src/frformat/formats/numero_departement.py index 81f2a14..c4e0381 100644 --- a/src/frformat/formats/numero_departement.py +++ b/src/frformat/formats/numero_departement.py @@ -24,6 +24,6 @@ Millesime.M2024, NUMEROS_DEPARTEMENTS_COG_2024 ) -NumeroDepartement = set_format.new_geo( +NumeroDepartement = set_format.new( "NumeroDepartement", name, description, numero_departement_versioned_data ) diff --git a/src/frformat/formats/pays.py b/src/frformat/formats/pays.py index e0e50e5..771c71f 100644 --- a/src/frformat/formats/pays.py +++ b/src/frformat/formats/pays.py @@ -11,4 +11,4 @@ pays_versioned_data = VersionedSet[Millesime]() pays_versioned_data.add_version(Millesime.M2024, PAYS_COG_2024) -Pays = set_format.new_geo("Pays", name, description, pays_versioned_data) +Pays = set_format.new("Pays", name, description, pays_versioned_data) diff --git a/src/frformat/formats/region.py b/src/frformat/formats/region.py index c6d1235..7928295 100644 --- a/src/frformat/formats/region.py +++ b/src/frformat/formats/region.py @@ -12,4 +12,4 @@ region_versioned_data.add_version(Millesime.M2023, REGIONS_COG_2023) region_versioned_data.add_version(Millesime.M2024, REGIONS_COG_2024) -Region = set_format.new_geo("Region", name, description, region_versioned_data) +Region = set_format.new("Region", name, description, region_versioned_data) diff --git a/src/frformat/set_format.py b/src/frformat/set_format.py index 277e824..dd69e9d 100644 --- a/src/frformat/set_format.py +++ b/src/frformat/set_format.py @@ -6,8 +6,6 @@ - GenericSetFormat creates a validator with valid data passed on the fly - `new` creates specialized versions where data is tied to the class -- `new_geo` creates an even more specialized version for geographical data - from INSEE """ from enum import Enum @@ -46,6 +44,28 @@ def is_valid(self, value: str) -> bool: V = TypeVar("V", bound="Version") +@total_ordering +class Millesime(Enum): + """Millesime class implements the `Version` protocol methods.""" + + M2023 = "2023" + M2024 = "2024" + LATEST = "latest" + + def __eq__(self, other) -> bool: + return self.value == other.value + + def __lt__(self, other) -> bool: + return self.value < other.value + + def get_id(self) -> str: + return self.value + + @classmethod + def is_sorted(cls) -> bool: + return True + + def new( class_name: str, name: str, @@ -86,52 +106,3 @@ def __init__(self, options: Options = Options()): specialized_set_format.metadata = Metadata(name, description) return specialized_set_format - - -################################ -# Insee Geo format ############# -################################ - - -@total_ordering -class Millesime(Enum): - """Millesime class implements the `Version` protocol methods.""" - - M2023 = "2023" - M2024 = "2024" - LATEST = "latest" - - def __eq__(self, other) -> bool: - return self.value == other.value - - def __lt__(self, other) -> bool: - return self.value < other.value - - def get_id(self) -> str: - return self.value - - @classmethod - def is_sorted(cls) -> bool: - return True - - -def new_geo( - class_name: str, name: str, description: str, valid_data: VersionedSet[Millesime] -) -> Type: - """A set format specialized on Insee geographical data, versioned by - the Millesime enum. - - The main difference is that the __init__ function takes a "cog" parameter for the version, - which means "Code officiel géographique" (Official Geographical Code). - - """ - VersionedSetFormat = new(class_name, name, description, valid_data) - - original_init = VersionedSetFormat.__init__ - - def new_init(self, cog: Union[Millesime, str], options=Options()): - original_init(self, cog, options) # type: ignore - - setattr(VersionedSetFormat, "__init__", new_init) - - return VersionedSetFormat diff --git a/src/tests/test_geo_fr_with_cog.py b/src/tests/test_insee_geo_format.py similarity index 95% rename from src/tests/test_geo_fr_with_cog.py rename to src/tests/test_insee_geo_format.py index e3b3606..34caaf1 100644 --- a/src/tests/test_geo_fr_with_cog.py +++ b/src/tests/test_insee_geo_format.py @@ -14,6 +14,13 @@ class ValidatorTest: + """ + This class tests all INSEE geographical formats, versioned by the Millesime enum. + + The __init__ function takes a cog parameter for the version, + which refers to the "Code officiel géographique" (Official Geographical Code). + """ + def __init__(self, cog, validTestCases, invalidTestCases, formatClass): self.cog = cog self.validTestCases = validTestCases @@ -215,7 +222,10 @@ def test_all_validators_with_cog(): for tc in test_cases: validatorTest = ValidatorTest( - tc["cog"], tc["validTestCases"], tc["invalidTestCases"], tc["formatClass"] + tc["cog"], + tc["validTestCases"], + tc["invalidTestCases"], + tc["formatClass"], ) validatorTest.run_all_tests() From 326dc3b8c0d10301a3f94a78489e6ca3a4ca96d0 Mon Sep 17 00:00:00 2001 From: sarrabah Date: Tue, 28 Jan 2025 12:26:35 +0100 Subject: [PATCH 2/9] test: Organize and renaming tests --- ..._format.py => test_geo_data_validation.py} | 0 src/tests/test_geo_format.py | 310 ++++++++++++++++++ src/tests/test_geo_fr.py | 57 ---- src/tests/test_insee_geo_format.py | 242 -------------- 4 files changed, 310 insertions(+), 299 deletions(-) rename src/tests/{test_geo_data_format.py => test_geo_data_validation.py} (100%) create mode 100644 src/tests/test_geo_format.py delete mode 100644 src/tests/test_geo_fr.py delete mode 100644 src/tests/test_insee_geo_format.py diff --git a/src/tests/test_geo_data_format.py b/src/tests/test_geo_data_validation.py similarity index 100% rename from src/tests/test_geo_data_format.py rename to src/tests/test_geo_data_validation.py diff --git a/src/tests/test_geo_format.py b/src/tests/test_geo_format.py new file mode 100644 index 0000000..9423f1e --- /dev/null +++ b/src/tests/test_geo_format.py @@ -0,0 +1,310 @@ +from frformat import ( + Canton, + CodeCommuneInsee, + CodeFantoir, + CodePaysISO2, + CodePaysISO3, + CodePostal, + CodeRegion, + Commune, + Departement, + LatitudeL93, + LongitudeL93, + Millesime, + NumeroDepartement, + Pays, + Region, +) +from frformat.common import NBSP, NNBSP + + +def test_insee_geo_format(): + class ValidatorTest: + """ + This class tests all INSEE geographical formats, versioned by the Millesime enum. + + The __init__ function takes a cog parameter for the version, + which refers to the "Code officiel géographique" (Official Geographical Code). + """ + + def __init__(self, cog, validTestCases, invalidTestCases, formatClass): + self.cog = cog + self.validTestCases = validTestCases + self.invalidTestCases = invalidTestCases + self.formatClass = formatClass + + def test_valid_cases(self): + for tc in self.validTestCases: + assert self.formatClass(self.cog).is_valid( + tc + ), f"Check that {tc} is not valid when the class format is {self.formatClass} and the cog is equal to {self.cog}" + + def test_invalid_cases(self): + for tc in self.invalidTestCases: + assert not self.formatClass(self.cog).is_valid( + tc + ), f"Check that {tc} is valid when the class format is {self.formatClass} and the cog is equal to {self.cog}." + + def run_all_tests(self): + self.test_valid_cases() + self.test_invalid_cases() + + def test_all_validators_with_cog(): + test_cases = [ + { + "name": "code_region_millesime2023", + "cog": Millesime.M2023, + "formatClass": CodeRegion, + "validTestCases": ["01", "75"], + "invalidTestCases": ["AA", "00", "7 5"], + }, + { + "name": "code_region_millesime2024", + "cog": Millesime.M2024, + "formatClass": CodeRegion, + "validTestCases": ["01", "75"], + "invalidTestCases": ["AA", "00", "7 5"], + }, + { + "name": "region_millesime2023", + "cog": Millesime.M2023, + "formatClass": Region, + "validTestCases": ["Centre-Val de Loire", "La Réunion", "Corse"], + "invalidTestCases": [ + "Beleriand", + "Canyon Cosmo", + "corse", + "Centre val de Loire", + "la reunion", + ], + }, + { + "name": "region_millesime2024", + "cog": Millesime.M2024, + "formatClass": Region, + "validTestCases": ["Centre-Val de Loire", "La Réunion", "Corse"], + "invalidTestCases": [ + "Beleriand", + "Canyon Cosmo", + "corse", + "Centre val de Loire", + "la reunion", + ], + }, + { + "name": "commune_millesime2023", + "cog": Millesime.M2023, + "formatClass": Commune, + "validTestCases": [ + "La Chapelle-Achard", + "Beaumont-les-Nonains", + "La Moncelle", + "Montestrucq", + ], + "invalidTestCases": [ + "Costa del Sol", + "Val-d'Usiers", + "La Chapelle-Fleurigné", + "Oullins-Pierre-Bénite", + "la chapelle Fleurigne", + "Costa-del Sol", + ], + }, + { + "name": "commune_millesime2024", + "cog": Millesime.M2024, + "formatClass": Commune, + "validTestCases": [ + "Oullins-Pierre-Bénite", + "Bellac", + "Val-d'Usiers", + "La Chapelle-Fleurigné", + ], + "invalidTestCases": [ + "Costa del Sol", + "Montestrucq", + "La Chapelle-Achard", + "Senonville", + "montestrucq", + "La Chapelle Achard", + ], + }, + { + "name": "canton_millesime2023", + "cog": Millesime.M2023, + "formatClass": Canton, + "validTestCases": [ + "Lagnieu", + "Meximieux", + ], + "invalidTestCases": ["Paris", "Lyon", "paris"], + }, + { + "name": "canton_millesime2024", + "cog": Millesime.M2024, + "formatClass": Canton, + "validTestCases": ["Paris", "Lyon"], + "invalidTestCases": ["Saint Quentin", "saint quentin"], + }, + { + "name": "code_paysISO2_millesime2023", + "cog": Millesime.M2023, + "formatClass": CodePaysISO2, + "validTestCases": ["BV", "SJ"], + "invalidTestCases": ["RWA", "TCD", "rwa"], + }, + { + "name": "code_paysISO2_millesime2024", + "cog": Millesime.M2024, + "formatClass": CodePaysISO2, + "validTestCases": ["FR", "JP"], + "invalidTestCases": ["BV", "SJ", "bv"], + }, + { + "name": "code_paysISO3_millesime2023", + "cog": Millesime.M2023, + "formatClass": CodePaysISO3, + "validTestCases": ["BVT", "SJM"], + "invalidTestCases": ["BF", "GH", "gh"], + }, + { + "name": "code_paysISO3_millesime2024", + "cog": Millesime.M2024, + "formatClass": CodePaysISO3, + "validTestCases": ["FRA", "JPN"], + "invalidTestCases": ["BVT", "SJM", "bvt"], + }, + { + "name": "departement_millesime2023", + "cog": Millesime.M2023, + "formatClass": Departement, + "validTestCases": ["Alpes-Maritimes", "Gard", "Mayotte", "Vendée"], + "invalidTestCases": [ + "Charente-Inférieure", + "Vendee", + "Alpes maritimes", + ], + }, + { + "name": "departement_millesime2024", + "cog": Millesime.M2024, + "formatClass": Departement, + "validTestCases": ["Alpes-Maritimes", "Gard", "Mayotte", "Vendée"], + "invalidTestCases": [ + "Charente-Inférieure", + "Vendee", + "Alpes maritimes", + ], + }, + { + "name": "pays_millesime2024", + "cog": Millesime.M2024, + "formatClass": Pays, + "validTestCases": ["France", "Pays-Bas", "Bosnie-Herzégovine"], + "invalidTestCases": ["L'Eldorado", "Zubrowska", "Pays Bas", "france"], + }, + { + "name": "numero_departement_millesime2023", + "cog": Millesime.M2023, + "formatClass": NumeroDepartement, + "validTestCases": ["05", "2B", "974"], + "invalidTestCases": ["99", "051", "2b", " 97 4"], + }, + { + "name": "numero_departement_millesime2024", + "cog": Millesime.M2024, + "formatClass": NumeroDepartement, + "validTestCases": ["05", "2B", "974"], + "invalidTestCases": ["99", "051", "2b", " 97 4"], + }, + { + "name": "code_commune_insee__millesime2023", + "cog": Millesime.M2023, + "formatClass": CodeCommuneInsee, + "validTestCases": ["01015", "2B002"], + "invalidTestCases": ["77777", " 01015"], + }, + { + "name": "code_commune_insee_millesime2024", + "cog": Millesime.M2024, + "formatClass": CodeCommuneInsee, + "validTestCases": ["64300", "2A331"], + "invalidTestCases": ["64402", "64 300"], + }, + ] + + for tc in test_cases: + validatorTest = ValidatorTest( + tc["cog"], + tc["validTestCases"], + tc["invalidTestCases"], + tc["formatClass"], + ) + validatorTest.run_all_tests() + + def test_code_commune_insee_format(): + code_commune_insee_cog_2023 = CodeCommuneInsee(Millesime.M2023) + code_commune_insee_cog_2024 = CodeCommuneInsee(Millesime.M2024) + + cog_2023_value = "01015" + assert code_commune_insee_cog_2023.format(cog_2023_value) == cog_2023_value + + cog_2024_value = "64300" + + assert code_commune_insee_cog_2024.format(cog_2024_value) == cog_2024_value + + +def test_geo_format(): + """This method tests geographical formats, which does not belong to the Official Geographic Code.""" + + def test_code_fantoir(): + fantoir_valid = "ZB03A" + fantoir_invalid = ["1000", "zB03A"] + + code_fantoir = CodeFantoir() + assert code_fantoir.is_valid(fantoir_valid) + for fi in fantoir_invalid: + assert not code_fantoir.is_valid(fi) + + def test_code_postal(): + value = "05560" + code_postal = CodePostal() + assert code_postal.is_valid(value) + assert code_postal.format(value) == value + codes_postales_invalides = ["77777", "2B002"] + for cpi in codes_postales_invalides: + assert not code_postal.is_valid(cpi) + + def test_longitude_l93(): + longitudel93 = LongitudeL93() + assert longitudel93.format(224234) == "224" + NNBSP + "234" + NBSP + "m" + assert longitudel93.format(224234.0) == "224" + NNBSP + "234,00" + NBSP + "m" + + invalid_test_cases = [-435522.3, -554234, 2076524, 5436780.23] + + for tc in invalid_test_cases: + assert not longitudel93.is_valid(tc) + + valid_test_cases = [0, 1234546, 1234546.32, -123554, -234.546] + + for tc in valid_test_cases: + assert longitudel93.is_valid(tc) + + def test_latitude_l93(): + latitudel93 = LatitudeL93() + assert ( + latitudel93.format(6757121) + == "6" + NNBSP + "757" + NNBSP + "121" + NBSP + "m" + ) + assert ( + latitudel93.format(6757121.337) + == "6" + NNBSP + "757" + NNBSP + "121,34" + NBSP + "m" + ) + + assert latitudel93.is_valid(6544234.2) + assert latitudel93.is_valid(7145278) + + invalid_test_cases = [0, -6145765.9, -7234567, 7233478, 6000658.5] + + for tc in invalid_test_cases: + assert not latitudel93.is_valid(tc) diff --git a/src/tests/test_geo_fr.py b/src/tests/test_geo_fr.py deleted file mode 100644 index 7cdd0cd..0000000 --- a/src/tests/test_geo_fr.py +++ /dev/null @@ -1,57 +0,0 @@ -from frformat import CodeFantoir, CodePostal, LatitudeL93, LongitudeL93 -from frformat.common import NBSP, NNBSP - - -def test_code_fantoir(): - fantoir_valid = "ZB03A" - fantoir_invalid = ["1000", "zB03A"] - - code_fantoir = CodeFantoir() - assert code_fantoir.is_valid(fantoir_valid) - for fi in fantoir_invalid: - assert not code_fantoir.is_valid(fi) - - -def test_code_postal(): - value = "05560" - code_postal = CodePostal() - assert code_postal.is_valid(value) - assert code_postal.format(value) == value - codes_postales_invalides = ["77777", "2B002"] - for cpi in codes_postales_invalides: - assert not code_postal.is_valid(cpi) - - -def test_longitude_l93(): - longitudel93 = LongitudeL93() - assert longitudel93.format(224234) == "224" + NNBSP + "234" + NBSP + "m" - assert longitudel93.format(224234.0) == "224" + NNBSP + "234,00" + NBSP + "m" - - invalid_test_cases = [-435522.3, -554234, 2076524, 5436780.23] - - for tc in invalid_test_cases: - assert not longitudel93.is_valid(tc) - - valid_test_cases = [0, 1234546, 1234546.32, -123554, -234.546] - - for tc in valid_test_cases: - assert longitudel93.is_valid(tc) - - -def test_latitude_l93(): - latitudel93 = LatitudeL93() - assert ( - latitudel93.format(6757121) == "6" + NNBSP + "757" + NNBSP + "121" + NBSP + "m" - ) - assert ( - latitudel93.format(6757121.337) - == "6" + NNBSP + "757" + NNBSP + "121,34" + NBSP + "m" - ) - - assert latitudel93.is_valid(6544234.2) - assert latitudel93.is_valid(7145278) - - invalid_test_cases = [0, -6145765.9, -7234567, 7233478, 6000658.5] - - for tc in invalid_test_cases: - assert not latitudel93.is_valid(tc) diff --git a/src/tests/test_insee_geo_format.py b/src/tests/test_insee_geo_format.py deleted file mode 100644 index 34caaf1..0000000 --- a/src/tests/test_insee_geo_format.py +++ /dev/null @@ -1,242 +0,0 @@ -from frformat import ( - Canton, - CodeCommuneInsee, - CodePaysISO2, - CodePaysISO3, - CodeRegion, - Commune, - Departement, - Millesime, - NumeroDepartement, - Pays, - Region, -) - - -class ValidatorTest: - """ - This class tests all INSEE geographical formats, versioned by the Millesime enum. - - The __init__ function takes a cog parameter for the version, - which refers to the "Code officiel géographique" (Official Geographical Code). - """ - - def __init__(self, cog, validTestCases, invalidTestCases, formatClass): - self.cog = cog - self.validTestCases = validTestCases - self.invalidTestCases = invalidTestCases - self.formatClass = formatClass - - def test_valid_cases(self): - for tc in self.validTestCases: - assert self.formatClass(self.cog).is_valid( - tc - ), f"Check that {tc} is not valid when the class format is {self.formatClass} and the cog is equal to {self.cog}" - - def test_invalid_cases(self): - for tc in self.invalidTestCases: - assert not self.formatClass(self.cog).is_valid( - tc - ), f"Check that {tc} is valid when the class format is {self.formatClass} and the cog is equal to {self.cog}." - - def run_all_tests(self): - self.test_valid_cases() - self.test_invalid_cases() - - -def test_all_validators_with_cog(): - test_cases = [ - { - "name": "code_region_millesime2023", - "cog": Millesime.M2023, - "formatClass": CodeRegion, - "validTestCases": ["01", "75"], - "invalidTestCases": ["AA", "00", "7 5"], - }, - { - "name": "code_region_millesime2024", - "cog": Millesime.M2024, - "formatClass": CodeRegion, - "validTestCases": ["01", "75"], - "invalidTestCases": ["AA", "00", "7 5"], - }, - { - "name": "region_millesime2023", - "cog": Millesime.M2023, - "formatClass": Region, - "validTestCases": ["Centre-Val de Loire", "La Réunion", "Corse"], - "invalidTestCases": [ - "Beleriand", - "Canyon Cosmo", - "corse", - "Centre val de Loire", - "la reunion", - ], - }, - { - "name": "region_millesime2024", - "cog": Millesime.M2024, - "formatClass": Region, - "validTestCases": ["Centre-Val de Loire", "La Réunion", "Corse"], - "invalidTestCases": [ - "Beleriand", - "Canyon Cosmo", - "corse", - "Centre val de Loire", - "la reunion", - ], - }, - { - "name": "commune_millesime2023", - "cog": Millesime.M2023, - "formatClass": Commune, - "validTestCases": [ - "La Chapelle-Achard", - "Beaumont-les-Nonains", - "La Moncelle", - "Montestrucq", - ], - "invalidTestCases": [ - "Costa del Sol", - "Val-d'Usiers", - "La Chapelle-Fleurigné", - "Oullins-Pierre-Bénite", - "la chapelle Fleurigne", - "Costa-del Sol", - ], - }, - { - "name": "commune_millesime2024", - "cog": Millesime.M2024, - "formatClass": Commune, - "validTestCases": [ - "Oullins-Pierre-Bénite", - "Bellac", - "Val-d'Usiers", - "La Chapelle-Fleurigné", - ], - "invalidTestCases": [ - "Costa del Sol", - "Montestrucq", - "La Chapelle-Achard", - "Senonville", - "montestrucq", - "La Chapelle Achard", - ], - }, - { - "name": "canton_millesime2023", - "cog": Millesime.M2023, - "formatClass": Canton, - "validTestCases": [ - "Lagnieu", - "Meximieux", - ], - "invalidTestCases": ["Paris", "Lyon", "paris"], - }, - { - "name": "canton_millesime2024", - "cog": Millesime.M2024, - "formatClass": Canton, - "validTestCases": ["Paris", "Lyon"], - "invalidTestCases": ["Saint Quentin", "saint quentin"], - }, - { - "name": "code_paysISO2_millesime2023", - "cog": Millesime.M2023, - "formatClass": CodePaysISO2, - "validTestCases": ["BV", "SJ"], - "invalidTestCases": ["RWA", "TCD", "rwa"], - }, - { - "name": "code_paysISO2_millesime2024", - "cog": Millesime.M2024, - "formatClass": CodePaysISO2, - "validTestCases": ["FR", "JP"], - "invalidTestCases": ["BV", "SJ", "bv"], - }, - { - "name": "code_paysISO3_millesime2023", - "cog": Millesime.M2023, - "formatClass": CodePaysISO3, - "validTestCases": ["BVT", "SJM"], - "invalidTestCases": ["BF", "GH", "gh"], - }, - { - "name": "code_paysISO3_millesime2024", - "cog": Millesime.M2024, - "formatClass": CodePaysISO3, - "validTestCases": ["FRA", "JPN"], - "invalidTestCases": ["BVT", "SJM", "bvt"], - }, - { - "name": "departement_millesime2023", - "cog": Millesime.M2023, - "formatClass": Departement, - "validTestCases": ["Alpes-Maritimes", "Gard", "Mayotte", "Vendée"], - "invalidTestCases": ["Charente-Inférieure", "Vendee", "Alpes maritimes"], - }, - { - "name": "departement_millesime2024", - "cog": Millesime.M2024, - "formatClass": Departement, - "validTestCases": ["Alpes-Maritimes", "Gard", "Mayotte", "Vendée"], - "invalidTestCases": ["Charente-Inférieure", "Vendee", "Alpes maritimes"], - }, - { - "name": "pays_millesime2024", - "cog": Millesime.M2024, - "formatClass": Pays, - "validTestCases": ["France", "Pays-Bas", "Bosnie-Herzégovine"], - "invalidTestCases": ["L'Eldorado", "Zubrowska", "Pays Bas", "france"], - }, - { - "name": "numero_departement_millesime2023", - "cog": Millesime.M2023, - "formatClass": NumeroDepartement, - "validTestCases": ["05", "2B", "974"], - "invalidTestCases": ["99", "051", "2b", " 97 4"], - }, - { - "name": "numero_departement_millesime2024", - "cog": Millesime.M2024, - "formatClass": NumeroDepartement, - "validTestCases": ["05", "2B", "974"], - "invalidTestCases": ["99", "051", "2b", " 97 4"], - }, - { - "name": "code_commune_insee__millesime2023", - "cog": Millesime.M2023, - "formatClass": CodeCommuneInsee, - "validTestCases": ["01015", "2B002"], - "invalidTestCases": ["77777", " 01015"], - }, - { - "name": "code_commune_insee_millesime2024", - "cog": Millesime.M2024, - "formatClass": CodeCommuneInsee, - "validTestCases": ["64300", "2A331"], - "invalidTestCases": ["64402", "64 300"], - }, - ] - - for tc in test_cases: - validatorTest = ValidatorTest( - tc["cog"], - tc["validTestCases"], - tc["invalidTestCases"], - tc["formatClass"], - ) - validatorTest.run_all_tests() - - -def test_code_commune_insee_format(): - code_commune_insee_cog_2023 = CodeCommuneInsee(Millesime.M2023) - code_commune_insee_cog_2024 = CodeCommuneInsee(Millesime.M2024) - - cog_2023_value = "01015" - assert code_commune_insee_cog_2023.format(cog_2023_value) == cog_2023_value - - cog_2024_value = "64300" - - assert code_commune_insee_cog_2024.format(cog_2024_value) == cog_2024_value From a72dba03fc552765c34ec3e56894898e69670433 Mon Sep 17 00:00:00 2001 From: Pierre Camilleri Date: Tue, 28 Jan 2025 16:49:05 +0100 Subject: [PATCH 3/9] refactor: improve docstrings - organize classes to have relevant docstrings for dynamically created classes --- src/frformat/formats/region.py | 3 + src/frformat/set_format.py | 118 ++++++++++++++++++-------- src/tests/test_geo_data_validation.py | 2 +- 3 files changed, 86 insertions(+), 37 deletions(-) diff --git a/src/frformat/formats/region.py b/src/frformat/formats/region.py index 7928295..a6bb7d3 100644 --- a/src/frformat/formats/region.py +++ b/src/frformat/formats/region.py @@ -8,8 +8,11 @@ "Vérifie les régions françaises valides pour un Code Officiel Géographique donné" ) + region_versioned_data = VersionedSet[Millesime]() region_versioned_data.add_version(Millesime.M2023, REGIONS_COG_2023) region_versioned_data.add_version(Millesime.M2024, REGIONS_COG_2024) Region = set_format.new("Region", name, description, region_versioned_data) + +Region.__doc__ = f"{description}\n\n{Region.__bases__[0].__doc__}" diff --git a/src/frformat/set_format.py b/src/frformat/set_format.py index dd69e9d..06fad2a 100644 --- a/src/frformat/set_format.py +++ b/src/frformat/set_format.py @@ -10,7 +10,7 @@ from enum import Enum from functools import total_ordering -from typing import FrozenSet, Type, TypeVar, Union +from typing import FrozenSet, Generic, Type, TypeVar, Union, overload from frformat import CustomStrFormat, Metadata from frformat.common import normalize_value @@ -18,22 +18,53 @@ from frformat.versioned_set import Version, VersionedSet -class GenericSetFormat(CustomStrFormat): - """A format that checks if a value is among a set of valid values. +@total_ordering +class Millesime(Enum): + """Millesime class implements the `Version` protocol methods.""" + + M2023 = "2023" + M2024 = "2024" + LATEST = "latest" + + def __eq__(self, other) -> bool: + return self.value == other.value + + def __lt__(self, other) -> bool: + return self.value < other.value - In the generic version, valid data is passed at object initialisation. + def get_id(self) -> str: + return self.value + + @classmethod + def is_sorted(cls) -> bool: + return True + + +class SingleSetFormat(CustomStrFormat): + """This format defines a closed list of valid values.""" + + _data: FrozenSet = frozenset() + """Dataset of valid values. + + Technical details: + + Beware, child classes may define an instance `_data` attribute, which + will always take precedence over the class attribute for the validation. """ - def __init__(self, valid_data: FrozenSet, options: Options = Options()): + def __init__(self, options: Options = Options()): self._options = options - self._data = valid_data normalized_extra_values = { normalize_value(e, self._options) for e in self._options.extra_valid_values } self._normalized_values = { - normalize_value(e, self._options) for e in self._data + normalize_value(e, self._options) + for e in self._data + # in child classes, `self._data` can reference an instance + # attribute, if applicable ; otherwise the class attribute will + # be used }.union(normalized_extra_values) def is_valid(self, value: str) -> bool: @@ -44,26 +75,44 @@ def is_valid(self, value: str) -> bool: V = TypeVar("V", bound="Version") -@total_ordering -class Millesime(Enum): - """Millesime class implements the `Version` protocol methods.""" +class VersionedSetFormat(SingleSetFormat, Generic[V]): + """This format defines a closed set of valid values, with different + versions to choose from. - M2023 = "2023" - M2024 = "2024" - LATEST = "latest" + Specific implementation details : - def __eq__(self, other) -> bool: - return self.value == other.value + - the type will hint at which version class to use for initializing the format validator. + - a description of the format can be consulted with `MyClass.metadata.description` or at the top of `help(MyClass)` - def __lt__(self, other) -> bool: - return self.value < other.value + Technical details: - def get_id(self) -> str: - return self.value + - In the versioned set format, the _data attribute is an instance attribute, + which takes precedence over the class attribute of the mother class. The + reason for this is that the exact valid values set is only known on instantiation. + """ - @classmethod - def is_sorted(cls) -> bool: - return True + _versioned_data: VersionedSet = VersionedSet() + + def __init__(self, version: Union[V, str], options: Options = Options()): + version_id = version if isinstance(version, str) else version.get_id() + data = self._versioned_data.get_data(version_id) + if data is None: + raise ValueError(f"No data available for version: {version_id}") + + self._data = data + super().__init__(options) + + +@overload +def new( + class_name: str, name: str, description: str, valid_data: VersionedSet[V] +) -> Type[VersionedSetFormat[V]]: ... + + +@overload +def new( + class_name: str, name: str, description: str, valid_data: FrozenSet +) -> Type[SingleSetFormat]: ... def new( @@ -71,7 +120,7 @@ def new( name: str, description: str, valid_data: Union[VersionedSet[V], FrozenSet[str]], -) -> Type: +) -> Union[Type[VersionedSetFormat[V]], Type[SingleSetFormat]]: """Utility function to create a specialized version of a SetFormat. The returned class is a fully featured format that once initialized @@ -82,27 +131,24 @@ def new( """ if isinstance(valid_data, VersionedSet): - class VersionedSetFormat(GenericSetFormat): - def __init__(self, version: Union[V, str], options: Options = Options()): - version_id = version if isinstance(version, str) else version.get_id() - data = valid_data.get_data(version_id) - if data is None: - raise ValueError(f"No data available for version: {version_id}") - - super().__init__(data, options) + class NewVersionedFormat(VersionedSetFormat): + _versioned_data = valid_data - specialized_set_format = VersionedSetFormat + specialized_set_format = NewVersionedFormat else: - class SingleSetFormat(GenericSetFormat): - def __init__(self, options: Options = Options()): - super().__init__(valid_data, options) + class NewFormat(SingleSetFormat): + _data = valid_data - specialized_set_format = SingleSetFormat + specialized_set_format = NewFormat specialized_set_format.__name__ = class_name specialized_set_format.__qualname__ = class_name + specialized_set_format.__doc__ = ( + f"{description}\n\n{specialized_set_format.__doc__}" + ) + specialized_set_format.metadata = Metadata(name, description) return specialized_set_format diff --git a/src/tests/test_geo_data_validation.py b/src/tests/test_geo_data_validation.py index d48eb28..85d13e3 100644 --- a/src/tests/test_geo_data_validation.py +++ b/src/tests/test_geo_data_validation.py @@ -54,4 +54,4 @@ def test_geo_data_format(): test_format = FormatTest(tc["version"]) assert ( test_format.is_valid(tc["value_to_test"]) == tc["expected_valid"] - ), f'Error on geo data format definition with version { tc["expected_version"] } and value { tc["value_to_test"] }' + ), f'Error on geo data format definition with version { tc["version"] } and value { tc["value_to_test"] }' From 24cdcfa8f450b0028db7a7bf64216ec0eed9dae6 Mon Sep 17 00:00:00 2001 From: Pierre Camilleri Date: Tue, 28 Jan 2025 16:50:45 +0100 Subject: [PATCH 4/9] fix: code artifact that was not meant to be commited --- src/frformat/formats/region.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/frformat/formats/region.py b/src/frformat/formats/region.py index a6bb7d3..4e67deb 100644 --- a/src/frformat/formats/region.py +++ b/src/frformat/formats/region.py @@ -14,5 +14,3 @@ region_versioned_data.add_version(Millesime.M2024, REGIONS_COG_2024) Region = set_format.new("Region", name, description, region_versioned_data) - -Region.__doc__ = f"{description}\n\n{Region.__bases__[0].__doc__}" From f1438a8526723581aba186c497d963b8bd9e5577 Mon Sep 17 00:00:00 2001 From: Pierre Camilleri Date: Tue, 28 Jan 2025 16:56:02 +0100 Subject: [PATCH 5/9] rename `_data` in `_valid_values` --- src/frformat/set_format.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/frformat/set_format.py b/src/frformat/set_format.py index 06fad2a..97f0604 100644 --- a/src/frformat/set_format.py +++ b/src/frformat/set_format.py @@ -41,14 +41,14 @@ def is_sorted(cls) -> bool: class SingleSetFormat(CustomStrFormat): - """This format defines a closed list of valid values.""" + """This format defines a closed list of valid values""" - _data: FrozenSet = frozenset() + _valid_values: FrozenSet = frozenset() """Dataset of valid values. Technical details: - Beware, child classes may define an instance `_data` attribute, which + Beware, child classes may define an instance `_valid_values` attribute, which will always take precedence over the class attribute for the validation. """ @@ -61,8 +61,8 @@ def __init__(self, options: Options = Options()): self._normalized_values = { normalize_value(e, self._options) - for e in self._data - # in child classes, `self._data` can reference an instance + for e in self._valid_values + # in child classes, `self._valid_values` can reference an instance # attribute, if applicable ; otherwise the class attribute will # be used }.union(normalized_extra_values) @@ -86,20 +86,20 @@ class VersionedSetFormat(SingleSetFormat, Generic[V]): Technical details: - - In the versioned set format, the _data attribute is an instance attribute, + - In the versioned set format, the `_valid_values` attribute is an instance attribute, which takes precedence over the class attribute of the mother class. The reason for this is that the exact valid values set is only known on instantiation. """ - _versioned_data: VersionedSet = VersionedSet() + _versioned_valid_values: VersionedSet = VersionedSet() def __init__(self, version: Union[V, str], options: Options = Options()): version_id = version if isinstance(version, str) else version.get_id() - data = self._versioned_data.get_data(version_id) + data = self._versioned_valid_values.get_data(version_id) if data is None: raise ValueError(f"No data available for version: {version_id}") - self._data = data + self._valid_values = data super().__init__(options) @@ -132,14 +132,14 @@ def new( if isinstance(valid_data, VersionedSet): class NewVersionedFormat(VersionedSetFormat): - _versioned_data = valid_data + _versioned_valid_values = valid_data specialized_set_format = NewVersionedFormat else: class NewFormat(SingleSetFormat): - _data = valid_data + _valid_values = valid_data specialized_set_format = NewFormat From 024c327b4ee9b93ce3194b5d05bd36fc7ac258d2 Mon Sep 17 00:00:00 2001 From: Pierre Camilleri Date: Tue, 28 Jan 2025 17:04:23 +0100 Subject: [PATCH 6/9] update black dependency --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0599af5..73a75e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ shapely = "^2.0.2" [tool.poetry.group.linting.dependencies] -black = "^23.12.1" +black = "^24.12.1" isort = "^5.13.2" pyright = "^1.1.369" flake8 = "^7.0.0" From e760eeaacc97461f8c5a872f03a5999e63ba63bb Mon Sep 17 00:00:00 2001 From: Pierre Camilleri Date: Tue, 28 Jan 2025 17:05:58 +0100 Subject: [PATCH 7/9] Oopsie --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 73a75e4..3611890 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ shapely = "^2.0.2" [tool.poetry.group.linting.dependencies] -black = "^24.12.1" +black = "^24.10" isort = "^5.13.2" pyright = "^1.1.369" flake8 = "^7.0.0" From 17324a6f872b5185aeb381ec8aaf503de67fa4e4 Mon Sep 17 00:00:00 2001 From: Pierre Camilleri Date: Tue, 28 Jan 2025 17:12:26 +0100 Subject: [PATCH 8/9] poetry.lock update --- poetry.lock | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/poetry.lock b/poetry.lock index fced7e8..284ddd6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,33 +2,33 @@ [[package]] name = "black" -version = "23.12.1" +version = "24.10.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, - {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, - {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, - {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, - {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, - {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, - {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, - {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, - {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, - {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, - {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, - {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, - {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, - {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, - {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, - {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, - {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, - {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, - {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, - {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, - {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, - {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, + {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, + {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, + {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, + {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, + {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, + {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, + {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, + {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, + {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, + {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, + {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, + {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, + {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, + {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, + {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, + {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, + {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, + {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, + {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, + {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, + {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, + {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, ] [package.dependencies] @@ -42,7 +42,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -521,4 +521,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "367611111f643b946a28255d3b78a494212ffb16ec60b02ab30ae9483d50c91d" +content-hash = "44d0f486da0bcfa47387c00e4741a05c81a67171d0132155c6a00d838580f7a3" From 25cee1a09cfa6ec6ee8753d2f1d9a8948a3addb3 Mon Sep 17 00:00:00 2001 From: sarrabah Date: Tue, 28 Jan 2025 17:20:07 +0100 Subject: [PATCH 9/9] fix: Linting --- src/frformat/custom_format.py | 3 +-- src/frformat/formatter.py | 3 +-- src/frformat/versioned_set.py | 21 +++++++-------------- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/frformat/custom_format.py b/src/frformat/custom_format.py index 9d49e9b..e14e234 100644 --- a/src/frformat/custom_format.py +++ b/src/frformat/custom_format.py @@ -19,8 +19,7 @@ class CustomFormat(ABC, Generic[ValueType]): formatter: Formatter = DefaultFormatter[ValueType]() @abstractmethod - def is_valid(self, value: ValueType) -> bool: - ... + def is_valid(self, value: ValueType) -> bool: ... def format(self, value: ValueType) -> str: if not self.is_valid(value): diff --git a/src/frformat/formatter.py b/src/frformat/formatter.py index b98e87d..dd28666 100644 --- a/src/frformat/formatter.py +++ b/src/frformat/formatter.py @@ -7,8 +7,7 @@ class Formatter(Protocol, Generic[ValueType]): - def format(self, value: ValueType) -> str: - ... + def format(self, value: ValueType) -> str: ... class DefaultFormatter(Generic[ValueType]): diff --git a/src/frformat/versioned_set.py b/src/frformat/versioned_set.py index 34f5d18..165a84c 100644 --- a/src/frformat/versioned_set.py +++ b/src/frformat/versioned_set.py @@ -16,8 +16,7 @@ class Version(Protocol): - def get_id(self) -> str: - ... + def get_id(self) -> str: ... @classmethod def is_sorted(cls) -> bool: @@ -32,23 +31,17 @@ class _SortableVersion(Version, Protocol): """A version subclass that is sortable For type checking purposes only""" - def __lt__(self, v) -> bool: - ... + def __lt__(self, v) -> bool: ... - def __le__(self, v) -> bool: - ... + def __le__(self, v) -> bool: ... - def __gt__(self, v) -> bool: - ... + def __gt__(self, v) -> bool: ... - def __ge__(self, v) -> bool: - ... + def __ge__(self, v) -> bool: ... - def __eq__(self, v) -> bool: - ... + def __eq__(self, v) -> bool: ... - def __ne__(self, v) -> bool: - ... + def __ne__(self, v) -> bool: ... class VersionedSet(Generic[V]):