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:
collerek
2024-03-23 19:28:28 +01:00
committed by GitHub
parent 3a206dd8dc
commit 500625f0ec
294 changed files with 8132 additions and 9311 deletions

View File

@ -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)

View File

@ -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"}],

View File

@ -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)

View File

@ -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")

View File

@ -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",

View File

@ -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")

View File

@ -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()

View File

@ -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)

View File

@ -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}")

View File

@ -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")

View File

@ -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)

View 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()
)

View File

@ -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()

View File

@ -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)

View File

@ -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"
)

View File

@ -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}")

View File

@ -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"

View File

@ -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)

View File

@ -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