now alice is basic worked

This commit is contained in:
long2ice 2020-05-15 10:45:40 +08:00
parent a79f5c1dc6
commit a99a06e563
14 changed files with 427 additions and 163 deletions

22
.github/workflows/pypi.yml vendored Normal file
View File

@ -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 }}

View File

@ -0,0 +1,10 @@
=========
ChangeLog
=========
0.1
===
0.1.1
-----
- Now alice is basic worked.

View File

@ -7,13 +7,44 @@ help:
@echo @echo
@echo "usage: make <target>" @echo "usage: make <target>"
@echo "Targets:" @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 " test Runs all tests"
@echo " style Auto-formats the code" @echo " style Auto-formats the code"
deps: deps:
@which pip-sync > /dev/null || pip install -q pip-tools @which pip-sync > /dev/null || pip install -q pip-tools
@pip install -r requirements-dev.txt @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 style: deps
isort -rc $(checkfiles) isort -rc $(checkfiles)
black $(black_opts) $(checkfiles) 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

View File

@ -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 <https://github.com/long2ice/alice/blob/master/LICENSE>`_ License.

View File

@ -1 +1 @@
__version__ = "0.1.0" __version__ = "0.1.1"

View File

@ -5,7 +5,7 @@ import sys
from enum import Enum from enum import Enum
import asyncclick as click 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 tortoise import Tortoise, generate_schema_for_client
from alice.migrate import Migrate from alice.migrate import Migrate
@ -23,7 +23,7 @@ class Color(str, Enum):
"--config", "--config",
default="settings", default="settings",
show_default=True, 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( @click.option(
"--tortoise-orm", "--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") raise BadOptionUsage(ctx=ctx, message=f'No module named "{config}"', option_name="--config")
config = getattr(config_module, tortoise_orm, None) config = getattr(config_module, tortoise_orm, None)
if not config: 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(): 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["config"] = config
ctx.obj["location"] = location ctx.obj["location"] = location
@ -142,7 +146,7 @@ def history(ctx):
@cli.command( @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( @click.option(
"--safe", "--safe",

View File

@ -2,10 +2,10 @@ from typing import List, Type
from tortoise import BaseDBAsyncClient, ForeignKeyFieldInstance, Model from tortoise import BaseDBAsyncClient, ForeignKeyFieldInstance, Model
from tortoise.backends.base.schema_generator import BaseSchemaGenerator 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 schema_generator_cls: Type[BaseSchemaGenerator] = BaseSchemaGenerator
DIALECT = "sql" DIALECT = "sql"
_DROP_TABLE_TEMPLATE = "DROP TABLE {table_name} IF EXISTS" _DROP_TABLE_TEMPLATE = "DROP TABLE {table_name} IF EXISTS"
@ -23,108 +23,25 @@ class DDL:
self.schema_generator = self.schema_generator_cls(client) self.schema_generator = self.schema_generator_cls(client)
def create_table(self, model: "Type[Model]"): 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]"): 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): def add_column(self, model: "Type[Model]", field_object: Field):
db_table = model._meta.db_table raise NotImplementedError
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,
),
)
def drop_column(self, model: "Type[Model]", column_name: str): def drop_column(self, model: "Type[Model]", column_name: str):
return self._DROP_COLUMN_TEMPLATE.format( raise NotImplementedError
table_name=model._meta.db_table, column_name=column_name
)
def add_index(self, model: "Type[Model]", field_names: List[str], unique=False): def add_index(self, model: "Type[Model]", field_names: List[str], unique=False):
return self._ADD_INDEX_TEMPLATE.format( raise NotImplementedError
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): def drop_index(self, model: "Type[Model]", field_names: List[str], unique=False):
return self._DROP_INDEX_TEMPLATE.format( raise NotImplementedError
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): def add_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance):
db_table = model._meta.db_table raise NotImplementedError
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,
)
def drop_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance): def drop_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance):
to_field_name = field.to_field_instance.source_field raise NotImplementedError
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,
),
)

View File

@ -1,8 +1,120 @@
from typing import List, Type
from tortoise import ForeignKeyFieldInstance, Model
from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator 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 schema_generator_cls = MySQLSchemaGenerator
DIALECT = MySQLSchemaGenerator.DIALECT 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,
),
)

View File

