Skip to content

Commit fe33af7

Browse files
authored
Better schema generation, TruncationTestCase, values defaults (tortoise#162)
Features: * .values() and .values_list() now default to all fields if none are specified. * generate_schema() now generates well-formatted DDL SQL statements. * Added TruncationTestCase testing class that truncates tables to allow faster testing of transactions. This allows tests to run 20% faster on SQLite, and about 7× faster for MySQL on my local system. (PG is 2×) * Cleaned up the examples a bit * Re-did generate_schema example & turned into test case * A new recursive-lookup example & turned into test case Bugfixes: * Fixed state leak between database drivers which could cause incorrect DDL generation. * Fixed missing table/column comment generation. * Fixed comment generation to escape properly for SQLite * Fixed comment generation for PostgreSQL to not duplicate comments Chores: * Minor tweaking to tests to run with one process to simplify stack traces * Lots of small formatting/linting fixes * Fixed requirements generation to work right on Py3.7 * Some documentation cleanup * Sphinx 2.1 breaks badly with the documentation theme, and <2 currently gives the best result, so force it to an older version for the forseeable future.
1 parent d8f4337 commit fe33af7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+969
-619
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ coverage.xml
5252
*,cover
5353
.hypothesis/
5454
.vscode/
55+
examples/*.sqlite3
5556

5657
# Translations
5758
*.mo

.pylintrc

+2-3
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,9 @@ confidence=
5454
# --enable=similarities". If you want to run only the classes checker, but have
5555
# no Warning level messages displayed, use"--disable=all --enable=classes
5656
# --disable=W"
57-
disable=C0301,C0330,C0412,C0411,
58-
W0613,W0212,W0611,
57+
disable=C0330,C0412,W0212,W0613,R0902,R0903,R0904,
5958
# tune down below here
60-
R,C0111,C0103
59+
C0103,C0111,R1702,R0912,R0913,R0914,R0915
6160

6261
# Enable the message, report, category or checker with the given id(s). You can
6362
# either give multiple identifier separated by comma (,) or put this option

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ env:
1212
- TORTOISE_TEST_DB="mysql://root:@127.0.0.1:3306/test_{}"
1313
matrix:
1414
include:
15-
- python: pypy3.5
15+
- python: pypy3.6-7.1.1
1616
env: TORTOISE_TEST_DB="sqlite:///tmp/test-{}.sqlite"
1717
install: pip install -r requirements-pypy.txt
1818
script: green
19-
- python: pypy3.5
19+
- python: pypy3.6-7.1.1
2020
env: TORTOISE_TEST_DB="mysql://root:@127.0.0.1:3306/test_{}"
2121
install: pip install -r requirements-pypy.txt
2222
script: green

CHANGELOG.rst

+61-29
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,83 @@
33
Changelog
44
=========
55

6-
0.12.9
7-
------
8-
* Example Sanic integration along with register_tortoise hook in contrib (#163)
9-
10-
0.12.7
11-
------
12-
* Support connecting to PostgreSQL via Unix domain socket (simple case).
13-
* Self-referential Foreign and Many-to-Many keys are now allowed
14-
15-
0.12.6
6+
0.13.0
167
------
8+
.. warning::
9+
**This release brings with it, deprecation of Python 3.5:**
10+
11+
We will increase the minimum supported version of Python to 3.6,
12+
as 3.5 is reaching end-of-life,
13+
and is missing many useful features for async applications.
14+
15+
We will discontinue Python 3.5 support on the next major release (Likely 0.14.0)
16+
17+
New Features:
18+
^^^^^^^^^^^^^
19+
- Example Sanic integration along with register_tortoise hook in contrib (#163)
20+
- ``.values()`` and ``.values_list()`` now default to all fields if none are specified.
21+
- ``generate_schema()`` now generates well-formatted DDL SQL statements.
22+
- Added ``TruncationTestCase`` testing class that truncates tables to allow faster testing of transactions.
23+
24+
Bugfixes:
25+
^^^^^^^^^
26+
- Fixed state leak between database drivers which could cause incorrect DDL generation.
27+
- Fixed missing table/column comment generation for ``ForeignKeyField`` and ``ManyToManyField``
28+
- Fixed comment generation to escape properly for ``SQLite``
29+
- Fixed comment generation for ``PostgreSQL`` to not duplicate comments
30+
31+
Docs/examples:
32+
^^^^^^^^^^^^^^
33+
- Examples have been reworked:
34+
35+
- Simplified init of many examples
36+
- Re-did ``generate_schema.py`` example
37+
- A new ``relations_recirsive.py`` example (turned into test case)
38+
39+
- Lots of small documentation cleanups
40+
41+
0.12.7 (retracted)
42+
------------------
43+
- Support connecting to PostgreSQL via Unix domain socket (simple case).
44+
- Self-referential Foreign and Many-to-Many keys are now allowed
45+
46+
0.12.6 / 0.12.8
47+
---------------
1748
* Handle a ``__models__`` variable within modules to override the model discovery mechanism.
1849

1950
If you define the ``__models__`` variable in ``yourapp.models`` (or wherever you specify to load your models from),
2051
``generate_schema()`` will use that list, rather than automatically finding all models for you.
2152

22-
* Split model consructor into from-Python and from-DB paths, leading to 15-25% speedup for large fetch operations.
23-
* More efficient queryset manipulation, 5-30% speedup for small fetches.
53+
- Split model consructor into from-Python and from-DB paths, leading to 15-25% speedup for large fetch operations.
54+
- More efficient queryset manipulation, 5-30% speedup for small fetches.
2455

2556
0.12.5
2657
------
27-
* Using non registered models or wrong references causes an ConfigurationError with a helpful message.
58+
- Using non registered models or wrong references causes an ConfigurationError with a helpful message.
2859

2960
0.12.4
3061
------
31-
* Inherit fields from Mixins, together with abstract model classes.
62+
- Inherit fields from Mixins, together with abstract model classes.
3263

3364
0.12.3
3465
------
35-
* Added description attribute to Field class. (#124)
36-
* Added the ability to leverage field description from (#124) to generate table column comments and ability to add table level comments
66+
- Added description attribute to Field class. (#124)
67+
- Added the ability to leverage field description from (#124) to generate table column comments and ability to add table level comments
3768

3869
0.12.2
3970
------
40-
* Fix accidental double order-by for ``.values()`` based queries. (#143)
71+
- Fix accidental double order-by for ``.values()`` based queries. (#143)
4172

4273
0.12.1
4374
------
44-
* Notable efficiency improvement for regular inserts
4575
* Bulk insert operation:
4676

4777
.. note::
4878
The bulk insert operation will do the minimum to ensure that the object
4979
created in the DB has all the defaults and generated fields set,
50-
but may be incomplete reference in Python.
80+
this may result in incomplete references in Python.
5181

52-
e.g. ``IntField`` primary keys will not be poplulated.
82+
e.g. ``IntField`` primary keys will not be populated.
5383

5484
This is recommend only for throw away inserts where you want to ensure optimal
5585
insert performance.
@@ -61,6 +91,8 @@ Changelog
6191
User(name="...", email="...")
6292
])
6393
94+
- Notable efficiency improvement for regular inserts
95+
6496
0.12.0
6597
------
6698
* Tortoise ORM now supports non-autonumber primary keys.
@@ -69,7 +101,7 @@ Changelog
69101
This is a big feature change. It should not break any existing implementations.
70102

71103
That primary key will be accesible through a reserved field ``pk`` which will be an alias of whichever field has been nominated as a primary key.
72-
That alias field can be used as a field name when doing filtering e.g. ``.filter(pk=...)`` etc...
104+
That alias field can be used as a field name when doing filtering e.g. ``.filter(pk=...)`` etc
73105

74106
We currently support single (non-composite) primary keys of any indexable field type, but only these field types are recommended:
75107

@@ -138,13 +170,13 @@ Changelog
138170

139171
0.11.4
140172
------
141-
- Fixed several convenince issues with foreign relations:
173+
- Fixed several convenience issues with foreign relations:
142174

143175
- FIXED: ``.all()`` actually returns the _query property as was documented.
144176
- New models with FK don't automatically fail to resolve any data. They can now be evaluated lazily.
145177

146178
- Some DB's don't support OFFSET without Limit, added caps to signal workaround, which is to automatically add limit of 1000000
147-
- Pylint plugin to know about default `related_name` for ForeignKey fields.
179+
- Pylint plugin to know about default ``related_name`` for ForeignKey fields.
148180
- Simplified capabilities to be static, and defined at class level.
149181

150182
0.11.3
@@ -161,19 +193,19 @@ Changelog
161193
162194
* Added per-field indexes.
163195

164-
When setting `index=True` on a field, Tortoise will now generate an index for it.
196+
When setting ``index=True`` on a field, Tortoise will now generate an index for it.
165197

166198
.. note::
167199
Due to MySQL limitation of not supporting conditional index creation,
168-
if `safe=True` (the default) is set, it won't create the index and emit a warning about it.
200+
if ``safe=True`` (the default) is set, it won't create the index and emit a warning about it.
169201

170202
We plan to work around this limitation in a future release.
171203

172204
- Performance fix with PyPika for small fetch queries
173205
- Remove parameter hack now that PyPika support Parametrized queries
174206
- Fix typos in JSONField docstring
175-
- Added `.explain()` method on `QuerySet`.
176-
- Add `required` read-only property to fields
207+
- Added ``.explain()`` method on ``QuerySet``.
208+
- Add ``required`` read-only property to fields
177209

178210
0.11.2
179211
------
@@ -194,8 +226,8 @@ Changelog
194226

195227
0.11.0
196228
------
197-
- Added `.exclude()` method for QuerySet
198-
- Q objects can now be negated for `NOT` query (`~Q(...)`)
229+
- Added ``.exclude()`` method for QuerySet
230+
- Q objects can now be negated for ``NOT`` query (``~Q(...)``)
199231
- Support subclassing on existing fields
200232
- Numerous bug fixes
201233
- Removed known broken connection pooling

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ help:
1818
up:
1919
CUSTOM_COMPILE_COMMAND="make up" pip-compile -o requirements-pypy.txt requirements-pypy.in -U
2020
CUSTOM_COMPILE_COMMAND="make up" pip-compile -o requirements-dev.txt requirements-dev.in -U
21+
cat docs/extra_requirements.txt >> requirements-pypy.txt
22+
cat docs/extra_requirements.txt >> requirements-dev.txt
23+
sed -i "s/^-e .*/-e ./" requirements-dev.txt
2124

2225
deps:
2326
@pip install -q pip-tools

README.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ You can find docs at `ReadTheDocs <http://tortoise-orm.readthedocs.io/en/latest/
3030
Tortoise ORM is young project and breaking changes are to be expected.
3131
We keep a `Changelog <http://tortoise-orm.readthedocs.io/en/latest/CHANGELOG.html>`_ and it will have possible breakage clearly documented.
3232

33-
Tortoise ORM is supported on CPython >= 3.5.3 for SQLite, MySQL and PostgreSQL, and PyPy3.5 >= 5.10 for SQLite and MySQL only.
33+
Tortoise ORM is supported on CPython >= 3.5.3 for SQLite, MySQL and PostgreSQL, and PyPy3.6 >= 7.1 for SQLite and MySQL only.
3434

3535
Why was Tortoise ORM built?
3636
---------------------------

docs/CONTRIBUTING.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ We have a ``Makefile`` that has the common operations listed, to get started jus
4747
docs Builds the documentation
4848
style Auto-formats the code
4949

50-
So to run the tests you just need to run ``make test``, etc...
50+
So to run the tests you just need to run ``make test``, etc
5151

5252
The code is structured in the following directories:
5353

docs/extra_requirements.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
aiocontextvars==0.2.2 ; python_version < "3.7"
2+
contextvars==2.4 ; python_version < "3.7"
3+
immutables==0.9 ; python_version < "3.7"

docs/index.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Why was Tortoise ORM built?
2222
---------------------------
2323

2424
Python has many existing and mature ORMs, unfortunately they are designed with an opposing paradigm of how I/O gets processed.
25-
``asyncio`` is relatively new technology that has a very different concurrency model, and the largest change is regarding how I/O is handled.
25+
``asyncio`` is relatively new technology that has a different concurrency model, and the largest change is regarding how I/O is handled.
2626

2727
However, Tortoise ORM is not first attempt of building ``asyncio`` ORM, there are many cases of developers attempting to map synchronous python ORMs to the async world, initial attempts did not have a clean API.
2828

docs/models.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Primary Keys
8282
In Tortoise ORM we require that a model has a primary key.
8383

8484
That primary key will be accesible through a reserved field ``pk`` which will be an alias of whichever field has been nominated as a primary key.
85-
That alias field can be used as a field name when doing filtering e.g. ``.filter(pk=...)`` etc...
85+
That alias field can be used as a field name when doing filtering e.g. ``.filter(pk=...)`` etc
8686

8787
We currently support single (non-composite) primary keys of any indexable field type, but only these field types are recommended:
8888

@@ -117,7 +117,7 @@ repetitive work by leveraging from inheritence.
117117
You can define fields in more generic classes and they are
118118
automatically available in derived classes. Base classes are
119119
not limited to Model classes. Any class will work. This way
120-
you are able to define your models in a very natural and easy
120+
you are able to define your models in a natural and easy
121121
to maintain way.
122122

123123
Let's have a look at some examples.

docs/query.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ produces 1 additional query, so ``.prefetch_related('events__participants')`` wi
116116
additional queries to fetch your data.
117117

118118
Sometimes, when performance is crucial, you don't want to make additional queries like this.
119-
In cases like this you could use `values()` or `values_list()` to produce more efficient query
119+
In cases like this you could use ``values()`` or ``values_list()`` to produce more efficient query
120120

121121
.. code-block:: python3
122122

docs/requirements.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-r ../requirements.txt
22

3-
sphinx
3+
sphinx < 2
44
cloud_sptheme
5-
sphinx-autodoc-typehints
5+
sphinx-autodoc-typehints < 1.7
66
asynctest

docs/roadmap.rst

+4-8
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@ For ``v1.0`` that involves:
1111

1212
* Schema discovery
1313
* Timezone support
14-
* Clear and concise examples
15-
* Refactored Fields Schema generation
1614
* DB transaction isolation
1715
* Connection pooling
18-
* Robust connection handling
1916
* Change to all-parametrized queries for safety
20-
17+
* Clear and concise examples
2118

2219
Mid-term
2320
========
@@ -26,7 +23,6 @@ Here we have all the features that is slightly further out, in no particular ord
2623

2724
* Performance work:
2825
* Sub queries
29-
* Bulk operations
3026
* Consider using Cython to accelerate critical loops
3127

3228
* Convenience/Ease-Of-Use work:
@@ -43,15 +39,15 @@ Here we have all the features that is slightly further out, in no particular ord
4339
* Expand annotation framework to add statistical functions
4440

4541
* Migrations
46-
* Comprehensive schema in Migrations
42+
* Comprehensive schema Migrations
4743
* Automatic forward Migration building
48-
* Ability to easily run arb code in a migration
44+
* Ability to easily run arbitrary code in a migration
4945
* Ability to get a the Models for that exact time of the migration, to ensure safe & consistent data migrations
5046
* Cross-DB support
5147
* Fixtures as a property of a migration
5248

5349
* Serialization support
54-
* Take inspiration from ``attrs`` and ``marshmallow``
50+
* Take inspiration from ``attrs``, ``marshmallow`` and ``pydantic``
5551
* Provide sane default serializers that will work as-is for CRUD
5652
* Provide sane default schema generators
5753
* Make default serializers support some validation

examples/aggregation.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import asyncio
2-
3-
from tortoise import Tortoise, fields
1+
from tortoise import Tortoise, fields, run_async
42
from tortoise.aggregation import Count, Min, Sum
53
from tortoise.models import Model
64

@@ -34,7 +32,7 @@ def __str__(self):
3432

3533

3634
async def run():
37-
await Tortoise.init(config_file="config.json")
35+
await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
3836
await Tortoise.generate_schemas()
3937
tournament = await Tournament.create(name="New Tournament")
4038
await tournament.save()
@@ -60,5 +58,4 @@ async def run():
6058

6159

6260
if __name__ == "__main__":
63-
loop = asyncio.get_event_loop()
64-
loop.run_until_complete(run())
61+
run_async(run())

examples/basic.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
"""
22
This example demonstrates most basic operations with single model
33
"""
4-
import asyncio
5-
6-
from tortoise import Tortoise, fields
4+
from tortoise import Tortoise, fields, run_async
75
from tortoise.models import Model
86

97

@@ -20,7 +18,7 @@ def __str__(self):
2018

2119

2220
async def run():
23-
await Tortoise.init(config_file="config.json")
21+
await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
2422
await Tortoise.generate_schemas()
2523

2624
event = await Event.create(name="Test")
@@ -34,5 +32,4 @@ async def run():
3432

3533

3634
if __name__ == "__main__":
37-
loop = asyncio.get_event_loop()
38-
loop.run_until_complete(run())
35+
run_async(run())

0 commit comments

Comments
 (0)