diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml new file mode 100644 index 0000000..efad5c5 --- /dev/null +++ b/.github/workflows/pypi.yml @@ -0,0 +1,22 @@ +name: pypi +on: + push: + paths: + - 'alice/__init__.py' + - '.github/workflows/pypi.yml' +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v1 + with: + python-version: '3.x' + - name: Build dists + run: | + python3 setup.py sdist + - name: Pypi Publish + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.pypi_password }} \ No newline at end of file diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e69de29..1e3a322 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -0,0 +1,10 @@ +========= +ChangeLog +========= + + +0.1 +=== +0.1.1 +----- +- Now alice is basic worked. \ No newline at end of file diff --git a/Makefile b/Makefile index 238116d..85a90cd 100644 --- a/Makefile +++ b/Makefile @@ -7,13 +7,44 @@ help: @echo @echo "usage: make " @echo "Targets:" + @echo " up Updates dev/test dependencies" + @echo " deps Ensure dev/test dependencies are installed" + @echo " check Checks that build is sane" + @echo " lint Reports all linter violations" @echo " test Runs all tests" - @echo " style Auto-formats the code" + @echo " style Auto-formats the code" deps: @which pip-sync > /dev/null || pip install -q pip-tools @pip install -r requirements-dev.txt +up: + CUSTOM_COMPILE_COMMAND="make up" pip-compile -o requirements-dev.txt -U + sed -i "s/^-e .*/-e ./" requirements.txt + style: deps isort -rc $(checkfiles) - black $(black_opts) $(checkfiles) \ No newline at end of file + black $(black_opts) $(checkfiles) + +check: deps +ifneq ($(shell which black),) + black --check $(black_opts) $(checkfiles) || (echo "Please run 'make style' to auto-fix style issues" && false) +endif + flake8 $(checkfiles) + mypy $(checkfiles) + pylint -d C,W,R $(checkfiles) + bandit -r $(checkfiles) + python setup.py check -mrs + +lint: deps +ifneq ($(shell which black),) + black --check $(black_opts) $(checkfiles) || (echo "Please run 'make style' to auto-fix style issues" && false) +endif + flake8 $(checkfiles) + mypy $(checkfiles) + pylint $(checkfiles) + bandit -r $(checkfiles) + python setup.py check -mrs + +test: deps + $(py_warn) py.test \ No newline at end of file diff --git a/README.rst b/README.rst index e69de29..0847a9f 100644 --- a/README.rst +++ b/README.rst @@ -0,0 +1,120 @@ +===== +Alice +===== + +.. image:: https://img.shields.io/pypi/v/alice.svg?style=flat + :target: https://pypi.python.org/pypi/alice +.. image:: https://img.shields.io/github/license/long2ice/alice + :target: https://github.com/long2ice/alice +.. image:: https://github.com/long2ice/alice/workflows/pypi/badge.svg + :target: https://github.com/long2ice/alice/actions?query=workflow:pypi + +Introduction +============ + +Tortoise-ORM is the best asyncio ORM now, but it lacks a database migrations tool like alembic for SQLAlchemy, or Django ORM with it's own migrations tool. + +This project aim to be a best migrations tool for Tortoise-ORM and which written by one of contributors of Tortoise-ORM. + +Install +======= + +Just install from pypi: + +.. code-block:: shell + + $ pip install alice + +Quick Start +=========== + +.. code-block:: shell + + $ alice -h + + Usage: alice [OPTIONS] COMMAND [ARGS]... + + Options: + --config TEXT Tortoise-ORM config module, will auto read config dict variable + from it. [default: settings] + --tortoise-orm TEXT Tortoise-ORM config dict variable. [default: + TORTOISE_ORM] + --location TEXT Migrate store location. [default: ./migrations] + --app TEXT Tortoise-ORM app name. [default: models] + -h, --help Show this message and exit. + + Commands: + downgrade Downgrade to previous version. + heads Show current available heads in migrate location. + history List all migrate items. + init Init migrate location and generate schema, you must exec first. + migrate Generate migrate changes file. + upgrade Upgrade to latest version. + +Usage +===== + +Init schema and migrate location +-------------------------------- + +.. code-block:: shell + + $ alice --config tests.backends.mysql init + + Success create migrate location ./migrations/models + Success init for app "models" + +Update models and make migrate +------------------------------ + +.. code-block:: shell + + $ alice --config tests.backends.mysql migrate --name drop_column + + Success migrate 1_202029051520102929_drop_column.json + +Format of migrate filename is {version}_{datetime}_{name|update}.json + +Upgrade to latest version +------------------------- + +.. code-block:: shell + + $ alice --config tests.backends.mysql upgrade + + Success upgrade 1_202029051520102929_drop_column.json + +Now your db is migrated to latest. + +Downgrade to previous version +----------------------------- + +.. code-block:: shell + + $ alice --config tests.backends.mysql downgrade + + Success downgrade 1_202029051520102929_drop_column.json + +Now your db rollback to previous version. + +Show history +------------ + +.. code-block:: shell + + $ alice --config tests.backends.mysql history + + 1_202029051520102929_drop_column.json + +Show heads to be migrated +------------------------- + +.. code-block:: shell + + $ alice --config tests.backends.mysql heads + + 1_202029051520102929_drop_column.json + +License +======= +This project is licensed under the `MIT `_ License. \ No newline at end of file diff --git a/alice/__init__.py b/alice/__init__.py index 3dc1f76..485f44a 100644 --- a/alice/__init__.py +++ b/alice/__init__.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.1.1" diff --git a/alice/cli.py b/alice/cli.py index b4f1a31..9f815b4 100644 --- a/alice/cli.py +++ b/alice/cli.py @@ -5,7 +5,7 @@ import sys from enum import Enum import asyncclick as click -from asyncclick import BadOptionUsage, BadParameter, Context, UsageError +from asyncclick import BadOptionUsage, Context, UsageError from tortoise import Tortoise, generate_schema_for_client from alice.migrate import Migrate @@ -23,7 +23,7 @@ class Color(str, Enum): "--config", default="settings", show_default=True, - help="Tortoise-ORM config module, will read config variable from it.", + help="Tortoise-ORM config module, will auto read dict config variable from it.", ) @click.option( "--tortoise-orm", @@ -44,10 +44,14 @@ async def cli(ctx: Context, config, tortoise_orm, location, app): raise BadOptionUsage(ctx=ctx, message=f'No module named "{config}"', option_name="--config") config = getattr(config_module, tortoise_orm, None) if not config: - raise BadOptionUsage(f'Can\'t get "{tortoise_orm}" from module "{config_module}"', ctx=ctx) + raise BadOptionUsage( + option_name="--config", + message=f'Can\'t get "{tortoise_orm}" from module "{config_module}"', + ctx=ctx, + ) if app not in config.get("apps").keys(): - raise BadOptionUsage(f'No app found in "{config}"', ctx=ctx) + raise BadOptionUsage(option_name="--config", message=f'No app found in "{config}"', ctx=ctx) ctx.obj["config"] = config ctx.obj["location"] = location @@ -142,7 +146,7 @@ def history(ctx): @cli.command( - help="Init migrate location and generate schema, you must exec first before other cmd." + help="Init migrate location and generate schema, you must exec first." ) @click.option( "--safe", diff --git a/alice/ddl/__init__.py b/alice/ddl/__init__.py index e6a5dc9..affff60 100644 --- a/alice/ddl/__init__.py +++ b/alice/ddl/__init__.py @@ -2,10 +2,10 @@ from typing import List, Type from tortoise import BaseDBAsyncClient, ForeignKeyFieldInstance, Model from tortoise.backends.base.schema_generator import BaseSchemaGenerator -from tortoise.fields import Field, JSONField, TextField, UUIDField +from tortoise.fields import Field -class DDL: +class BaseDDL: schema_generator_cls: Type[BaseSchemaGenerator] = BaseSchemaGenerator DIALECT = "sql" _DROP_TABLE_TEMPLATE = "DROP TABLE {table_name} IF EXISTS" @@ -23,108 +23,25 @@ class DDL: self.schema_generator = self.schema_generator_cls(client) def create_table(self, model: "Type[Model]"): - return self.schema_generator._get_table_sql(model, True)["table_creation_string"] + raise NotImplementedError def drop_table(self, model: "Type[Model]"): - return self._DROP_TABLE_TEMPLATE.format(table_name=model._meta.db_table) + raise NotImplementedError def add_column(self, model: "Type[Model]", field_object: Field): - db_table = model._meta.db_table - default = field_object.default - db_column = field_object.model_field_name - auto_now_add = getattr(field_object, "auto_now_add", False) - auto_now = getattr(field_object, "auto_now", False) - if default is not None or auto_now or auto_now_add: - if callable(default) or isinstance(field_object, (UUIDField, TextField, JSONField)): - default = "" - else: - default = field_object.to_db_value(default, model) - try: - default = self.schema_generator._column_default_generator( - db_table, - db_column, - self.schema_generator._escape_default_value(default), - auto_now_add, - auto_now, - ) - except NotImplementedError: - default = "" - else: - default = "" - return self._ADD_COLUMN_TEMPLATE.format( - table_name=db_table, - column=self.schema_generator._create_string( - db_column=field_object.model_field_name, - field_type=field_object.get_for_dialect(self.DIALECT, "SQL_TYPE"), - nullable="NOT NULL" if not field_object.null else "", - unique="UNIQUE" if field_object.unique else "", - comment=self.schema_generator._column_comment_generator( - table=db_table, - column=field_object.model_field_name, - comment=field_object.description, - ) - if field_object.description - else "", - is_primary_key=field_object.pk, - default=default, - ), - ) + raise NotImplementedError def drop_column(self, model: "Type[Model]", column_name: str): - return self._DROP_COLUMN_TEMPLATE.format( - table_name=model._meta.db_table, column_name=column_name - ) + raise NotImplementedError def add_index(self, model: "Type[Model]", field_names: List[str], unique=False): - return self._ADD_INDEX_TEMPLATE.format( - unique="UNIQUE" if unique else "", - index_name=self.schema_generator._generate_index_name( - "idx" if not unique else "uid", model, field_names - ), - table_name=model._meta.db_table, - column_names=", ".join([self.schema_generator.quote(f) for f in field_names]), - ) + raise NotImplementedError def drop_index(self, model: "Type[Model]", field_names: List[str], unique=False): - return self._DROP_INDEX_TEMPLATE.format( - index_name=self.schema_generator._generate_index_name( - "idx" if not unique else "uid", model, field_names - ), - table_name=model._meta.db_table, - ) + raise NotImplementedError def add_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance): - db_table = model._meta.db_table - to_field_name = field.to_field_instance.source_field - if not to_field_name: - to_field_name = field.to_field_instance.model_field_name - - fk_name = self.schema_generator._generate_fk_name( - from_table=db_table, - from_field=field.source_field or field.model_field_name + "_id", - to_table=field.related_model._meta.db_table, - to_field=to_field_name, - ) - return self._ADD_FK_TEMPLATE.format( - table_name=db_table, - fk_name=fk_name, - db_column=field.source_field or field.model_field_name + "_id", - table=field.related_model._meta.db_table, - field=to_field_name, - on_delete=field.on_delete, - ) + raise NotImplementedError def drop_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance): - to_field_name = field.to_field_instance.source_field - if not to_field_name: - to_field_name = field.to_field_instance.model_field_name - db_table = model._meta.db_table - return self._DROP_FK_TEMPLATE.format( - table_name=db_table, - fk_name=self.schema_generator._generate_fk_name( - from_table=db_table, - from_field=field.source_field or field.model_field_name + "_id", - to_table=field.related_model._meta.db_table, - to_field=to_field_name, - ), - ) + raise NotImplementedError diff --git a/alice/ddl/mysql/__init__.py b/alice/ddl/mysql/__init__.py index 474f47f..ffd0720 100644 --- a/alice/ddl/mysql/__init__.py +++ b/alice/ddl/mysql/__init__.py @@ -1,8 +1,120 @@ +from typing import List, Type + +from tortoise import ForeignKeyFieldInstance, Model from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator +from tortoise.fields import Field, JSONField, TextField, UUIDField -from alice.ddl import DDL +from alice.ddl import BaseDDL -class MysqlDDL(DDL): +class MysqlDDL(BaseDDL): schema_generator_cls = MySQLSchemaGenerator DIALECT = MySQLSchemaGenerator.DIALECT + + def create_table(self, model: "Type[Model]"): + return self.schema_generator._get_table_sql(model, True)["table_creation_string"] + + def drop_table(self, model: "Type[Model]"): + return self._DROP_TABLE_TEMPLATE.format(table_name=model._meta.db_table) + + def add_column(self, model: "Type[Model]", field_object: Field): + db_table = model._meta.db_table + default = field_object.default + db_column = field_object.model_field_name + auto_now_add = getattr(field_object, "auto_now_add", False) + auto_now = getattr(field_object, "auto_now", False) + if default is not None or auto_now_add: + if callable(default) or isinstance(field_object, (UUIDField, TextField, JSONField)): + default = "" + else: + default = field_object.to_db_value(default, model) + try: + default = self.schema_generator._column_default_generator( + db_table, + db_column, + self.schema_generator._escape_default_value(default), + auto_now_add, + auto_now, + ) + except NotImplementedError: + default = "" + else: + default = "" + return self._ADD_COLUMN_TEMPLATE.format( + table_name=db_table, + column=self.schema_generator._create_string( + db_column=field_object.model_field_name, + field_type=field_object.get_for_dialect(self.DIALECT, "SQL_TYPE"), + nullable="NOT NULL" if not field_object.null else "", + unique="UNIQUE" if field_object.unique else "", + comment=self.schema_generator._column_comment_generator( + table=db_table, + column=field_object.model_field_name, + comment=field_object.description, + ) + if field_object.description + else "", + is_primary_key=field_object.pk, + default=default, + ), + ) + + def drop_column(self, model: "Type[Model]", column_name: str): + return self._DROP_COLUMN_TEMPLATE.format( + table_name=model._meta.db_table, column_name=column_name + ) + + def add_index(self, model: "Type[Model]", field_names: List[str], unique=False): + return self._ADD_INDEX_TEMPLATE.format( + unique="UNIQUE" if unique else "", + index_name=self.schema_generator._generate_index_name( + "idx" if not unique else "uid", model, field_names + ), + table_name=model._meta.db_table, + column_names=", ".join([self.schema_generator.quote(f) for f in field_names]), + ) + + def drop_index(self, model: "Type[Model]", field_names: List[str], unique=False): + return self._DROP_INDEX_TEMPLATE.format( + index_name=self.schema_generator._generate_index_name( + "idx" if not unique else "uid", model, field_names + ), + table_name=model._meta.db_table, + ) + + def add_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance): + db_table = model._meta.db_table + to_field_name = field.to_field_instance.source_field + if not to_field_name: + to_field_name = field.to_field_instance.model_field_name + + db_column = field.source_field or field.model_field_name + "_id" + fk_name = self.schema_generator._generate_fk_name( + from_table=db_table, + from_field=db_column, + to_table=field.related_model._meta.db_table, + to_field=to_field_name, + ) + return self._ADD_FK_TEMPLATE.format( + table_name=db_table, + fk_name=fk_name, + db_column=db_column, + table=field.related_model._meta.db_table, + field=to_field_name, + on_delete=field.on_delete, + ) + + def drop_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance): + to_field_name = field.to_field_instance.source_field + if not to_field_name: + to_field_name = field.to_field_instance.model_field_name + db_table = model._meta.db_table + return self._DROP_FK_TEMPLATE.format( + table_name=db_table, + fk_name=self.schema_generator._generate_fk_name( + from_table=db_table, + from_field=field.source_field or field.model_field_name + "_id", + to_table=field.related_model._meta.db_table, + to_field=to_field_name, + ), + ) diff --git a/alice/migrate.py b/alice/migrate.py index b68cc4f..9d86bd2 100644 --- a/alice/migrate.py +++ b/alice/migrate.py @@ -9,7 +9,7 @@ from tortoise import BackwardFKRelation, ForeignKeyFieldInstance, Model, Tortois from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator from tortoise.fields import Field -from alice.ddl import DDL +from alice.ddl import BaseDDL from alice.ddl.mysql import MysqlDDL from alice.exceptions import ConfigurationError from alice.utils import get_app_connection @@ -21,7 +21,7 @@ class Migrate: _upgrade_fk_operators: List[str] = [] _downgrade_fk_operators: List[str] = [] - ddl: DDL + ddl: BaseDDL migrate_config: dict old_models = "old_models" diff_app = "diff_models" @@ -85,6 +85,11 @@ class Migrate: @classmethod def migrate(cls, name): + """ + diff old models and new models to generate diff content + :param name: + :return: + """ if not cls.migrate_config: raise ConfigurationError("You must call init_with_old_models() first!") apps = Tortoise.apps @@ -103,6 +108,13 @@ class Migrate: @classmethod def _add_operator(cls, operator: str, upgrade=True, fk=False): + """ + add operator,differentiate fk because fk is order limit + :param operator: + :param upgrade: + :param fk: + :return: + """ if upgrade: if fk: cls._upgrade_fk_operators.append(operator) @@ -134,6 +146,13 @@ class Migrate: @classmethod def _get_migrate_config(cls, config: dict, app: str, location: str): + """ + generate tmp config with old models + :param config: + :param app: + :param location: + :return: + """ temp_config = deepcopy(config) path = os.path.join(location, app, cls.old_models) path = path.replace("/", ".").lstrip(".") @@ -142,6 +161,13 @@ class Migrate: @classmethod def write_old_models(cls, config: dict, app: str, location: str): + """ + write new models to old models + :param config: + :param app: + :param location: + :return: + """ old_model_files = [] models = config.get("apps").get(app).get("models") for model in models: @@ -235,6 +261,11 @@ class Migrate: @classmethod def _exclude_field(cls, field: Field): + """ + exclude BackwardFKRelation + :param field: + :return: + """ return isinstance(field, BackwardFKRelation) @classmethod @@ -251,11 +282,23 @@ class Migrate: return cls.ddl.drop_column(model, field.model_field_name) @classmethod - def _add_fk(cls, model: Type[Model], field: Field): + def _add_fk(cls, model: Type[Model], field: ForeignKeyFieldInstance): + """ + add fk + :param model: + :param field: + :return: + """ return cls.ddl.add_fk(model, field) @classmethod - def _remove_fk(cls, model: Type[Model], field: Field): + def _remove_fk(cls, model: Type[Model], field: ForeignKeyFieldInstance): + """ + drop fk + :param model: + :param field: + :return: + """ return cls.ddl.drop_fk(model, field) @classmethod diff --git a/poetry.lock b/poetry.lock index fa597e5..c952d18 100644 --- a/poetry.lock +++ b/poetry.lock @@ -259,7 +259,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.5.13" +version = "2020.5.14" [[package]] category = "main" @@ -470,27 +470,27 @@ pypika = [ {file = "PyPika-0.37.6.tar.gz", hash = "sha256:64510fa36667e8bb654bdc1be5a3a77bac1dbc2f03d4848efac08e39d9cac6f5"}, ] regex = [ - {file = "regex-2020.5.13-cp27-cp27m-win32.whl", hash = "sha256:d20ba8d3a844d6cd9bbe127a60cc8f61cfe2d2b77da997775639999a48fbbfe3"}, - {file = "regex-2020.5.13-cp27-cp27m-win_amd64.whl", hash = "sha256:2cdf6bb8112a6b49092a9320edc823d41b21a06c8c7ac88a845b73462193f3ac"}, - {file = "regex-2020.5.13-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9d801d3693c5a6af5a506f9905b0e6d8ae419a00054d8d80ed9d65f81fc37e1f"}, - {file = "regex-2020.5.13-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:705e334ac42cf807f33d4daafe58da33e23a93389233ab2f80f63dee09488d9b"}, - {file = "regex-2020.5.13-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:78014742b047ea2c9849e85db2dc84cad365b7f2dee404f86882d1fb9ff38df2"}, - {file = "regex-2020.5.13-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:078024a52a72c98f157c380bea7beab7e0b907854ca337e3d4eecd44b363d4fb"}, - {file = "regex-2020.5.13-cp36-cp36m-win32.whl", hash = "sha256:4088da3b99f1341c2904679ffbfe6f08f5cc13e5cad1c6b053728da7cf68d28c"}, - {file = "regex-2020.5.13-cp36-cp36m-win_amd64.whl", hash = "sha256:14026bf953137a5cdc6a2a8fda314a0296ce5cd6da6e46fe79d6e03caf3c1bac"}, - {file = "regex-2020.5.13-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:03284826c5f5cd4b252ab7d510cb4d6b7e7f849cdea8e1b384c57e0996a9a3f9"}, - {file = "regex-2020.5.13-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:36e6e7ca33a70f859e532110c2b1af28f98622424681e2e158f0f49735f1a9c8"}, - {file = "regex-2020.5.13-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:707d2fcfdce12ca946830839c4c243c1b258c0d2c61350dc2efe0af00a4d2fdf"}, - {file = "regex-2020.5.13-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:76668d1f91af08275313799bbd6ab04971ab08919defde886f5c94c7fc0f4623"}, - {file = "regex-2020.5.13-cp37-cp37m-win32.whl", hash = "sha256:0be1cb724d43a7fb017e868d809640de03be7db88ab83d212fd802bc3d0277a0"}, - {file = "regex-2020.5.13-cp37-cp37m-win_amd64.whl", hash = "sha256:9d42213927eede46bd4eb0c225600d82cf2b3c8882eb449f00b7cfa9bbf0975e"}, - {file = "regex-2020.5.13-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7163cac9621e9099dc8768ddec32372f50893c934be961f58826d46f0668ea0c"}, - {file = "regex-2020.5.13-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:efae79f5eb3a6e2d9fa246605870887e0187ed66a4c56fc4cf22da00aa2ec220"}, - {file = "regex-2020.5.13-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:89d4a97682170c32a13c4223e72cf75f9d0c6223b40fb4abe717bbb6c271c6ea"}, - {file = "regex-2020.5.13-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4f144eb977800d7ef593893204c2e7f1f109e8a943f6e822990d22385b12c5d6"}, - {file = "regex-2020.5.13-cp38-cp38-win32.whl", hash = "sha256:3b7f9c0051179325d7efd76271b783de593a50608e48e130c1590a95ea411f59"}, - {file = "regex-2020.5.13-cp38-cp38-win_amd64.whl", hash = "sha256:3cec763e0428beb8668edf004aa9a8a4c1b502d0ecb97dc4d77e5a67a9077186"}, - {file = "regex-2020.5.13.tar.gz", hash = "sha256:cd931f9cca663617ba7a74b6500c6857405271b142edff68b2530e458b80a116"}, + {file = "regex-2020.5.14-cp27-cp27m-win32.whl", hash = "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e"}, + {file = "regex-2020.5.14-cp27-cp27m-win_amd64.whl", hash = "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd"}, + {file = "regex-2020.5.14-cp36-cp36m-win32.whl", hash = "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994"}, + {file = "regex-2020.5.14-cp36-cp36m-win_amd64.whl", hash = "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f"}, + {file = "regex-2020.5.14-cp37-cp37m-win32.whl", hash = "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929"}, + {file = "regex-2020.5.14-cp37-cp37m-win_amd64.whl", hash = "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7"}, + {file = "regex-2020.5.14-cp38-cp38-win32.whl", hash = "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927"}, + {file = "regex-2020.5.14-cp38-cp38-win_amd64.whl", hash = "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108"}, + {file = "regex-2020.5.14.tar.gz", hash = "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5"}, ] six = [ {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, diff --git a/requirements-dev.txt b/requirements-dev.txt index 3897ee1..451b6b0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,31 +1,19 @@ -aiomysql==0.0.20 -aiosqlite==0.13.0 -anyio==1.3.0 -appdirs==1.4.4 -async-generator==1.10 -asyncclick==7.0.9 -asynctest==0.13.0 -attrs==19.3.0 -black==19.10b0 -cffi==1.14.0 -ciso8601==2.1.3; sys_platform != "win32" and implementation_name == "cpython" -click==7.1.2 -cryptography==2.9.2 -flake8==3.8.1 -iso8601==0.1.12; sys_platform == "win32" or implementation_name != "cpython" -isort==4.3.21 -mccabe==0.6.1 -pathspec==0.8.0 -pycodestyle==2.6.0 -pycparser==2.20 -pyflakes==2.2.0 -pymysql==0.9.2 -pypika==0.37.6 -regex==2020.5.13 -six==1.14.0 -sniffio==1.1.0 -taskipy==1.2.1 -toml==0.10.1 --e git+https://github.com/tortoise/tortoise-orm.git@95c384a4742ee5980f8e4ae934bfdb0d8137bb40#egg=tortoise-orm -typed-ast==1.4.1 -typing-extensions==3.7.4.2 +# +# This file is autogenerated by pip-compile +# To update, run: +# +# make up +# +aiomysql==0.0.20 # via alice (setup.py) +aiosqlite==0.13.0 # via alice (setup.py) +anyio==1.3.0 # via alice (setup.py), asyncclick +async-generator==1.10 # via alice (setup.py), anyio +asyncclick==7.0.9 # via alice (setup.py) +cffi==1.14.0 # via alice (setup.py), cryptography +cryptography==2.9.2 # via alice (setup.py), pymysql +pycparser==2.20 # via alice (setup.py), cffi +pymysql==0.9.2 # via aiomysql, alice (setup.py) +pypika==0.37.6 # via alice (setup.py) +six==1.14.0 # via alice (setup.py), cryptography +sniffio==1.1.0 # via alice (setup.py), anyio +typing-extensions==3.7.4.2 # via alice (setup.py) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..8442426 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,18 @@ +[flake8] +max-line-length = 100 +exclude = +ignore = E501,W503,DAR101,DAR201,DAR402 + +[darglint] +docstring_style=sphinx + +[isort] +not_skip=__init__.py +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +use_parentheses=True +line_length=100 + + + diff --git a/setup.py b/setup.py index 9acc9ec..f15cc4c 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,8 @@ setup( }, platforms='any', keywords=( - 'migrations Tortoise-ORM mysql' + 'migrate Tortoise-ORM mysql' ), + dependency_links=['https://github.com/tortoise/tortoise-orm.git@branch#egg=tortoise-orm'], install_requires=requirements(), ) diff --git a/tests/models.py b/tests/models.py index 3d912f9..ea0311c 100644 --- a/tests/models.py +++ b/tests/models.py @@ -29,8 +29,6 @@ class User(Model): is_superuser = fields.BooleanField(default=False, description="Is SuperUser") avatar = fields.CharField(max_length=200, default="") intro = fields.TextField(default="") - created_at = fields.DatetimeField(auto_now_add=True) - updated_at = fields.DatetimeField(auto_now=True) def __str__(self): return f"{self.pk}#{self.username}"