@ -9,7 +9,7 @@ from tortoise import BackwardFKRelation, ForeignKeyFieldInstance, Model, Tortois
from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator
from tortoise.fields import Field from tortoise.fields import Field
from alice.ddl import DDL from alice.ddl import BaseDDL
from alice.ddl.mysql import MysqlDDL from alice.ddl.mysql import MysqlDDL
from alice.exceptions import ConfigurationError from alice.exceptions import ConfigurationError
from alice.utils import get_app_connection from alice.utils import get_app_connection
@ -21,7 +21,7 @@ class Migrate:
_upgrade_fk_operators: List[str] = [] _upgrade_fk_operators: List[str] = []
_downgrade_fk_operators: List[str] = [] _downgrade_fk_operators: List[str] = []
ddl: DDL ddl: BaseDDL
migrate_config: dict migrate_config: dict
old_models = "old_models" old_models = "old_models"
diff_app = "diff_models" diff_app = "diff_models"
@ -85,6 +85,11 @@ class Migrate:
@classmethod @classmethod
def migrate(cls, name): def migrate(cls, name):
"""
diff old models and new models to generate diff content
:param name:
:return:
"""
if not cls.migrate_config: if not cls.migrate_config:
raise ConfigurationError("You must call init_with_old_models() first!") raise ConfigurationError("You must call init_with_old_models() first!")
apps = Tortoise.apps apps = Tortoise.apps
@ -103,6 +108,13 @@ class Migrate:
@classmethod @classmethod
def _add_operator(cls, operator: str, upgrade=True, fk=False): 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 upgrade:
if fk: if fk:
cls._upgrade_fk_operators.append(operator) cls._upgrade_fk_operators.append(operator)
@ -134,6 +146,13 @@ class Migrate:
@classmethod @classmethod
def _get_migrate_config(cls, config: dict, app: str, location: str): 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) temp_config = deepcopy(config)
path = os.path.join(location, app, cls.old_models) path = os.path.join(location, app, cls.old_models)
path = path.replace("/", ".").lstrip(".") path = path.replace("/", ".").lstrip(".")
@ -142,6 +161,13 @@ class Migrate:
@classmethod @classmethod
def write_old_models(cls, config: dict, app: str, location: str): 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 = [] old_model_files = []
models = config.get("apps").get(app).get("models") models = config.get("apps").get(app).get("models")
for model in models: for model in models:
@ -235,6 +261,11 @@ class Migrate:
@classmethod @classmethod
def _exclude_field(cls, field: Field): def _exclude_field(cls, field: Field):
"""
exclude BackwardFKRelation
:param field:
:return:
"""
return isinstance(field, BackwardFKRelation) return isinstance(field, BackwardFKRelation)
@classmethod @classmethod
@ -251,11 +282,23 @@ class Migrate:
return cls.ddl.drop_column(model, field.model_field_name) return cls.ddl.drop_column(model, field.model_field_name)
@classmethod @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) return cls.ddl.add_fk(model, field)
@classmethod @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) return cls.ddl.drop_fk(model, field)
@classmethod @classmethod

44
poetry.lock generated
View File

