more checks for table and pydantic model creation

This commit is contained in:
collerek
2020-08-03 17:49:01 +02:00
parent 876f225d0b
commit d7355b8c9b
5 changed files with 75 additions and 14 deletions

View File

@ -0,0 +1,17 @@
from orm.fields import Integer, BigInteger, Boolean, Time, Text, String, JSON, DateTime, Date, Decimal, Float
from orm.models import Model
__all__ = [
"Integer",
"BigInteger",
"Boolean",
"Time",
"Text",
"String",
"JSON",
"DateTime",
"Date",
"Decimal",
"Float",
"Model"
]

View File

@ -1,5 +1,6 @@
import datetime
import decimal
from typing import Any
import pydantic
import sqlalchemy
@ -10,6 +11,10 @@ from orm.exceptions import ModelDefinitionError
class BaseField:
__type__ = None
def __new__(cls, *args, **kwargs):
cls.__annotations__ = {}
return super().__new__(cls)
def __init__(self, *args, **kwargs):
name = kwargs.pop('name', None)
args = list(args)
@ -32,6 +37,10 @@ class BaseField:
self.index = kwargs.pop('index', None)
self.unique = kwargs.pop('unique', None)
self.pydantic_only = kwargs.pop('pydantic_only', False)
if self.pydantic_only and self.primary_key:
raise ModelDefinitionError('Primary key column cannot be pydantic only.')
def get_column(self, name=None) -> sqlalchemy.Column:
name = self.name or name
constraints = self.get_constraints()

View File

@ -1,4 +1,4 @@
from typing import Any, Optional
from typing import Any
import sqlalchemy
from pydantic import create_model
@ -33,20 +33,29 @@ class ModelMetaclass(type):
pkname = None
columns = []
for field_name, field in new_model.__dict__.items():
if isinstance(field, BaseField):
for field_name, field in attrs.items():
if isinstance(field, BaseField) and not field.pydantic_only:
if field.primary_key:
pkname = field_name
columns.append(field.get_column(field_name))
pydantic_fields = parse_pydantic_field_from_model_fields(new_model.__dict__)
# sqlalchemy table creation
attrs['__table__'] = sqlalchemy.Table(tablename, metadata, *columns)
attrs['__columns__'] = columns
attrs['__pkname__'] = pkname
new_model.__table__ = sqlalchemy.Table(tablename, metadata, *columns)
new_model.__columns__ = columns
new_model.__pkname__ = pkname
new_model.__pydantic_fields__ = pydantic_fields
new_model.__pydantic_model__ = create_model(name, **pydantic_fields)
new_model.__fields__ = new_model.__pydantic_model__.__fields__
# pydantic model creation
pydantic_fields = parse_pydantic_field_from_model_fields(attrs)
pydantic_model = create_model(name, **pydantic_fields)
attrs['__pydantic_fields__'] = pydantic_fields
attrs['__pydantic_model__'] = pydantic_model
attrs['__fields__'] = pydantic_model.__fields__
attrs['__signature__'] = pydantic_model.__signature__
attrs['__annotations__'] = pydantic_model.__annotations__
new_model = super().__new__( # type: ignore
mcs, name, bases, attrs
)
return new_model
@ -62,9 +71,10 @@ class Model(metaclass=ModelMetaclass):
def __setattr__(self, key, value):
if key in self.__fields__:
setattr(self.values, key, value)
super().__setattr__(key, value)
else:
super().__setattr__(key, value)
def __getattribute__(self, item):
def __getattribute__(self, item) -> Any:
if item != '__fields__' and item in self.__fields__:
return getattr(self.values, item)
return super().__getattribute__(item)