{"id":13424955,"url":"https://github.com/bali-framework/bali","last_synced_at":"2025-04-06T15:11:51.451Z","repository":{"id":36952174,"uuid":"303596896","full_name":"bali-framework/bali","owner":"bali-framework","description":"Simplify declarative cloud-native development base on FastAPI and gRPC. https://bali-framework.github.io/bali/","archived":false,"fork":false,"pushed_at":"2024-07-19T03:51:16.000Z","size":1531,"stargazers_count":273,"open_issues_count":11,"forks_count":34,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-30T14:09:42.592Z","etag":null,"topics":["fastapi","grpc","micorservices","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bali-framework.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-13T05:25:45.000Z","updated_at":"2025-03-30T12:35:31.000Z","dependencies_parsed_at":"2023-12-05T07:24:33.683Z","dependency_job_id":"14df4b15-8904-40f9-ad80-3d649f2f5e1b","html_url":"https://github.com/bali-framework/bali","commit_stats":{"total_commits":437,"total_committers":10,"mean_commits":43.7,"dds":"0.33409610983981697","last_synced_commit":"efa992fb061dbee182fd65e6a659253b8ddb239c"},"previous_names":[],"tags_count":80,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bali-framework%2Fbali","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bali-framework%2Fbali/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bali-framework%2Fbali/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bali-framework%2Fbali/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bali-framework","download_url":"https://codeload.github.com/bali-framework/bali/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247500468,"owners_count":20948880,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","grpc","micorservices","python"],"created_at":"2024-07-31T00:01:01.214Z","updated_at":"2025-04-06T15:11:51.428Z","avatar_url":"https://github.com/bali-framework.png","language":"Python","funding_links":[],"categories":["Projects","Python","Language-Specific"],"sub_categories":["Open Source Projects","Python"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/bali-framework/bali/master/docs/img/bali.png\" alt='bali framework' /\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003e🏝 Simplify Cloud Native Microservices development base on FastAPI and gRPC.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://pepy.tech/project/bali-core\"\u003e\n        \u003cimg src=\"https://pepy.tech/badge/bali-core\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/bali-core/\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/v/bali-core\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/bali-framework/bali/actions/workflows/python-ci.yml\"\u003e\n      \u003cimg src=\"https://github.com/bali-framework/bali/actions/workflows/python-ci.yml/badge.svg\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n**Documentation**: [https://bali-framework.github.io/bali/](https://bali-framework.github.io/bali/)\n\n---\n\n# Bali\n\nBali is a framework integrate FastAPI and gRPC. \nIf you want to provide both HTTP and RPC, it can improve development efficiency.\n\nIt gives you the following features:\n\n* A simple layout of file structure rule.\n* Integrated `SQLAlchemy` ORM and provide generic model methods.\n* Utilities of transform models to Pydantic schemas.\n* GZipMiddleware included and GZip decompression enabled.\n* 🍻 **Resource** layer to write code once support both HTTP and RPC\n\n## Who's using bali framework\n\n\u003ca href=\"https://www.360shuke.com/\"\u003e\n    \u003cimg width=\"200\" src=\"https://raw.githubusercontent.com/bali-framework/bali/master/docs/img/cases/qfin.png\" /\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://www.xinfei.cn/\"\u003e\n    \u003cimg width=\"200\" src=\"https://raw.githubusercontent.com/bali-framework/bali/master/docs/img/cases/xinfei.png\" /\u003e\n\u003c/a\u003e\n\n## Requirements\n\n    1. Python 3.7+\n    2. FastAPI 0.63+\n    3. grpcio\u003e=1.32,\u003c1.50\n\n\n## Install\n\n```bash\npip install bali-core # Bali framework \npip install bali-cli # Bali command line tool \n```\n\n## Project structure layout\n\n\n## Application \n\nCreate Application\n\n```python\napp = Bali() # Initialized App\n```\n\nLaunch \n\n```bash\n\n# With bali-cli \nbali run http\nbali run rpc\nbali run event\n\npython main.py run --http  # launch HTTP in development mode \npython main.py run --rpc  # launch RPC \npython main.py run --event  # launch Event \n```\n\nMore usage of `Application`: [example](examples/main.py)\n\n\n## Database \n\n### connect\n\n```python\nfrom bali import db\n\n# connect to database when app started\n# db is a sqla-wrapper instance\ndb.connect('DATABASE_URI')  \n  \n```\n\n### Declarative mode with sqla-wrapper\n\n```python\n\nclass User(db.Model):\n    __tablename__ \"users\"\n    id = db.Column(db.Integer, primary_key=True)\n    ...\n\ndb.create_all()\n\ndb.add(User(...))\ndb.commit()\n\ntodos = db.query(User).all()\n```\n\nMore convenient usage, ref to [SQLA-Wrapper](https://github.com/jpsca/sqla-wrapper)\n\n\n### Declare models inherit from convenient base models\n\n*BaseModel*\n\n```python\n# using BaseModel\nclass User(db.BaseModel):\n    __tablename__ \"users\"\n    id = db.Column(db.Integer, primary_key=True)\n    ...\n```\n\n```python\n# BaseModel's source code \n\nclass BaseModel(db.Model):\n    __abstract__ = True\n\n    created_time = Column(DateTime(timezone=True), default=datetime.utcnow)\n    updated_time = Column(\n        DateTime(timezone=True), default=datetime.utcnow, onupdate=datetime.utcnow\n    )\n    is_active = Column(Boolean(), default=True)\n```\n\n### Transaction\n\nSQLA-wrapper default model behavior is auto commit, auto commit will be disabled with `db.transaction` context. \n\n```python\nwith db.transaction():\n    item = Item.create(name='test1')\n```\n\n### Operators\n\nOperators provided `get_filters_expr` to transform filters (dict) to SQLAlchemy expressions.  \n\n```python\nfrom bali.db.operators import get_filters_expr\nfrom models import User\n\nusers = User.query().filter(*get_filters_expr(User, **filters)).all()\n```\n\n## Schema\n\n*model_to_schema*\n\n```python\n# generate pydantic schema from models\n# `User` is a db.Model or db.BaseModel instance \nfrom bali.schemas import model_to_schema\nUserSchema = model_to_schema(User)\n```\n\n## Resource\n\n\u003ci\u003eNew in version 2.0.\u003c/i\u003e\n\nResource’s design borrows several key concepts from the REST architectural style.\n\nInspired by `ViewSet` in Django REST Framework.\n\nActions' name according [`Standard methods` in Google API design guide](https://cloud.google.com/apis/design/standard_methods) \n\n### Generic HTTP/RPC Actions\n\nGeneric HTTP/RPC support actions:\n\n|Action |Route |Method | RPC  | Description|\n--- |--- | --- | --- | ---\n|get |/{id} |GET |Get{Resource} |Get an existing resource matching the given id |\n|list |/ |GET |List{Resource} |Get all the resources |\n|create |/ |POST |Create{Resource} |Create a new resource |\n|update |/{id} |PATCH |Update{Resource} |Update an existing resource matching the given id |\n|delete |/{id} |DELETE |Delete{Resource} |Delete an existing resource matching the given id |\n\nGeneric Actions examples:\n\n```python\n\n# 1. import `Resource` base class\nfrom bali.resources import Resource\n\n\n# 2. implementation actions inherited from Resource\n\nclass GreeterResource(Resource):\n\n    schema = Greeter\n\n    @action()\n    def get(self, pk=None):\n        return [g for g in GREETERS if g.get('id') == pk][0]\n\n    @action()\n    def list(self, schema_in: ListRequest):\n        return GREETERS[:schema_in.limit]\n\n    @action()\n    def create(self, schema_in: schema):\n        return {'id': schema_in.id, 'content': schema_in.content}\n\n    @action()\n    def update(self, schema_in: schema, pk=None):\n        return {'id': pk, 'content': schema_in.content}\n\n    @action()\n    def delete(self, pk=None):\n        return {'id': pk, 'result': True}  # using `id` instand of `result`\n\n```\n\n\n### Custom HTTP/RPC Actions\n\nCustom actions also decorated by `@action`, but `detail` signature is required.\n\n```python\n@action(detail=False)\ndef custom_action(self):\n    pass\n```\n\n`detail` has no default value.\n\u003e `True` means action to single resource, url path is '/{resources}/{id}'.\n\u003e \n\u003e `False` means action set of resources, url path is '/{resources}'.\n\u003e \n\n### Override HTTP Actions\n\nIf the default HTTP action template is not satisfied your request, you can override HTTP actions.\n\n```python\n# Get the origin router \nrouter = GreeterResource.as_router()\n\n# Override the actions using the FastAPI normal way\n@router.get(\"/\")\ndef root():\n    return {\"message\": \"Hello World\"}\n```\n\n\u003e More usage of `Resource`: [GreeterResource](examples/resources/greeter.py)\n\n\n### ModelResource\n\n\u003ci\u003eNew in version 2.1.\u003c/i\u003e\n\n```python\nclass UserResource(ModelResource):\n    model = User\n    schema = UserSchema\n    filters = [\n        {'username': str},\n        {'age': Optional[str]},\n    ]  # yapf: disable\n    permission_classes = [IsAuthenticated]\n```\n\n\n## Service Mixin\n\n```python\n# import \nfrom bali.mixins import ServiceMixin\n\nclass Hello(hello_pb2_grpc.HelloServiceServicer, ServiceMixin):\n    pass\n```\n\n## Cache\n\n### Cache API\n\n```python\nfrom bali import cache\n\n# Usage example (API)\n\n# Read cache \ncache.get(key)\n\n# Set cache \ncache.set(key, value, timeout=10)\n```\n\n### cache memoize\n\n```python\n# Import the cache_memoize from bali core \nfrom bali import cache_memoize\n\n# Attach decorator to cacheable function with a timeout of 100 seconds.\n@cache_memoize(100)\ndef expensive_function(start, end):\n    return random.randint(start, end)\n```\n\n## Utils\n\n**dateparser** \n\n[dateparser docs](https://dateparser.readthedocs.io/en/v1.0.0/)\n\n**MessageToDict/ParseDict**\n\nOptimized MessageToDict/ParseDict from `google.protobuf.js_format`\n\n```python\nfrom bali.utils import MessageToDict, ParseDict\n```\n\n## Tests\n\n**gRPC service tests**\n\n```python\nfrom bali.tests import GRPCTestBase\nfrom service.demo import demo_service, demo_pb2, demo_pb2_grpc\n\n\nclass TestDemoRPC(GRPCTestBase):\n    server_class = demo_service.DemoService  # Provided service \n\n    pb2 = demo_pb2  # Provided pb2\n    pb2_grpc = demo_pb2_grpc  # Provided pb2 grpc\n\n    def setup_method(self):  # Pytest setup \n        pass\n\n    def teardown_method(self):  # Pytest teardown\n        pass\n\n    def test_demo(self):\n        pass\n```\n\n## Related Projects\n\n[![bali-cli](https://github-readme-stats.vercel.app/api/pin/?username=bali-framework\u0026repo=bali-cli)](https://github.com/bali-framework/bali-cli)\n[![cookiecutter-bali](https://github-readme-stats.vercel.app/api/pin/?username=bali-framework\u0026repo=cookiecutter-bali)](https://github.com/bali-framework/cookiecutter-bali)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbali-framework%2Fbali","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbali-framework%2Fbali","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbali-framework%2Fbali/lists"}