@ -259,7 +259,7 @@ description = "Alternative regular expression module, to replace re."
name = "regex" name = "regex"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "2020.5.13" version = "2020.5.14"
[[package]] [[package]]
category = "main" category = "main"
@ -470,27 +470,27 @@ pypika = [
{file = "PyPika-0.37.6.tar.gz", hash = "sha256:64510fa36667e8bb654bdc1be5a3a77bac1dbc2f03d4848efac08e39d9cac6f5"}, {file = "PyPika-0.37.6.tar.gz", hash = "sha256:64510fa36667e8bb654bdc1be5a3a77bac1dbc2f03d4848efac08e39d9cac6f5"},
] ]
regex = [ regex = [
{file = "regex-2020.5.13-cp27-cp27m-win32.whl", hash = "sha256:d20ba8d3a844d6cd9bbe127a60cc8f61cfe2d2b77da997775639999a48fbbfe3"}, {file = "regex-2020.5.14-cp27-cp27m-win32.whl", hash = "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e"},
{file = "regex-2020.5.13-cp27-cp27m-win_amd64.whl", hash = "sha256:2cdf6bb8112a6b49092a9320edc823d41b21a06c8c7ac88a845b73462193f3ac"}, {file = "regex-2020.5.14-cp27-cp27m-win_amd64.whl", hash = "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a"},
{file = "regex-2020.5.13-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9d801d3693c5a6af5a506f9905b0e6d8ae419a00054d8d80ed9d65f81fc37e1f"}, {file = "regex-2020.5.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561"},
{file = "regex-2020.5.13-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:705e334ac42cf807f33d4daafe58da33e23a93389233ab2f80f63dee09488d9b"}, {file = "regex-2020.5.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01"},
{file = "regex-2020.5.13-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:78014742b047ea2c9849e85db2dc84cad365b7f2dee404f86882d1fb9ff38df2"}, {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577"},
{file = "regex-2020.5.13-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:078024a52a72c98f157c380bea7beab7e0b907854ca337e3d4eecd44b363d4fb"}, {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd"},
{file = "regex-2020.5.13-cp36-cp36m-win32.whl", hash = "sha256:4088da3b99f1341c2904679ffbfe6f08f5cc13e5cad1c6b053728da7cf68d28c"}, {file = "regex-2020.5.14-cp36-cp36m-win32.whl", hash = "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994"},
{file = "regex-2020.5.13-cp36-cp36m-win_amd64.whl", hash = "sha256:14026bf953137a5cdc6a2a8fda314a0296ce5cd6da6e46fe79d6e03caf3c1bac"}, {file = "regex-2020.5.14-cp36-cp36m-win_amd64.whl", hash = "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1"},
{file = "regex-2020.5.13-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:03284826c5f5cd4b252ab7d510cb4d6b7e7f849cdea8e1b384c57e0996a9a3f9"}, {file = "regex-2020.5.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4"},
{file = "regex-2020.5.13-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:36e6e7ca33a70f859e532110c2b1af28f98622424681e2e158f0f49735f1a9c8"}, {file = "regex-2020.5.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4"},
{file = "regex-2020.5.13-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:707d2fcfdce12ca946830839c4c243c1b258c0d2c61350dc2efe0af00a4d2fdf"}, {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c"},
{file = "regex-2020.5.13-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:76668d1f91af08275313799bbd6ab04971ab08919defde886f5c94c7fc0f4623"}, {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f"},
{file = "regex-2020.5.13-cp37-cp37m-win32.whl", hash = "sha256:0be1cb724d43a7fb017e868d809640de03be7db88ab83d212fd802bc3d0277a0"}, {file = "regex-2020.5.14-cp37-cp37m-win32.whl", hash = "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929"},
{file = "regex-2020.5.13-cp37-cp37m-win_amd64.whl", hash = "sha256:9d42213927eede46bd4eb0c225600d82cf2b3c8882eb449f00b7cfa9bbf0975e"}, {file = "regex-2020.5.14-cp37-cp37m-win_amd64.whl", hash = "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd"},
{file = "regex-2020.5.13-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7163cac9621e9099dc8768ddec32372f50893c934be961f58826d46f0668ea0c"}, {file = "regex-2020.5.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3"},
{file = "regex-2020.5.13-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:efae79f5eb3a6e2d9fa246605870887e0187ed66a4c56fc4cf22da00aa2ec220"}, {file = "regex-2020.5.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad"},
{file = "regex-2020.5.13-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:89d4a97682170c32a13c4223e72cf75f9d0c6223b40fb4abe717bbb6c271c6ea"}, {file = "regex-2020.5.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe"},
{file = "regex-2020.5.13-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4f144eb977800d7ef593893204c2e7f1f109e8a943f6e822990d22385b12c5d6"}, {file = "regex-2020.5.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7"},
{file = "regex-2020.5.13-cp38-cp38-win32.whl", hash = "sha256:3b7f9c0051179325d7efd76271b783de593a50608e48e130c1590a95ea411f59"}, {file = "regex-2020.5.14-cp38-cp38-win32.whl", hash = "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927"},
{file = "regex-2020.5.13-cp38-cp38-win_amd64.whl", hash = "sha256:3cec763e0428beb8668edf004aa9a8a4c1b502d0ecb97dc4d77e5a67a9077186"}, {file = "regex-2020.5.14-cp38-cp38-win_amd64.whl", hash = "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108"},
{file = "regex-2020.5.13.tar.gz", hash = "sha256:cd931f9cca663617ba7a74b6500c6857405271b142edff68b2530e458b80a116"}, {file = "regex-2020.5.14.tar.gz", hash = "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5"},
] ]
six = [ six = [
{file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"},

View File

@ -1,31 +1,19 @@
aiomysql==0.0.20 #
aiosqlite==0.13.0 # This file is autogenerated by pip-compile
anyio==1.3.0 # To update, run:
appdirs==1.4.4 #
async-generator==1.10 # make up
asyncclick==7.0.9 #
asynctest==0.13.0 aiomysql==0.0.20 # via alice (setup.py)
attrs==19.3.0 aiosqlite==0.13.0 # via alice (setup.py)
black==19.10b0 anyio==1.3.0 # via alice (setup.py), asyncclick
cffi==1.14.0 async-generator==1.10 # via alice (setup.py), anyio
ciso8601==2.1.3; sys_platform != "win32" and implementation_name == "cpython" asyncclick==7.0.9 # via alice (setup.py)
click==7.1.2 cffi==1.14.0 # via alice (setup.py), cryptography
cryptography==2.9.2 cryptography==2.9.2 # via alice (setup.py), pymysql
flake8==3.8.1 pycparser==2.20 # via alice (setup.py), cffi
iso8601==0.1.12; sys_platform == "win32" or implementation_name != "cpython" pymysql==0.9.2 # via aiomysql, alice (setup.py)
isort==4.3.21 pypika==0.37.6 # via alice (setup.py)
mccabe==0.6.1 six==1.14.0 # via alice (setup.py), cryptography
pathspec==0.8.0 sniffio==1.1.0 # via alice (setup.py), anyio
pycodestyle==2.6.0 typing-extensions==3.7.4.2 # via alice (setup.py)
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

18
setup.cfg Normal file
View File

@ -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

View File

@ -37,7 +37,8 @@ setup(
}, },
platforms='any', platforms='any',
keywords=( 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(), install_requires=requirements(),
) )

View File

@ -29,8 +29,6 @@ class User(Model):
is_superuser = fields.BooleanField(default=False, description="Is SuperUser") is_superuser = fields.BooleanField(default=False, description="Is SuperUser")
avatar = fields.CharField(max_length=200, default="") avatar = fields.CharField(max_length=200, default="")
intro = fields.TextField(default="") intro = fields.TextField(default="")
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
def __str__(self): def __str__(self):
return f"{self.pk}#{self.username}" return f"{self.pk}#{self.username}"