Skip to content

Commit

Permalink
Merge branch 'tortoise:develop' into omidekz/feature/postgres-unique-…
Browse files Browse the repository at this point in the history
…index
  • Loading branch information
omidekz committed Jun 13, 2024
2 parents 8f8928a + d1e4be0 commit 86e0643
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 255 deletions.
13 changes: 10 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ jobs:
run: |
pip install -U pip poetry
poetry config virtualenvs.create false
- name: Install requirements
run: make deps
- name: Install ODBC driver
run: |
sudo curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
Expand All @@ -71,8 +69,17 @@ jobs:
ACCEPT_EULA=Y sudo apt-get install -y msodbcsql18
- name: Run ci
run: make ci
- name: Test Examples
run: |
export DEST=examples/blacksheep && PYTHONPATH=$DEST pytest $PYTEST_ARGS $DEST/_tests.py
export DEST=examples/fastapi && PYTHONPATH=$DEST pytest $PYTEST_ARGS $DEST/_tests.py
env:
PYTHONDEVMODE: 1
PYTEST_ARGS: "-n auto --cov=tortoise --cov-append --tb=native -q"
- name: Upload Coverage
run: coveralls --service=github
run: |
pip3 install --upgrade coveralls
coveralls --service=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_FLAG_NAME: ${{ matrix.python-version }}
Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
checkfiles = tortoise/ examples/ tests/ conftest.py
py_warn = PYTHONDEVMODE=1
pytest_opts = -n auto --cov=tortoise --tb=native -q
pytest_opts = -n auto --cov=tortoise --cov-append --tb=native -q

help:
@echo "Tortoise ORM development makefile"
Expand Down Expand Up @@ -37,7 +37,7 @@ endif
ruff check $(checkfiles)
mypy $(checkfiles)
#pylint $(checkfiles)
bandit -r $(checkfiles)
bandit -c pyproject.toml -r $(checkfiles)
twine check dist/*

test: deps
Expand Down Expand Up @@ -65,11 +65,11 @@ test_oracle:
$(py_warn) TORTOISE_TEST_DB="oracle://SYSTEM:$(TORTOISE_ORACLE_PASS)@127.0.0.1:1521/test_\{\}?driver=$(TORTOISE_ORACLE_DRIVER)" pytest $(pytest_opts) --cov-append --cov-report=

_testall: test_sqlite test_postgres_asyncpg test_postgres_psycopg test_mysql_myisam test_mysql test_mssql
coverage report

testall: deps _testall
coverage report

ci: check testall
ci: check _testall

docs: deps
rm -fR ./build
Expand Down
484 changes: 246 additions & 238 deletions poetry.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,6 @@ show_missing = true

[tool.ruff.lint]
ignore = ["E501"]

[tool.bandit]
exclude_dirs = ["tests", 'examples/*/_tests.py', "conftest.py"]
19 changes: 17 additions & 2 deletions tests/test_model_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
MultipleObjectsReturned,
OperationalError,
ParamsError,
ObjectDoesNotExistError,
ValidationError,
)
from tortoise.expressions import F, Q
Expand Down Expand Up @@ -252,12 +253,26 @@ async def test_index_access(self):
self.assertEqual(obj, self.mdl)

async def test_index_badval(self):
with self.assertRaises(KeyError):
with self.assertRaises(ObjectDoesNotExistError) as cm:
await self.cls[100000]
the_exception = cm.exception
# For compatibility reasons this should be an instance of KeyError
self.assertIsInstance(the_exception, KeyError)
self.assertIs(the_exception.model, self.cls)
self.assertEqual(the_exception.pk_name, "id")
self.assertEqual(the_exception.pk_val, 100000)
self.assertEqual(str(the_exception), f"{self.cls.__name__} has no object with id=100000")

