From fc5fc23c5d46886ba22e6fa6db33a1f8477bbdcb Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 7 Jan 2024 16:24:06 -0600 Subject: [PATCH] ex 7.3 --- stock.py | 13 ++++++++++--- structure.py | 20 ++++++++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/stock.py b/stock.py index 920b9f7..64e051c 100644 --- a/stock.py +++ b/stock.py @@ -1,14 +1,21 @@ from structure import Structure +from validate import PositiveFloat, PositiveInteger, String class Stock(Structure): - _fields = ('name', 'shares', 'price') + _types = () + name = String() + shares = PositiveInteger() + price = PositiveFloat() @property def cost(self): return self.shares * self.price - def sell(self, nshares): + def sell(self, nshares: PositiveInteger): self.shares -= nshares -Stock.create_init() + @classmethod + def from_row(cls, row): + rowdata = [func(val) for func, val in zip(cls._types, row)] + return cls(*rowdata) diff --git a/structure.py b/structure.py index d6476c4..0bf6c73 100644 --- a/structure.py +++ b/structure.py @@ -1,10 +1,26 @@ -import inspect -import sys +from validate import Validator, validated + + +def validate_attributes(cls): + validators = [] + for name, val in vars(cls).items(): + if isinstance(val, Validator): + validators.append(val) + elif callable(val) and val.__annotations__: + setattr(cls, name, validated(val)) + cls._fields = tuple(val.name for val 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: _fields = () + def __init_subclass__(cls): + validate_attributes(cls) + def __repr__(self): args = map(lambda field: f"{field}={getattr(self, field)!r}", self._fields) return f"{type(self).__name__}({', '.join(args)})"