diff --git a/.gitignore b/.gitignore index e11d16b4..83cecc09 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,12 @@ docs/_build/ # PyBuilder target/ +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + + # pyenv python configuration file .python-version @@ -73,3 +79,6 @@ target/ # extension stub files src/gino/ext/*.pyi + +# virtual env +venv/ diff --git a/docs/conf.py b/docs/conf.py index c59f8894..b21c12c8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,7 +51,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'python-gino' +html_theme = "python-gino" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/src/gino/api.py b/src/gino/api.py index e3895423..575f5806 100644 --- a/src/gino/api.py +++ b/src/gino/api.py @@ -210,6 +210,15 @@ async def __aexit__(self, exc_type, exc_val, exc_tb): await self._args[0].pop_bind().close() +NAMING_CONVENTION = { + "ix": "ix_%(column_0_label)s", + "uq": "uq_%(table_name)s_%(column_0_name)s", + "ck": "ck_%(table_name)s_%(constraint_name)s", + "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", + "pk": "pk_%(table_name)s", +} + + class Gino(sa.MetaData): """ All-in-one API class of GINO, providing several shortcuts. @@ -355,7 +364,10 @@ def __init__( :class:`~sqlalchemy.schema.MetaData`. """ - super().__init__(bind=bind, **kwargs) + preset_kwargs = dict(naming_convention=NAMING_CONVENTION, bind=bind) + preset_kwargs.update(kwargs) + super().__init__(**preset_kwargs) + if model_classes is None: model_classes = self.model_base_classes self._model = declarative_base(self, model_classes) diff --git a/tests/models.py b/tests/models.py index 0b6dc36e..bcc75f0b 100644 --- a/tests/models.py +++ b/tests/models.py @@ -2,12 +2,15 @@ import enum import random import string +import uuid from datetime import datetime import pytest from gino import Gino from gino.dialects.asyncpg import JSONB +from sqlalchemy.dialects.postgresql import UUID + DB_ARGS = dict( host=os.getenv("DB_HOST", "localhost"), @@ -46,9 +49,9 @@ class User(db.Model): balance = db.IntegerProperty(default=0) birthday = db.DateTimeProperty(default=lambda i: datetime.utcfromtimestamp(0)) team_id = db.Column(db.ForeignKey("gino_teams.id")) - weight = db.IntegerProperty(prop_name='parameter') - height = db.IntegerProperty(default=170, prop_name='parameter') - bio = db.StringProperty(prop_name='parameter') + weight = db.IntegerProperty(prop_name="parameter") + height = db.IntegerProperty(default=170, prop_name="parameter") + bio = db.StringProperty(prop_name="parameter") @balance.after_get def balance(self, val): @@ -134,7 +137,7 @@ def add_team(self, team): class UserSetting(db.Model): __tablename__ = "gino_user_settings" - # No constraints defined on columns + # No constraints defined on these columns id = db.Column(db.BigInteger()) user_id = db.Column(db.BigInteger()) setting = db.Column(db.Text()) @@ -142,11 +145,15 @@ class UserSetting(db.Model): col1 = db.Column(db.Integer, default=1) col2 = db.Column(db.Integer, default=2) + # Some constraints defined on these columns + col3 = db.Column(UUID, default=uuid.uuid4, unique=True) + col4 = db.Column(db.Integer, default=4, nullable=False) + # Define indexes and constraints inline id_pkey = db.PrimaryKeyConstraint("id") user_id_fk = db.ForeignKeyConstraint(["user_id"], ["gino_users.id"]) user_id_setting_unique = db.UniqueConstraint("user_id", "setting") - col1_check = db.CheckConstraint("col1 >= 1 AND col1 <= 5") + col1_check = db.CheckConstraint("col1 >= 1 AND col1 <= 5", "check_col1") col2_idx = db.Index("col2_idx", "col2") diff --git a/tests/test_engine.py b/tests/test_engine.py index b3439eec..b6c07bc0 100644 --- a/tests/test_engine.py +++ b/tests/test_engine.py @@ -411,21 +411,21 @@ async def test_repr(): from gino.dialects.asyncpg import NullPool e = await create_engine(PG_URL, pool_class=NullPool) - assert 'cur=0' in repr(e) + assert "cur=0" in repr(e) async with e.acquire(): - assert 'cur=1' in repr(e) + assert "cur=1" in repr(e) async with e.acquire(): - assert 'cur=2' in repr(e) - assert 'cur=1' in repr(e) - assert 'cur=0' in repr(e) - assert 'NullPool' in e.repr(color=True) + assert "cur=2" in repr(e) + assert "cur=1" in repr(e) + assert "cur=0" in repr(e) + assert "NullPool" in e.repr(color=True) e = await create_engine(PG_URL) - assert 'cur=10 use=0' in repr(e) + assert "cur=10 use=0" in repr(e) async with e.acquire(): - assert 'cur=10 use=1' in repr(e) + assert "cur=10 use=1" in repr(e) async with e.acquire(): - assert 'cur=10 use=2' in repr(e) - assert 'cur=10 use=1' in repr(e) - assert 'cur=10 use=0' in repr(e) - assert 'asyncpg.pool.Pool' in e.repr(color=True) + assert "cur=10 use=2" in repr(e) + assert "cur=10 use=1" in repr(e) + assert "cur=10 use=0" in repr(e) + assert "asyncpg.pool.Pool" in e.repr(color=True)