bali-framework / bali Goto Github PK
View Code? Open in Web Editor NEWSimplify declarative cloud-native development base on FastAPI and gRPC. https://bali-framework.github.io/bali/
License: MIT License
Simplify declarative cloud-native development base on FastAPI and gRPC. https://bali-framework.github.io/bali/
License: MIT License
when using alembic with asyncpg, it will return errors.
root@cartdrgdip:/app/pyfgserver# python3 --version
Python 3.12.3
root@cartdrgdip:/app/pyfgserver# pip install bali-core
WARNING: Skipping /usr/lib/python3.12/dist-packages/argcomplete-3.1.4.dist-info due to invalid metadata entry 'name'
Collecting bali-core
Using cached bali_core-3.5.1-py3-none-any.whl.metadata (10 kB)
Collecting greenlet<=2.0.1,>1.0 (from bali-core)
Using cached greenlet-2.0.1.tar.gz (163 kB)
Preparing metadata (setup.py) ... done
Collecting aiomysql (from bali-core)
Using cached aiomysql-0.2.0-py3-none-any.whl.metadata (11 kB)
Collecting aiosqlite (from bali-core)
Using cached aiosqlite-0.20.0-py3-none-any.whl.metadata (4.3 kB)
Collecting dateparser>=1.1.0 (from bali-core)
Using cached dateparser-1.2.0-py2.py3-none-any.whl.metadata (28 kB)
Collecting fastapi<=0.92,>=0.69.0 (from fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached fastapi-0.92.0-py3-none-any.whl.metadata (25 kB)
Collecting fastapi-migrate==0.1.1 (from bali-core)
Using cached fastapi_migrate-0.1.1-py3-none-any.whl.metadata (425 bytes)
Collecting fastapi-pagination<=0.10,>=0.9.0 (from bali-core)
Using cached fastapi_pagination-0.10.0-py3-none-any.whl.metadata (7.9 kB)
Collecting grpcio<=1.50.0,>=1.32.0 (from bali-core)
Using cached grpcio-1.50.0.tar.gz (22.1 MB)
Preparing metadata (setup.py) ... done
Collecting grpcio-tools<=1.50.0,>=1.32.0 (from bali-core)
Using cached grpcio-tools-1.50.0.tar.gz (2.3 MB)
Preparing metadata (setup.py) ... done
Collecting grpc-interceptor==0.15.0 (from bali-core)
Using cached grpc_interceptor-0.15.0-py3-none-any.whl.metadata (7.4 kB)
Collecting importlib-metadata<5.0.0 (from bali-core)
Using cached importlib_metadata-4.13.0-py3-none-any.whl.metadata (4.9 kB)
Collecting kombu<6.0,>=5.2.4 (from bali-core)
Using cached kombu-5.3.7-py3-none-any.whl.metadata (3.1 kB)
Collecting MarkupSafe==2.0.1 (from bali-core)
Using cached MarkupSafe-2.0.1-cp312-cp312-linux_x86_64.whl
Collecting PyMySQL<=1.0.2,>=0.9 (from bali-core)
Using cached PyMySQL-1.0.2-py3-none-any.whl.metadata (5.1 kB)
Collecting passlib==1.7.2 (from passlib[bcrypt]==1.7.2->bali-core)
Using cached passlib-1.7.2-py2.py3-none-any.whl.metadata (1.7 kB)
Collecting pillow<8.4,>=7.2.0 (from bali-core)
Using cached Pillow-8.3.2.tar.gz (48.8 MB)
Preparing metadata (setup.py) ... done
Collecting pydantic-sqlalchemy<1,>=0.0.7 (from bali-core)
Using cached pydantic_sqlalchemy-0.0.9-py3-none-any.whl.metadata (6.1 kB)
Collecting pyhumps (from bali-core)
Using cached pyhumps-3.8.0-py3-none-any.whl.metadata (4.0 kB)
Collecting pytz==2021.1 (from bali-core)
Using cached pytz-2021.1-py2.py3-none-any.whl.metadata (21 kB)
Collecting redis<4.3,>=3.5.3 (from bali-core)
Using cached redis-4.2.2-py3-none-any.whl.metadata (51 kB)
Collecting regex==2022.1.18 (from bali-core)
Using cached regex-2022.1.18-cp312-cp312-linux_x86_64.whl
Collecting sqla-wrapper<5.6,>=5.0.0 (from bali-core)
Using cached sqla_wrapper-5.5-py3-none-any.whl.metadata (2.7 kB)
Collecting typer>=0.4 (from bali-core)
Using cached typer-0.12.3-py3-none-any.whl.metadata (15 kB)
Collecting alembic<2.0.0,>=1.4.2 (from fastapi-migrate==0.1.1->bali-core)
Using cached alembic-1.13.2-py3-none-any.whl.metadata (7.4 kB)
Collecting click<8.0.0,>=7.1.2 (from fastapi-migrate==0.1.1->bali-core)
Using cached click-7.1.2-py2.py3-none-any.whl.metadata (2.9 kB)
Requirement already satisfied: bcrypt>=3.1.0 in /usr/lib/python3/dist-packages (from passlib[bcrypt]==1.7.2->bali-core) (3.2.2)
Collecting python-dateutil (from dateparser>=1.1.0->bali-core)
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting tzlocal (from dateparser>=1.1.0->bali-core)
Using cached tzlocal-5.2-py3-none-any.whl.metadata (7.8 kB)
Collecting pydantic!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0,>=1.6.2 (from fastapi<=0.92,>=0.69.0->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached pydantic-1.10.17-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (151 kB)
Collecting starlette<0.26.0,>=0.25.0 (from fastapi<=0.92,>=0.69.0->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached starlette-0.25.0-py3-none-any.whl.metadata (5.8 kB)
Collecting email-validator>=1.1.1 (from fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached email_validator-2.2.0-py3-none-any.whl.metadata (25 kB)
Collecting httpx>=0.23.0 (from fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached httpx-0.27.0-py3-none-any.whl.metadata (7.2 kB)
Requirement already satisfied: itsdangerous>=1.1.0 in /usr/lib/python3.12/dist-packages (from fastapi[all]<=0.92,>=0.69.0->bali-core) (2.2.0)
Requirement already satisfied: jinja2>=2.11.2 in /usr/lib/python3/dist-packages (from fastapi[all]<=0.92,>=0.69.0->bali-core) (3.1.2)
Collecting orjson>=3.2.1 (from fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (50 kB)
Collecting python-multipart>=0.0.5 (from fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached python_multipart-0.0.9-py3-none-any.whl.metadata (2.5 kB)
Requirement already satisfied: pyyaml>=5.3.1 in /usr/lib/python3/dist-packages (from fastapi[all]<=0.92,>=0.69.0->bali-core) (6.0.1)
Collecting ujson!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,>=4.0.1 (from fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (9.3 kB)
Collecting uvicorn>=0.12.0 (from uvicorn[standard]>=0.12.0; extra == "all"->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached uvicorn-0.30.1-py3-none-any.whl.metadata (6.3 kB)
Requirement already satisfied: six>=1.5.2 in /usr/lib/python3/dist-packages (from grpcio<=1.50.0,>=1.32.0->bali-core) (1.16.0)
Collecting protobuf<5.0dev,>=4.21.6 (from grpcio-tools<=1.50.0,>=1.32.0->bali-core)
Using cached protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl.metadata (541 bytes)
Requirement already satisfied: setuptools in /usr/lib/python3/dist-packages (from grpcio-tools<=1.50.0,>=1.32.0->bali-core) (68.1.2)
Collecting zipp>=0.5 (from importlib-metadata<5.0.0->bali-core)
Using cached zipp-3.19.2-py3-none-any.whl.metadata (3.6 kB)
Collecting amqp<6.0.0,>=5.1.1 (from kombu<6.0,>=5.2.4->bali-core)
Using cached amqp-5.2.0-py3-none-any.whl.metadata (8.9 kB)
Collecting vine (from kombu<6.0,>=5.2.4->bali-core)
Using cached vine-5.1.0-py3-none-any.whl.metadata (2.7 kB)
Collecting sqlalchemy<2.0.0,>=1.3.16 (from pydantic-sqlalchemy<1,>=0.0.7->bali-core)
Using cached SQLAlchemy-1.4.52-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (10 kB)
Collecting deprecated>=1.2.3 (from redis<4.3,>=3.5.3->bali-core)
Using cached Deprecated-1.2.14-py2.py3-none-any.whl.metadata (5.4 kB)
Requirement already satisfied: packaging>=20.4 in /usr/lib/python3/dist-packages (from redis<4.3,>=3.5.3->bali-core) (24.0)
Collecting async-timeout>=4.0.2 (from redis<4.3,>=3.5.3->bali-core)
Using cached async_timeout-4.0.3-py3-none-any.whl.metadata (4.2 kB)
INFO: pip is looking at multiple versions of typer to determine which version is compatible with other requirements. This could take a while.
Collecting typer>=0.4 (from bali-core)
Using cached typer-0.12.2-py3-none-any.whl.metadata (15 kB)
Using cached typer-0.12.1-py3-none-any.whl.metadata (15 kB)
Using cached typer-0.12.0-py3-none-any.whl.metadata (15 kB)
Collecting typer-slim==0.12.0 (from typer-slim[standard]==0.12.0->typer>=0.4->bali-core)
Using cached typer_slim-0.12.0-py3-none-any.whl.metadata (15 kB)
Collecting typer-cli==0.12.0 (from typer>=0.4->bali-core)
Using cached typer_cli-0.12.0-py3-none-any.whl.metadata (3.5 kB)
INFO: pip is looking at multiple versions of typer-slim to determine which version is compatible with other requirements. This could take a while.
Collecting typer>=0.4 (from bali-core)
Using cached typer-0.11.1-py3-none-any.whl.metadata (13 kB)
Using cached typer-0.11.0-py3-none-any.whl.metadata (13 kB)
INFO: pip is still looking at multiple versions of typer to determine which version is compatible with other requirements. This could take a while.
Using cached typer-0.10.0-py3-none-any.whl.metadata (14 kB)
Collecting typing-extensions>=3.7.4.3 (from typer>=0.4->bali-core)
Using cached typing_extensions-4.12.2-py3-none-any.whl.metadata (3.0 kB)
Collecting Mako (from alembic<2.0.0,>=1.4.2->fastapi-migrate==0.1.1->bali-core)
Using cached Mako-1.3.5-py3-none-any.whl.metadata (2.9 kB)
Collecting wrapt<2,>=1.10 (from deprecated>=1.2.3->redis<4.3,>=3.5.3->bali-core)
Using cached wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.6 kB)
Collecting dnspython>=2.0.0 (from email-validator>=1.1.1->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached dnspython-2.6.1-py3-none-any.whl.metadata (5.8 kB)
Requirement already satisfied: idna>=2.0.0 in /usr/lib/python3/dist-packages (from email-validator>=1.1.1->fastapi[all]<=0.92,>=0.69.0->bali-core) (3.6)
Collecting anyio (from httpx>=0.23.0->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached anyio-4.4.0-py3-none-any.whl.metadata (4.6 kB)
Requirement already satisfied: certifi in /usr/lib/python3/dist-packages (from httpx>=0.23.0->fastapi[all]<=0.92,>=0.69.0->bali-core) (2023.11.17)
Collecting httpcore==1.* (from httpx>=0.23.0->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached httpcore-1.0.5-py3-none-any.whl.metadata (20 kB)
Collecting sniffio (from httpx>=0.23.0->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached sniffio-1.3.1-py3-none-any.whl.metadata (3.9 kB)
Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx>=0.23.0->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached h11-0.14.0-py3-none-any.whl.metadata (8.2 kB)
Collecting httptools>=0.5.0 (from uvicorn[standard]>=0.12.0; extra == "all"->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.6 kB)
Collecting python-dotenv>=0.13 (from uvicorn[standard]>=0.12.0; extra == "all"->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached python_dotenv-1.0.1-py3-none-any.whl.metadata (23 kB)
Collecting uvloop!=0.15.0,!=0.15.1,>=0.14.0 (from uvicorn[standard]>=0.12.0; extra == "all"->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.9 kB)
Collecting watchfiles>=0.13 (from uvicorn[standard]>=0.12.0; extra == "all"->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.9 kB)
Collecting websockets>=10.4 (from uvicorn[standard]>=0.12.0; extra == "all"->fastapi[all]<=0.92,>=0.69.0->bali-core)
Using cached websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.6 kB)
Using cached bali_core-3.5.1-py3-none-any.whl (47 kB)
Using cached fastapi_migrate-0.1.1-py3-none-any.whl (8.0 kB)
Using cached grpc_interceptor-0.15.0-py3-none-any.whl (20 kB)
Using cached passlib-1.7.2-py2.py3-none-any.whl (507 kB)
Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
Using cached dateparser-1.2.0-py2.py3-none-any.whl (294 kB)
Using cached fastapi-0.92.0-py3-none-any.whl (56 kB)
Using cached fastapi_pagination-0.10.0-py3-none-any.whl (21 kB)
Using cached importlib_metadata-4.13.0-py3-none-any.whl (23 kB)
Using cached kombu-5.3.7-py3-none-any.whl (200 kB)
Using cached pydantic_sqlalchemy-0.0.9-py3-none-any.whl (4.5 kB)
Using cached PyMySQL-1.0.2-py3-none-any.whl (43 kB)
Using cached redis-4.2.2-py3-none-any.whl (226 kB)
Using cached sqla_wrapper-5.5-py3-none-any.whl (16 kB)
Using cached click-7.1.2-py2.py3-none-any.whl (82 kB)
Using cached typer-0.10.0-py3-none-any.whl (46 kB)
Using cached aiomysql-0.2.0-py3-none-any.whl (44 kB)
Using cached aiosqlite-0.20.0-py3-none-any.whl (15 kB)
Using cached pyhumps-3.8.0-py3-none-any.whl (6.1 kB)
Using cached alembic-1.13.2-py3-none-any.whl (232 kB)
Using cached amqp-5.2.0-py3-none-any.whl (50 kB)
Using cached async_timeout-4.0.3-py3-none-any.whl (5.7 kB)
Using cached Deprecated-1.2.14-py2.py3-none-any.whl (9.6 kB)
Using cached email_validator-2.2.0-py3-none-any.whl (33 kB)
Using cached httpx-0.27.0-py3-none-any.whl (75 kB)
Using cached httpcore-1.0.5-py3-none-any.whl (77 kB)
Using cached orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (141 kB)
Using cached protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl (294 kB)
Using cached pydantic-1.10.17-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB)
Using cached python_multipart-0.0.9-py3-none-any.whl (22 kB)
Using cached SQLAlchemy-1.4.52-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB)
Using cached starlette-0.25.0-py3-none-any.whl (66 kB)
Using cached typing_extensions-4.12.2-py3-none-any.whl (37 kB)
Using cached ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (53 kB)
Using cached uvicorn-0.30.1-py3-none-any.whl (62 kB)
Using cached vine-5.1.0-py3-none-any.whl (9.6 kB)
Using cached zipp-3.19.2-py3-none-any.whl (9.0 kB)
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
Using cached tzlocal-5.2-py3-none-any.whl (17 kB)
Using cached anyio-4.4.0-py3-none-any.whl (86 kB)
Using cached dnspython-2.6.1-py3-none-any.whl (307 kB)
Using cached h11-0.14.0-py3-none-any.whl (58 kB)
Using cached httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (344 kB)
Using cached python_dotenv-1.0.1-py3-none-any.whl (19 kB)
Using cached sniffio-1.3.1-py3-none-any.whl (10 kB)
Using cached uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.2 MB)
Using cached watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB)
Using cached websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (131 kB)
Using cached wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (87 kB)
Using cached Mako-1.3.5-py3-none-any.whl (78 kB)
Building wheels for collected packages: greenlet, grpcio, grpcio-tools, pillow
Building wheel for greenlet (setup.py) ... error
error: subprocess-exited-with-error
× python setup.py bdist_wheel did not run successfully.
│ exit code: 1
╰─> [158 lines of output]
running bdist_wheel
running build
running build_py
creating build
creating build/lib.linux-x86_64-cpython-312
creating build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/__init__.py -> build/lib.linux-x86_64-cpython-312/greenlet
creating build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/__init__.py -> build/lib.linux-x86_64-cpython-312/greenlet/platform
creating build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_generator.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_greenlet.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_throw.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/__init__.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_gc.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_cpp.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_generator_nested.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/leakcheck.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_stack_saved.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_contextvars.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_version.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_greenlet_trash.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_extension_interface.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_weakref.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_leaks.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/test_tracing.py -> build/lib.linux-x86_64-cpython-312/greenlet/tests
running egg_info
writing src/greenlet.egg-info/PKG-INFO
writing dependency_links to src/greenlet.egg-info/dependency_links.txt
writing requirements to src/greenlet.egg-info/requires.txt
writing top-level names to src/greenlet.egg-info/top_level.txt
reading manifest file 'src/greenlet.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no previously-included files found matching 'benchmarks/*.json'
no previously-included directories found matching 'docs/_build'
warning: no files found matching '*.py' under directory 'appveyor'
warning: no previously-included files matching '*.pyc' found anywhere in distribution
warning: no previously-included files matching '*.pyd' found anywhere in distribution
warning: no previously-included files matching '*.so' found anywhere in distribution
warning: no previously-included files matching '.coverage' found anywhere in distribution
adding license file 'LICENSE'
adding license file 'LICENSE.PSF'
adding license file 'AUTHORS'
writing manifest file 'src/greenlet.egg-info/SOURCES.txt'
copying src/greenlet/greenlet.cpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet.h -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_allocator.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_compiler_compat.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_cpython_compat.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_exceptions.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_greenlet.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_internal.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_refs.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_slp_switch.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_thread_state.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_thread_state_dict_cleanup.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/greenlet_thread_support.hpp -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/slp_platformselect.h -> build/lib.linux-x86_64-cpython-312/greenlet
copying src/greenlet/platform/setup_switch_x64_masm.cmd -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_aarch64_gcc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_alpha_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_amd64_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_arm32_gcc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_arm32_ios.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_arm64_masm.asm -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_arm64_masm.obj -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_arm64_msvc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_csky_gcc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_m68k_gcc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_mips_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_ppc64_aix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_ppc64_linux.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_ppc_aix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_ppc_linux.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_ppc_macosx.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_ppc_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_riscv_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_s390_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_sparc_sun_gcc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_x32_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_x64_masm.asm -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_x64_masm.obj -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_x64_msvc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_x86_msvc.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/platform/switch_x86_unix.h -> build/lib.linux-x86_64-cpython-312/greenlet/platform
copying src/greenlet/tests/_test_extension.c -> build/lib.linux-x86_64-cpython-312/greenlet/tests
copying src/greenlet/tests/_test_extension_cpp.cpp -> build/lib.linux-x86_64-cpython-312/greenlet/tests
running build_ext
building 'greenlet._greenlet' extension
creating build/temp.linux-x86_64-cpython-312
creating build/temp.linux-x86_64-cpython-312/src
creating build/temp.linux-x86_64-cpython-312/src/greenlet
x86_64-linux-gnu-gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O2 -Wall -fPIC -I/usr/include/python3.12 -c src/greenlet/greenlet.cpp -o build/temp.linux-x86_64-cpython-312/src/greenlet/greenlet.o
In file included from src/greenlet/greenlet_internal.hpp:20,
from src/greenlet/greenlet.cpp:19:
src/greenlet/greenlet_greenlet.hpp: In member function ‘void greenlet::PythonState::operator<<(const PyThreadState*)’:
src/greenlet/greenlet_greenlet.hpp:831:41: error: ‘_PyCFrame’ {aka ‘struct _PyCFrame’} has no member named ‘use_tracing’
831 | this->use_tracing = tstate->cframe->use_tracing;
| ^~~~~~~~~~~
src/greenlet/greenlet_greenlet.hpp:834:37: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_limit’; did you mean ‘py_recursion_limit’?
834 | this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
| ^~~~~~~~~~~~~~~
| py_recursion_limit
src/greenlet/greenlet_greenlet.hpp:834:63: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_remaining’; did you mean ‘c_recursion_remaining’?
834 | this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
| ^~~~~~~~~~~~~~~~~~~
| c_recursion_remaining
src/greenlet/greenlet_greenlet.hpp:848:42: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘trash_delete_nesting’
848 | this->trash_delete_nesting = tstate->trash_delete_nesting;
| ^~~~~~~~~~~~~~~~~~~~
src/greenlet/greenlet_greenlet.hpp: In member function ‘void greenlet::PythonState::operator>>(PyThreadState*)’:
src/greenlet/greenlet_greenlet.hpp:867:21: error: ‘_PyCFrame’ {aka ‘struct _PyCFrame’} has no member named ‘use_tracing’
867 | tstate->cframe->use_tracing = this->use_tracing;
| ^~~~~~~~~~~
src/greenlet/greenlet_greenlet.hpp:870:13: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘recursion_remaining’; did you mean ‘c_recursion_remaining’?
870 | tstate->recursion_remaining = tstate->recursion_limit - this->recursion_depth;
| ^~~~~~~~~~~~~~~~~~~
| c_recursion_remaining
src/greenlet/greenlet_greenlet.hpp:870:43: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘recursion_limit’; did you mean ‘py_recursion_limit’?
870 | tstate->recursion_remaining = tstate->recursion_limit - this->recursion_depth;
| ^~~~~~~~~~~~~~~
| py_recursion_limit
src/greenlet/greenlet_greenlet.hpp:881:13: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘trash_delete_nesting’
881 | tstate->trash_delete_nesting = this->trash_delete_nesting;
| ^~~~~~~~~~~~~~~~~~~~
src/greenlet/greenlet_greenlet.hpp: In member function ‘void greenlet::PythonState::will_switch_from(PyThreadState*)’:
src/greenlet/greenlet_greenlet.hpp:891:48: error: ‘_PyCFrame’ {aka ‘struct _PyCFrame’} has no member named ‘use_tracing’
891 | this->use_tracing = origin_tstate->cframe->use_tracing;
| ^~~~~~~~~~~
src/greenlet/greenlet_greenlet.hpp: In member function ‘void greenlet::PythonState::set_initial_state(const PyThreadState*)’:
src/greenlet/greenlet_greenlet.hpp:899:37: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_limit’; did you mean ‘py_recursion_limit’?
899 | this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
| ^~~~~~~~~~~~~~~
| py_recursion_limit
src/greenlet/greenlet_greenlet.hpp:899:63: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_remaining’; did you mean ‘c_recursion_remaining’?
899 | this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
| ^~~~~~~~~~~~~~~~~~~
| c_recursion_remaining
In file included from /usr/include/c++/13/ext/alloc_traits.h:34,
from /usr/include/c++/13/bits/basic_string.h:39,
from /usr/include/c++/13/string:54,
from src/greenlet/greenlet.cpp:10:
/usr/include/c++/13/bits/alloc_traits.h: In instantiation of ‘struct std::__allocator_traits_base::__rebind<greenlet::PythonAllocator<_greenlet*>, _greenlet*, void>’:
/usr/include/c++/13/bits/alloc_traits.h:94:11: required by substitution of ‘template<class _Alloc, class _Up> using std::__alloc_rebind = typename std::__allocator_traits_base::__rebind<_Alloc, _Up>::type [with _Alloc = greenlet::PythonAllocator<_greenlet*>; _Up = _greenlet*]’
/usr/include/c++/13/bits/alloc_traits.h:228:8: required by substitution of ‘template<class _Alloc> template<class _Tp> using std::allocator_traits< <template-parameter-1-1> >::rebind_alloc = std::__alloc_rebind<_Alloc, _Tp> [with _Tp = _greenlet*; _Alloc = greenlet::PythonAllocator<_greenlet*>]’
/usr/include/c++/13/ext/alloc_traits.h:126:65: required from ‘struct __gnu_cxx::__alloc_traits<greenlet::PythonAllocator<_greenlet*>, _greenlet*>::rebind<_greenlet*>’
/usr/include/c++/13/bits/stl_vector.h:88:21: required from ‘struct std::_Vector_base<_greenlet*, greenlet::PythonAllocator<_greenlet*> >’
/usr/include/c++/13/bits/stl_vector.h:428:11: required from ‘class std::vector<_greenlet*, greenlet::PythonAllocator<_greenlet*> >’
src/greenlet/greenlet_thread_state.hpp:115:16: required from here
/usr/include/c++/13/bits/alloc_traits.h:70:31: error: static assertion failed: allocator_traits<A>::rebind_alloc<A::value_type> must be A
70 | _Tp>::value,
| ^~~~~
/usr/include/c++/13/bits/alloc_traits.h:70:31: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
src/greenlet/greenlet.cpp: In function ‘PyObject* mod_get_tstate_trash_delete_nesting(PyObject*)’:
src/greenlet/greenlet.cpp:3090:36: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘trash_delete_nesting’
3090 | return PyLong_FromLong(tstate->trash_delete_nesting);
| ^~~~~~~~~~~~~~~~~~~~
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for greenlet
Running setup.py clean for greenlet
python version: 3.9.2
pip version: 22.0.4
ERROR: Could not build wheels for ujson, which is required to install pyproject.toml-based projects
Is necessary for 'fastapi[all]' in requirement.txt
我似乎并不能像fastapi示例那样直接在函数上加上response对象
@app.put("/get-or-create-task/{task_id}", status_code=200)
def get_or_create_task(task_id: str, response: Response):
if task_id not in tasks:
tasks[task_id] = "This didn't exist before"
response.status_code = status.HTTP_201_CREATED
return tasks[task_id]
如果加上了response对象参数,发送接口时会提示缺少response关键字参数,这在重写ModelResource的方法时应该也会遇到;而且似乎Resource是无法使用fastapi中的Depends这个十分方便的特性,想问下是不是除了基础的crud,其他的api其实还是需要fastapi原生的方法来写,比如上传下载文件之类的,然后include_router到_app.routes里?
说到这边还有个疑问,Resource/ModelResource怎样和APIRoute配合形成类似flask和sanic中blueprint的效果?
from bali.core import cache
# Usage example (API)
# Read cache
cache.get(key)
# Set cache
cache.set(key, value, timeout=10)
As FastAPI docs metioned, backgroud task could been added using background_tasks.add_task
:
https://fastapi.tiangolo.com/tutorial/background-tasks/.
@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
background_tasks.add_task(write_notification, email, message="some notification")
return {"message": "Notification sent in the background"}
But how to create a background task in gRPC service's RPC?
Filters must defined in resource.filters
class GreeterResource(Resource):
schema = Greeter
filters = {}
The following packages should been updated:
grpcio
pillow
pydantic-sqlalchemy
sqla-wrapper
SQLAlchemy
typer
Permission must defined in resource.permission_class
class GreeterResource(Resource):
schema = Greeter
permission_class = {
"get": IsAdmin,
}
All actions using same permission class
class GreeterResource(Resource):
schema = Greeter
permission_class = [IsAdmin,]
The permission class will return a boolean result to determine whether the request is allowed, and will fill in request.user
infos
希望完善一下tour和examples
As Martin Fowler introduced https://www.youtube.com/watch?v=STKCRSUsyP0
Event-Driven architecture
is a necessary part of microservices.
bali-cli
(https://github.com/bali-framework/bali/) is based on the practice of protobuf, which comes from the best practice by Google results.
But we never tell the detail of it.
能否把 click, pydantic-sqlalchemy, pytz 的依赖升级一下
I added the following path to PYTHONPATH
manually in the Dockerfile
ENV PYTHONPATH="$PYTHONPATH:/finance"
ENV PYTHONPATH="$PYTHONPATH:/finance/clients"
ENV PYTHONPATH="$PYTHONPATH:/finance/clients/auth"
ENV PYTHONPATH="$PYTHONPATH:/finance/clients/user"
ENV PYTHONPATH="$PYTHONPATH:/finance/services/rpc"
Now we need it included in bali
initialized period.
According to 12 factor
's config specification. Our configuration still in python code.
We need to enhance it using environment or dotenv.
custom parameters
that allow separate registration of HTTP Router
and RPC Service
.routing prefix
and then continue to register the resource
with app.register()
, duplicate HTTP API
registrations occur.add parameters
in the app.register()
method, allow only registering rpc_service
, skip
registering http router.here:
http=True
, rpc=True
.@singleton
class Bali:
...
def register(self, resources_cls, http=True, rpc=True):
if not isinstance(resources_cls, list):
resources_cls = [resources_cls]
for resource_cls in resources_cls:
# Register HTTP service
if http:
self._app.include_router(
router=resource_cls.as_router(),
prefix=resource_cls._http_endpoint,
)
# Register RPC service
if rpc and self._rpc_servicer:
resource_cls.as_servicer(self)
if http:
add_pagination(self._app)
from bali.application import Bali
from proto.config import settings
from internal.router import router_v1
from internal.event.event import EventHandler
from internal.resource import TodoResource
app = Bali(
base_settings=None,
title=settings.SERVER_NAME,
routers=[{
'router': router_v1,
# 'prefix': '/v1',
}],
backend_cors_origins=['http://127.0.0.1'], # ["*"]
# rpc_service=grpc_server_async,
event_handler=EventHandler
)
#
#
#
app.register(TodoResource, http=false) # fix here!
if __name__ == "__main__":
app.start()
An base class include "Create" "List" "Retrieve" "Update" "Destroy" methods. Subclasses complete business logic through declarative style like "rest_framework" did.
Need a cache memoize feature according django-cache-memoize
https://pypi.org/project/django-cache-memoize/
# Import the cache_memoize from bali core
from bali.core import cache_memoize
# Attach decorator to cacheable function with a timeout of 100 seconds.
@cache_memoize(100)
def expensive_function(start, end):
return random.randint(start, end)
Inherited from Resource, but dedicated to working with Model resources.
~sqlalchemy.pool.QueuePool
as~sqlalchemy.pool.SingletonThreadPool
. With~sqlalchemy.pool.QueuePool
, a pool_size
settingpoolclass
to~sqlalchemy.pool.NullPool
instead.python: 3.10.4
bali-core: 3.2.2
app.register
注册含有这个的ModelResource类
class Permission(BaseMixin, db.BaseModel): # type: ignore
table_comment = "权限表"
name_doc = "权限名称"
description_doc = "权限描述"
module_doc = "所属模块"
name: str = db.Column(db.String(120), doc=name_doc,
comment=name_doc, nullable=False)
description: str = db.Column(
db.Text(500), doc=description_doc, comment=description_doc)
permission_role: 'Permission' = db.relationship(
'GroupRole', back_populates='permission')
permission_roles = association_proxy('permission_role', 'role')
permission_role_ids = association_proxy('permission_role', 'role_id')
module_id: int = db.Column(db.ForeignKey(
't_module.id'), doc=module_doc, comment=module_doc)
打开swagger就会报错
INFO: 127.0.0.1:60036 - "GET /openapi.json HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 376, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\bali\application.py", line 71, in __call__
await self._app.__call__(scope, receive, send) # pragma: no cover
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\fastapi\applications.py", line 261, in __call__
await super().__call__(scope, receive, send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
raise exc
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\exceptions.py", line 82, in __call__
raise exc
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
raise e
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\routing.py", line 656, in __call__
await route.handle(scope, receive, send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\routing.py", line 259, in handle
await self.app(scope, receive, send)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\starlette\routing.py", line 61, in app
response = await func(request)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\fastapi\applications.py", line 216, in openapi
return JSONResponse(self.openapi())
File "C:\Users\Administrator\PycharmProjects\test_platform\backend\main.py", line 56, in custom_openapi
openapi_schema = get_openapi(
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\fastapi\openapi\utils.py", line 418, in get_openapi
definitions = get_model_definitions(
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\fastapi\utils.py", line 29, in get_model_definitions
m_schema, m_definitions, m_nested_models = model_process_schema(
File "pydantic\schema.py", line 580, in pydantic.schema.model_process_schema
File "pydantic\schema.py", line 621, in pydantic.schema.model_type_schema
File "pydantic\schema.py", line 254, in pydantic.schema.field_schema
File "pydantic\schema.py", line 461, in pydantic.schema.field_type_schema
File "pydantic\schema.py", line 847, in pydantic.schema.field_singleton_schema
File "pydantic\schema.py", line 698, in pydantic.schema.field_singleton_sub_fields_schema
File "pydantic\schema.py", line 526, in pydantic.schema.field_type_schema
File "pydantic\schema.py", line 921, in pydantic.schema.field_singleton_schema
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\abc.py", line 123, in __subclasscheck__
return _abc_subclasscheck(cls, subclass)
TypeError: issubclass() arg 1 must be a class
像如下的model就不会,看上去似乎没有什么区别
class Tag(BaseMixin, db.BaseModel): # type: ignore
table_comment = "标签表"
name_doc = "标签名称"
color_doc = "标签颜色"
tag_type_doc = "标签类型"
description_doc = "标签描述"
name: str = db.Column(db.String(120), doc=name_doc,
comment=name_doc, nullable=False)
color: str = db.Column(db.String(120), doc=color_doc, comment=color_doc)
tag_type: int = db.Column(
db.Integer, doc=tag_type_doc, comment=tag_type_doc, default=get_tag_enum)
description: str = db.Column(
db.Text(500), doc=description_doc, comment=description_doc)
tag_project: 'ProjectInfo' = db.relationship(
'ProjectTag', back_populates='tag', lazy='selectin', join_depth=2)
tag_projects = association_proxy('tag_project', 'project')
tag_project_ids = association_proxy('tag_project', 'project_id')
tag_testcase_site: 'TestcaseSite' = db.relationship(
'TestcaseSiteTag', back_populates='tag', lazy='selectin', join_depth=2)
tag_testcase_sites = association_proxy(
'tag_testcase_site', 'testcase_site')
tag_testcase_site_ids = association_proxy(
'tag_testcase_site', 'testcase_site_id')
tag_testcase: 'Testcase' = db.relationship(
'TestcaseTag', back_populates='tag', lazy='selectin', join_depth=2)
tag_testcases = association_proxy('tag_testcase', 'testcase')
tag_testcase_ids = association_proxy('tag_testcase', 'testcase_id')
并且from bali.schemas import model_to_schema
这个函数转化有关系字段的模型(relationship/association_proxy)也有问题
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\clsregistry.py", line 393, in _resolve_name
rval = d[token]
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\util\_collections.py", line 746, in __missing__
self[key] = val = self.creator(key)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\clsregistry.py", line 372, in _access_cls
return self.fallback[key]
KeyError: 'ProjectMaster'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Administrator\PycharmProjects\test_platform\backend\main.py", line 13, in <module>
from app.system.view import (
File "C:\Users\Administrator\PycharmProjects\test_platform\backend\app\system\view.py", line 11, in <module>
from app.system.schema import (
File "C:\Users\Administrator\PycharmProjects\test_platform\backend\app\system\schema.py", line 15, in <module>
_UserSchema = model_to_schema(User)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\bali\schemas\__init__.py", line 25, in model_to_schema
for attr in mapper.attrs:
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\util\langhelpers.py", line 1184, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\mapper.py", line 2488, in attrs
self._check_configure()
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\mapper.py", line 1924, in _check_configure
_configure_registries({self.registry}, cascade=True)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\mapper.py", line 3483, in _configure_registries
_do_configure_registries(registries, cascade)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\mapper.py", line 3522, in _do_configure_registries
mapper._post_configure_properties()
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\mapper.py", line 1941, in _post_configure_properties
prop.init()
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\interfaces.py", line 231, in init
self.do_init()
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\relationships.py", line 2145, in do_init
self._process_dependent_arguments()
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\relationships.py", line 2240, in _process_dependent_arguments
self.target = self.entity.persist_selectable
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\util\langhelpers.py", line 1113, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\relationships.py", line 2107, in entity
argument = self._clsregistry_resolve_name(self.argument)()
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\clsregistry.py", line 397, in _resolve_name
self._raise_for_name(name, err)
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\orm\clsregistry.py", line 375, in _raise_for_name
util.raise_(
File "C:\ProgramData\Anaconda3\envs\test_platform\lib\site-packages\sqlalchemy\util\compat.py", line 208, in raise_
raise exception
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class User->t_user, expression 'ProjectMaster' failed to locate a name ('ProjectMaster'). If this is a class name, consider adding this relationship() to the <class 'app.system.model.User'> class after both dependent classes have been defined.
由于无法使用model_to_schema
,所以我直接使用的pydantic.BaseModel
去定义的schema
class ModelSerializer(BaseModel):
created_time: datetime | None
updated_time: datetime | None
id: int | None
class Config:
orm_mode = True
fields = {'is_active': {'exclude': True}}
anystr_strip_whitespace = True
max_anystr_length = 120
arbitrary_types_allowed = True
@classmethod
def from_orm(cls: Type, obj: Any) -> ModelSerializer:
# 用来主动调用from_orm datetime->str
original = super().from_orm(obj)
for k, v in original.__fields__.items():
if v.type_ == datetime:
original.__dict__[k] = original.__dict__[k].strftime(settings.DATETIME_FORMAT)
return original
class PermissionSchema(ModelSerializer):
name: constr(min_length=2)
description: constr()
permission_roles: list['Role'] | None
permission_role_ids: list[int] | None
module_id: int
class TagSchema(ModelSerializer):
name: constr(min_length=2)
color: constr(min_length=2)
tag_type: int
description: constr()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.