Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

Changelog
=========
0.15.0
-------
New features:
^^^^^^^^^^^^^
- Pooling has been implemented, allowing for multiple concurrent databases and all the benefits that comes with it.
- Enabled by default for databases that support it (mysql and postgres) with a minimum pool size of 1, and a maximum of 5
- Not supported by sqlite
- Can be changed by passing the ``minsize`` and ``maxsize`` connection parameters

Deprecations:
^^^^^^^^^^^^^
- ``start_transaction`` is deprecated, please use ``@atomic()`` or ``async with in_transaction():`` instead.

0.14.0
------
.. caution::
Expand Down
18 changes: 13 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,22 @@ endif
bandit -r $(checkfiles)
python setup.py check -mrs

test: deps
test:
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory: py.test

_testall:
test_sqlite:
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory: py.test --cov-report=
python -V | grep PyPy || $(py_warn) TORTOISE_TEST_DB=postgres://postgres:$(TORTOISE_POSTGRES_PASS)@127.0.0.1:5432/test_\{\} py.test --cov-append --cov-report=
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}?storage_engine=MYISAM" py.test --cov-append --cov-report=
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}" py.test --cov-append

test_postgres:
python -V | grep PyPy || $(py_warn) TORTOISE_TEST_DB="postgres://postgres:$(TORTOISE_POSTGRES_PASS)@127.0.0.1:5432/test_\{\}?minsize=1&maxsize=20" py.test --cov-append --cov-report=

test_mysql_myisam:
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}?minsize=10&maxsize=10&storage_engine=MYISAM" py.test --cov-append --cov-report=

test_mysql:
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}?minsize=1&maxsize=10" py.test --cov-append

_testall: test_sqlite test_postgres test_mysql_myisam test_mysql

testall: deps _testall

Expand Down
21 changes: 20 additions & 1 deletion docs/CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,28 @@ Running tests natively on windows isn't supported (yet). Best way to run them at
Postgres uses the default ``postgres`` user, mysql uses ``root``. If either of them has a password you can set it with the ``TORTOISE_POSTGRES_PASS`` and ``TORTOISE_MYSQL_PASS`` env variables respectively.



Different types of tests
-----------------------------
- ``make test``: most basic quick test. only runs the tests on in an memory sqlite database
- ``make test``: most basic quick test. only runs the tests on in an memory sqlite database without generating a coverage report.
- ``make test_sqlite``: Runs the tests on a sqlite in memory database
- ``make test_postgres``: Runs the tests on the postgres database
- ``make test_mysql_myisam``: Runs the tests on the mysql database using the ``MYISAM`` storage engine (no transactions)
- ``make test_mysql``: Runs the tests on the mysql database
- ``make testall``: runs the tests on all 4 database types: sqlite (in memory), postgress, MySQL-MyISAM and MySQL-InnoDB
- ``green``: runs the same tests as ``make test``, ensures the green plugin works
- ``nose2 --plugin tortoise.contrib.test.nose2 --db-module tests.testmodels --db-url sqlite://:memory: ``: same test as ``make test`` , ensures the nose2 plugin works


