diff --git a/.gitignore b/.gitignore index 04a1e29..e6bb63f 100644 --- a/.gitignore +++ b/.gitignore @@ -135,3 +135,4 @@ dmypy.json # test and example sqlite db file tests/test.db examples/**/*.sqlite +examples/**/migrations diff --git a/CHANGELOG b/CHANGELOG index 317859b..f7a289f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,18 @@ # This project adheres to [Semantic Versioning](http://semver.org/). # includes Added / Changed / Fixed +## [3.4.0] UNRELEASED + ## [3.3.0] UNRELEASED +### Added +- Integrated database migrate by `FastAPI-Migrate` +- Declarative API simple resource version (Major feature in 4.0) + +### Changed +- upgrade grpc plugin versions + +### Fixed +- Fixed importlib-metadata 5.0 conflict with kombu ## [3.2.2] 2022-07-11 ### Fixed diff --git a/bali/__init__.py b/bali/__init__.py index 5bc4b47..4b7fc24 100644 --- a/bali/__init__.py +++ b/bali/__init__.py @@ -5,7 +5,7 @@ from bali.decorators import event_handler, init_handler from bali.resources import Resource, ModelResource -__version__ = '3.3.0-rc.1' +__version__ = '3.3.0' class Schema(BaseModel): diff --git a/bali/application.py b/bali/application.py index 6772c91..b07cf0c 100644 --- a/bali/application.py +++ b/bali/application.py @@ -10,13 +10,15 @@ from fastapi import FastAPI, Request, Response from fastapi.middleware.gzip import GZipMiddleware from fastapi.routing import APIRoute +from fastapi_migrate import Migrate from fastapi_pagination import add_pagination from starlette.middleware.cors import CORSMiddleware from ._utils import singleton +from .cli import entry from .middlewares import process_middleware -from .utils import sync_exec from .servicer import get_servicer, make_grpc_serve +from .utils import sync_exec logger = logging.getLogger('bali') @@ -215,6 +217,7 @@ def launch( event: bool = False, shell: bool = False, ): + """Bali App entry for version < 4.0""" if not any([http, rpc, event, shell]): typer.echo( 'Please provided service type: ' @@ -266,4 +269,16 @@ def resolve_declarative(self): self.register([factory() for factory in API.resources_factories]) def start(self): - typer.run(self.launch) + # Integrated FastAPI-Migrate + try: + from bali import db + from config import settings + Migrate( + self, + model=db.Model, + db_uri=settings.SQLALCHEMY_DATABASE_URI, + ) + except ImportError: + logger.debug("No `config.py` provide settings") + + entry(self) # cli entry diff --git a/bali/cli.py b/bali/cli.py new file mode 100644 index 0000000..992d287 --- /dev/null +++ b/bali/cli.py @@ -0,0 +1,41 @@ +import typer + +typer_app = typer.Typer() + + +def callback(): + """ + Bali App entry 4.0 style + """ + + +def entry(application): + """Bali application CLI entry + """ + + # When migrate enabled, cli group will changed + # in <4.0, ENABLE_MIGRATE default is `False` + # in >=4.0, ENABLE_MIGRATE default is `True` + # + # migrate disabled: cli used as same as bali < 4.0 + # eg: python main.py --http + # migrate enabled: cli used as same as bali >= 4.0 + # eg: bali run http + try: + from config import settings + enable_migrate = settings.ENABLE_MIGRATE + except: + enable_migrate = False + + if enable_migrate: + typer_app.command()(application.launch) + typer_app.callback()(callback) + + from fastapi_migrate.cli import db + typer_click_object = typer.main.get_command(typer_app) + typer_click_object.add_command(db, "db") + + typer_click_object() + else: + typer_app.command()(application.launch) + typer_app() diff --git a/bali/declarative/__init__.py b/bali/declarative/__init__.py index 3543b70..b8e3ffc 100644 --- a/bali/declarative/__init__.py +++ b/bali/declarative/__init__.py @@ -1,12 +1,11 @@ import collections -import uuid import humps import pydantic - from pydantic import BaseModel, create_model -from ..resources import Resource, ModelResource, GENERIC_ACTIONS + from ..decorators import action +from ..resources import Resource, GENERIC_ACTIONS __all__ = ["API"] diff --git a/docs/config.md b/docs/config.md new file mode 100644 index 0000000..41cd275 --- /dev/null +++ b/docs/config.md @@ -0,0 +1,20 @@ +# config + +## configuration file + +Configuration file is a python file location in project root directory. + +```bash +todos +├── README.md +├── client.py +├── config.py <-- configuration file +├── main.py +├── migrations +├── models.py +├── protos +├── resources.py +└── todo.sqlite +``` + +Todos Example project configuration file: [config.py](examples/todos/config.py) diff --git a/docs/database.md b/docs/database.md index 4f55fd3..8e6d333 100644 --- a/docs/database.md +++ b/docs/database.md @@ -67,3 +67,43 @@ from bali.db.operators import get_filters_expr from models import User users = User.query().filter(*get_filters_expr(User, **filters)).all() ``` + +## Migrate + +#### Migrate Config + +In <4.0 versions, you should enable migrate first. + +`ENABLE_MIGRATE` default value is `False` in <4.0, and will be `True` after 4.0 release. + +```python +class Settings(BaseSettings): + SQLALCHEMY_DATABASE_URI: str = 'sqlite:///todo.sqlite' + ENABLE_MIGRATE: bool = True +``` + +#### Migrate commands + +```bash +python main.py db init +``` +This will add a migrations folder to your application. +The contents of this folder need to be added to version control along with your other source files. + + +```bash +python main.py db migrate +``` +Generate migration, the migration script needs to be reviewed and edited, as Alembic currently does not detect every change you make to your models. + + +```bash +python main.py db upgrade +``` +Apply the migration to the database + + +```bash +python main.py db --help +``` +To see all the commands that are available run this command diff --git a/docs/quick-start.md b/docs/quick-start.md new file mode 100644 index 0000000..05cf8c1 --- /dev/null +++ b/docs/quick-start.md @@ -0,0 +1 @@ +# Quick Start diff --git a/docs/zh/docs/quick-start.md b/docs/zh/docs/quick-start.md new file mode 100644 index 0000000..05cf8c1 --- /dev/null +++ b/docs/zh/docs/quick-start.md @@ -0,0 +1 @@ +# Quick Start diff --git a/docs/zh/mkdocs.yml b/docs/zh/mkdocs.yml index 8d698e1..f2772c9 100644 --- a/docs/zh/mkdocs.yml +++ b/docs/zh/mkdocs.yml @@ -22,7 +22,9 @@ repo_url: https://github.com/bali-framework/bali edit_uri: "" nav: -- 简介: index.md +- 开始: + - 简介: index.md + - 快速上手: quick-start.md - App: application.md - 数据库: database.md - 缓存: cache.md diff --git a/examples/todos/config.py b/examples/todos/config.py index fcd6857..649d18d 100644 --- a/examples/todos/config.py +++ b/examples/todos/config.py @@ -4,6 +4,7 @@ class Settings(BaseSettings): SQLALCHEMY_DATABASE_URI: str = 'sqlite:///todo.sqlite' + ENABLE_MIGRATE: bool = True settings: Settings = Settings() diff --git a/mkdocs.yml b/mkdocs.yml index d8abd8c..f117717 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -22,8 +22,11 @@ repo_url: https://github.com/bali-framework/bali edit_uri: "" nav: -- Introduction: index.md +- Getting Started: + - Introduction: index.md + - Quick Start: quick-start.md - Application: application.md +- Config: config.md - Database: database.md - Cache: cache.md - Resource: resource.md diff --git a/requirements.txt b/requirements.txt index 414692b..9972f85 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ aiosqlite dateparser>=1.1.0 decamelize==0.1.2 fastapi[all]>=0.63.0,<0.76 +fastapi-migrate==0.1.1 fastapi-pagination~=0.9.0 greenlet~=1.0 grpcio>=1.32.0,<=1.48 diff --git a/setup.py b/setup.py index 7f3faa6..e6f4da8 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,24 @@ def read(f): author_email='josh.yu_8@live.com', license='MIT', install_requires=INSTALL_REQUIREMENTS, + classifiers=[ + 'Intended Audience :: Developers', + 'Development Status :: 5 - Production/Stable', + "Topic :: Internet", + "Topic :: Software Development :: Libraries :: Application Frameworks", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development", + "Topic :: Internet :: WWW/HTTP :: HTTP Servers", + "Topic :: Internet :: WWW/HTTP", + "Environment :: Web Environment", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + ], packages=find_packages( exclude=[ 'examples',