From 1f4b203f6192f8178c106f112d1ad278fb24f232 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 7 Jan 2024 17:02:32 -0600 Subject: [PATCH] ex 7.6 --- stock.py | 7 ++++++- structure.py | 17 +++++++++++++++-- validate.py | 12 +++++++++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/stock.py b/stock.py index 64e051c..d829351 100644 --- a/stock.py +++ b/stock.py @@ -1,5 +1,4 @@ from structure import Structure -from validate import PositiveFloat, PositiveInteger, String class Stock(Structure): @@ -19,3 +18,9 @@ class Stock(Structure): def from_row(cls, row): rowdata = [func(val) for func, val in zip(cls._types, row)] return cls(*rowdata) + + +if __name__ == '__main__': + from reader import read_csv_as_instances + + portfolio = read_csv_as_instances('Data/portfolio.csv', Stock) diff --git a/structure.py b/structure.py index 0f81c0d..e07d647 100644 --- a/structure.py +++ b/structure.py @@ -1,3 +1,5 @@ +from collections import ChainMap + from validate import Validator, validated @@ -8,14 +10,25 @@ def validate_attributes(cls): validators.append(val) elif callable(val) and val.__annotations__: setattr(cls, name, validated(val)) - cls._fields = tuple(val.name for val in validators) + cls._fields = tuple(v.name for v in validators) cls._types = tuple(getattr(v, 'expected_type', lambda x: x) for v in validators) if cls._fields: cls.create_init() return cls -class Structure: +class StructureMeta(type): + @classmethod + def __prepare__(meta, clsname, bases): + return ChainMap({}, Validator.validators) + + @staticmethod + def __new__(meta, name, bases, methods): + methods = methods.maps[0] + return super().__new__(meta, name, bases, methods) + + +class Structure(metaclass=StructureMeta): _fields = () def __init_subclass__(cls): diff --git a/validate.py b/validate.py index dc9cd60..7e4c9b9 100644 --- a/validate.py +++ b/validate.py @@ -3,9 +3,15 @@ from functools import wraps class Validator: + validators = {} + def __init__(self, name=None): self.name = name + @classmethod + def __init_subclass__(cls): + cls.validators[cls.__name__] = cls + @classmethod def check(cls, value): return value @@ -28,9 +34,9 @@ class Typed(Validator): _typed_classes = [ - ('Integer', 'int'), - ('Float', 'float'), - ('String', 'str'), + ('Integer', int), + ('Float', float), + ('String', str), ] globals().update((name, type(name, (Typed,), {'expected_type': ty}))