From 2f77206b8fa99c82171687d0866b41e1e0621284 Mon Sep 17 00:00:00 2001 From: Bertrand Benjamin Date: Sun, 18 Feb 2024 17:40:52 +0100 Subject: [PATCH] Feat: add Interseptor --- scripts/__init__.py | 0 scripts/intersept_not_valid.py | 28 ++++++++++++++ tests/__ini__.py | 0 tests/test_intersept_not_valid.py | 63 +++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 scripts/__init__.py create mode 100644 scripts/intersept_not_valid.py create mode 100644 tests/__ini__.py create mode 100644 tests/test_intersept_not_valid.py diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/intersept_not_valid.py b/scripts/intersept_not_valid.py new file mode 100644 index 0000000..db0b41f --- /dev/null +++ b/scripts/intersept_not_valid.py @@ -0,0 +1,28 @@ +from collections.abc import Callable + +import pandas as pd +from pydantic import BaseModel, ValidationError + + +class Interseptor: + def __init__(self, model: BaseModel): + self.model = model + self.not_valid_rows = [] + + def __call__(self, func: Callable[..., pd.DataFrame]): + def wrapped(*args, **kwrds): + res = func(*args, **kwrds) + df_dict = res.to_dict(orient="records") + valid_rows = [] + for i, r in enumerate(df_dict): + try: + self.model(**r) + except ValidationError: + r["InterseptorOrigin"] = func.__name__ + r["InterseptorIndex"] = i + self.not_valid_rows.append(r) + else: + valid_rows.append(r) + return pd.DataFrame.from_records(valid_rows) + + return wrapped diff --git a/tests/__ini__.py b/tests/__ini__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_intersept_not_valid.py b/tests/test_intersept_not_valid.py new file mode 100644 index 0000000..d91098c --- /dev/null +++ b/tests/test_intersept_not_valid.py @@ -0,0 +1,63 @@ +import random + +import pandas as pd +import pytest +from pydantic import BaseModel + +from scripts.intersept_not_valid import Interseptor + + +class FakeModel(BaseModel): + name: str + age: int + + +def test_init_composed(): + interceptor = Interseptor(FakeModel) + + def df_generator(nrows=3): + records = [{"name": "plop", "age": random.randint(1, 50)} for _ in range(nrows)] + return pd.DataFrame.from_records(records) + + df_generator_val = interceptor(df_generator) + + df = df_generator_val(3) + assert len(df) == 3 + assert interceptor.not_valid_rows == [] + + +def test_init_decorator(): + interceptor = Interseptor(FakeModel) + + @interceptor + def df_generator(nrows=3): + records = [{"name": "plop", "age": random.randint(1, 50)} for _ in range(nrows)] + return pd.DataFrame.from_records(records) + + df = df_generator(3) + assert len(df) == 3 + assert interceptor.not_valid_rows == [] + + +def test_intersept_not_valid(): + interceptor = Interseptor(FakeModel) + + @interceptor + def df_generator(): + records = [ + {"name": "plop", "age": 12}, + {"name": "hop", "age": "ui"}, + {"name": "pipo", "age": 12}, + ] + return pd.DataFrame.from_records(records) + + df = df_generator() + assert len(df) == 2 + assert interceptor.not_valid_rows == [ + { + "name": "hop", + "age": "ui", + "InterseptorOrigin": "df_generator", + "InterseptorIndex": 1, + } + ]