WIP - Pydantic v2 support (#1238)
* WIP * WIP - make test_model_definition tests pass * WIP - make test_model_methods pass * WIP - make whole test suit at least run - failing 49/443 tests * WIP fix part of the getting pydantic tests as types of fields are now kept in core schema and not on fieldsinfo * WIP fix validation in update by creating individual fields validators, failing 36/443 * WIP fix __pydantic_extra__ in intializing model, fix test related to pydantic config checks, failing 32/442 * WIP - fix enum schema in model_json_schema, failing 31/442 * WIP - fix copying through model, fix setting pydantic fields on through, fix default config and inheriting from it, failing 26/442 * WIP fix tests checking pydantic schema, fix excluding parent fields, failing 21/442 * WIP some missed files * WIP - fix validators inheritance and fix validators in generated pydantic, failing 17/442 * WIP - fix through models setting - only on reverse side of relation, but always on reverse side, failing 15/442 * WIP - fix through models setting - only on reverse side of relation, but always on reverse side, failing 15/442 * WIP - working on proper populating __dict__ for relations for new schema dumping, some work on openapi docs, failing 13/442 * WIP - remove property fields as pydantic has now computed_field on its own, failing 9/442 * WIP - fixes in docs, failing 8/442 * WIP - fix tests for largebinary schema, wrapped bytes fields fail in pydantic, will be fixed in pydantic-core, remaining is circural schema for related models, failing 6/442 * WIP - fix to pk only models in schemas * Getting test suites to pass (#1249) * wip, fixing tests * iteration, fixing some more tests * iteration, fixing some more tests * adhere to comments * adhere to comments * remove unnecessary dict call, re-add getattribute for testing * todo for reverse relationship * adhere to comments, remove prints * solve circular refs * all tests pass 🎉 * remove 3.7 from tests * add lint and type check jobs * reforat with ruff, fix jobs * rename jobs * fix imports * fix evaluate in py3.8 * partially fix coverage * fix coverage, add more tests * fix test ids * fix test ids * fix lint, fix docs, make docs fully working scripts, add test docs job * fix pyproject * pin py ver in test docs * change dir in test docs * fix pydantic warning hack * rm poetry call in test_docs * switch to pathlib in test docs * remove coverage req test docs * fix type check tests, fix part of types * fix/skip next part of types * fix next part of types * fix next part of types * fix coverage * fix coverage * fix type (bit dirty 🤷) * fix some code smells * change pre-commit * tweak workflows * remove no root from tests * switch to full python path by passing sys.executable * some small refactor in new base model, one sample test, change makefile * small refactors to reduce complexity of methods * temp add tests for prs against pydantic_v2 * remove all references to __fields__ * remove all references to construct, deprecate the method and update model_construct to be in line with pydantic * deprecate dict and add model_dump, todo switch to model_dict in calls * fix tests * change to union * change to union * change to model_dump and model_dump_json from dict and json deprecated methods, deprecate them in ormar too * finish switching dict() -> model_dump() * finish switching json() -> model_dump_json() * remove fully pydantic_only * switch to extra for payment card, change missed json calls * fix coverage - no more warnings internal * fix coverage - no more warnings internal - part 2 * split model_construct into own and pydantic parts * split determine pydantic field type * change to new field validators * fix benchmarks, add codspeed instead of pytest-benchmark, add action and gh workflow * restore pytest-benchmark * remove codspeed * pin pydantic version, restore codspeed * change on push to pydantic_v2 to trigger first one * Use lifespan function instead of event (#1259) * check return types * fix imports order, set warnings=False on json that passes the dict, fix unnecessary loop in one of the test * remove references to model's meta as it's now ormar config, rename related methods too * filter out pydantic serializer warnings * remove choices leftovers * remove leftovers after property_fields, keep only enough to exclude them in initialization * add migration guide * fix meta references * downgrade databases for now * Change line numbers in documentation (#1265) * proofread and fix the docs, part 1 * proofread and fix the docs for models * proofread and fix the docs for fields * proofread and fix the docs for relations * proofread and fix rest of the docs, add release notes for 0.20 * create tables in new docs src * cleanup old deps, uncomment docs publish on tag * fix import reorder --------- Co-authored-by: TouwaStar <30479449+TouwaStar@users.noreply.github.com> Co-authored-by: Goran Mekić <meka@tilda.center>
This commit is contained in:
@ -1,10 +1,10 @@
|
||||
import random
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
@ -16,10 +16,11 @@ def key():
|
||||
|
||||
|
||||
class Model(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "models"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = ormar.OrmarConfig(
|
||||
tablename="models",
|
||||
metadata=metadata,
|
||||
database=database,
|
||||
)
|
||||
|
||||
id: str = ormar.String(primary_key=True, default=key, max_length=8)
|
||||
name: str = ormar.String(max_length=32)
|
||||
|
||||
@ -2,13 +2,13 @@ from random import choice
|
||||
from string import ascii_uppercase
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import sqlalchemy
|
||||
from ormar import Float, String
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
from ormar import Float, String
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
@ -19,14 +19,14 @@ def get_id() -> str:
|
||||
return "".join(choice(ascii_uppercase) for _ in range(12))
|
||||
|
||||
|
||||
class MainMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = database
|
||||
base_ormar_config = ormar.OrmarConfig(
|
||||
metadata=metadata,
|
||||
database=database,
|
||||
)
|
||||
|
||||
|
||||
class PositionOrm(ormar.Model):
|
||||
class Meta(MainMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
name: str = String(primary_key=True, max_length=50)
|
||||
x: float = Float()
|
||||
@ -35,8 +35,7 @@ class PositionOrm(ormar.Model):
|
||||
|
||||
|
||||
class PositionOrmDef(ormar.Model):
|
||||
class Meta(MainMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
name: str = String(primary_key=True, max_length=50, default=get_id)
|
||||
x: float = Float()
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import uuid
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
metadata = sqlalchemy.MetaData()
|
||||
@ -13,10 +13,11 @@ db = databases.Database(DATABASE_URL)
|
||||
|
||||
|
||||
class User(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "user"
|
||||
metadata = metadata
|
||||
database = db
|
||||
ormar_config = ormar.OrmarConfig(
|
||||
tablename="user",
|
||||
metadata=metadata,
|
||||
database=db,
|
||||
)
|
||||
|
||||
id: uuid.UUID = ormar.UUID(
|
||||
primary_key=True, default=uuid.uuid4, uuid_format="string"
|
||||
@ -29,10 +30,11 @@ class User(ormar.Model):
|
||||
|
||||
|
||||
class Token(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "token"
|
||||
metadata = metadata
|
||||
database = db
|
||||
ormar_config = ormar.OrmarConfig(
|
||||
tablename="token",
|
||||
metadata=metadata,
|
||||
database=db,
|
||||
)
|
||||
|
||||
id = ormar.Integer(primary_key=True)
|
||||
text = ormar.String(max_length=4, unique=True)
|
||||
|
||||
@ -1,21 +1,16 @@
|
||||
from typing import List, Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Child(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "children"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="children")
|
||||
|
||||
id: int = ormar.Integer(name="child_id", primary_key=True)
|
||||
first_name: str = ormar.String(name="fname", max_length=100)
|
||||
@ -24,10 +19,7 @@ class Child(ormar.Model):
|
||||
|
||||
|
||||
class Artist(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "artists"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="artists")
|
||||
|
||||
id: int = ormar.Integer(name="artist_id", primary_key=True)
|
||||
first_name: str = ormar.String(name="fname", max_length=100)
|
||||
@ -37,37 +29,28 @@ class Artist(ormar.Model):
|
||||
|
||||
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "music_albums"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="music_albums")
|
||||
|
||||
id: int = ormar.Integer(name="album_id", primary_key=True)
|
||||
name: str = ormar.String(name="album_name", max_length=100)
|
||||
artist: Optional[Artist] = ormar.ForeignKey(Artist, name="artist_id")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_table_structure():
|
||||
assert "album_id" in [x.name for x in Album.Meta.table.columns]
|
||||
assert "album_name" in [x.name for x in Album.Meta.table.columns]
|
||||
assert "fname" in [x.name for x in Artist.Meta.table.columns]
|
||||
assert "lname" in [x.name for x in Artist.Meta.table.columns]
|
||||
assert "year" in [x.name for x in Artist.Meta.table.columns]
|
||||
assert "album_id" in [x.name for x in Album.ormar_config.table.columns]
|
||||
assert "album_name" in [x.name for x in Album.ormar_config.table.columns]
|
||||
assert "fname" in [x.name for x in Artist.ormar_config.table.columns]
|
||||
assert "lname" in [x.name for x in Artist.ormar_config.table.columns]
|
||||
assert "year" in [x.name for x in Artist.ormar_config.table.columns]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_working_with_aliases():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
artist = await Artist.objects.create(
|
||||
first_name="Ted", last_name="Mosbey", born_year=1975
|
||||
)
|
||||
@ -124,7 +107,7 @@ async def test_working_with_aliases():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_operations_and_fields():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
d1 = Child(first_name="Daughter", last_name="1", born_year=1990)
|
||||
d2 = Child(first_name="Daughter", last_name="2", born_year=1991)
|
||||
await Child.objects.bulk_create([d1, d2])
|
||||
@ -155,8 +138,8 @@ async def test_bulk_operations_and_fields():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_working_with_aliases_get_or_create():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
artist, created = await Artist.objects.get_or_create(
|
||||
first_name="Teddy", last_name="Bear", born_year=2020
|
||||
)
|
||||
@ -169,7 +152,7 @@ async def test_working_with_aliases_get_or_create():
|
||||
assert artist == artist2
|
||||
assert created is False
|
||||
|
||||
art3 = artist2.dict()
|
||||
art3 = artist2.model_dump()
|
||||
art3["born_year"] = 2019
|
||||
await Artist.objects.update_or_create(**art3)
|
||||
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
import datetime
|
||||
from enum import Enum
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pydantic
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar import ModelDefinitionError
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config(force_rollback=True)
|
||||
|
||||
|
||||
def time():
|
||||
@ -24,10 +22,7 @@ class MyEnum(Enum):
|
||||
|
||||
|
||||
class Example(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "example"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="example")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=200, default="aaa")
|
||||
@ -41,25 +36,17 @@ class Example(ormar.Model):
|
||||
|
||||
|
||||
class EnumExample(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "enum_example"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="enum_example")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
size: MyEnum = ormar.Enum(enum_class=MyEnum, default=MyEnum.SMALL)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_proper_enum_column_type():
|
||||
assert Example.__fields__["size"].type_ == MyEnum
|
||||
assert Example.model_fields["size"].__type__ == MyEnum
|
||||
|
||||
|
||||
def test_accepts_only_proper_enums():
|
||||
@ -73,7 +60,7 @@ def test_accepts_only_proper_enums():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_enum_bulk_operations():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
examples = [EnumExample(), EnumExample()]
|
||||
await EnumExample.objects.bulk_create(examples)
|
||||
|
||||
@ -90,7 +77,7 @@ async def test_enum_bulk_operations():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_enum_filter():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
examples = [EnumExample(), EnumExample(size=MyEnum.BIG)]
|
||||
await EnumExample.objects.bulk_create(examples)
|
||||
|
||||
@ -103,7 +90,7 @@ async def test_enum_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_crud():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
example = Example()
|
||||
await example.save()
|
||||
|
||||
@ -130,15 +117,12 @@ async def test_model_crud():
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalid_enum_field():
|
||||
async with database:
|
||||
async def test_invalid_enum_field() -> None:
|
||||
async with base_ormar_config.database:
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class Example2(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "example"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="example2")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
size: MyEnum = ormar.Enum(enum_class=[])
|
||||
size: MyEnum = ormar.Enum(enum_class=[]) # type: ignore
|
||||
|
||||
@ -1,21 +1,14 @@
|
||||
import uuid
|
||||
from typing import ClassVar
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from pydantic import root_validator
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
from pydantic import model_validator
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
database = database
|
||||
metadata = metadata
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Mol(ormar.Model):
|
||||
@ -24,8 +17,7 @@ class Mol(ormar.Model):
|
||||
"12345678-abcd-1234-abcd-123456789abc"
|
||||
)
|
||||
|
||||
class Meta(BaseMeta):
|
||||
tablename = "mols"
|
||||
ormar_config = base_ormar_config.copy(tablename="mols")
|
||||
|
||||
id: uuid.UUID = ormar.UUID(primary_key=True, index=True, uuid_format="hex")
|
||||
smiles: str = ormar.String(nullable=False, unique=True, max_length=256)
|
||||
@ -36,7 +28,7 @@ class Mol(ormar.Model):
|
||||
kwargs["id"] = self._UUID_NAMESPACE
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@root_validator()
|
||||
@model_validator(mode="before")
|
||||
def make_canonical_smiles_and_uuid(cls, values):
|
||||
values["id"], values["smiles"] = cls.uuid(values["smiles"])
|
||||
return values
|
||||
@ -47,17 +39,12 @@ class Mol(ormar.Model):
|
||||
return id_, smiles
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_json_column():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
await Mol.objects.create(smiles="Cc1ccccc1")
|
||||
count = await Mol.objects.count()
|
||||
assert count == 1
|
||||
|
||||
@ -1,21 +1,16 @@
|
||||
from datetime import timezone, timedelta, datetime, date, time
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from datetime import date, datetime, time, timedelta, timezone
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
|
||||
from tests.settings import DATABASE_URL
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class DateFieldsModel(ormar.Model):
|
||||
class Meta:
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
created_date: datetime = ormar.DateTime(
|
||||
@ -29,27 +24,21 @@ class DateFieldsModel(ormar.Model):
|
||||
|
||||
|
||||
class SampleModel(ormar.Model):
|
||||
class Meta:
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
updated_at: datetime = ormar.DateTime()
|
||||
|
||||
|
||||
class TimeModel(ormar.Model):
|
||||
class Meta:
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
elapsed: time = ormar.Time()
|
||||
|
||||
|
||||
class DateModel(ormar.Model):
|
||||
class Meta:
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
creation_date: date = ormar.Date()
|
||||
@ -59,24 +48,15 @@ class MyModel(ormar.Model):
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
created_at: datetime = ormar.DateTime(timezone=True, nullable=False)
|
||||
|
||||
class Meta:
|
||||
tablename = "mymodels"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="mymodels")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_crud_with_timezone():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
datemodel = await DateFieldsModel().save()
|
||||
assert datemodel.created_date is not None
|
||||
assert datemodel.updated_date is not None
|
||||
@ -84,7 +64,7 @@ async def test_model_crud_with_timezone():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_with_datetime_in_filter():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
creation_dt = datetime(2021, 5, 18, 0, 0, 0, 0)
|
||||
sample = await SampleModel.objects.create(updated_at=creation_dt)
|
||||
|
||||
@ -98,7 +78,7 @@ async def test_query_with_datetime_in_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_with_date_in_filter():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
sample = await TimeModel.objects.create(elapsed=time(0, 20, 20))
|
||||
await TimeModel.objects.create(elapsed=time(0, 12, 0))
|
||||
await TimeModel.objects.create(elapsed=time(0, 19, 55))
|
||||
@ -114,7 +94,7 @@ async def test_query_with_date_in_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_with_time_in_filter():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
await DateModel.objects.create(creation_date=date(2021, 5, 18))
|
||||
sample2 = await DateModel.objects.create(creation_date=date(2021, 5, 19))
|
||||
sample3 = await DateModel.objects.create(creation_date=date(2021, 5, 20))
|
||||
@ -130,7 +110,7 @@ async def test_query_with_time_in_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_filtering_by_timezone_with_timedelta():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
now_utc = datetime.now(timezone.utc)
|
||||
object = MyModel(created_at=now_utc)
|
||||
await object.save()
|
||||
|
||||
@ -1,38 +1,26 @@
|
||||
# type: ignore
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar import ModelDefinitionError, property_field
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Song(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "songs"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="songs")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_equality():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
song1 = await Song.objects.create(name="Song")
|
||||
song2 = await Song.objects.create(name="Song")
|
||||
song3 = Song(name="Song")
|
||||
@ -49,7 +37,7 @@ async def test_equality():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_hash_doesnt_change_with_fields_if_pk():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
song1 = await Song.objects.create(name="Song")
|
||||
prev_hash = hash(song1)
|
||||
|
||||
@ -59,7 +47,7 @@ async def test_hash_doesnt_change_with_fields_if_pk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_hash_changes_with_fields_if_no_pk():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
song1 = Song(name="Song")
|
||||
prev_hash = hash(song1)
|
||||
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
import databases
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar import Extra
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config(force_rollback=True)
|
||||
|
||||
|
||||
class Child(ormar.Model):
|
||||
class Meta(ormar.ModelMeta):
|
||||
tablename = "children"
|
||||
metadata = metadata
|
||||
database = database
|
||||
extra = Extra.ignore
|
||||
ormar_config = base_ormar_config.copy(
|
||||
tablename="children",
|
||||
extra=Extra.ignore,
|
||||
)
|
||||
|
||||
id: int = ormar.Integer(name="child_id", primary_key=True)
|
||||
first_name: str = ormar.String(name="fname", max_length=100)
|
||||
last_name: str = ormar.String(name="lname", max_length=100)
|
||||
|
||||
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_allow_extra_parameter():
|
||||
child = Child(first_name="Test", last_name="Name", extra_param="Unexpected")
|
||||
assert child.first_name == "Test"
|
||||
|
||||
@ -1,57 +1,43 @@
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config(force_rollback=True)
|
||||
|
||||
|
||||
class SchoolClass(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "app.schoolclasses"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="app.schoolclasses")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "app.categories"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="app.categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Student(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "app.students"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="app.students")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
gpa: float = ormar.Float()
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass, related_name="students")
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True, related_name="students")
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(
|
||||
SchoolClass, related_name="students"
|
||||
)
|
||||
category: Optional[Category] = ormar.ForeignKey(
|
||||
Category, nullable=True, related_name="students"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
async def create_data():
|
||||
@ -59,27 +45,37 @@ async def create_data():
|
||||
class2 = await SchoolClass.objects.create(name="Logic")
|
||||
category = await Category.objects.create(name="Foreign")
|
||||
category2 = await Category.objects.create(name="Domestic")
|
||||
await Student.objects.create(name="Jane", category=category, schoolclass=class1, gpa=3.2)
|
||||
await Student.objects.create(name="Judy", category=category2, schoolclass=class1, gpa=2.6)
|
||||
await Student.objects.create(name="Jack", category=category2, schoolclass=class2, gpa=3.8)
|
||||
await Student.objects.create(
|
||||
name="Jane", category=category, schoolclass=class1, gpa=3.2
|
||||
)
|
||||
await Student.objects.create(
|
||||
name="Judy", category=category2, schoolclass=class1, gpa=2.6
|
||||
)
|
||||
await Student.objects.create(
|
||||
name="Jack", category=category2, schoolclass=class2, gpa=3.8
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quotes_left_join():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await create_data()
|
||||
students = await Student.objects.filter(
|
||||
(Student.schoolclass.name == "Math") | (Student.category.name == "Foreign")
|
||||
(Student.schoolclass.name == "Math")
|
||||
| (Student.category.name == "Foreign")
|
||||
).all()
|
||||
for student in students:
|
||||
assert student.schoolclass.name == "Math" or student.category.name == "Foreign"
|
||||
assert (
|
||||
student.schoolclass.name == "Math"
|
||||
or student.category.name == "Foreign"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quotes_reverse_join():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await create_data()
|
||||
schoolclasses = await SchoolClass.objects.filter(students__gpa__gt=3).all()
|
||||
for schoolclass in schoolclasses:
|
||||
@ -89,11 +85,12 @@ async def test_quotes_reverse_join():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quotes_deep_join():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await create_data()
|
||||
schoolclasses = await SchoolClass.objects.filter(students__category__name="Domestic").all()
|
||||
schoolclasses = await SchoolClass.objects.filter(
|
||||
students__category__name="Domestic"
|
||||
).all()
|
||||
for schoolclass in schoolclasses:
|
||||
for student in schoolclass.students:
|
||||
assert student.category.name == "Domestic"
|
||||
|
||||
|
||||
@ -1,31 +1,22 @@
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
from ormar import BaseField
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = database
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class PriceList(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "price_lists"
|
||||
ormar_config = base_ormar_config.copy(tablename="price_lists")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "categories"
|
||||
ormar_config = base_ormar_config.copy(tablename="categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -33,8 +24,7 @@ class Category(ormar.Model):
|
||||
|
||||
|
||||
class Product(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "product"
|
||||
ormar_config = base_ormar_config.copy(tablename="product")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -42,19 +32,13 @@ class Product(ormar.Model):
|
||||
category = ormar.ForeignKey(Category)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_fields_access():
|
||||
# basic access
|
||||
assert Product.id._field == Product.Meta.model_fields["id"]
|
||||
assert Product.id.id == Product.Meta.model_fields["id"]
|
||||
assert Product.id._field == Product.ormar_config.model_fields["id"]
|
||||
assert Product.id.id == Product.ormar_config.model_fields["id"]
|
||||
assert Product.pk.id == Product.id.id
|
||||
assert isinstance(Product.id._field, BaseField)
|
||||
assert Product.id._access_chain == "id"
|
||||
@ -62,19 +46,19 @@ def test_fields_access():
|
||||
|
||||
# nested models
|
||||
curr_field = Product.category.name
|
||||
assert curr_field._field == Category.Meta.model_fields["name"]
|
||||
assert curr_field._field == Category.ormar_config.model_fields["name"]
|
||||
assert curr_field._access_chain == "category__name"
|
||||
assert curr_field._source_model == Product
|
||||
|
||||
# deeper nesting
|
||||
curr_field = Product.category.price_lists.name
|
||||
assert curr_field._field == PriceList.Meta.model_fields["name"]
|
||||
assert curr_field._field == PriceList.ormar_config.model_fields["name"]
|
||||
assert curr_field._access_chain == "category__price_lists__name"
|
||||
assert curr_field._source_model == Product
|
||||
|
||||
# reverse nesting
|
||||
curr_field = PriceList.categories.products.rating
|
||||
assert curr_field._field == Product.Meta.model_fields["rating"]
|
||||
assert curr_field._field == Product.ormar_config.model_fields["rating"]
|
||||
assert curr_field._access_chain == "categories__products__rating"
|
||||
assert curr_field._source_model == PriceList
|
||||
|
||||
@ -191,8 +175,8 @@ def test_combining_groups_together():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_filtering_by_field_access():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
category = await Category(name="Toys").save()
|
||||
product2 = await Product(
|
||||
name="My Little Pony", rating=3.8, category=category
|
||||
|
||||
@ -1,25 +1,17 @@
|
||||
import uuid
|
||||
from typing import List, Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from typing import Optional
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = database
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class PageLink(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "pagelinks"
|
||||
ormar_config = base_ormar_config.copy(tablename="pagelinks")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
value: str = ormar.String(max_length=2048)
|
||||
@ -27,8 +19,7 @@ class PageLink(ormar.Model):
|
||||
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "posts"
|
||||
ormar_config = base_ormar_config.copy(tablename="posts")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=500)
|
||||
@ -38,16 +29,14 @@ class Post(ormar.Model):
|
||||
|
||||
|
||||
class Department(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: uuid.UUID = ormar.UUID(primary_key=True, default=uuid.uuid4())
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Course(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -55,18 +44,13 @@ class Course(ormar.Model):
|
||||
department: Optional[Department] = ormar.ForeignKey(Department)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pass_int_values_as_fk():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
link = await PageLink(id=1, value="test", country="USA").save()
|
||||
await Post.objects.create(title="My post", link=link.id)
|
||||
post_check = await Post.objects.select_related("link").get()
|
||||
@ -75,7 +59,7 @@ async def test_pass_int_values_as_fk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pass_uuid_value_as_fk():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
dept = await Department(name="Department test").save()
|
||||
await Course(name="Test course", department=dept.id).save()
|
||||
|
||||
@ -1,31 +1,24 @@
|
||||
import uuid
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
from ormar.exceptions import QueryDefinitionError
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class User(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "users3"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="users3")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, default="")
|
||||
|
||||
|
||||
class User2(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "users4"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="users4")
|
||||
|
||||
id: uuid.UUID = ormar.UUID(
|
||||
uuid_format="string", primary_key=True, default=uuid.uuid4
|
||||
@ -34,10 +27,7 @@ class User2(ormar.Model):
|
||||
|
||||
|
||||
class Task(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tasks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="tasks")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, default="")
|
||||
@ -45,10 +35,7 @@ class Task(ormar.Model):
|
||||
|
||||
|
||||
class Task2(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tasks2"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="tasks2")
|
||||
|
||||
id: uuid.UUID = ormar.UUID(
|
||||
uuid_format="string", primary_key=True, default=uuid.uuid4
|
||||
@ -57,27 +44,21 @@ class Task2(ormar.Model):
|
||||
user: User2 = ormar.ForeignKey(to=User2)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_empty_result():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
async for user in User.objects.iterate():
|
||||
pass # pragma: no cover
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User.objects.create(name="Tom")
|
||||
jane = await User.objects.create(name="Jane")
|
||||
lucy = await User.objects.create(name="Lucy")
|
||||
@ -88,8 +69,8 @@ async def test_model_iterator():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_filter():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Jane")
|
||||
await User.objects.create(name="Lucy")
|
||||
@ -100,8 +81,8 @@ async def test_model_iterator_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_relations():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User.objects.create(name="Tom")
|
||||
jane = await User.objects.create(name="Jane")
|
||||
lucy = await User.objects.create(name="Lucy")
|
||||
@ -120,8 +101,8 @@ async def test_model_iterator_relations():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_relations_queryset_proxy():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User.objects.create(name="Tom")
|
||||
jane = await User.objects.create(name="Jane")
|
||||
|
||||
@ -146,8 +127,8 @@ async def test_model_iterator_relations_queryset_proxy():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_uneven_number_of_relations():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User.objects.create(name="Tom")
|
||||
jane = await User.objects.create(name="Jane")
|
||||
lucy = await User.objects.create(name="Lucy")
|
||||
@ -168,8 +149,8 @@ async def test_model_iterator_uneven_number_of_relations():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_uuid_pk():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User2.objects.create(name="Tom")
|
||||
jane = await User2.objects.create(name="Jane")
|
||||
lucy = await User2.objects.create(name="Lucy")
|
||||
@ -180,8 +161,8 @@ async def test_model_iterator_uuid_pk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_filter_uuid_pk():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User2.objects.create(name="Tom")
|
||||
await User2.objects.create(name="Jane")
|
||||
await User2.objects.create(name="Lucy")
|
||||
@ -192,8 +173,8 @@ async def test_model_iterator_filter_uuid_pk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_relations_uuid_pk():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User2.objects.create(name="Tom")
|
||||
jane = await User2.objects.create(name="Jane")
|
||||
lucy = await User2.objects.create(name="Lucy")
|
||||
@ -212,8 +193,8 @@ async def test_model_iterator_relations_uuid_pk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_relations_queryset_proxy_uuid_pk():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User2.objects.create(name="Tom")
|
||||
jane = await User2.objects.create(name="Jane")
|
||||
|
||||
@ -238,8 +219,8 @@ async def test_model_iterator_relations_queryset_proxy_uuid_pk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_uneven_number_of_relations_uuid_pk():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User2.objects.create(name="Tom")
|
||||
jane = await User2.objects.create(name="Jane")
|
||||
lucy = await User2.objects.create(name="Lucy")
|
||||
@ -262,7 +243,7 @@ async def test_model_iterator_uneven_number_of_relations_uuid_pk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_iterator_with_prefetch_raises_error():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
with pytest.raises(QueryDefinitionError):
|
||||
async for user in User.objects.prefetch_related(User.tasks).iterate():
|
||||
pass # pragma: no cover
|
||||
|
||||
@ -1,38 +1,27 @@
|
||||
from typing import List
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class NickNames(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "nicks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="nicks")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=False, name="hq_name")
|
||||
|
||||
|
||||
class NicksHq(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "nicks_x_hq"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="nicks_x_hq")
|
||||
|
||||
|
||||
class HQ(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "hqs"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="hqs")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=False, name="hq_name")
|
||||
@ -40,10 +29,7 @@ class HQ(ormar.Model):
|
||||
|
||||
|
||||
class Company(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "companies"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="companies")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=False, name="company_name")
|
||||
@ -51,47 +37,47 @@ class Company(ormar.Model):
|
||||
hq: HQ = ormar.ForeignKey(HQ)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_construct_with_empty_relation():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
hq = await HQ.objects.create(name="Main")
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await HQ.objects.create(name="Main")
|
||||
comp = Company(name="Banzai", hq=None, founded=1988)
|
||||
comp2 = Company.construct(**dict(name="Banzai", hq=None, founded=1988))
|
||||
assert comp.dict() == comp2.dict()
|
||||
comp2 = Company.model_construct(
|
||||
**dict(name="Banzai", hq=None, founded=1988)
|
||||
)
|
||||
assert comp.model_dump() == comp2.model_dump()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_init_and_construct_has_same_effect():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
hq = await HQ.objects.create(name="Main")
|
||||
comp = Company(name="Banzai", hq=hq, founded=1988)
|
||||
comp2 = Company.construct(**dict(name="Banzai", hq=hq, founded=1988))
|
||||
assert comp.dict() == comp2.dict()
|
||||
comp2 = Company.model_construct(**dict(name="Banzai", hq=hq, founded=1988))
|
||||
assert comp.model_dump() == comp2.model_dump()
|
||||
|
||||
comp3 = Company.construct(**dict(name="Banzai", hq=hq.dict(), founded=1988))
|
||||
assert comp.dict() == comp3.dict()
|
||||
comp3 = Company.model_construct(
|
||||
**dict(name="Banzai", hq=hq.model_dump(), founded=1988)
|
||||
)
|
||||
assert comp.model_dump() == comp3.model_dump()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_init_and_construct_has_same_effect_with_m2m():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
n1 = await NickNames(name="test").save()
|
||||
n2 = await NickNames(name="test2").save()
|
||||
hq = HQ(name="Main", nicks=[n1, n2])
|
||||
hq2 = HQ.construct(**dict(name="Main", nicks=[n1, n2]))
|
||||
assert hq.dict() == hq2.dict()
|
||||
hq2 = HQ.model_construct(**dict(name="Main", nicks=[n1, n2]))
|
||||
assert hq.model_dump() == hq2.model_dump()
|
||||
|
||||
hq3 = HQ.construct(**dict(name="Main", nicks=[n1.dict(), n2.dict()]))
|
||||
assert hq.dict() == hq3.dict()
|
||||
hq3 = HQ.model_construct(
|
||||
**dict(name="Main", nicks=[n1.model_dump(), n2.model_dump()])
|
||||
)
|
||||
assert hq.model_dump() == hq3.model_dump()
|
||||
|
||||
@ -1,30 +1,23 @@
|
||||
# type: ignore
|
||||
import asyncio
|
||||
import datetime
|
||||
import decimal
|
||||
|
||||
import databases
|
||||
import pydantic
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import sqlalchemy
|
||||
import typing
|
||||
|
||||
import ormar
|
||||
import pydantic
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from ormar.exceptions import ModelDefinitionError
|
||||
from ormar.models import Model
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class ExampleModel(Model):
|
||||
class Meta:
|
||||
tablename = "example"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="example")
|
||||
|
||||
test: int = ormar.Integer(primary_key=True)
|
||||
test_string: str = ormar.String(max_length=250)
|
||||
@ -55,21 +48,13 @@ fields_to_check = [
|
||||
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "examples"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="example2")
|
||||
|
||||
test: int = ormar.Integer(primary_key=True)
|
||||
test_string: str = ormar.String(max_length=250)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@ -84,7 +69,7 @@ def example():
|
||||
|
||||
|
||||
def test_not_nullable_field_is_required():
|
||||
with pytest.raises(pydantic.error_wrappers.ValidationError):
|
||||
with pytest.raises(pydantic.ValidationError):
|
||||
ExampleModel(test=1, test_string="test")
|
||||
|
||||
|
||||
@ -116,9 +101,10 @@ def test_missing_metadata():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class JsonSample2(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "jsons2"
|
||||
database = database
|
||||
ormar_config = ormar.OrmarConfig(
|
||||
tablename="jsons2",
|
||||
database=base_ormar_config.database,
|
||||
)
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
test_json = ormar.JSON(nullable=True)
|
||||
@ -128,8 +114,18 @@ def test_missing_database():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class JsonSample3(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "jsons3"
|
||||
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)
|
||||
@ -150,13 +146,15 @@ def test_primary_key_access_and_setting(example):
|
||||
|
||||
def test_pydantic_model_is_created(example):
|
||||
assert issubclass(example.__class__, pydantic.BaseModel)
|
||||
assert all([field in example.__fields__ for field in fields_to_check])
|
||||
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.Meta.table.__class__, sqlalchemy.Table)
|
||||
assert all([field in example.Meta.table.columns for field in fields_to_check])
|
||||
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
|
||||
@ -164,10 +162,7 @@ def test_no_pk_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError): # type: ignore
|
||||
|
||||
class ExampleModel2(Model): # type: ignore
|
||||
class Meta:
|
||||
tablename = "example2"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="example2")
|
||||
|
||||
test_string: str = ormar.String(max_length=250) # type: ignore
|
||||
|
||||
@ -178,37 +173,18 @@ def test_two_pks_in_model_definition():
|
||||
|
||||
@typing.no_type_check
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example3"
|
||||
database = database
|
||||
metadata = metadata
|
||||
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_setting_pk_column_as_pydantic_only_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example4"
|
||||
database = database
|
||||
metadata = metadata
|
||||
|
||||
test: int = ormar.Integer(primary_key=True, pydantic_only=True)
|
||||
|
||||
|
||||
@typing.no_type_check
|
||||
def test_decimal_error_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example5"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="example5")
|
||||
|
||||
test: decimal.Decimal = ormar.Decimal(primary_key=True)
|
||||
|
||||
@ -218,10 +194,7 @@ def test_binary_error_without_length_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example6"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="example6")
|
||||
|
||||
test: bytes = ormar.LargeBinary(primary_key=True, max_length=-1)
|
||||
|
||||
@ -231,10 +204,7 @@ def test_string_error_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example6"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="example6")
|
||||
|
||||
test: str = ormar.String(primary_key=True, max_length=0)
|
||||
|
||||
|
||||
@ -3,26 +3,22 @@ import base64
|
||||
import datetime
|
||||
import os
|
||||
import uuid
|
||||
from typing import List
|
||||
from enum import Enum
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pydantic
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar.exceptions import ModelError, NoMatch, QueryDefinitionError
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class JsonSample(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "jsons"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="jsons")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
test_json = ormar.JSON(nullable=True)
|
||||
@ -33,13 +29,10 @@ blob2 = b"test2icac89uc98"
|
||||
|
||||
|
||||
class LargeBinarySample(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "my_bolbs"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="my_bolbs")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
test_binary: bytes = ormar.LargeBinary(max_length=100000, choices=[blob, blob2])
|
||||
test_binary: bytes = ormar.LargeBinary(max_length=100000)
|
||||
|
||||
|
||||
blob3 = os.urandom(64)
|
||||
@ -47,47 +40,34 @@ blob4 = os.urandom(100)
|
||||
|
||||
|
||||
class LargeBinaryStr(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "my_str_blobs"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="my_str_bolbs")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
test_binary: str = ormar.LargeBinary(
|
||||
max_length=100000, choices=[blob3, blob4], represent_as_base64_str=True
|
||||
max_length=100000, represent_as_base64_str=True
|
||||
)
|
||||
|
||||
|
||||
class LargeBinaryNullableStr(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "my_str_blobs2"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="my_str_bolbs2")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
test_binary: str = ormar.LargeBinary(
|
||||
max_length=100000,
|
||||
choices=[blob3, blob4],
|
||||
represent_as_base64_str=True,
|
||||
nullable=True,
|
||||
)
|
||||
|
||||
|
||||
class UUIDSample(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "uuids"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="uuids")
|
||||
|
||||
id: uuid.UUID = ormar.UUID(primary_key=True, default=uuid.uuid4)
|
||||
test_text: str = ormar.Text()
|
||||
|
||||
|
||||
class UUIDSample2(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "uuids2"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="uuids2")
|
||||
|
||||
id: uuid.UUID = ormar.UUID(
|
||||
primary_key=True, default=uuid.uuid4, uuid_format="string"
|
||||
@ -96,95 +76,78 @@ class UUIDSample2(ormar.Model):
|
||||
|
||||
|
||||
class User(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "users"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="users")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, default="")
|
||||
|
||||
|
||||
class User2(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "users2"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="users2")
|
||||
|
||||
id: str = ormar.String(primary_key=True, max_length=100)
|
||||
name: str = ormar.String(max_length=100, default="")
|
||||
|
||||
|
||||
class Product(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "product"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="product")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
rating: int = ormar.Integer(minimum=1, maximum=5)
|
||||
in_stock: bool = ormar.Boolean(default=False)
|
||||
last_delivery: datetime.date = ormar.Date(default=datetime.datetime.now)
|
||||
last_delivery: datetime.date = ormar.Date(default=datetime.date.today)
|
||||
|
||||
|
||||
country_name_choices = ("Canada", "Algeria", "United States", "Belize")
|
||||
country_taxed_choices = (True,)
|
||||
country_country_code_choices = (-10, 1, 213, 1200)
|
||||
class CountryNameEnum(Enum):
|
||||
CANADA = "Canada"
|
||||
ALGERIA = "Algeria"
|
||||
USA = "United States"
|
||||
BELIZE = "Belize"
|
||||
|
||||
|
||||
class CountryCodeEnum(int, Enum):
|
||||
MINUS_TEN = -10
|
||||
ONE = 1
|
||||
TWO_HUNDRED_THIRTEEN = 213
|
||||
THOUSAND_TWO_HUNDRED = 1200
|
||||
|
||||
|
||||
class Country(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "country"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="country")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(
|
||||
max_length=9, choices=country_name_choices, default="Canada"
|
||||
)
|
||||
taxed: bool = ormar.Boolean(choices=country_taxed_choices, default=True)
|
||||
country_code: int = ormar.Integer(
|
||||
minimum=0, maximum=1000, choices=country_country_code_choices, default=1
|
||||
)
|
||||
name: CountryNameEnum = ormar.Enum(enum_class=CountryNameEnum, default="Canada")
|
||||
taxed: bool = ormar.Boolean(default=True)
|
||||
country_code: int = ormar.Enum(enum_class=CountryCodeEnum, default=1)
|
||||
|
||||
|
||||
class NullableCountry(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "country2"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="country2")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=9, choices=country_name_choices, nullable=True)
|
||||
name: CountryNameEnum = ormar.Enum(enum_class=CountryNameEnum, nullable=True)
|
||||
|
||||
|
||||
class NotNullableCountry(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "country3"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="country3")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=9, choices=country_name_choices, nullable=False)
|
||||
name: CountryNameEnum = ormar.Enum(enum_class=CountryNameEnum, nullable=False)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_model_class():
|
||||
assert list(User.Meta.model_fields.keys()) == ["id", "name"]
|
||||
assert issubclass(User.Meta.model_fields["id"].__class__, pydantic.fields.FieldInfo)
|
||||
assert User.Meta.model_fields["id"].primary_key is True
|
||||
assert isinstance(User.Meta.model_fields["name"], pydantic.fields.FieldInfo)
|
||||
assert User.Meta.model_fields["name"].max_length == 100
|
||||
assert isinstance(User.Meta.table, sqlalchemy.Table)
|
||||
assert list(User.ormar_config.model_fields.keys()) == ["id", "name"]
|
||||
assert issubclass(
|
||||
User.ormar_config.model_fields["id"].__class__, pydantic.fields.FieldInfo
|
||||
)
|
||||
assert User.ormar_config.model_fields["id"].primary_key is True
|
||||
assert isinstance(User.ormar_config.model_fields["name"], pydantic.fields.FieldInfo)
|
||||
assert User.ormar_config.model_fields["name"].max_length == 100
|
||||
assert isinstance(User.ormar_config.table, sqlalchemy.Table)
|
||||
|
||||
|
||||
def test_wrong_field_name():
|
||||
@ -200,8 +163,8 @@ def test_model_pk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_json_column():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await JsonSample.objects.create(test_json=dict(aa=12))
|
||||
await JsonSample.objects.create(test_json='{"aa": 12}')
|
||||
|
||||
@ -216,8 +179,8 @@ async def test_json_column():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_binary_column():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await LargeBinarySample.objects.create(test_binary=blob)
|
||||
await LargeBinarySample.objects.create(test_binary=blob2)
|
||||
|
||||
@ -232,8 +195,8 @@ async def test_binary_column():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_binary_str_column():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await LargeBinaryStr(test_binary=blob3).save()
|
||||
await LargeBinaryStr.objects.create(test_binary=blob4)
|
||||
|
||||
@ -248,8 +211,8 @@ async def test_binary_str_column():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_binary_nullable_str_column():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await LargeBinaryNullableStr().save()
|
||||
await LargeBinaryNullableStr.objects.create()
|
||||
items = await LargeBinaryNullableStr.objects.all()
|
||||
@ -279,8 +242,8 @@ async def test_binary_nullable_str_column():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_uuid_column():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
u1 = await UUIDSample.objects.create(test_text="aa")
|
||||
u2 = await UUIDSample.objects.create(test_text="bb")
|
||||
|
||||
@ -303,7 +266,7 @@ async def test_uuid_column():
|
||||
assert item2.id == item3.id
|
||||
assert isinstance(item3.id, uuid.UUID)
|
||||
|
||||
u3 = await UUIDSample2(**u1.dict()).save()
|
||||
u3 = await UUIDSample2(**u1.model_dump()).save()
|
||||
|
||||
u1_2 = await UUIDSample.objects.get(pk=u3.id)
|
||||
assert u1_2 == u1
|
||||
@ -314,8 +277,8 @@ async def test_uuid_column():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_crud():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
users = await User.objects.all()
|
||||
assert users == []
|
||||
|
||||
@ -341,8 +304,8 @@ async def test_model_crud():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_get():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
with pytest.raises(ormar.NoMatch):
|
||||
await User.objects.get()
|
||||
|
||||
@ -366,8 +329,8 @@ async def test_model_get():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_filter():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Jane")
|
||||
await User.objects.create(name="Lucy")
|
||||
@ -422,7 +385,7 @@ async def test_model_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wrong_query_contains_model():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
with pytest.raises(QueryDefinitionError):
|
||||
product = Product(name="90%-Cotton", rating=2)
|
||||
await Product.objects.filter(name__contains=product).count()
|
||||
@ -430,8 +393,8 @@ async def test_wrong_query_contains_model():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_exists():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Tom")
|
||||
assert await User.objects.filter(name="Tom").exists() is True
|
||||
assert await User.objects.filter(name="Jane").exists() is False
|
||||
@ -439,8 +402,8 @@ async def test_model_exists():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_count():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Jane")
|
||||
await User.objects.create(name="Lucy")
|
||||
@ -451,8 +414,8 @@ async def test_model_count():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_limit():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Jane")
|
||||
await User.objects.create(name="Lucy")
|
||||
@ -462,8 +425,8 @@ async def test_model_limit():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_limit_with_filter():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Tom")
|
||||
@ -475,8 +438,8 @@ async def test_model_limit_with_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_offset():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Jane")
|
||||
|
||||
@ -486,8 +449,8 @@ async def test_offset():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_first():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
tom = await User.objects.create(name="Tom")
|
||||
jane = await User.objects.create(name="Jane")
|
||||
|
||||
@ -500,27 +463,11 @@ async def test_model_first():
|
||||
assert await User.objects.order_by("name").first() == jane
|
||||
|
||||
|
||||
def not_contains(a, b):
|
||||
return a not in b
|
||||
|
||||
|
||||
def contains(a, b):
|
||||
return a in b
|
||||
|
||||
|
||||
def check_choices(values: tuple, ops: List):
|
||||
ops_dict = {"in": contains, "out": not_contains}
|
||||
checks = (country_name_choices, country_taxed_choices, country_country_code_choices)
|
||||
assert all(
|
||||
[ops_dict[op](value, check) for value, op, check in zip(values, ops, checks)]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_choices():
|
||||
"""Test that choices work properly for various types of fields."""
|
||||
async with database:
|
||||
# Test valid choices.
|
||||
"""Test that enum work properly for various types of fields."""
|
||||
async with base_ormar_config.database:
|
||||
# Test valid enums values.
|
||||
await asyncio.gather(
|
||||
Country.objects.create(name="Canada", taxed=True, country_code=1),
|
||||
Country.objects.create(name="Algeria", taxed=True, country_code=213),
|
||||
@ -529,54 +476,12 @@ async def test_model_choices():
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = "Saudi Arabia", True, 1
|
||||
check_choices((name, taxed, country_code), ["out", "in", "in"])
|
||||
await Country.objects.create(
|
||||
name=name, taxed=taxed, country_code=country_code
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = "Algeria", False, 1
|
||||
check_choices((name, taxed, country_code), ["in", "out", "in"])
|
||||
await Country.objects.create(
|
||||
name=name, taxed=taxed, country_code=country_code
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = "Algeria", True, 967
|
||||
check_choices((name, taxed, country_code), ["in", "in", "out"])
|
||||
await Country.objects.create(
|
||||
name=name, taxed=taxed, country_code=country_code
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = (
|
||||
"United States",
|
||||
True,
|
||||
1,
|
||||
) # name is too long but is a valid choice
|
||||
check_choices((name, taxed, country_code), ["in", "in", "in"])
|
||||
await Country.objects.create(
|
||||
name=name, taxed=taxed, country_code=country_code
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = (
|
||||
"Algeria",
|
||||
True,
|
||||
-10,
|
||||
) # country code is too small but is a valid choice
|
||||
check_choices((name, taxed, country_code), ["in", "in", "in"])
|
||||
await Country.objects.create(
|
||||
name=name, taxed=taxed, country_code=country_code
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = (
|
||||
"Algeria",
|
||||
True,
|
||||
1200,
|
||||
) # country code is too large but is a valid choice
|
||||
check_choices((name, taxed, country_code), ["in", "in", "in"])
|
||||
await Country.objects.create(
|
||||
name=name, taxed=taxed, country_code=country_code
|
||||
)
|
||||
@ -584,34 +489,24 @@ async def test_model_choices():
|
||||
# test setting after init also triggers validation
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = "Algeria", True, 967
|
||||
check_choices((name, taxed, country_code), ["in", "in", "out"])
|
||||
country = Country()
|
||||
country.country_code = country_code
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = "Saudi Arabia", True, 1
|
||||
check_choices((name, taxed, country_code), ["out", "in", "in"])
|
||||
country = Country()
|
||||
country.name = name
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = "Algeria", False, 1
|
||||
check_choices((name, taxed, country_code), ["in", "out", "in"])
|
||||
country = Country()
|
||||
country.taxed = taxed
|
||||
|
||||
# check also update from queryset
|
||||
with pytest.raises(ValueError):
|
||||
name, taxed, country_code = "Algeria", False, 1
|
||||
check_choices((name, taxed, country_code), ["in", "out", "in"])
|
||||
await Country(name="Belize").save()
|
||||
await Country.objects.filter(name="Belize").update(name="Vietnam")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_nullable_field_model_choices():
|
||||
"""Test that choices work properly for according to nullable setting"""
|
||||
async with database:
|
||||
async def test_nullable_field_model_enum():
|
||||
"""Test that enum work properly for according to nullable setting"""
|
||||
async with base_ormar_config.database:
|
||||
c1 = await NullableCountry(name=None).save()
|
||||
assert c1.name is None
|
||||
|
||||
@ -621,8 +516,8 @@ async def test_nullable_field_model_choices():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_start_and_end_filters():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Markos Uj")
|
||||
await User.objects.create(name="Maqua Bigo")
|
||||
await User.objects.create(name="maqo quidid")
|
||||
@ -651,8 +546,8 @@ async def test_start_and_end_filters():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_and_first():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await User.objects.create(name="Tom")
|
||||
await User.objects.create(name="Jane")
|
||||
await User.objects.create(name="Lucy")
|
||||
@ -681,4 +576,4 @@ async def test_get_and_first():
|
||||
def test_constraints():
|
||||
with pytest.raises(pydantic.ValidationError) as e:
|
||||
Product(name="T-Shirt", rating=50, in_stock=True)
|
||||
assert "ensure this value is less than or equal to 5" in str(e.value)
|
||||
assert "Input should be less than or equal to 5 " in str(e.value)
|
||||
|
||||
@ -1,22 +1,17 @@
|
||||
import pickle
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class User(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "users"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="users")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -24,28 +19,19 @@ class User(ormar.Model):
|
||||
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "posts"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="posts")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
created_by: Optional[User] = ormar.ForeignKey(User)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dumping_and_loading_model_works():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
user = await User(name="Test", properties={"aa": "bb"}).save()
|
||||
post = Post(name="Test post")
|
||||
await user.posts.add(post)
|
||||
|
||||
@ -1,52 +1,44 @@
|
||||
from typing import Dict, Optional
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from pydantic import Json, PositiveInt, ValidationError
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class OverwriteTest(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "overwrites"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="overwrites")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
my_int: int = ormar.Integer(overwrite_pydantic_type=PositiveInt)
|
||||
constraint_dict: Json = ormar.JSON(
|
||||
overwrite_pydantic_type=Optional[Json[Dict[str, int]]] # type: ignore
|
||||
)
|
||||
overwrite_pydantic_type=Optional[Json[Dict[str, int]]]
|
||||
) # type: ignore
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_constraints():
|
||||
with pytest.raises(ValidationError) as e:
|
||||
OverwriteTest(my_int=-10)
|
||||
assert "ensure this value is greater than 0" in str(e.value)
|
||||
assert "Input should be greater than 0" in str(e.value)
|
||||
|
||||
with pytest.raises(ValidationError) as e:
|
||||
OverwriteTest(my_int=10, constraint_dict={"aa": "ab"})
|
||||
assert "value is not a valid integer" in str(e.value)
|
||||
assert (
|
||||
"Input should be a valid integer, unable to parse string as an integer"
|
||||
in str(e.value)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_saving():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
await OverwriteTest(my_int=5, constraint_dict={"aa": 123}).save()
|
||||
|
||||
test = await OverwriteTest.objects.get()
|
||||
|
||||
@ -2,28 +2,19 @@ import sqlite3
|
||||
from typing import Optional
|
||||
|
||||
import asyncpg
|
||||
import databases
|
||||
import pymysql
|
||||
import sqlalchemy
|
||||
from sqlalchemy import create_engine, text
|
||||
|
||||
import ormar
|
||||
import pymysql
|
||||
import pytest
|
||||
from sqlalchemy import text
|
||||
|
||||
from tests.settings import DATABASE_URL
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
db = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class PrimaryModel(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "primary_models"
|
||||
ormar_config = base_ormar_config.copy(tablename="primary_models")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=255, index=True)
|
||||
@ -33,17 +24,12 @@ class PrimaryModel(ormar.Model):
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = create_engine(DATABASE_URL)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_models():
|
||||
async with db:
|
||||
async with base_ormar_config.database:
|
||||
primary = await PrimaryModel(
|
||||
name="Foo", some_text="Bar", some_other_text="Baz"
|
||||
).save()
|
||||
|
||||
@ -1,39 +1,32 @@
|
||||
import databases
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = database
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class AutoincrementModel(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
|
||||
|
||||
class NonAutoincrementModel(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True, autoincrement=False)
|
||||
|
||||
|
||||
class ExplicitNullableModel(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True, nullable=True)
|
||||
|
||||
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_pk_field_is_not_null():
|
||||
for model in [AutoincrementModel, NonAutoincrementModel, ExplicitNullableModel]:
|
||||
assert not model.Meta.table.c.get("id").nullable
|
||||
assert not model.ormar_config.table.c.get("id").nullable
|
||||
|
||||
@ -1,79 +1,68 @@
|
||||
# type: ignore
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar import ModelDefinitionError, property_field
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
from pydantic import PydanticUserError, computed_field
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Song(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "songs"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="songs")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
sort_order: int = ormar.Integer()
|
||||
|
||||
@property_field
|
||||
def sorted_name(self):
|
||||
@computed_field
|
||||
def sorted_name(self) -> str:
|
||||
return f"{self.sort_order}: {self.name}"
|
||||
|
||||
@property_field
|
||||
def sample(self):
|
||||
@computed_field
|
||||
def sample(self) -> str:
|
||||
return "sample"
|
||||
|
||||
@property_field
|
||||
def sample2(self):
|
||||
@computed_field
|
||||
def sample2(self) -> str:
|
||||
return "sample2"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sort_order_on_main_model():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
await Song.objects.create(name="Song 3", sort_order=3)
|
||||
await Song.objects.create(name="Song 1", sort_order=1)
|
||||
await Song.objects.create(name="Song 2", sort_order=2)
|
||||
|
||||
songs = await Song.objects.all()
|
||||
song_dict = [song.dict() for song in songs]
|
||||
song_dict = [song.model_dump() for song in songs]
|
||||
assert all("sorted_name" in x for x in song_dict)
|
||||
assert all(
|
||||
x["sorted_name"] == f"{x['sort_order']}: {x['name']}" for x in song_dict
|
||||
)
|
||||
song_json = [song.json() for song in songs]
|
||||
song_json = [song.model_dump_json() for song in songs]
|
||||
assert all("sorted_name" in x for x in song_json)
|
||||
|
||||
check_include = songs[0].dict(include={"sample"})
|
||||
check_include = songs[0].model_dump(include={"sample"})
|
||||
assert "sample" in check_include
|
||||
assert "sample2" not in check_include
|
||||
assert "sorted_name" not in check_include
|
||||
|
||||
check_include = songs[0].dict(exclude={"sample"})
|
||||
check_include = songs[0].model_dump(exclude={"sample"})
|
||||
assert "sample" not in check_include
|
||||
assert "sample2" in check_include
|
||||
assert "sorted_name" in check_include
|
||||
|
||||
|
||||
def test_wrong_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
with pytest.raises(PydanticUserError):
|
||||
|
||||
class WrongModel(ormar.Model): # pragma: no cover
|
||||
@property_field
|
||||
@computed_field
|
||||
def test(self, aa=10, bb=30):
|
||||
pass
|
||||
|
||||
@ -1,31 +1,24 @@
|
||||
import random
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from pydantic import BaseModel, Field, HttpUrl, PaymentCardNumber
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
from pydantic import BaseModel, Field, HttpUrl
|
||||
from pydantic_extra_types.payment import PaymentCardNumber
|
||||
|
||||
database = databases.Database(DATABASE_URL)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = database
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class ModelTest(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=200)
|
||||
url: HttpUrl = "https://www.example.com" # type: ignore
|
||||
number: Optional[PaymentCardNumber]
|
||||
number: Optional[PaymentCardNumber] = None
|
||||
|
||||
|
||||
CARD_NUMBERS = [
|
||||
@ -42,8 +35,7 @@ def get_number():
|
||||
|
||||
|
||||
class ModelTest2(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=200)
|
||||
@ -57,8 +49,7 @@ class PydanticTest(BaseModel):
|
||||
|
||||
|
||||
class ModelTest3(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
kwargs["number"] = get_number()
|
||||
@ -72,18 +63,12 @@ class ModelTest3(ormar.Model):
|
||||
pydantic_test: PydanticTest
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_working_with_pydantic_fields():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
test = ModelTest(name="Test")
|
||||
assert test.name == "Test"
|
||||
assert test.url == "https://www.example.com"
|
||||
@ -103,7 +88,7 @@ async def test_working_with_pydantic_fields():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_default_factory_for_pydantic_fields():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
test = ModelTest2(name="Test2", number="4000000000000002")
|
||||
assert test.name == "Test2"
|
||||
assert test.url == "https://www.example2.com"
|
||||
@ -123,7 +108,7 @@ async def test_default_factory_for_pydantic_fields():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_init_setting_for_pydantic_fields():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
test = ModelTest3(name="Test3")
|
||||
assert test.name == "Test3"
|
||||
assert test.url == "https://www.example3.com"
|
||||
|
||||
@ -1,32 +1,28 @@
|
||||
import datetime
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar import property_field
|
||||
from tests.settings import DATABASE_URL
|
||||
import pydantic
|
||||
import pytest
|
||||
from pydantic import computed_field
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "albums"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="albums")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
timestamp: datetime.datetime = ormar.DateTime(pydantic_only=True)
|
||||
timestamp: datetime.datetime = pydantic.Field(default=None)
|
||||
|
||||
@property_field
|
||||
@computed_field
|
||||
def name10(self) -> str:
|
||||
return self.name + "_10"
|
||||
|
||||
@property_field
|
||||
@computed_field
|
||||
def name20(self) -> str:
|
||||
return self.name + "_20"
|
||||
|
||||
@ -34,24 +30,18 @@ class Album(ormar.Model):
|
||||
def name30(self) -> str:
|
||||
return self.name + "_30"
|
||||
|
||||
@property_field
|
||||
@computed_field
|
||||
def name40(self) -> str:
|
||||
return self.name + "_40"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pydantic_only_fields():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
album = await Album.objects.create(name="Hitchcock")
|
||||
assert album.pk is not None
|
||||
assert album.saved
|
||||
@ -63,14 +53,14 @@ async def test_pydantic_only_fields():
|
||||
album = await Album.objects.fields({"name", "timestamp"}).get()
|
||||
assert album.timestamp is None
|
||||
|
||||
test_dict = album.dict()
|
||||
test_dict = album.model_dump()
|
||||
assert "timestamp" in test_dict
|
||||
assert test_dict["timestamp"] is None
|
||||
|
||||
assert album.name30 == "Hitchcock_30"
|
||||
|
||||
album.timestamp = datetime.datetime.now()
|
||||
test_dict = album.dict()
|
||||
test_dict = album.model_dump()
|
||||
assert "timestamp" in test_dict
|
||||
assert test_dict["timestamp"] is not None
|
||||
assert test_dict.get("name10") == "Hitchcock_10"
|
||||
|
||||
@ -1,24 +1,16 @@
|
||||
from typing import List
|
||||
|
||||
import databases
|
||||
import sqlalchemy
|
||||
import ormar
|
||||
from pydantic import PrivateAttr
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = database
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Subscription(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "subscriptions"
|
||||
ormar_config = base_ormar_config.copy(tablename="subscriptions")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
stripe_subscription_id: str = ormar.String(nullable=False, max_length=256)
|
||||
@ -29,6 +21,9 @@ class Subscription(ormar.Model):
|
||||
self._add_payments.append(payment)
|
||||
|
||||
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_private_attribute():
|
||||
sub = Subscription(stripe_subscription_id="2312312sad231")
|
||||
sub.add_payment("test")
|
||||
|
||||
@ -1,22 +1,17 @@
|
||||
from typing import List
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
from ormar.exceptions import ModelPersistenceError
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class NickNames(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "nicks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="nicks")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=False, name="hq_name")
|
||||
@ -24,17 +19,11 @@ class NickNames(ormar.Model):
|
||||
|
||||
|
||||
class NicksHq(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "nicks_x_hq"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="nicks_x_hq")
|
||||
|
||||
|
||||
class HQ(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "hqs"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="hqs")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=False, name="hq_name")
|
||||
@ -42,10 +31,7 @@ class HQ(ormar.Model):
|
||||
|
||||
|
||||
class Company(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "companies"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="companies")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=False, name="company_name")
|
||||
@ -53,19 +39,13 @@ class Company(ormar.Model):
|
||||
hq: HQ = ormar.ForeignKey(HQ)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_instantiation_false_save_true():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
comp = Company(name="Banzai", founded=1988)
|
||||
assert not comp.saved
|
||||
await comp.save()
|
||||
@ -74,8 +54,8 @@ async def test_instantiation_false_save_true():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_saved_edited_not_saved():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
comp = await Company.objects.create(name="Banzai", founded=1988)
|
||||
assert comp.saved
|
||||
comp.name = "Banzai2"
|
||||
@ -96,8 +76,8 @@ async def test_saved_edited_not_saved():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_adding_related_gets_dirty():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
hq = await HQ.objects.create(name="Main")
|
||||
comp = await Company.objects.create(name="Banzai", founded=1988)
|
||||
assert comp.saved
|
||||
@ -123,8 +103,8 @@ async def test_adding_related_gets_dirty():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_adding_many_to_many_does_not_gets_dirty():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
nick1 = await NickNames.objects.create(name="Bazinga", is_lame=False)
|
||||
nick2 = await NickNames.objects.create(name="Bazinga2", is_lame=True)
|
||||
|
||||
@ -152,8 +132,8 @@ async def test_adding_many_to_many_does_not_gets_dirty():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
comp = await Company.objects.create(name="Banzai", founded=1988)
|
||||
assert comp.saved
|
||||
await comp.delete()
|
||||
@ -165,8 +145,8 @@ async def test_delete():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_load():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
comp = await Company.objects.create(name="Banzai", founded=1988)
|
||||
assert comp.saved
|
||||
comp.name = "AA"
|
||||
@ -179,8 +159,8 @@ async def test_load():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_queryset_methods():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
await Company.objects.create(name="Banzai", founded=1988)
|
||||
await Company.objects.create(name="Yuhu", founded=1989)
|
||||
await Company.objects.create(name="Konono", founded=1990)
|
||||
@ -208,7 +188,7 @@ async def test_queryset_methods():
|
||||
assert comp3.pk == comp.pk
|
||||
assert created is False
|
||||
|
||||
update_dict = comp.dict()
|
||||
update_dict = comp.model_dump()
|
||||
update_dict["founded"] = 2010
|
||||
comp = await Company.objects.update_or_create(**update_dict)
|
||||
assert comp.saved
|
||||
@ -222,8 +202,8 @@ async def test_queryset_methods():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_methods():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
c1 = Company(name="Banzai", founded=1988)
|
||||
c2 = Company(name="Yuhu", founded=1989)
|
||||
|
||||
|
||||
@ -1,23 +1,16 @@
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import sqlalchemy
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
|
||||
from tests.settings import DATABASE_URL
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
db = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class PrimaryModel(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = db
|
||||
tablename = "primary_models"
|
||||
ormar_config = base_ormar_config.copy(tablename="primary_models")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=255, index=True)
|
||||
@ -27,10 +20,7 @@ class PrimaryModel(ormar.Model):
|
||||
|
||||
|
||||
class SecondaryModel(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = db
|
||||
tablename = "secondary_models"
|
||||
ormar_config = base_ormar_config.copy(tablename="secondary_models")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -39,18 +29,13 @@ class SecondaryModel(ormar.Model):
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = create_engine(DATABASE_URL)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_models():
|
||||
async with db:
|
||||
async with db.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
primary = await PrimaryModel(
|
||||
name="Foo", some_text="Bar", some_other_text="Baz"
|
||||
).save()
|
||||
|
||||
@ -1,24 +1,18 @@
|
||||
import asyncio
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from sqlalchemy import func, text
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Product(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "product"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="product")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -27,25 +21,21 @@ class Product(ormar.Model):
|
||||
created: datetime = ormar.DateTime(server_default=func.now())
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_table_defined_properly():
|
||||
assert Product.Meta.model_fields["created"].nullable
|
||||
assert not Product.__fields__["created"].required
|
||||
assert Product.Meta.table.columns["created"].server_default.arg.name == "now"
|
||||
assert Product.ormar_config.model_fields["created"].nullable
|
||||
assert not Product.model_fields["created"].is_required()
|
||||
assert (
|
||||
Product.ormar_config.table.columns["created"].server_default.arg.name == "now"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_creation():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
async with base_ormar_config.database:
|
||||
async with base_ormar_config.database.transaction(force_rollback=True):
|
||||
p1 = Product(name="Test")
|
||||
assert p1.created is None
|
||||
await p1.save()
|
||||
|
||||
@ -1,36 +1,25 @@
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
from ormar.models import Model
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Comment(Model):
|
||||
class Meta(ormar.ModelMeta):
|
||||
tablename = "comments"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="comments")
|
||||
|
||||
test: int = ormar.Integer(primary_key=True, comment="primary key of comments")
|
||||
test_string: str = ormar.String(max_length=250, comment="test that it works")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_comments_are_set_in_db():
|
||||
columns = Comment.Meta.table.c
|
||||
columns = Comment.ormar_config.table.c
|
||||
for c in columns:
|
||||
assert c.comment == Comment.Meta.model_fields[c.name].comment
|
||||
assert c.comment == Comment.ormar_config.model_fields[c.name].comment
|
||||
|
||||
Reference in New Issue
Block a user