Files
ormar/tests/test_model_definition/test_model_definition.py

246 lines
6.7 KiB
Python

# type: ignore
import datetime
import decimal
import typing
import ormar
import pydantic
import pytest
import sqlalchemy
from ormar.exceptions import ModelDefinitionError
from ormar.models import Model
from tests.lifespan import init_tests
from tests.settings import create_config
base_ormar_config = create_config()
class ExampleModel(Model):
ormar_config = base_ormar_config.copy(tablename="example")
test: int = ormar.Integer(primary_key=True)
test_string: str = ormar.String(max_length=250)
test_text: str = ormar.Text(default="")
test_bool: bool = ormar.Boolean(nullable=False)
test_float = ormar.Float(nullable=True)
test_datetime = ormar.DateTime(default=datetime.datetime.now)
test_date = ormar.Date(default=datetime.date.today)
test_time = ormar.Time(default=datetime.time)
test_json = ormar.JSON(default={})
test_bigint: int = ormar.BigInteger(default=0)
test_smallint: int = ormar.SmallInteger(default=0)
test_decimal = ormar.Decimal(scale=2, precision=10)
test_decimal2 = ormar.Decimal(max_digits=10, decimal_places=2)
fields_to_check = [
"test",
"test_text",
"test_string",
"test_datetime",
"test_date",
"test_text",
"test_float",
"test_bigint",
"test_json",
]
class ExampleModel2(Model):
ormar_config = base_ormar_config.copy(tablename="example2")
test: int = ormar.Integer(primary_key=True)
test_string: str = ormar.String(max_length=250)
class User(ormar.Model):
ormar_config = base_ormar_config.copy(tablename="users")
id: int = ormar.Integer(primary_key=True)
class Account(ormar.Model):
ormar_config = base_ormar_config.copy(tablename="accounts")
id: int = ormar.Integer(primary_key=True)
user: User = ormar.ForeignKey(User, index=False)
class Purchase(ormar.Model):
ormar_config = base_ormar_config.copy(tablename="purchases")
id: int = ormar.Integer(primary_key=True)
user: User = ormar.ForeignKey(User, index=True)
create_test_database = init_tests(base_ormar_config)
@pytest.fixture()
def example():
return ExampleModel(
pk=1,
test_string="test",
test_bool=True,
test_decimal=decimal.Decimal(3.5),
test_decimal2=decimal.Decimal(5.5),
)
def test_not_nullable_field_is_required():
with pytest.raises(pydantic.ValidationError):
ExampleModel(test=1, test_string="test")
def test_model_attribute_access(example):
assert example.test == 1
assert example.test_string == "test"
assert example.test_datetime.year == datetime.datetime.now().year
assert example.test_date == datetime.date.today()
assert example.test_text == ""
assert example.test_float is None
assert example.test_bigint == 0
assert example.test_json == {}
assert example.test_decimal == 3.5
assert example.test_decimal2 == 5.5
example.test = 12
assert example.test == 12
example._orm_saved = True
assert example._orm_saved
def test_model_attribute_json_access(example):
example.test_json = dict(aa=12)
assert example.test_json == dict(aa=12)
def test_missing_metadata():
with pytest.raises(ModelDefinitionError):
class JsonSample2(ormar.Model):
ormar_config = ormar.OrmarConfig(
tablename="jsons2",
database=base_ormar_config.database,
)
id: int = ormar.Integer(primary_key=True)
test_json = ormar.JSON(nullable=True)
def test_missing_database():
with pytest.raises(ModelDefinitionError):
class JsonSample3(ormar.Model):
ormar_config = ormar.OrmarConfig(tablename="jsons3")
id: int = ormar.Integer(primary_key=True)
test_json = ormar.JSON(nullable=True)
def test_wrong_pydantic_config():
with pytest.raises(ModelDefinitionError):
class ErrorSample(ormar.Model):
model_config = ["test"]
ormar_config = ormar.OrmarConfig(tablename="jsons3")
id: int = ormar.Integer(primary_key=True)
test_json = ormar.JSON(nullable=True)
def test_non_existing_attr(example):
with pytest.raises(ValueError):
example.new_attr = 12
def test_primary_key_access_and_setting(example):
assert example.pk == 1
example.pk = 2
assert example.pk == 2
assert example.test == 2
def test_pydantic_model_is_created(example):
assert issubclass(example.__class__, pydantic.BaseModel)
assert all([field in example.model_fields for field in fields_to_check])
assert example.test == 1
def test_sqlalchemy_table_is_created(example):
assert issubclass(example.ormar_config.table.__class__, sqlalchemy.Table)
assert all(
[field in example.ormar_config.table.columns for field in fields_to_check]
)
@typing.no_type_check
def test_no_pk_in_model_definition():
with pytest.raises(ModelDefinitionError): # type: ignore
class ExampleModel2(Model): # type: ignore
ormar_config = base_ormar_config.copy(tablename="example2")
test_string: str = ormar.String(max_length=250) # type: ignore
@typing.no_type_check
def test_two_pks_in_model_definition():
with pytest.raises(ModelDefinitionError):
@typing.no_type_check
class ExampleModel2(Model):
ormar_config = base_ormar_config.copy(tablename="example3")
id: int = ormar.Integer(primary_key=True)
test_string: str = ormar.String(max_length=250, primary_key=True)
@typing.no_type_check
def test_decimal_error_in_model_definition():
with pytest.raises(ModelDefinitionError):
class ExampleModel2(Model):
ormar_config = base_ormar_config.copy(tablename="example5")
test: decimal.Decimal = ormar.Decimal(primary_key=True)
@typing.no_type_check
def test_binary_error_without_length_model_definition():
with pytest.raises(ModelDefinitionError):
class ExampleModel2(Model):
ormar_config = base_ormar_config.copy(tablename="example6")
test: bytes = ormar.LargeBinary(primary_key=True, max_length=-1)
@typing.no_type_check
def test_string_error_in_model_definition():
with pytest.raises(ModelDefinitionError):
class ExampleModel2(Model):
ormar_config = base_ormar_config.copy(tablename="example6")
test: str = ormar.String(primary_key=True, max_length=0)
@typing.no_type_check
def test_json_conversion_in_model():
with pytest.raises(pydantic.ValidationError):
ExampleModel(
test_json=datetime.datetime.now(),
test=1,
test_string="test",
test_bool=True,
)
def test_foreign_key_index():
assert Account.ormar_config.table.columns.user.index is False
assert Purchase.ormar_config.table.columns.user.index is True