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,41 +1,30 @@
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import sqlalchemy
|
||||
|
||||
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)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Band(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "bands"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="bands")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class ArtistsBands(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "artists_x_bands"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="artists_x_bands")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
|
||||
|
||||
class Artist(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "artists"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="artists")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -43,10 +32,7 @@ class Artist(ormar.Model):
|
||||
|
||||
|
||||
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)
|
||||
@ -54,36 +40,27 @@ class Album(ormar.Model):
|
||||
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tracks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="tracks")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album, ondelete="CASCADE")
|
||||
title: 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_asyncio.fixture(scope="function")
|
||||
async def cleanup():
|
||||
yield
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
await Band.objects.delete(each=True)
|
||||
await Artist.objects.delete(each=True)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_simple_cascade(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
artist = await Artist(name="Dr Alban").save()
|
||||
await Album(name="Jamaica", artist=artist).save()
|
||||
await Artist.objects.delete(id=artist.id)
|
||||
@ -96,7 +73,7 @@ async def test_simple_cascade(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_nested_cascade(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
artist = await Artist(name="Dr Alban").save()
|
||||
album = await Album(name="Jamaica", artist=artist).save()
|
||||
await Track(title="Yuhu", album=album).save()
|
||||
@ -115,7 +92,7 @@ async def test_nested_cascade(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_many_to_many_cascade(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
artist = await Artist(name="Dr Alban").save()
|
||||
band = await Band(name="Scorpions").save()
|
||||
await artist.bands.add(band)
|
||||
@ -137,7 +114,7 @@ async def test_many_to_many_cascade(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_reverse_many_to_many_cascade(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
artist = await Artist(name="Dr Alban").save()
|
||||
band = await Band(name="Scorpions").save()
|
||||
await artist.bands.add(band)
|
||||
|
||||
@ -1,27 +1,21 @@
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
metadata = sqlalchemy.MetaData()
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Course(ormar.Model):
|
||||
class Meta:
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
course_name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Student(ormar.Model):
|
||||
class Meta:
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -32,27 +26,21 @@ class Student(ormar.Model):
|
||||
)
|
||||
|
||||
|
||||
# create db and tables
|
||||
@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_tables_columns():
|
||||
through_meta = Student.Meta.model_fields["courses"].through.Meta
|
||||
assert "course_id" in through_meta.table.c
|
||||
assert "student_id" in through_meta.table.c
|
||||
assert "course_id" in through_meta.model_fields
|
||||
assert "student_id" in through_meta.model_fields
|
||||
through_config = Student.ormar_config.model_fields["courses"].through.ormar_config
|
||||
assert "course_id" in through_config.table.c
|
||||
assert "student_id" in through_config.table.c
|
||||
assert "course_id" in through_config.model_fields
|
||||
assert "student_id" in through_config.model_fields
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_working_with_changed_through_names():
|
||||
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):
|
||||
to_save = {
|
||||
"course_name": "basic1",
|
||||
"students": [{"name": "Jack"}, {"name": "Abi"}],
|
||||
|
||||
@ -1,33 +1,25 @@
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar.fields.foreign_key import validate_referential_action
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Artist(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "artists"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="artists")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
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)
|
||||
@ -35,18 +27,14 @@ class Album(ormar.Model):
|
||||
|
||||
|
||||
class A(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=64, nullalbe=False)
|
||||
|
||||
|
||||
class B(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=64, nullalbe=False)
|
||||
@ -54,25 +42,18 @@ class B(ormar.Model):
|
||||
|
||||
|
||||
class C(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=64, nullalbe=False)
|
||||
b: B = ormar.ForeignKey(to=B, ondelete=ormar.ReferentialAction.CASCADE)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_simple_cascade():
|
||||
inspector = sqlalchemy.inspect(engine)
|
||||
inspector = sqlalchemy.inspect(base_ormar_config.engine)
|
||||
columns = inspector.get_columns("albums")
|
||||
assert len(columns) == 3
|
||||
col_names = [col.get("name") for col in columns]
|
||||
@ -88,7 +69,7 @@ def test_simple_cascade():
|
||||
def test_validations_referential_action():
|
||||
CASCADE = ormar.ReferentialAction.CASCADE.value
|
||||
|
||||
assert validate_referential_action(None) == None
|
||||
assert validate_referential_action(None) is None
|
||||
assert validate_referential_action("cascade") == CASCADE
|
||||
assert validate_referential_action(ormar.ReferentialAction.CASCADE) == CASCADE
|
||||
|
||||
@ -98,11 +79,11 @@ def test_validations_referential_action():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cascade_clear():
|
||||
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):
|
||||
a = await A.objects.create(name="a")
|
||||
b = await B.objects.create(name="b", a=a)
|
||||
c = await C.objects.create(name="c", b=b)
|
||||
await C.objects.create(name="c", b=b)
|
||||
|
||||
await a.bs.clear(keep_reversed=False)
|
||||
|
||||
|
||||
@ -1,22 +1,17 @@
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar.exceptions import NoMatch, MultipleMatches, RelationshipInstanceError
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
from ormar.exceptions import MultipleMatches, NoMatch, RelationshipInstanceError
|
||||
|
||||
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)
|
||||
@ -24,10 +19,7 @@ class Album(ormar.Model):
|
||||
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tracks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="tracks")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
@ -38,10 +30,7 @@ class Track(ormar.Model):
|
||||
|
||||
|
||||
class Cover(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "covers"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="covers")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album, related_name="cover_pictures")
|
||||
@ -49,20 +38,14 @@ class Cover(ormar.Model):
|
||||
|
||||
|
||||
class Organisation(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "org"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="org")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
ident: str = ormar.String(max_length=100, choices=["ACME Ltd", "Other ltd"])
|
||||
ident: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Team(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "teams"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="teams")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
org: Optional[Organisation] = ormar.ForeignKey(Organisation)
|
||||
@ -70,43 +53,34 @@ class Team(ormar.Model):
|
||||
|
||||
|
||||
class Member(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "members"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="members")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
team: Optional[Team] = ormar.ForeignKey(Team)
|
||||
email: 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_wrong_query_foreign_key_type():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
with pytest.raises(RelationshipInstanceError):
|
||||
Track(title="The Error", album="wrong_pk_type")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setting_explicitly_empty_relation():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
track = Track(album=None, title="The Bird", position=1)
|
||||
assert track.album is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_related_name():
|
||||
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="Vanilla")
|
||||
await Cover.objects.create(album=album, title="The cover file")
|
||||
assert len(album.cover_pictures) == 1
|
||||
@ -114,8 +88,8 @@ async def test_related_name():
|
||||
|
||||
@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):
|
||||
album = Album(name="Jamaica")
|
||||
await album.save()
|
||||
track1 = Track(album=album, title="The Bird", position=1)
|
||||
@ -146,8 +120,8 @@ async def test_model_crud():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_select_related():
|
||||
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 = Album(name="Malibu")
|
||||
await album.save()
|
||||
track1 = Track(album=album, title="The Bird", position=1)
|
||||
@ -175,8 +149,8 @@ async def test_select_related():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_removal_from_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):
|
||||
album = Album(name="Chichi")
|
||||
await album.save()
|
||||
track1 = Track(album=album, title="The Birdman", position=1)
|
||||
@ -217,8 +191,8 @@ async def test_model_removal_from_relations():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fk_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):
|
||||
malibu = Album(name="Malibu%")
|
||||
await malibu.save()
|
||||
await Track.objects.create(album=malibu, title="The Bird", position=1)
|
||||
@ -277,8 +251,8 @@ async def test_fk_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_multiple_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):
|
||||
acme = await Organisation.objects.create(ident="ACME Ltd")
|
||||
red_team = await Team.objects.create(org=acme, name="Red Team")
|
||||
blue_team = await Team.objects.create(org=acme, name="Blue Team")
|
||||
@ -301,18 +275,10 @@ async def test_multiple_fk():
|
||||
assert member.team.org.ident == "ACME Ltd"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wrong_choices():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
with pytest.raises(ValueError):
|
||||
await Organisation.objects.create(ident="Test 1")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pk_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):
|
||||
fantasies = await Album.objects.create(name="Test")
|
||||
track = await Track.objects.create(
|
||||
album=fantasies, title="Test1", position=1
|
||||
@ -334,8 +300,8 @@ async def test_pk_filter():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_limit_and_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):
|
||||
fantasies = await Album.objects.create(name="Limitless")
|
||||
await Track.objects.create(
|
||||
id=None, album=fantasies, title="Sample", position=1
|
||||
@ -366,8 +332,8 @@ async def test_limit_and_offset():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_exceptions():
|
||||
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):
|
||||
fantasies = await Album.objects.create(name="Test")
|
||||
|
||||
with pytest.raises(NoMatch):
|
||||
@ -382,8 +348,8 @@ async def test_get_exceptions():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wrong_model_passed_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):
|
||||
with pytest.raises(RelationshipInstanceError):
|
||||
org = await Organisation.objects.create(ident="ACME Ltd")
|
||||
await Track.objects.create(album=org, title="Test1", position=1)
|
||||
@ -391,8 +357,8 @@ async def test_wrong_model_passed_as_fk():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_update_model_with_no_children():
|
||||
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="Test")
|
||||
album.name = "Test2"
|
||||
await Album.objects.bulk_update([album], columns=["name"])
|
||||
@ -403,8 +369,8 @@ async def test_bulk_update_model_with_no_children():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_update_model_with_children():
|
||||
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):
|
||||
best_seller = await Album.objects.create(name="to_be_best_seller")
|
||||
best_seller2 = await Album.objects.create(name="to_be_best_seller2")
|
||||
not_best_seller = await Album.objects.create(name="unpopular")
|
||||
|
||||
@ -1,33 +1,23 @@
|
||||
from typing import Any, Sequence, cast
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from pydantic.typing import ForwardRef
|
||||
from typing import Any, ForwardRef
|
||||
|
||||
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):
|
||||
database = database
|
||||
metadata = metadata
|
||||
base_ormar_config = create_config(force_rollback=True)
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "categories"
|
||||
ormar_config = base_ormar_config.copy(tablename="categories")
|
||||
|
||||
id = ormar.Integer(primary_key=True)
|
||||
name = ormar.String(max_length=40)
|
||||
|
||||
|
||||
class PostCategory(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "posts_x_categories"
|
||||
ormar_config = base_ormar_config.copy(tablename="posts_x_categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
sort_order: int = ormar.Integer(nullable=True)
|
||||
@ -35,16 +25,14 @@ class PostCategory(ormar.Model):
|
||||
|
||||
|
||||
class Blog(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
@ -52,26 +40,18 @@ class Post(ormar.Model):
|
||||
blog = ormar.ForeignKey(Blog)
|
||||
|
||||
|
||||
@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)
|
||||
|
||||
|
||||
class PostCategory2(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "posts_x_categories2"
|
||||
ormar_config = base_ormar_config.copy(tablename="posts_x_categories2")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
sort_order: int = ormar.Integer(nullable=True)
|
||||
|
||||
|
||||
class Post2(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
@ -80,16 +60,16 @@ class Post2(ormar.Model):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_ref_is_updated():
|
||||
async with database:
|
||||
assert Post2.Meta.requires_ref_update
|
||||
async with base_ormar_config.database:
|
||||
assert Post2.ormar_config.requires_ref_update
|
||||
Post2.update_forward_refs()
|
||||
|
||||
assert Post2.Meta.model_fields["postcategory2"].to == PostCategory2
|
||||
assert Post2.ormar_config.model_fields["postcategory2"].to == PostCategory2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setting_fields_on_through_model():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
category = await Category(name="Test category").save()
|
||||
await post.categories.add(category)
|
||||
@ -100,7 +80,7 @@ async def test_setting_fields_on_through_model():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setting_additional_fields_on_through_model_in_add():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
category = await Category(name="Test category").save()
|
||||
await post.categories.add(category, sort_order=1)
|
||||
@ -110,7 +90,7 @@ async def test_setting_additional_fields_on_through_model_in_add():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setting_additional_fields_on_through_model_in_create():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category2", postcategory={"sort_order": 2}
|
||||
@ -121,7 +101,7 @@ async def test_setting_additional_fields_on_through_model_in_create():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_getting_additional_fields_from_queryset() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1", postcategory={"sort_order": 1}
|
||||
@ -143,7 +123,7 @@ async def test_getting_additional_fields_from_queryset() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_only_one_side_has_through() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1", postcategory={"sort_order": 1}
|
||||
@ -168,7 +148,7 @@ async def test_only_one_side_has_through() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_filtering_by_through_model() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1",
|
||||
@ -195,7 +175,7 @@ async def test_filtering_by_through_model() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_deep_filtering_by_through_model() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
blog = await Blog(title="My Blog").save()
|
||||
post = await Post(title="Test post", blog=blog).save()
|
||||
|
||||
@ -226,7 +206,7 @@ async def test_deep_filtering_by_through_model() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ordering_by_through_model() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1",
|
||||
@ -261,7 +241,7 @@ async def test_ordering_by_through_model() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_through_models_from_queryset_on_through() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1",
|
||||
@ -290,7 +270,7 @@ async def test_update_through_models_from_queryset_on_through() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_through_model_after_load() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1",
|
||||
@ -309,7 +289,7 @@ async def test_update_through_model_after_load() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_through_from_related() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1",
|
||||
@ -338,7 +318,7 @@ async def test_update_through_from_related() -> Any:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_excluding_fields_on_through_model() -> Any:
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
post = await Post(title="Test post").save()
|
||||
await post.categories.create(
|
||||
name="Test category1",
|
||||
|
||||
@ -1,24 +1,18 @@
|
||||
import asyncio
|
||||
from typing import List, Optional
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from ormar.exceptions import ModelPersistenceError, NoMatch, RelationshipInstanceError
|
||||
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 Author(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "authors"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="authors")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
first_name: str = ormar.String(max_length=80)
|
||||
@ -26,20 +20,14 @@ class Author(ormar.Model):
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=40)
|
||||
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "posts"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="posts")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
@ -47,26 +35,14 @@ class Post(ormar.Model):
|
||||
author: Optional[Author] = ormar.ForeignKey(Author)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def event_loop():
|
||||
loop = asyncio.get_event_loop()
|
||||
yield loop
|
||||
loop.close()
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(autouse=True, scope="module")
|
||||
async 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_asyncio.fixture(scope="function")
|
||||
async def cleanup():
|
||||
yield
|
||||
async with database:
|
||||
PostCategory = Post.Meta.model_fields["categories"].through
|
||||
async with base_ormar_config.database:
|
||||
PostCategory = Post.ormar_config.model_fields["categories"].through
|
||||
await PostCategory.objects.delete(each=True)
|
||||
await Post.objects.delete(each=True)
|
||||
await Category.objects.delete(each=True)
|
||||
@ -75,7 +51,7 @@ async def cleanup():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_not_saved_raises_error(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author(first_name="Guido", last_name="Van Rossum").save()
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = Category(name="News")
|
||||
@ -86,7 +62,7 @@ async def test_not_saved_raises_error(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_not_existing_raises_error(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author(first_name="Guido", last_name="Van Rossum").save()
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
|
||||
@ -98,7 +74,7 @@ async def test_not_existing_raises_error(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_assigning_related_objects(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = await Category.objects.create(name="News")
|
||||
@ -121,7 +97,7 @@ async def test_assigning_related_objects(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quering_of_the_m2m_models(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
# orm can do this already.
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
@ -156,7 +132,7 @@ async def test_quering_of_the_m2m_models(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_removal_of_the_relations(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = await Category.objects.create(name="News")
|
||||
@ -183,7 +159,7 @@ async def test_removal_of_the_relations(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_selecting_related(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = await Category.objects.create(name="News")
|
||||
@ -210,7 +186,7 @@ async def test_selecting_related(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_selecting_related_fail_without_saving(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = Post(title="Hello, M2M", author=guido)
|
||||
with pytest.raises(RelationshipInstanceError):
|
||||
@ -219,7 +195,7 @@ async def test_selecting_related_fail_without_saving(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_adding_unsaved_related(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = Category(name="News")
|
||||
@ -233,7 +209,7 @@ async def test_adding_unsaved_related(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_removing_unsaved_related(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = Category(name="News")
|
||||
|
||||
@ -4,19 +4,13 @@ from datetime import date
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import EmailStr
|
||||
|
||||
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
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
base_ormar_config = create_config(force_rollback=True)
|
||||
|
||||
|
||||
class PrimaryKeyMixin:
|
||||
@ -28,26 +22,18 @@ class Level(Enum):
|
||||
STAFF = "1"
|
||||
|
||||
|
||||
class MainMeta(ormar.ModelMeta):
|
||||
database = database
|
||||
metadata = metadata
|
||||
|
||||
|
||||
class User(PrimaryKeyMixin, ormar.Model):
|
||||
"""User Model Class to Implement Method for Operations of User Entity"""
|
||||
|
||||
mobile: str = ormar.String(unique=True, index=True, max_length=10)
|
||||
password: str = ormar.String(max_length=128)
|
||||
level: str = ormar.String(
|
||||
max_length=1, choices=list(Level), default=Level.STAFF.value
|
||||
)
|
||||
level: Level = ormar.Enum(default=Level.STAFF, enum_class=Level)
|
||||
email: Optional[str] = ormar.String(max_length=255, nullable=True, default=None)
|
||||
avatar: Optional[str] = ormar.String(max_length=255, nullable=True, default=None)
|
||||
fullname: Optional[str] = ormar.String(max_length=64, nullable=True, default=None)
|
||||
is_active: bool = ormar.Boolean(index=True, nullable=False, default=True)
|
||||
|
||||
class Meta(MainMeta):
|
||||
orders_by = ["-is_active", "-level"]
|
||||
ormar_config = base_ormar_config.copy(order_by=["-is_active", "-level"])
|
||||
|
||||
|
||||
class Task(PrimaryKeyMixin, ormar.Model):
|
||||
@ -60,24 +46,20 @@ class Task(PrimaryKeyMixin, ormar.Model):
|
||||
is_halted: bool = ormar.Boolean(index=True, nullable=False, default=True)
|
||||
user: User = ormar.ForeignKey(to=User)
|
||||
|
||||
class Meta(MainMeta):
|
||||
orders_by = ["-end_date", "-start_date"]
|
||||
constraints = [
|
||||
ormar_config = base_ormar_config.copy(
|
||||
order_by=["-end_date", "-start_date"],
|
||||
constraints=[
|
||||
ormar.UniqueColumns("user", "name"),
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@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_selecting_related_with_limit():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
user1 = await User(mobile="9928917653", password="pass1").save()
|
||||
user2 = await User(mobile="9928917654", password="pass2").save()
|
||||
await Task(name="one", user=user1).save()
|
||||
|
||||
@ -1,31 +1,23 @@
|
||||
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(force_rollback=True)
|
||||
|
||||
|
||||
class RandomSet(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "randoms"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="randoms")
|
||||
|
||||
id: int = ormar.Integer(name="random_id", primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Tonation(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tonations"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="tonations")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(name="tonation_name", max_length=100)
|
||||
@ -33,20 +25,14 @@ class Tonation(ormar.Model):
|
||||
|
||||
|
||||
class Division(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "divisions"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="divisions")
|
||||
|
||||
id: int = ormar.Integer(name="division_id", primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=True)
|
||||
|
||||
|
||||
class Shop(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "shops"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="shops")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, nullable=True)
|
||||
@ -54,17 +40,11 @@ class Shop(ormar.Model):
|
||||
|
||||
|
||||
class AlbumShops(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "albums_x_shops"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="albums_x_shops")
|
||||
|
||||
|
||||
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, nullable=True)
|
||||
@ -72,10 +52,7 @@ class Album(ormar.Model):
|
||||
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tracks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="tracks")
|
||||
|
||||
id: int = ormar.Integer(name="track_id", primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
@ -85,10 +62,7 @@ class Track(ormar.Model):
|
||||
|
||||
|
||||
class Cover(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "covers"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="covers")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(
|
||||
@ -98,19 +72,13 @@ class Cover(ormar.Model):
|
||||
artist: str = ormar.String(max_length=200, nullable=True)
|
||||
|
||||
|
||||
@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_prefetch_related():
|
||||
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 = Album(name="Malibu")
|
||||
await album.save()
|
||||
ton1 = await Tonation.objects.create(name="B-mol")
|
||||
@ -188,8 +156,8 @@ async def test_prefetch_related():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prefetch_related_with_many_to_many():
|
||||
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):
|
||||
div = await Division.objects.create(name="Div 1")
|
||||
shop1 = await Shop.objects.create(name="Shop 1", division=div)
|
||||
shop2 = await Shop.objects.create(name="Shop 2", division=div)
|
||||
@ -237,8 +205,8 @@ async def test_prefetch_related_with_many_to_many():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prefetch_related_empty():
|
||||
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 Track.objects.create(title="The Bird", position=1)
|
||||
track = await Track.objects.prefetch_related(["album__cover_pictures"]).get(
|
||||
title="The Bird"
|
||||
@ -249,8 +217,8 @@ async def test_prefetch_related_empty():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prefetch_related_with_select_related():
|
||||
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):
|
||||
div = await Division.objects.create(name="Div 1")
|
||||
shop1 = await Shop.objects.create(name="Shop 1", division=div)
|
||||
shop2 = await Shop.objects.create(name="Shop 2", division=div)
|
||||
@ -322,8 +290,8 @@ async def test_prefetch_related_with_select_related():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prefetch_related_with_select_related_and_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):
|
||||
div = await Division.objects.create(name="Div 1")
|
||||
shop1 = await Shop.objects.create(name="Shop 1", division=div)
|
||||
shop2 = await Shop.objects.create(name="Shop 2", division=div)
|
||||
|
||||
@ -1,42 +1,29 @@
|
||||
from typing import List, 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)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class User(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = db
|
||||
tablename = "test_users"
|
||||
ormar_config = base_ormar_config.copy(tablename="test_users")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=50)
|
||||
|
||||
|
||||
class Signup(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = db
|
||||
tablename = "test_signup"
|
||||
ormar_config = base_ormar_config.copy(tablename="test_signup")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
|
||||
|
||||
class Session(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = db
|
||||
tablename = "test_sessions"
|
||||
ormar_config = base_ormar_config.copy(tablename="test_sessions")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=255, index=True)
|
||||
@ -50,17 +37,12 @@ class Session(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_add_students():
|
||||
async with db:
|
||||
async with base_ormar_config.database:
|
||||
for user_id in [1, 2, 3, 4, 5]:
|
||||
await User.objects.create(name=f"User {user_id}")
|
||||
|
||||
|
||||
@ -1,22 +1,17 @@
|
||||
from typing import List, Optional
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import sqlalchemy
|
||||
|
||||
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 Author(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "authors"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="authors")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
first_name: str = ormar.String(max_length=80)
|
||||
@ -24,20 +19,14 @@ class Author(ormar.Model):
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=40)
|
||||
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "posts"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="posts")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
@ -45,19 +34,14 @@ class Post(ormar.Model):
|
||||
author: Optional[Author] = ormar.ForeignKey(Author, related_name="author_posts")
|
||||
|
||||
|
||||
@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_asyncio.fixture(scope="function")
|
||||
async def cleanup():
|
||||
yield
|
||||
async with database:
|
||||
PostCategory = Post.Meta.model_fields["categories"].through
|
||||
async with base_ormar_config.database:
|
||||
PostCategory = Post.ormar_config.model_fields["categories"].through
|
||||
await PostCategory.objects.delete(each=True)
|
||||
await Post.objects.delete(each=True)
|
||||
await Category.objects.delete(each=True)
|
||||
@ -66,7 +50,7 @@ async def cleanup():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_selecting_related(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = await Category.objects.create(name="News")
|
||||
|
||||
@ -1,23 +1,18 @@
|
||||
# type: ignore
|
||||
from typing import List, Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
from ormar.exceptions 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()
|
||||
|
||||
|
||||
class Author(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "authors"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="authors")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
first_name: str = ormar.String(max_length=80)
|
||||
@ -25,23 +20,20 @@ class Author(ormar.Model):
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=40)
|
||||
|
||||
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_fk_error():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "posts"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="posts")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
@ -53,10 +45,7 @@ def test_m2m_error():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "posts"
|
||||
database = database
|
||||
metadata = metadata
|
||||
ormar_config = base_ormar_config.copy(tablename="posts")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
|
||||
43
tests/test_relations/test_replacing_models_with_copy.py
Normal file
43
tests/test_relations/test_replacing_models_with_copy.py
Normal file
@ -0,0 +1,43 @@
|
||||
from typing import Any, Optional, Tuple, Union
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Album(ormar.Model):
|
||||
ormar_config = base_ormar_config.copy(tablename="albums")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
is_best_seller: bool = ormar.Boolean(default=False)
|
||||
properties: Tuple[str, Any]
|
||||
score: Union[str, int]
|
||||
|
||||
|
||||
class Track(ormar.Model):
|
||||
ormar_config = base_ormar_config.copy(tablename="tracks")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
title: str = ormar.String(max_length=100)
|
||||
position: int = ormar.Integer()
|
||||
play_count: int = ormar.Integer(nullable=True, default=0)
|
||||
is_disabled: bool = ormar.Boolean(default=False)
|
||||
properties: Tuple[str, Any]
|
||||
|
||||
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_is_replaced_by_a_copy():
|
||||
assert Album.model_fields["tracks"].annotation.__args__[1] != Track
|
||||
assert (
|
||||
Album.model_fields["tracks"].annotation.__args__[1].model_fields.keys()
|
||||
== Track.model_fields.keys()
|
||||
)
|
||||
@ -1,23 +1,17 @@
|
||||
from typing import Union
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
from ormar.exceptions import ModelPersistenceError
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
metadata = sa.MetaData()
|
||||
db = databases.Database(DATABASE_URL)
|
||||
from tests.lifespan import init_tests
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
metadata = metadata
|
||||
database = db
|
||||
ormar_config = base_ormar_config.copy(tablename="categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=50, unique=True, index=True)
|
||||
@ -25,10 +19,7 @@ class Category(ormar.Model):
|
||||
|
||||
|
||||
class Workshop(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "workshops"
|
||||
metadata = metadata
|
||||
database = db
|
||||
ormar_config = base_ormar_config.copy(tablename="workshops")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
topic: str = ormar.String(max_length=255, index=True)
|
||||
@ -37,18 +28,13 @@ class Workshop(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_model_relationship():
|
||||
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):
|
||||
cat = await Category(name="Foo", code=123).save()
|
||||
ws = await Workshop(topic="Topic 1", category=cat).save()
|
||||
|
||||
@ -66,8 +52,8 @@ async def test_model_relationship():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_relationship_with_not_saved():
|
||||
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):
|
||||
cat = Category(name="Foo", code=123)
|
||||
with pytest.raises(ModelPersistenceError):
|
||||
await Workshop(topic="Topic 1", category=cat).save()
|
||||
|
||||
@ -1,42 +1,29 @@
|
||||
from typing import List, 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 Keyword(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = db
|
||||
tablename = "keywords"
|
||||
ormar_config = base_ormar_config.copy(tablename="keywords")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=50)
|
||||
|
||||
|
||||
class KeywordPrimaryModel(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = db
|
||||
tablename = "primary_models_keywords"
|
||||
ormar_config = base_ormar_config.copy(tablename="primary_models_keywords")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
|
||||
|
||||
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)
|
||||
@ -48,10 +35,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)
|
||||
@ -62,7 +46,7 @@ class SecondaryModel(ormar.Model):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_primary_models():
|
||||
async with db:
|
||||
async with base_ormar_config.database:
|
||||
for name, some_text, some_other_text in [
|
||||
("Primary 1", "Some text 1", "Some other text 1"),
|
||||
("Primary 2", "Some text 2", "Some other text 2"),
|
||||
@ -150,9 +134,4 @@ async def test_create_primary_models():
|
||||
assert len(models5[2].keywords) == 0
|
||||
|
||||
|
||||
@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)
|
||||
|
||||
@ -2,27 +2,19 @@
|
||||
from datetime import date
|
||||
from typing import List, Optional, Union
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
from ormar import ModelDefinitionError
|
||||
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 MainMeta(ormar.ModelMeta):
|
||||
metadata = metadata
|
||||
database = database
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Role(ormar.Model):
|
||||
class Meta(MainMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
name: str = ormar.String(primary_key=True, max_length=1000)
|
||||
order: int = ormar.Integer(default=0, name="sort_order")
|
||||
@ -30,20 +22,17 @@ class Role(ormar.Model):
|
||||
|
||||
|
||||
class Company(ormar.Model):
|
||||
class Meta(MainMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
name: str = ormar.String(primary_key=True, max_length=1000)
|
||||
|
||||
|
||||
class UserRoleCompany(ormar.Model):
|
||||
class Meta(MainMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
|
||||
class User(ormar.Model):
|
||||
class Meta(MainMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
registrationnumber: str = ormar.String(primary_key=True, max_length=1000)
|
||||
company: Company = ormar.ForeignKey(Company)
|
||||
@ -56,20 +45,14 @@ class User(ormar.Model):
|
||||
lastupdate: date = ormar.DateTime(server_default=sqlalchemy.func.now())
|
||||
|
||||
|
||||
@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)
|
||||
|
||||
|
||||
def test_wrong_model():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class User(ormar.Model):
|
||||
class Meta(MainMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
registrationnumber: str = ormar.Text(primary_key=True)
|
||||
company: Company = ormar.ForeignKey(Company)
|
||||
@ -78,7 +61,7 @@ def test_wrong_model():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_primary_models():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
await Role.objects.create(
|
||||
name="user", order=0, description="no administration right"
|
||||
)
|
||||
|
||||
@ -1,41 +1,29 @@
|
||||
from typing import List, Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
import pytest
|
||||
|
||||
database = databases.Database(DATABASE_URL)
|
||||
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:
|
||||
metadata = metadata
|
||||
database = database
|
||||
tablename = "test_users"
|
||||
ormar_config = base_ormar_config.copy(tablename="test_users")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=50)
|
||||
|
||||
|
||||
class Signup(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = database
|
||||
tablename = "test_signup"
|
||||
ormar_config = base_ormar_config.copy(tablename="test_signup")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
|
||||
|
||||
class Session(ormar.Model):
|
||||
class Meta:
|
||||
metadata = metadata
|
||||
database = database
|
||||
tablename = "test_sessions"
|
||||
ormar_config = base_ormar_config.copy(tablename="test_sessions")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=255, index=True)
|
||||
@ -44,17 +32,12 @@ class Session(ormar.Model):
|
||||
students: Optional[List[User]] = ormar.ManyToMany(User, through=Signup)
|
||||
|
||||
|
||||
@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_list_sessions_for_user():
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
for user_id in [1, 2, 3, 4, 5]:
|
||||
await User.objects.create(name=f"User {user_id}")
|
||||
|
||||
|
||||
@ -1,25 +1,17 @@
|
||||
from typing import List, Optional
|
||||
|
||||
import databases
|
||||
import ormar
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import sqlalchemy
|
||||
|
||||
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)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
|
||||
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
database = database
|
||||
metadata = metadata
|
||||
base_ormar_config = create_config()
|
||||
|
||||
|
||||
class Author(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
first_name: str = ormar.String(max_length=80)
|
||||
@ -27,16 +19,14 @@ class Author(ormar.Model):
|
||||
|
||||
|
||||
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=40)
|
||||
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
@ -44,19 +34,14 @@ class Post(ormar.Model):
|
||||
author: Optional[Author] = ormar.ForeignKey(Author, skip_reverse=True)
|
||||
|
||||
|
||||
@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_asyncio.fixture(scope="function")
|
||||
async def cleanup():
|
||||
yield
|
||||
async with database:
|
||||
PostCategory = Post.Meta.model_fields["categories"].through
|
||||
async with base_ormar_config.database:
|
||||
PostCategory = Post.ormar_config.model_fields["categories"].through
|
||||
await PostCategory.objects.delete(each=True)
|
||||
await Post.objects.delete(each=True)
|
||||
await Category.objects.delete(each=True)
|
||||
@ -83,7 +68,7 @@ def test_model_definition():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_assigning_related_objects(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = await Category.objects.create(name="News")
|
||||
@ -111,7 +96,7 @@ async def test_assigning_related_objects(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quering_of_related_model_works_but_no_result(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = await Category.objects.create(name="News")
|
||||
@ -121,7 +106,7 @@ async def test_quering_of_related_model_works_but_no_result(cleanup):
|
||||
post_categories = await post.categories.all()
|
||||
assert len(post_categories) == 1
|
||||
|
||||
assert "posts" not in post.dict().get("categories", [])[0]
|
||||
assert "posts" not in post.model_dump().get("categories", [])[0]
|
||||
|
||||
assert news == await post.categories.get(name="News")
|
||||
|
||||
@ -135,7 +120,7 @@ async def test_quering_of_related_model_works_but_no_result(cleanup):
|
||||
.get()
|
||||
)
|
||||
assert category == news
|
||||
assert "posts" not in category.dict()
|
||||
assert "posts" not in category.model_dump()
|
||||
|
||||
# relation not in json
|
||||
category2 = (
|
||||
@ -144,14 +129,14 @@ async def test_quering_of_related_model_works_but_no_result(cleanup):
|
||||
.get()
|
||||
)
|
||||
assert category2 == news
|
||||
assert "posts" not in category2.json()
|
||||
assert "posts" not in category2.model_dump_json()
|
||||
|
||||
assert "posts" not in Category.schema().get("properties")
|
||||
assert "posts" not in Category.model_json_schema().get("properties")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_removal_of_the_relations(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
post = await Post.objects.create(title="Hello, M2M", author=guido)
|
||||
news = await Category.objects.create(name="News")
|
||||
@ -176,7 +161,7 @@ async def test_removal_of_the_relations(cleanup):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_selecting_related(cleanup):
|
||||
async with database:
|
||||
async with base_ormar_config.database:
|
||||
guido = await Author.objects.create(first_name="Guido", last_name="Van Rossum")
|
||||
guido2 = await Author.objects.create(
|
||||
first_name="Guido2", last_name="Van Rossum"
|
||||
|
||||
@ -1,39 +1,30 @@
|
||||
# type: ignore
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
import pytest
|
||||
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()
|
||||
|
||||
|
||||
def test_through_with_relation_fails():
|
||||
class BaseMeta(ormar.ModelMeta):
|
||||
database = database
|
||||
metadata = metadata
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "categories"
|
||||
ormar_config = base_ormar_config.copy(tablename="categories")
|
||||
|
||||
id = ormar.Integer(primary_key=True)
|
||||
name = ormar.String(max_length=40)
|
||||
|
||||
class Blog(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
|
||||
class PostCategory(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "posts_x_categories"
|
||||
ormar_config = base_ormar_config.copy(tablename="posts_x_categories")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
sort_order: int = ormar.Integer(nullable=True)
|
||||
@ -43,9 +34,11 @@ def test_through_with_relation_fails():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class Post(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
pass
|
||||
ormar_config = base_ormar_config.copy()
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
title: str = ormar.String(max_length=200)
|
||||
categories = ormar.ManyToMany(Category, through=PostCategory)
|
||||
|
||||
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
@ -1,32 +1,20 @@
|
||||
from typing import Optional, Type
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
from tests.settings import create_config
|
||||
|
||||
base_ormar_config = create_config()
|
||||
from tests.lifespan import init_tests
|
||||
|
||||
|
||||
class Band(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "bands"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="bands")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Artist(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "artists"
|
||||
metadata = metadata
|
||||
database = database
|
||||
ormar_config = base_ormar_config.copy(tablename="artists")
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
@ -34,6 +22,9 @@ class Artist(ormar.Model):
|
||||
band: Band = ormar.ForeignKey(Band)
|
||||
|
||||
|
||||
create_test_database = init_tests(base_ormar_config)
|
||||
|
||||
|
||||
def test_weakref_init():
|
||||
band = Band(name="Band")
|
||||
artist1 = Artist(name="Artist 1", band=band)
|
||||
@ -49,4 +40,4 @@ def test_weakref_init():
|
||||
band.artists # Force it to clean
|
||||
|
||||
assert len(band.artists) == 1
|
||||
assert band.artists[0].name == "Artist 2"
|
||||
assert band.artists[0].name == artist2.name
|
||||
|
||||
Reference in New Issue
Block a user