From 10b7272ca8071ebb7265118b9cdac60e07da4229 Mon Sep 17 00:00:00 2001 From: - <-> Date: Thu, 10 Jun 2021 16:52:03 +0200 Subject: [PATCH 1/4] Added an configuration option to specify the path of the source folder. This will make aerich work with various folder structures (e.g. ./src/MyPythonModule) Additionally this will try to import in init and show the user the error message on failure. --- aerich/cli.py | 27 ++++++++++++++++++++++----- aerich/utils.py | 27 +++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/aerich/cli.py b/aerich/cli.py index 8625a73..6e8a82e 100644 --- a/aerich/cli.py +++ b/aerich/cli.py @@ -1,6 +1,5 @@ import asyncio import os -import sys from configparser import ConfigParser from functools import wraps from pathlib import Path @@ -16,6 +15,7 @@ from tortoise.utils import get_schema_sql from aerich.inspectdb import InspectDb from aerich.migrate import Migrate from aerich.utils import ( + add_src_path, get_app_connection, get_app_connection_name, get_models_describe, @@ -23,7 +23,6 @@ from aerich.utils import ( get_version_content_from_file, write_version_file, ) - from . import __version__ from .enums import Color from .models import Aerich @@ -74,6 +73,10 @@ async def cli(ctx: Context, config, app, name): location = parser[name]["location"] tortoise_orm = parser[name]["tortoise_orm"] + src_folder = parser[name]["src_folder"] + + # Add specified source folder to path + add_src_path(src_folder) tortoise_config = get_tortoise_config(ctx, tortoise_orm) app = app or list(tortoise_config.get("apps").keys())[0] @@ -214,19 +217,34 @@ async def history(ctx: Context): @click.option( "--location", default="./migrations", show_default=True, help="Migrate store location.", ) +@click.option( + "-s", + "--src_folder", default=".", show_default=False, help="Folder of the source, relative to the project root." +) @click.pass_context @coro async def init( - ctx: Context, tortoise_orm, location, + ctx: Context, tortoise_orm, location, src_folder ): config_file = ctx.obj["config_file"] name = ctx.obj["name"] if Path(config_file).exists(): - return click.secho("You have inited", fg=Color.yellow) + return click.secho("Configuration file already created", fg=Color.yellow) + + if os.path.isabs(src_folder): + src_folder = os.path.relpath(os.getcwd(), src_folder) + # Add ./ so it's clear that this is relative path + if not src_folder.startswith('./'): + src_folder = './' + src_folder + + # check that we can find the configuration, if not we can fail before the config file gets created + add_src_path(src_folder) + get_tortoise_config(ctx, tortoise_orm) parser.add_section(name) parser.set(name, "tortoise_orm", tortoise_orm) parser.set(name, "location", location) + parser.set(name, "src_folder", src_folder) with open(config_file, "w", encoding="utf-8") as f: parser.write(f) @@ -294,7 +312,6 @@ async def inspectdb(ctx: Context, table: List[str]): def main(): - sys.path.insert(0, ".") cli() diff --git a/aerich/utils.py b/aerich/utils.py index 5b32599..e289b77 100644 --- a/aerich/utils.py +++ b/aerich/utils.py @@ -1,12 +1,30 @@ import importlib +import os import re +import sys from pathlib import Path from typing import Dict -from click import BadOptionUsage, Context +from click import BadOptionUsage, Context, ClickException from tortoise import BaseDBAsyncClient, Tortoise +def add_src_path(path: str) -> str: + """ + add a folder to the paths so we can import from there + :param path: path to add + :return: absolute path + """ + if not os.path.isabs(path): + # use the absolute path, otherwise some other things (e.g. __file__) won't work properly + path = os.path.abspath(path) + if not os.path.isdir(path): + raise ClickException(f"Specified source folder does not exist: {path}") + if path not in sys.path: + sys.path.insert(0, path) + return path + + def get_app_connection_name(config, app_name: str) -> str: """ get connection name @@ -42,7 +60,12 @@ def get_tortoise_config(ctx: Context, tortoise_orm: str) -> dict: splits = tortoise_orm.split(".") config_path = ".".join(splits[:-1]) tortoise_config = splits[-1] - config_module = importlib.import_module(config_path) + + try: + config_module = importlib.import_module(config_path) + except ModuleNotFoundError as e: + raise ClickException(f'Error while importing configuration module: {e}') from None + config = getattr(config_module, tortoise_config, None) if not config: raise BadOptionUsage( From 8e783e031e9ea0776fa3d8167a965ebbc5cfad36 Mon Sep 17 00:00:00 2001 From: - <-> Date: Thu, 10 Jun 2021 16:56:30 +0200 Subject: [PATCH 2/4] updated readme --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 076f131..3264037 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,12 @@ Just install from pypi: Usage: aerich [OPTIONS] COMMAND [ARGS]... Options: + -V, --version Show the version and exit. -c, --config TEXT Config file. [default: aerich.ini] - --app TEXT Tortoise-ORM app name. [default: models] + --app TEXT Tortoise-ORM app name. -n, --name TEXT Name of section in .ini file to use for aerich config. [default: aerich] + -h, --help Show this message and exit. Commands: @@ -40,7 +42,7 @@ Commands: init-db Generate schema and generate app migrate location. inspectdb Introspects the database tables to standard output as... migrate Generate migrate changes file. - upgrade Upgrade to latest version. + upgrade Upgrade to specified version. ``` ## Usage @@ -68,10 +70,12 @@ Usage: aerich init [OPTIONS] Init config file and generate root migrate location. -Options: - -t, --tortoise-orm TEXT Tortoise-ORM config module dict variable, like settings.TORTOISE_ORM. - [required] +OOptions: + -t, --tortoise-orm TEXT Tortoise-ORM config module dict variable, like + settings.TORTOISE_ORM. [required] + --location TEXT Migrate store location. [default: ./migrations] + -s, --src_folder TEXT Folder of the source, relative to the project root. -h, --help Show this message and exit. ``` From 185514f71113f2e0f8250e1458240b2170f174bf Mon Sep 17 00:00:00 2001 From: - <-> Date: Fri, 11 Jun 2021 15:18:06 +0200 Subject: [PATCH 3/4] reformatted with black --- aerich/cli.py | 38 +++++++++++++++++++++++++++----------- aerich/utils.py | 5 +++-- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/aerich/cli.py b/aerich/cli.py index 6e8a82e..63bc522 100644 --- a/aerich/cli.py +++ b/aerich/cli.py @@ -48,7 +48,11 @@ def coro(f): @click.group(context_settings={"help_option_names": ["-h", "--help"]}) @click.version_option(__version__, "-V", "--version") @click.option( - "-c", "--config", default="aerich.ini", show_default=True, help="Config file.", + "-c", + "--config", + default="aerich.ini", + show_default=True, + help="Config file.", ) @click.option("--app", required=False, help="Tortoise-ORM app name.") @click.option( @@ -121,7 +125,9 @@ async def upgrade(ctx: Context): for upgrade_query in upgrade_query_list: await conn.execute_script(upgrade_query) await Aerich.create( - version=version_file, app=app, content=get_models_describe(app), + version=version_file, + app=app, + content=get_models_describe(app), ) click.secho(f"Success upgrade {version_file}", fg=Color.green) migrated = True @@ -215,17 +221,21 @@ async def history(ctx: Context): help="Tortoise-ORM config module dict variable, like settings.TORTOISE_ORM.", ) @click.option( - "--location", default="./migrations", show_default=True, help="Migrate store location.", + "--location", + default="./migrations", + show_default=True, + help="Migrate store location.", ) @click.option( "-s", - "--src_folder", default=".", show_default=False, help="Folder of the source, relative to the project root." + "--src_folder", + default=".", + show_default=False, + help="Folder of the source, relative to the project root.", ) @click.pass_context @coro -async def init( - ctx: Context, tortoise_orm, location, src_folder -): +async def init(ctx: Context, tortoise_orm, location, src_folder): config_file = ctx.obj["config_file"] name = ctx.obj["name"] if Path(config_file).exists(): @@ -234,8 +244,8 @@ async def init( if os.path.isabs(src_folder): src_folder = os.path.relpath(os.getcwd(), src_folder) # Add ./ so it's clear that this is relative path - if not src_folder.startswith('./'): - src_folder = './' + src_folder + if not src_folder.startswith("./"): + src_folder = "./" + src_folder # check that we can find the configuration, if not we can fail before the config file gets created add_src_path(src_folder) @@ -287,7 +297,9 @@ async def init_db(ctx: Context, safe): version = await Migrate.generate_version() await Aerich.create( - version=version, app=app, content=get_models_describe(app), + version=version, + app=app, + content=get_models_describe(app), ) content = { "upgrade": [schema], @@ -298,7 +310,11 @@ async def init_db(ctx: Context, safe): @cli.command(help="Introspects the database tables to standard output as TortoiseORM model.") @click.option( - "-t", "--table", help="Which tables to inspect.", multiple=True, required=False, + "-t", + "--table", + help="Which tables to inspect.", + multiple=True, + required=False, ) @click.pass_context @coro diff --git a/aerich/utils.py b/aerich/utils.py index e289b77..25547f1 100644 --- a/aerich/utils.py +++ b/aerich/utils.py @@ -36,7 +36,8 @@ def get_app_connection_name(config, app_name: str) -> str: if app: return app.get("default_connection", "default") raise BadOptionUsage( - option_name="--app", message=f'Can\'t get app named "{app_name}"', + option_name="--app", + message=f'Can\'t get app named "{app_name}"', ) @@ -64,7 +65,7 @@ def get_tortoise_config(ctx: Context, tortoise_orm: str) -> dict: try: config_module = importlib.import_module(config_path) except ModuleNotFoundError as e: - raise ClickException(f'Error while importing configuration module: {e}') from None + raise ClickException(f"Error while importing configuration module: {e}") from None config = getattr(config_module, tortoise_config, None) if not config: From 62840136be572ece6d0cdf908c71f3cdfece4fdd Mon Sep 17 00:00:00 2001 From: - <-> Date: Fri, 11 Jun 2021 15:36:54 +0200 Subject: [PATCH 4/4] used old black version --- aerich/cli.py | 25 +++++-------------------- aerich/utils.py | 3 +-- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/aerich/cli.py b/aerich/cli.py index 63bc522..8b7c310 100644 --- a/aerich/cli.py +++ b/aerich/cli.py @@ -48,11 +48,7 @@ def coro(f): @click.group(context_settings={"help_option_names": ["-h", "--help"]}) @click.version_option(__version__, "-V", "--version") @click.option( - "-c", - "--config", - default="aerich.ini", - show_default=True, - help="Config file.", + "-c", "--config", default="aerich.ini", show_default=True, help="Config file.", ) @click.option("--app", required=False, help="Tortoise-ORM app name.") @click.option( @@ -125,9 +121,7 @@ async def upgrade(ctx: Context): for upgrade_query in upgrade_query_list: await conn.execute_script(upgrade_query) await Aerich.create( - version=version_file, - app=app, - content=get_models_describe(app), + version=version_file, app=app, content=get_models_describe(app), ) click.secho(f"Success upgrade {version_file}", fg=Color.green) migrated = True @@ -221,10 +215,7 @@ async def history(ctx: Context): help="Tortoise-ORM config module dict variable, like settings.TORTOISE_ORM.", ) @click.option( - "--location", - default="./migrations", - show_default=True, - help="Migrate store location.", + "--location", default="./migrations", show_default=True, help="Migrate store location.", ) @click.option( "-s", @@ -297,9 +288,7 @@ async def init_db(ctx: Context, safe): version = await Migrate.generate_version() await Aerich.create( - version=version, - app=app, - content=get_models_describe(app), + version=version, app=app, content=get_models_describe(app), ) content = { "upgrade": [schema], @@ -310,11 +299,7 @@ async def init_db(ctx: Context, safe): @cli.command(help="Introspects the database tables to standard output as TortoiseORM model.") @click.option( - "-t", - "--table", - help="Which tables to inspect.", - multiple=True, - required=False, + "-t", "--table", help="Which tables to inspect.", multiple=True, required=False, ) @click.pass_context @coro diff --git a/aerich/utils.py b/aerich/utils.py index 25547f1..d56e5a2 100644 --- a/aerich/utils.py +++ b/aerich/utils.py @@ -36,8 +36,7 @@ def get_app_connection_name(config, app_name: str) -> str: if app: return app.get("default_connection", "default") raise BadOptionUsage( - option_name="--app", - message=f'Can\'t get app named "{app_name}"', + option_name="--app", message=f'Can\'t get app named "{app_name}"', )