From 8eec1f5524e5bfdabb35c5f1c6547534c49434f1 Mon Sep 17 00:00:00 2001 From: MLingerTechletes Date: Tue, 4 Aug 2026 13:35:39 +0200 Subject: [PATCH] added country-code patch --- zero_friction/__init__.py | 4 + zero_friction/patches/__init__.py | 4 + .../patches/apply_patched_country_code.py | 36 +++++++++ zero_friction/patches/core.py | 3 +- zero_friction/patches/patched_country_code.py | 76 +++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 zero_friction/patches/apply_patched_country_code.py create mode 100644 zero_friction/patches/patched_country_code.py diff --git a/zero_friction/__init__.py b/zero_friction/__init__.py index 7222b211..d7356cb1 100644 --- a/zero_friction/__init__.py +++ b/zero_friction/__init__.py @@ -1 +1,5 @@ """Unified Zero Friction SDK package.""" + +from .patches import apply_patches + +apply_patches() diff --git a/zero_friction/patches/__init__.py b/zero_friction/patches/__init__.py index b3030d3c..5410b783 100644 --- a/zero_friction/patches/__init__.py +++ b/zero_friction/patches/__init__.py @@ -1 +1,5 @@ """Runtime patches applied to generated SDK clients.""" + +from .core import apply_patches + +__all__ = ["apply_patches"] diff --git a/zero_friction/patches/apply_patched_country_code.py b/zero_friction/patches/apply_patched_country_code.py new file mode 100644 index 00000000..28e337ef --- /dev/null +++ b/zero_friction/patches/apply_patched_country_code.py @@ -0,0 +1,36 @@ +"""Apply the CountryCode compatibility patch.""" + + +def apply_patched_country_code() -> None: + """Apply the patched country code enum. + + Replace the generated SDK enum with a version that accepts unknown values. + """ + import importlib + + from masterdata_client import models as models_pkg + + from .core import rebind_symbol_everywhere + from .patched_country_code import PatchedCountryCode + + country_mod = importlib.import_module("masterdata_client.models.country_code") + + # Replace original enum + country_mod.CountryCode = PatchedCountryCode # type: ignore[attr-defined] + + # Replace imports in generated modules + rebind_symbol_everywhere( + models_pkg, + "CountryCode", + PatchedCountryCode, + ) + + # Fix already-created Pydantic models + address_mod = importlib.import_module("masterdata_client.models.address_dto") + + AddressDTO = address_mod.AddressDTO + + # Pydantic v2 builds validators when the model class is created. + # Rebuild the model after replacing the enum annotation. + AddressDTO.model_fields["country"].annotation = PatchedCountryCode + AddressDTO.model_rebuild(force=True) diff --git a/zero_friction/patches/core.py b/zero_friction/patches/core.py index a8bc4632..1f1b56f7 100644 --- a/zero_friction/patches/core.py +++ b/zero_friction/patches/core.py @@ -33,10 +33,11 @@ def apply_patches() -> None: from .apply_patched_billing_calculations_type_parameters_dto import ( apply_patched_billing_calculations_type_parameters_dto, ) + from .apply_patched_country_code import apply_patched_country_code for fn in [ apply_patched_billing_calculations_type_parameters_dto, - # add future patch functions here + apply_patched_country_code, ]: _apply_once(fn) diff --git a/zero_friction/patches/patched_country_code.py b/zero_friction/patches/patched_country_code.py new file mode 100644 index 00000000..7c867367 --- /dev/null +++ b/zero_friction/patches/patched_country_code.py @@ -0,0 +1,76 @@ +"""Patched country code enum allowing unknown API values.""" + +import json +from enum import Enum +from typing import Self + + +class PatchedCountryCode(str, Enum): + """Patched country code enum. + + Accepts country codes returned by the API that are not included in the generated SDK. + """ + + AUT = "aut" + BEL = "bel" + BGR = "bgr" + CYP = "cyp" + CZE = "cze" + DNK = "dnk" + EST = "est" + FIN = "fin" + FRA = "fra" + DEU = "deu" + GRC = "grc" + HUN = "hun" + IRL = "irl" + ITA = "ita" + LVA = "lva" + LTU = "ltu" + LUX = "lux" + MLT = "mlt" + NLD = "nld" + POL = "pol" + PRT = "prt" + ROU = "rou" + SVK = "svk" + ESP = "esp" + SWE = "swe" + GBR = "gbr" + CHE = "che" + ISL = "isl" + NOR = "nor" + RUS = "rus" + BLR = "blr" + UKR = "ukr" + MDA = "mda" + SRB = "srb" + ALB = "alb" + MNE = "mne" + MKD = "mkd" + TUR = "tur" + LIE = "lie" + SMR = "smr" + AND = "and" + MCO = "mco" + BIH = "bih" + BRA = "bra" + USA = "usa" + SGP = "sgp" + ZAF = "zaf" + CUW = "cuw" + + @classmethod + def _missing_(cls, value: object) -> Self: + """Allow unknown country codes.""" + value = str(value) + + member = str.__new__(cls, value) + member._name_ = value.upper() + member._value_ = value + return member + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create a country code instance from JSON.""" + return cls(json.loads(json_str))