fix fk migrate

This commit is contained in:
long2ice 2020-05-14 23:49:07 +08:00
parent 2da90ecca6
commit a79f5c1dc6
8 changed files with 681 additions and 72 deletions

View File

@ -5,18 +5,17 @@ import sys
from enum import Enum from enum import Enum
import asyncclick as click import asyncclick as click
from asyncclick import BadParameter, ClickException from asyncclick import BadOptionUsage, BadParameter, Context, UsageError
from tortoise import generate_schema_for_client, ConfigurationError, Tortoise from tortoise import Tortoise, generate_schema_for_client
from alice.migrate import Migrate from alice.migrate import Migrate
from alice.utils import get_app_connection from alice.utils import get_app_connection
sys.path.append(os.getcwd())
class Color(str, Enum): class Color(str, Enum):
green = "green" green = "green"
red = "red" red = "red"
yellow = "yellow"
@click.group(context_settings={"help_option_names": ["-h", "--help"]}) @click.group(context_settings={"help_option_names": ["-h", "--help"]})
@ -37,55 +36,55 @@ class Color(str, Enum):
) )
@click.option("--app", default="models", show_default=True, help="Tortoise-ORM app name.") @click.option("--app", default="models", show_default=True, help="Tortoise-ORM app name.")
@click.pass_context @click.pass_context
async def cli(ctx, config, tortoise_orm, location, app): async def cli(ctx: Context, config, tortoise_orm, location, app):
ctx.ensure_object(dict) ctx.ensure_object(dict)
try: try:
config_module = importlib.import_module(config) config_module = importlib.import_module(config, ".")
except ModuleNotFoundError: except ModuleNotFoundError:
raise BadParameter(param_hint=["--tortoise-orm"], message=f'No module named "{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 BadParameter( raise BadOptionUsage(f'Can\'t get "{tortoise_orm}" from module "{config_module}"', ctx=ctx)
param_hint=["--config"],
message=f'Can\'t get "{tortoise_orm}" from module "{config_module}"',
)
if app not in config.get("apps").keys(): if app not in config.get("apps").keys():
raise BadParameter(param_hint=["--app"], message=f'No app found in "{config}"') raise BadOptionUsage(f'No app found in "{config}"', ctx=ctx)
ctx.obj["config"] = config ctx.obj["config"] = config
ctx.obj["location"] = location ctx.obj["location"] = location
ctx.obj["app"] = app ctx.obj["app"] = app
try:
if ctx.invoked_subcommand == "init":
await Tortoise.init(config=config)
else:
if not os.path.isdir(location):
raise UsageError("You must exec init first", ctx=ctx)
await Migrate.init_with_old_models(config, app, location) await Migrate.init_with_old_models(config, app, location)
except ConfigurationError:
pass
@cli.command(help="Generate migrate changes file.") @cli.command(help="Generate migrate changes file.")
@click.option("--name", default="update", show_default=True, help="Migrate name.") @click.option("--name", default="update", show_default=True, help="Migrate name.")
@click.pass_context @click.pass_context
async def migrate(ctx, name): async def migrate(ctx: Context, name):
config = ctx.obj["config"] config = ctx.obj["config"]
location = ctx.obj["location"] location = ctx.obj["location"]
app = ctx.obj["app"] app = ctx.obj["app"]
ret = Migrate.migrate(name) ret = Migrate.migrate(name)
if not ret: if not ret:
click.secho("No changes detected", fg=Color.green) return click.secho("No changes detected", fg=Color.yellow)
else: Migrate.write_old_models(config, app, location)
Migrate.write_old_models(config, app, location) click.secho(f"Success migrate {ret}", fg=Color.green)
click.secho(f"Success migrate {ret}", fg=Color.green)
@cli.command(help="Upgrade to latest version.") @cli.command(help="Upgrade to latest version.")
@click.pass_context @click.pass_context
async def upgrade(ctx): async def upgrade(ctx: Context):
app = ctx.obj["app"] app = ctx.obj["app"]
config = ctx.obj["config"] config = ctx.obj["config"]
connection = get_app_connection(config, app) connection = get_app_connection(config, app)
available_versions = Migrate.get_all_version_files(is_all=False) available_versions = Migrate.get_all_version_files(is_all=False)
if not available_versions: if not available_versions:
return click.secho("No migrate items", fg=Color.green) return click.secho("No migrate items", fg=Color.yellow)
async with connection._in_transaction() as conn: async with connection._in_transaction() as conn:
for file in available_versions: for file in available_versions:
file_path = os.path.join(Migrate.migrate_location, file) file_path = os.path.join(Migrate.migrate_location, file)
@ -103,16 +102,16 @@ async def upgrade(ctx):
@cli.command(help="Downgrade to previous version.") @cli.command(help="Downgrade to previous version.")
@click.pass_context @click.pass_context
async def downgrade(ctx): async def downgrade(ctx: Context):
app = ctx.obj["app"] app = ctx.obj["app"]
config = ctx.obj["config"] config = ctx.obj["config"]
connection = get_app_connection(config, app) connection = get_app_connection(config, app)
available_versions = Migrate.get_all_version_files() available_versions = Migrate.get_all_version_files()
if not available_versions: if not available_versions:
return click.secho("No migrate items", fg=Color.green) return click.secho("No migrate items", fg=Color.yellow)
async with connection._in_transaction() as conn: async with connection._in_transaction() as conn:
for file in available_versions: for file in reversed(available_versions):
file_path = os.path.join(Migrate.migrate_location, file) file_path = os.path.join(Migrate.migrate_location, file)
with open(file_path, "r") as f: with open(file_path, "r") as f:
content = json.load(f) content = json.load(f)
@ -120,7 +119,8 @@ async def downgrade(ctx):
downgrade_query_list = content.get("downgrade") downgrade_query_list = content.get("downgrade")
for downgrade_query in downgrade_query_list: for downgrade_query in downgrade_query_list:
await conn.execute_query(downgrade_query) await conn.execute_query(downgrade_query)
else:
continue
with open(file_path, "w") as f: with open(file_path, "w") as f:
content["migrate"] = False content["migrate"] = False
json.dump(content, f, indent=4) json.dump(content, f, indent=4)
@ -129,20 +129,20 @@ async def downgrade(ctx):
@cli.command(help="Show current available heads in migrate location.") @cli.command(help="Show current available heads in migrate location.")
@click.pass_context @click.pass_context
def heads(ctx): def heads(ctx: Context):
for version in Migrate.get_all_version_files(is_all=False): for version in Migrate.get_all_version_files(is_all=False):
click.secho(version, fg=Color.green) click.secho(version, fg=Color.yellow)
@cli.command(help="List all migrate items.") @cli.command(help="List all migrate items.")
@click.pass_context @click.pass_context
def history(ctx): def history(ctx):
for version in Migrate.get_all_version_files(): for version in Migrate.get_all_version_files():
click.secho(version, fg=Color.green) click.secho(version, fg=Color.yellow)
@cli.command( @cli.command(
help="Init migrate location and generate schema, you must call first before other actions." help="Init migrate location and generate schema, you must exec first before other cmd."
) )
@click.option( @click.option(
"--safe", "--safe",
@ -152,7 +152,7 @@ def history(ctx):
show_default=True, show_default=True,
) )
@click.pass_context @click.pass_context
async def init(ctx, safe): async def init(ctx: Context, safe):
location = ctx.obj["location"] location = ctx.obj["location"]
app = ctx.obj["app"] app = ctx.obj["app"]
config = ctx.obj["config"] config = ctx.obj["config"]
@ -165,15 +165,16 @@ async def init(ctx, safe):
os.mkdir(dirname) os.mkdir(dirname)
click.secho(f"Success create migrate location {dirname}", fg=Color.green) click.secho(f"Success create migrate location {dirname}", fg=Color.green)
else: else:
raise ClickException(f"Already inited app `{app}`") return click.secho(f'Already inited app "{app}"', fg=Color.yellow)
Migrate.write_old_models(config, app, location) Migrate.write_old_models(config, app, location)
await Migrate.init_with_old_models(config, app, location) connection = get_app_connection(config, app)
await generate_schema_for_client(get_app_connection(config, app), safe) await generate_schema_for_client(connection, safe)
click.secho(f"Success init for app `{app}`", fg=Color.green) return click.secho(f'Success init for app "{app}"', fg=Color.green)
def main(): def main():
sys.path.insert(0, ".")
cli(_anyio_backend="asyncio") cli(_anyio_backend="asyncio")