Things to be aware of when running the test suite
---------------------------------------------------
- Some tests always run regardless of what test suite you are running (the connection tests for mysql and postgres for example, you don't need a database running as it doesn't actually connect though)
- Some tests use hardcoded databases (usually sqlite) for testing, regardless of what DB url you specified.
- The postgres driver does not work under Pypy so those tests will be skipped if you are running under pypy
- You can run only specific tests by running `` py.test <testfiles>`` or ``green -s 1 <testfile>``
- If you want a peek under the hood of test that hang to debug try running them with ``green -s 1 -vv -d -a <test>``
- ``-s 1`` means it only runs one test at a time
- ``-vv`` very verbose output
- ``-d`` log debug output
- ``-a`` don't capture stdout but just let it output
- Mysql tends to be relatively slow but there are some settings you can tweak to make it faster, however this also means less redundant. Use at own risk: http://www.tocker.ca/2013/11/04/reducing-mysql-durability-for-testing.html
14 changes: 7 additions & 7 deletions docs/databases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ Parameters
Network port that database is available at. (defaults to ``5432``)
``database``:
Database to use.
``min_size``:
Minimum connection pool size (not used right now)
``max_size``:
Maximum connection pool size (not used right now)
``minsize``:
Minimum connection pool size (defaults to ``1``)
``maxsize``:
Maximum connection pool size (defaults to ``5``)
``max_queries``:
Maximum no of queries to allow before forcing a re-connect.
Maximum no of queries before a connection is closed and replaced. (defaults to ``50000``)
``max_inactive_connection_lifetime``:
Duration of inactive connection before assuming that it has gone stale, and force a re-connect.
``schema``:
Expand Down Expand Up @@ -109,9 +109,9 @@ Parameters
``database``:
Database to use.
``minsize``:
Minimum connection pool size (not used right now)
Minimum connection pool size (defaults to ``1``)
``maxsize``:
Maximum connection pool size (not used right now)
Maximum connection pool size (defaults to ``5``)
``connect_timeout``:
Duration to wait for connection before throwing error.
``echo``:
Expand Down
8 changes: 6 additions & 2 deletions tests/test_connection_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class TestConnectionParams(test.TestCase):
async def test_mysql_connection_params(self):
with patch("aiomysql.connect", new=CoroutineMock()) as mysql_connect:
with patch("aiomysql.create_pool", new=CoroutineMock()) as mysql_connect:
await Tortoise._init_connections(
{
"models": {
Expand Down Expand Up @@ -34,11 +34,13 @@ async def test_mysql_connection_params(self):
password="foomip",
port=3306,
user="root",
maxsize=5,
minsize=1,
)

async def test_postres_connection_params(self):
try:
with patch("asyncpg.connect", new=CoroutineMock()) as asyncpg_connect:
with patch("asyncpg.create_pool", new=CoroutineMock()) as asyncpg_connect:
await Tortoise._init_connections(
{
"models": {
Expand Down Expand Up @@ -66,6 +68,8 @@ async def test_postres_connection_params(self):
ssl=True,
timeout=30,
user="root",
max_size=5,
min_size=1,
)
except ImportError:
self.skipTest("asyncpg not installed")
4 changes: 2 additions & 2 deletions tests/test_generate_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ async def test_schema_safe(self):
class TestGenerateSchemaMySQL(TestGenerateSchema):
async def init_for(self, module: str, safe=False) -> None:
try:
with patch("aiomysql.connect", new=CoroutineMock()):
with patch("aiomysql.create_pool", new=CoroutineMock()):
await Tortoise.init(
{
"connections": {
Expand Down Expand Up @@ -430,7 +430,7 @@ async def test_schema_safe(self):
class TestGenerateSchemaPostgresSQL(TestGenerateSchema):
async def init_for(self, module: str, safe=False) -> None:
try:
with patch("asyncpg.connect", new=CoroutineMock()):
with patch("asyncpg.create_pool", new=CoroutineMock()):
await Tortoise.init(
{
"connections": {
Expand Down
8 changes: 8 additions & 0 deletions tests/test_reconnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ async def test_reconnect(self):
await Tournament.create(name="1")

await Tortoise._connections["models"]._close()
await Tortoise._connections["models"].create_connection(with_db=True)

await Tournament.create(name="2")

await Tortoise._connections["models"]._close()
await Tortoise._connections["models"].create_connection(with_db=True)

self.assertEqual([f"{a.id}:{a.name}" for a in await Tournament.all()], ["1:1", "2:2"])

@test.skip("closes the pool, needs a better way to simulate failures")
async def test_reconnect_fail(self):
await Tournament.create(name="1")

Expand All @@ -36,15 +39,20 @@ async def test_reconnect_transaction_start(self):
await Tournament.create(name="1")

await Tortoise._connections["models"]._close()
await Tortoise._connections["models"].create_connection(with_db=True)

async with in_transaction():
await Tournament.create(name="2")

await Tortoise._connections["models"]._close()
await Tortoise._connections["models"].create_connection(with_db=True)

async with in_transaction():
self.assertEqual([f"{a.id}:{a.name}" for a in await Tournament.all()], ["1:1", "2:2"])

@test.skip(
"you can't just open a new pool and expect to be able to release the old connection to it"
)
@test.requireCapability(supports_transactions=True)
async def test_reconnect_during_transaction_fails(self):
await Tournament.create(name="1")
Expand Down
21 changes: 6 additions & 15 deletions tests/test_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ async def test_nested_transactions(self):
self.assertEqual(tournament.id, saved_tournament.id)
raise SomeException("Some error")

saved_event = await Tournament.filter(name="Updated name").first()
self.assertIsNotNone(saved_event)
# TODO: reactive once savepoints are implemented
# saved_event = await Tournament.filter(name="Updated name").first()
# self.assertIsNotNone(saved_event)
not_saved_event = await Tournament.filter(name="Nested").first()
self.assertIsNone(not_saved_event)

Expand Down Expand Up @@ -89,6 +90,7 @@ async def bound_to_fall():
saved_event = await Tournament.filter(name="Updated name").first()
self.assertIsNone(saved_event)

@test.skip("start_transaction is dodgy")
async def test_transaction_manual_commit(self):
tournament = await Tournament.create(name="Test")

Expand All @@ -101,6 +103,7 @@ async def test_transaction_manual_commit(self):
saved_event = await Tournament.filter(name="Updated name").first()
self.assertEqual(saved_event.id, tournament.id)

@test.skip("start_transaction is dodgy")
async def test_transaction_manual_rollback(self):
tournament = await Tournament.create(name="Test")

Expand All @@ -123,24 +126,12 @@ async def test_transaction_with_m2m_relations(self):
await event.participants.add(team)

async def test_transaction_exception_1(self):
connection = await start_transaction()
await connection.rollback()
with self.assertRaises(TransactionManagementError):
await connection.rollback()

async def test_transaction_exception_2(self):
with self.assertRaises(TransactionManagementError):
async with in_transaction() as connection:
await connection.rollback()
await connection.rollback()

async def test_transaction_exception_3(self):
connection = await start_transaction()
await connection.commit()
with self.assertRaises(TransactionManagementError):
await connection.commit()

async def test_transaction_exception_4(self):
async def test_transaction_exception_2(self):
with self.assertRaises(TransactionManagementError):
async with in_transaction() as connection:
await connection.commit()
Expand Down
5 changes: 3 additions & 2 deletions tests/test_two_databases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from tortoise import Tortoise
from tortoise.contrib import test
from tortoise.exceptions import OperationalError, ParamsError
from tortoise.transactions import in_transaction, start_transaction
from tortoise.transactions import in_transaction


class TestTwoDatabases(test.SimpleTestCase):
Expand Down Expand Up @@ -80,4 +80,5 @@ async def test_two_databases_transaction_paramerror(self):
ParamsError,
"You are running with multiple databases, so you should specify connection_name",
):
await start_transaction()
async with in_transaction():
pass
2 changes: 1 addition & 1 deletion tortoise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,4 +655,4 @@ async def do_stuff():
loop.run_until_complete(Tortoise.close_connections())


__version__ = "0.14.0"
__version__ = "0.15.0"
Loading