async def test_index_badtype(self):
with self.assertRaises(KeyError):
with self.assertRaises(ObjectDoesNotExistError) as cm:
await self.cls["asdf"]
the_exception = cm.exception
# For compatibility reasons this should be an instance of KeyError
self.assertIsInstance(the_exception, KeyError)
self.assertIs(the_exception.model, self.cls)
self.assertEqual(the_exception.pk_name, "id")
self.assertEqual(the_exception.pk_val, "asdf")
self.assertEqual(str(the_exception), f"{self.cls.__name__} has no object with id=asdf")

async def test_clone(self):
mdl2 = self.mdl.clone()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ async def test_select_related_sets_valid_nulls(self) -> None:
retrieved_root = (
await DoubleFK.all()
.select_related("left__left__left", "right")
.get(id=getattr(root, "id")) # noqa
.get(id=getattr(root, "id"))
)
self.assertIsNone(retrieved_root.right)
assert retrieved_root.left is not None
Expand Down
4 changes: 2 additions & 2 deletions tests/testmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,8 @@ async def full_hierarchy__async_for(self, level=0):
"{}{} (to: {}) (from: {})".format(
level * " ",
self,
", ".join(sorted([str(val) async for val in self.talks_to])), # noqa
", ".join(sorted([str(val) async for val in self.gets_talked_to])), # noqa
", ".join(sorted([str(val) async for val in self.talks_to])),
", ".join(sorted([str(val) async for val in self.gets_talked_to])),
)
]
async for member in self.team_members:
Expand Down
2 changes: 1 addition & 1 deletion tortoise/backends/oracle/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ async def _process_insert_result(self, instance: Model, results: int) -> None:
seq = ret[0]["SEQUENCE_NAME"]
except IndexError:
return
sql = f"SELECT {seq}.CURRVAL FROM DUAL"
sql = f"SELECT {seq}.CURRVAL FROM DUAL" # nosec:B608
ret = await self.db.execute_query_dict(sql)
await super(OracleExecutor, self)._process_insert_result(instance, ret[0]["CURRVAL"])
4 changes: 2 additions & 2 deletions tortoise/contrib/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ async def _tearDownDB(self) -> None:
for app in Tortoise.apps.values():
for model in app.values():
quote_char = model._meta.db.query_class._builder().QUOTE_CHAR
await model._meta.db.execute_script( # nosec
f"DELETE FROM {quote_char}{model._meta.db_table}{quote_char}"
await model._meta.db.execute_script(
f"DELETE FROM {quote_char}{model._meta.db_table}{quote_char}" # nosec
)
await super()._tearDownDB()

Expand Down
16 changes: 15 additions & 1 deletion tortoise/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
from tortoise import Model, Type
Expand Down Expand Up @@ -66,6 +66,20 @@ def __str__(self):
return f'Multiple objects returned for "{self.model.__name__}", expected exactly one'


class ObjectDoesNotExistError(OperationalError, KeyError):
"""
The DoesNotExist exception is raised when an item with the passed primary key does not exist
"""

def __init__(self, model: "Type[Model]", pk_name: str, pk_val: Any):
self.model: "Type[Model]" = model
self.pk_name: str = pk_name
self.pk_val: Any = pk_val

def __str__(self):
return f"{self.model.__name__} has no object with {self.pk_name}={self.pk_val}"


class DoesNotExist(OperationalError):
"""
The DoesNotExist exception is raised when expecting data, such as a ``.get()`` operation.
Expand Down
3 changes: 2 additions & 1 deletion tortoise/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
IntegrityError,
OperationalError,
ParamsError,
ObjectDoesNotExistError,
)
from tortoise.fields.base import Field
from tortoise.fields.data import IntField
Expand Down Expand Up @@ -783,7 +784,7 @@ async def _getbypk(cls: Type[MODEL], key: Any) -> MODEL:
try:
return await cls.get(pk=key)
except (DoesNotExist, ValueError):
raise KeyError(f"{cls._meta.full_name} has no object {repr(key)}")
raise ObjectDoesNotExistError(cls, cls._meta.pk_attr, key)

def clone(self: MODEL, pk: Any = EMPTY) -> MODEL:
"""
Expand Down

0 comments on commit 86e0643

Please sign in to comment.