View File

@ -101,14 +101,14 @@ class DDL:
fk_name = self.schema_generator._generate_fk_name( fk_name = self.schema_generator._generate_fk_name(
from_table=db_table, from_table=db_table,
from_field=field.model_field_name, from_field=field.source_field or field.model_field_name + "_id",
to_table=field.related_model._meta.db_table, to_table=field.related_model._meta.db_table,
to_field=to_field_name, to_field=to_field_name,
) )
return self._ADD_FK_TEMPLATE.format( return self._ADD_FK_TEMPLATE.format(
table_name=db_table, table_name=db_table,
fk_name=fk_name, fk_name=fk_name,
db_column=field.model_field_name, db_column=field.source_field or field.model_field_name + "_id",
table=field.related_model._meta.db_table, table=field.related_model._meta.db_table,
field=to_field_name, field=to_field_name,
on_delete=field.on_delete, on_delete=field.on_delete,
@ -118,11 +118,12 @@ class DDL:
to_field_name = field.to_field_instance.source_field to_field_name = field.to_field_instance.source_field
if not to_field_name: if not to_field_name:
to_field_name = field.to_field_instance.model_field_name to_field_name = field.to_field_instance.model_field_name
db_table = model._meta.db_table
return self._DROP_FK_TEMPLATE.format( return self._DROP_FK_TEMPLATE.format(
table_name=model._meta.db_table, table_name=db_table,
fk_name=self.schema_generator._generate_fk_name( fk_name=self.schema_generator._generate_fk_name(
from_table=model._meta.db_table, from_table=db_table,
from_field=field.model_field_name, from_field=field.source_field or field.model_field_name + "_id",
to_table=field.related_model._meta.db_table, to_table=field.related_model._meta.db_table,
to_field=to_field_name, to_field=to_field_name,
), ),

View File

@ -5,7 +5,7 @@ from copy import deepcopy
from datetime import datetime from datetime import datetime
from typing import Dict, List, Type from typing import Dict, List, Type
from tortoise import ForeignKeyFieldInstance, Model, Tortoise from tortoise import BackwardFKRelation, ForeignKeyFieldInstance, Model, Tortoise
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
@ -18,6 +18,9 @@ from alice.utils import get_app_connection
class Migrate: class Migrate:
upgrade_operators: List[str] = [] upgrade_operators: List[str] = []
downgrade_operators: List[str] = [] downgrade_operators: List[str] = []
_upgrade_fk_operators: List[str] = []
_downgrade_fk_operators: List[str] = []
ddl: DDL ddl: DDL
migrate_config: dict migrate_config: dict
old_models = "old_models" old_models = "old_models"
@ -73,7 +76,7 @@ class Migrate:
filename = f"{cls._get_latest_version() + 1}_{now}_{name}.json" filename = f"{cls._get_latest_version() + 1}_{now}_{name}.json"
content = { content = {
"upgrade": cls.upgrade_operators, "upgrade": cls.upgrade_operators,
"download": cls.downgrade_operators, "downgrade": cls.downgrade_operators,
"migrate": False, "migrate": False,
} }
with open(os.path.join(cls.migrate_location, filename), "w") as f: with open(os.path.join(cls.migrate_location, filename), "w") as f:
@ -94,18 +97,26 @@ class Migrate:
if not cls.upgrade_operators: if not cls.upgrade_operators:
return False return False
cls._merge_operators()
return cls._generate_diff_sql(name) return cls._generate_diff_sql(name)
@classmethod @classmethod
def _add_operator(cls, operator: str, upgrade=True): def _add_operator(cls, operator: str, upgrade=True, fk=False):
if upgrade: if upgrade:
cls.upgrade_operators.append(operator) if fk:
cls._upgrade_fk_operators.append(operator)
else:
cls.upgrade_operators.append(operator)
else: else:
cls.downgrade_operators.append(operator) if fk:
cls._downgrade_fk_operators.append(operator)
else:
cls.downgrade_operators.append(operator)
@classmethod @classmethod
def cp_models( def cp_models(
cls, model_files: List[str], old_model_file, cls, model_files: List[str], old_model_file,
): ):
""" """
cp currents models to old_model_files cp currents models to old_model_files
@ -113,13 +124,11 @@ class Migrate:
:param old_model_file: :param old_model_file:
:return: :return:
""" """
pattern = ( pattern = r"(ManyToManyField|ForeignKeyField|OneToOneField)\(('|\")(\w+)."
r"(ManyToManyField|ForeignKeyField|OneToOneField)\((model_name)?(\"|\')(\w+)(.+)\)"
)
for i, model_file in enumerate(model_files): for i, model_file in enumerate(model_files):
with open(model_file, "r") as f: with open(model_file, "r") as f:
content = f.read() content = f.read()
ret = re.sub(pattern, rf"\1\2(\3{cls.diff_app}\5)", content) ret = re.sub(pattern, rf"\1(\2{cls.diff_app}.", content)
with open(old_model_file, "w" if i == 0 else "w+a") as f: with open(old_model_file, "w" if i == 0 else "w+a") as f:
f.write(ret) f.write(ret)
@ -142,7 +151,7 @@ class Migrate:
@classmethod @classmethod
def _diff_models( def _diff_models(
cls, old_models: Dict[str, Type[Model]], new_models: Dict[str, Type[Model]], upgrade=True cls, old_models: Dict[str, Type[Model]], new_models: Dict[str, Type[Model]], upgrade=True
): ):
""" """
diff models and add operators diff models and add operators
@ -184,18 +193,37 @@ class Migrate:
new_keys = new_fields_map.keys() new_keys = new_fields_map.keys()
for new_key in new_keys: for new_key in new_keys:
new_field = new_fields_map.get(new_key) new_field = new_fields_map.get(new_key)
if cls._exclude_field(new_field):
continue
if new_key not in old_keys: if new_key not in old_keys:
cls._add_operator(cls._add_field(new_model, new_field), upgrade) cls._add_operator(
cls._add_field(new_model, new_field),
upgrade,
isinstance(new_field, ForeignKeyFieldInstance),
)
else: else:
old_field = old_fields_map.get(new_key) old_field = old_fields_map.get(new_key)
if old_field.index and not new_field.index: if old_field.index and not new_field.index:
cls._add_operator(cls._remove_index(old_model, old_field), upgrade) cls._add_operator(
cls._remove_index(old_model, old_field),
upgrade,
isinstance(old_field, ForeignKeyFieldInstance),
)
elif new_field.index and not old_field.index: elif new_field.index and not old_field.index:
cls._add_operator(cls._add_index(new_model, new_field), upgrade) cls._add_operator(
cls._add_index(new_model, new_field),
upgrade,
isinstance(new_field, ForeignKeyFieldInstance),
)
for old_key in old_keys: for old_key in old_keys:
if old_key not in new_keys: field = old_fields_map.get(old_key)
field = old_fields_map.get(old_key) if old_key not in new_keys and not cls._exclude_field(field):
cls._add_operator(cls._remove_field(old_model, field), upgrade) cls._add_operator(
cls._remove_field(old_model, field),
upgrade,
isinstance(field, ForeignKeyFieldInstance),
)
@classmethod @classmethod
def _remove_index(cls, model: Type[Model], field: Field): def _remove_index(cls, model: Type[Model], field: Field):
@ -205,6 +233,10 @@ class Migrate:
def _add_index(cls, model: Type[Model], field: Field): def _add_index(cls, model: Type[Model], field: Field):
return cls.ddl.add_index(model, [field.model_field_name], field.unique) return cls.ddl.add_index(model, [field.model_field_name], field.unique)
@classmethod
def _exclude_field(cls, field: Field):
return isinstance(field, BackwardFKRelation)
@classmethod @classmethod
def _add_field(cls, model: Type[Model], field: Field): def _add_field(cls, model: Type[Model], field: Field):
if isinstance(field, ForeignKeyFieldInstance): if isinstance(field, ForeignKeyFieldInstance):
@ -217,3 +249,28 @@ class Migrate:
if isinstance(field, ForeignKeyFieldInstance): if isinstance(field, ForeignKeyFieldInstance):
return cls.ddl.drop_fk(model, field) return cls.ddl.drop_fk(model, field)
return cls.ddl.drop_column(model, field.model_field_name) return cls.ddl.drop_column(model, field.model_field_name)
@classmethod
def _add_fk(cls, model: Type[Model], field: Field):
return cls.ddl.add_fk(model, field)
@classmethod
def _remove_fk(cls, model: Type[Model], field: Field):
return cls.ddl.drop_fk(model, field)
@classmethod
def _merge_operators(cls):
"""
fk must be last when add,first when drop
:return:
"""
for _upgrade_fk_operator in cls._upgrade_fk_operators:
if "ADD" in _upgrade_fk_operator:
cls.upgrade_operators.append(_upgrade_fk_operator)
else:
cls.upgrade_operators.insert(0, _upgrade_fk_operator)
for _downgrade_fk_operator in cls._downgrade_fk_operators:
if "ADD" in _downgrade_fk_operator:
cls.downgrade_operators.append(_downgrade_fk_operator)
else:
cls.downgrade_operators.insert(0, _downgrade_fk_operator)

539
poetry.lock generated Normal file
View File

@ -0,0 +1,539 @@
[[package]]
category = "main"
description = "MySQL driver for asyncio."
name = "aiomysql"
optional = false
python-versions = "*"
version = "0.0.20"
[package.dependencies]
PyMySQL = ">=0.9,<=0.9.2"
[package.extras]
sa = ["sqlalchemy (>=1.0)"]
[[package]]
category = "main"
description = "asyncio bridge to the standard sqlite3 module"
name = "aiosqlite"
optional = false
python-versions = ">=3.6"
version = "0.13.0"
[[package]]
category = "main"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
name = "anyio"
optional = false
python-versions = ">=3.5.3"
version = "1.3.0"
[package.dependencies]
async-generator = "*"
sniffio = ">=1.1"
[package.extras]
curio = ["curio (>=0.9)"]
doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
test = ["coverage (>=4.5)", "hypothesis (>=4.0)", "pytest (>=3.7.2)", "uvloop"]
trio = ["trio (>=0.12)"]
[[package]]
category = "dev"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
name = "appdirs"
optional = false
python-versions = "*"
version = "1.4.4"
[[package]]
category = "main"
description = "Async generators and context managers for Python 3.5+"
name = "async-generator"
optional = false
python-versions = ">=3.5"
version = "1.10"
[[package]]
category = "main"
description = "A simple anyio-compatible fork of Click, for powerful command line utilities."
name = "asyncclick"
optional = false
python-versions = ">=3.6"
version = "7.0.9"
[package.dependencies]
anyio = "*"
[package.extras]
dev = ["coverage", "pytest-runner", "pytest-trio", "pytest (>=3)", "sphinx", "tox"]
docs = ["sphinx"]
[[package]]
category = "dev"
description = "Enhance the standard unittest package with features for testing asyncio libraries"
name = "asynctest"
optional = false
python-versions = ">=3.5"
version = "0.13.0"
[[package]]
category = "dev"
description = "Classes Without Boilerplate"
name = "attrs"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "19.3.0"
[package.extras]
azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"]
docs = ["sphinx", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
[[package]]
category = "dev"
description = "The uncompromising code formatter."
name = "black"
optional = false
python-versions = ">=3.6"
version = "19.10b0"
[package.dependencies]
appdirs = "*"
attrs = ">=18.1.0"
click = ">=6.5"
pathspec = ">=0.6,<1"
regex = "*"
toml = ">=0.9.4"
typed-ast = ">=1.4.0"
[package.extras]
d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
[[package]]
category = "main"
description = "Foreign Function Interface for Python calling C code."
name = "cffi"
optional = false
python-versions = "*"
version = "1.14.0"
[package.dependencies]
pycparser = "*"
[[package]]
category = "main"
description = "Fast ISO8601 date time parser for Python written in C"
marker = "sys_platform != \"win32\" and implementation_name == \"cpython\""
name = "ciso8601"
optional = false
python-versions = "*"
version = "2.1.3"
[[package]]
category = "dev"
description = "Composable command line interface toolkit"
name = "click"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "7.1.2"
[[package]]
category = "main"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
name = "cryptography"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
version = "2.9.2"
[package.dependencies]
cffi = ">=1.8,<1.11.3 || >1.11.3"
six = ">=1.4.1"
[package.extras]
docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"]
docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
idna = ["idna (>=2.1)"]
pep8test = ["flake8", "flake8-import-order", "pep8-naming"]
test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"]
[[package]]
category = "dev"
description = "the modular source code checker: pep8 pyflakes and co"
name = "flake8"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
version = "3.8.1"
[package.dependencies]
mccabe = ">=0.6.0,<0.7.0"
pycodestyle = ">=2.6.0a1,<2.7.0"
pyflakes = ">=2.2.0,<2.3.0"
[[package]]
category = "main"
description = "Simple module to parse ISO 8601 dates"
marker = "sys_platform == \"win32\" or implementation_name != \"cpython\""
name = "iso8601"
optional = false
python-versions = "*"
version = "0.1.12"
[[package]]
category = "dev"
description = "A Python utility / library to sort Python imports."
name = "isort"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "4.3.21"
[package.extras]
pipfile = ["pipreqs", "requirementslib"]
pyproject = ["toml"]
requirements = ["pipreqs", "pip-api"]
xdg_home = ["appdirs (>=1.4.0)"]
[[package]]
category = "dev"
description = "McCabe checker, plugin for flake8"
name = "mccabe"
optional = false
python-versions = "*"
version = "0.6.1"
[[package]]
category = "dev"
description = "Utility library for gitignore style pattern matching of file paths."
name = "pathspec"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "0.8.0"
[[package]]
category = "dev"
description = "Python style guide checker"
name = "pycodestyle"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.6.0"
[[package]]
category = "main"
description = "C parser in Python"
name = "pycparser"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.20"
[[package]]
category = "dev"
description = "passive checker of Python programs"
name = "pyflakes"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.2.0"
[[package]]
category = "main"
description = "Pure Python MySQL Driver"
name = "pymysql"
optional = false
python-versions = "*"
version = "0.9.2"
[package.dependencies]
cryptography = "*"
[[package]]
category = "main"
description = "A SQL query builder API for Python"
name = "pypika"
optional = false
python-versions = "*"
version = "0.37.6"
[[package]]
category = "dev"
description = "Alternative regular expression module, to replace re."
name = "regex"
optional = false
python-versions = "*"
version = "2020.5.13"
[[package]]
category = "main"
description = "Python 2 and 3 compatibility utilities"
name = "six"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
version = "1.14.0"
[[package]]
category = "main"
description = "Sniff out which async library your code is running under"
name = "sniffio"
optional = false
python-versions = ">=3.5"
version = "1.1.0"
[[package]]
category = "dev"
description = "tasks runner for python projects"
name = "taskipy"
optional = false
python-versions = ">=3.6,<4.0"
version = "1.2.1"
[package.dependencies]
toml = ">=0.10.0,<0.11.0"
[[package]]
category = "dev"
description = "Python Library for Tom's Obvious, Minimal Language"
name = "toml"
optional = false
python-versions = "*"
version = "0.10.1"
[[package]]
category = "main"
description = "Easy async ORM for python, built with relations in mind"
name = "tortoise-orm"
optional = false
python-versions = "*"
version = "0.16.11"
[package.dependencies]
aiosqlite = ">=0.11.0"
ciso8601 = ">=2.1.2"
iso8601 = ">=0.1.12"
pypika = ">=0.36.5"
typing-extensions = ">=3.7"
[package.source]
reference = "95c384a4742ee5980f8e4ae934bfdb0d8137bb40"
type = "git"
url = "https://github.com/tortoise/tortoise-orm.git"
[[package]]
category = "dev"
description = "a fork of Python 2 and 3 ast modules with type comment support"
name = "typed-ast"
optional = false
python-versions = "*"
version = "1.4.1"
[[package]]
category = "main"
description = "Backported and Experimental Type Hints for Python 3.5+"
name = "typing-extensions"
optional = false
python-versions = "*"
version = "3.7.4.2"
[metadata]
content-hash = "9ce51215dcc82924bab54fca5ee46097cb5ccc2f6ecd455994b9b9f37b801523"
python-versions = "^3.8"
[metadata.files]
aiomysql = [
{file = "aiomysql-0.0.20-py3-none-any.whl", hash = "sha256:5fd798481f16625b424eec765c56d712ac78a51f3bd0175a3de94107aae43307"},
{file = "aiomysql-0.0.20.tar.gz", hash = "sha256:d89ce25d44dadb43cf2d9e4603bd67b7a0ad12d5e67208de013629ba648df2ba"},
]
aiosqlite = [
{file = "aiosqlite-0.13.0-py3-none-any.whl", hash = "sha256:50688c40632ae249f986ab3ae2c66a45c0535b84a5d4aae0e0be572b5fed6909"},
{file = "aiosqlite-0.13.0.tar.gz", hash = "sha256:6e92961ae9e606b43b05e29b129e346b29e400fcbd63e3c0c564d89230257645"},
]
anyio = [
{file = "anyio-1.3.0-py3-none-any.whl", hash = "sha256:db2c3d21576870b95d4fd0b8f4a0f9c64057f777c578f3a8127179a17c8c067e"},
{file = "anyio-1.3.0.tar.gz", hash = "sha256:7deae0315dd10aa41c21528b83352e4b52f44e6153a21081a3d1cd8c03728e46"},
]
appdirs = [
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
]
async-generator = [
{file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"},
{file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"},
]
asyncclick = [
{file = "asyncclick-7.0.9.tar.gz", hash = "sha256:62cebf3eca36d973802e2dd521ca1db11c5bf4544e9795e093d1a53cb688a8c2"},
]
asynctest = [
{file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"},
{file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"},
]
attrs = [
{file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
{file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
]
black = [
{file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"},
{file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"},
]
cffi = [
{file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"},
{file = "cffi-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30"},
{file = "cffi-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"},
{file = "cffi-1.14.0-cp27-cp27m-win32.whl", hash = "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78"},
{file = "cffi-1.14.0-cp27-cp27m-win_amd64.whl", hash = "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793"},
{file = "cffi-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e"},
{file = "cffi-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a"},
{file = "cffi-1.14.0-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff"},
{file = "cffi-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f"},
{file = "cffi-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa"},
{file = "cffi-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5"},
{file = "cffi-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4"},
{file = "cffi-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d"},
{file = "cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc"},
{file = "cffi-1.14.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac"},
{file = "cffi-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f"},
{file = "cffi-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b"},
{file = "cffi-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3"},
{file = "cffi-1.14.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66"},
{file = "cffi-1.14.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0"},
{file = "cffi-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f"},
{file = "cffi-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26"},
{file = "cffi-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd"},
{file = "cffi-1.14.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55"},
{file = "cffi-1.14.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2"},
{file = "cffi-1.14.0-cp38-cp38-win32.whl", hash = "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8"},
{file = "cffi-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b"},
{file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"},
]
ciso8601 = [
{file = "ciso8601-2.1.3.tar.gz", hash = "sha256:bdbb5b366058b1c87735603b23060962c439ac9be66f1ae91e8c7dbd7d59e262"},
]
click = [
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
]
cryptography = [
{file = "cryptography-2.9.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e"},
{file = "cryptography-2.9.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b"},
{file = "cryptography-2.9.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365"},
{file = "cryptography-2.9.2-cp27-cp27m-win32.whl", hash = "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"},
{file = "cryptography-2.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55"},
{file = "cryptography-2.9.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270"},
{file = "cryptography-2.9.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf"},
{file = "cryptography-2.9.2-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d"},
{file = "cryptography-2.9.2-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785"},
{file = "cryptography-2.9.2-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b"},
{file = "cryptography-2.9.2-cp35-cp35m-win32.whl", hash = "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae"},
{file = "cryptography-2.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b"},
{file = "cryptography-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6"},
{file = "cryptography-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3"},
{file = "cryptography-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b"},
{file = "cryptography-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e"},
{file = "cryptography-2.9.2-cp38-cp38-win32.whl", hash = "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0"},
{file = "cryptography-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5"},
{file = "cryptography-2.9.2.tar.gz", hash = "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229"},
]
flake8 = [
{file = "flake8-3.8.1-py2.py3-none-any.whl", hash = "sha256:6c1193b0c3f853ef763969238f6c81e9e63ace9d024518edc020d5f1d6d93195"},
{file = "flake8-3.8.1.tar.gz", hash = "sha256:ea6623797bf9a52f4c9577d780da0bb17d65f870213f7b5bcc9fca82540c31d5"},
]
iso8601 = [
{file = "iso8601-0.1.12-py2.py3-none-any.whl", hash = "sha256:210e0134677cc0d02f6028087fee1df1e1d76d372ee1db0bf30bf66c5c1c89a3"},
{file = "iso8601-0.1.12-py3-none-any.whl", hash = "sha256:bbbae5fb4a7abfe71d4688fd64bff70b91bbd74ef6a99d964bab18f7fdf286dd"},
{file = "iso8601-0.1.12.tar.gz", hash = "sha256:49c4b20e1f38aa5cf109ddcd39647ac419f928512c869dc01d5c7098eddede82"},
]
isort = [
{file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"},
{file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"},
]
mccabe = [
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
]
pathspec = [
{file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"},
{file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"},
]
pycodestyle = [
{file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"},
{file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"},
]
pycparser = [
{file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"},
{file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
]
pyflakes = [
{file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"},
{file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"},
]
pymysql = [
{file = "PyMySQL-0.9.2-py2.py3-none-any.whl", hash = "sha256:95f057328357e0e13a30e67857a8c694878b0175797a9a203ee7adbfb9b1ec5f"},
{file = "PyMySQL-0.9.2.tar.gz", hash = "sha256:9ec760cbb251c158c19d6c88c17ca00a8632bac713890e465b2be01fdc30713f"},
]
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"},
]
six = [
{file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"},
{file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"},
]
sniffio = [
{file = "sniffio-1.1.0-py3-none-any.whl", hash = "sha256:20ed6d5b46f8ae136d00b9dcb807615d83ed82ceea6b2058cecb696765246da5"},
{file = "sniffio-1.1.0.tar.gz", hash = "sha256:8e3810100f69fe0edd463d02ad407112542a11ffdc29f67db2bf3771afb87a21"},
]
taskipy = [
{file = "taskipy-1.2.1-py3-none-any.whl", hash = "sha256:99bdaf5b19791c2345806847147e0fc2d28e1ac9446058def5a8b6b3fc9f23e2"},
{file = "taskipy-1.2.1.tar.gz", hash = "sha256:5eb2c3b1606c896c7fa799848e71e8883b880759224958d07ba760e5db263175"},
]
toml = [
{file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"},
{file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"},
]
tortoise-orm = []
typed-ast = [
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"},
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"},
{file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"},
{file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"},
{file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"},
{file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"},
{file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"},
{file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"},
{file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"},
{file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"},
{file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"},
{file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"},
{file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"},
{file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"},
{file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"},
{file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"},
{file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"},
{file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"},
{file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"},
{file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"},
{file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"},
]
typing-extensions = [
{file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"},
{file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"},
{file = "typing_extensions-3.7.4.2.tar.gz", hash = "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae"},
]

View File

@ -15,12 +15,13 @@ taskipy = "*"
asynctest = "*" asynctest = "*"
flake8 = "*" flake8 = "*"
isort = "*" isort = "*"
black = "*" black = "^19.10b0"
[tool.taskipy.tasks]
export = "poetry export -f requirements.txt --without-hashes > requirements.txt"
export-dev = "poetry export -f requirements.txt --dev --without-hashes > requirements-dev.txt"
[build-system] [build-system]
requires = ["poetry>=0.12"] requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api" build-backend = "poetry.masonry.api"
[tool.taskipy.tasks]
export = "poetry export -f requirements.txt --without-hashes > requirements.txt"
export-dev = "poetry export -f requirements.txt --dev --without-hashes > requirements-dev.txt"

View File

@ -1,24 +1,31 @@
aiomysql==0.0.20 aiomysql==0.0.20
aiosqlite==0.13.0 aiosqlite==0.13.0
anyio==1.3.0 anyio==1.3.0
appdirs==1.4.4
async-generator==1.10 async-generator==1.10
asyncclick==7.0.9 asyncclick==7.0.9
asynctest==0.13.0 asynctest==0.13.0
attrs==19.3.0
black==19.10b0
cffi==1.14.0 cffi==1.14.0
ciso8601==2.1.3; sys_platform != "win32" and implementation_name == "cpython" ciso8601==2.1.3; sys_platform != "win32" and implementation_name == "cpython"
click==7.1.2
cryptography==2.9.2 cryptography==2.9.2
flake8==3.8.1 flake8==3.8.1
iso8601==0.1.12; sys_platform == "win32" or implementation_name != "cpython" iso8601==0.1.12; sys_platform == "win32" or implementation_name != "cpython"
isort==4.3.21 isort==4.3.21
mccabe==0.6.1 mccabe==0.6.1
pathspec==0.8.0
pycodestyle==2.6.0 pycodestyle==2.6.0
pycparser==2.20 pycparser==2.20
pyflakes==2.2.0 pyflakes==2.2.0
pymysql==0.9.2 pymysql==0.9.2
pypika==0.37.6 pypika==0.37.6
regex==2020.5.13
six==1.14.0 six==1.14.0
sniffio==1.1.0 sniffio==1.1.0
taskipy==1.2.1 taskipy==1.2.1
toml==0.10.1 toml==0.10.1
-e git+https://github.com/tortoise/tortoise-orm.git@95c384a4742ee5980f8e4ae934bfdb0d8137bb40#egg=tortoise-orm -e git+https://github.com/tortoise/tortoise-orm.git@95c384a4742ee5980f8e4ae934bfdb0d8137bb40#egg=tortoise-orm
typed-ast==1.4.1
typing-extensions==3.7.4.2 typing-extensions==3.7.4.2

View File

@ -1,6 +1,17 @@
from tests.backends.mysql import DBTestCase from asynctest import TestCase
from tortoise import Tortoise
from alice.migrate import Migrate
from tests.backends.mysql import TORTOISE_ORM
class TestMigrate(DBTestCase): class TestMigrate(TestCase):
async def setUp(self) -> None:
await Migrate.init_with_old_models(TORTOISE_ORM, "models", "./migrations")
async def test_migrate(self): async def test_migrate(self):
pass Migrate.diff_model(
Tortoise.apps.get("models").get("Category"),
Tortoise.apps.get("diff_models").get("Category"),
)
print(Migrate.upgrade_operators)

View File

@ -9,11 +9,3 @@ commands=
make ci make ci
deps = deps =
-r requirements-dev.txt -r requirements-dev.txt
[testenv:pypy3]
deps =
-r tests/requirements-pypy.txt
setenv =
PYTEST_ADDOPTS="--no-cov"
commands=
make _testall