Class decorator that scans a class definition for Validators and builds a _fields variable that captures their definition order.
(cls)
| 40 | validate_attributes(cls) |
| 41 | |
| 42 | def validate_attributes(cls): |
| 43 | ''' |
| 44 | Class decorator that scans a class definition for Validators |
| 45 | and builds a _fields variable that captures their definition order. |
| 46 | ''' |
| 47 | validators = [] |
| 48 | for name, val in vars(cls).items(): |
| 49 | if isinstance(val, Validator): |
| 50 | validators.append(val) |
| 51 | |
| 52 | # Apply validated decorator to any callable with annotations |
| 53 | elif callable(val) and val.__annotations__: |
| 54 | setattr(cls, name, validated(val)) |
| 55 | |
| 56 | # Collect all of the field names |
| 57 | cls._fields = tuple([v.name for v in validators]) |
| 58 | |
| 59 | # Collect type conversions. The lambda x:x is an identity |
| 60 | # function that's used in case no expected_type is found. |
| 61 | cls._types = tuple([ getattr(v, 'expected_type', lambda x: x) |
| 62 | for v in validators ]) |
| 63 | |
| 64 | # Create the __init__ method |
| 65 | if cls._fields: |
| 66 | cls.create_init() |
| 67 | |
| 68 | |
| 69 | return cls |
| 70 | |
| 71 | def typed_structure(clsname, **validators): |
| 72 | cls = type(clsname, (Structure,), validators) |
no test coverage detected