# Flask-Super
[![image](https://img.shields.io/pypi/v/flask_super.svg)](https://pypi.python.org/pypi/flask_super)
[![Documentation Status](https://readthedocs.org/projects/flask-super/badge/?version=latest)](https://flask-super.readthedocs.io/en/latest/?version=latest)
> "Any sufficiently complicated Python program contains an ad-hoc, informally-specified
> bug-ridden slow implementation of half of the Zope Component Architecture." (S. Fermigier, December 2023).
> [!WARNING]
> Due to PyPI refusing the submission of a package called "FLask-Plus", the package
> has been renamed (temporarily?) "Flask-Super".
>
> (I know this sucks. Either way, it's temporary. Stay tuned.)
## Flask patterns and idoms
- Free software: Apache Software License 2.0
## Features
- Decorator-based registration system for services (using [svcs](https://svcs.hynek.me/))
- Powerful inspection CLI command (`flask inspect` and `flask config`).
- Flask initialisation helpers.
## Status
This is a preview. Expect the API to change.
## Sample usage
```python
import svcs
from flask import Flask
from flask_super import register_services
from flask_super.scanner import scan_package
# Assuming you have developped the proper decorators and registration logic
# in app.lib (or any other module)
from app.lib import register_routes, register_components
def create_app():
app = Flask(__name__)
svcs.flask.init_app(app)
scan_package("app.services")
register_services(app)
# Or just scan a package if using a framework like SQLAlchemy which
# automatically registers classes on import
scan_package("app.models")
# You may also scan custom things (e.g. models, routes, components, etc.)
scan_package("app.routes")
register_routes(app)
scan_package("app.components")
register_components(app)
return app
app = create_app()
```
Currently, `flask-super` provides the following decorators:
- `@service`: register a service with a per-request lifecycle (on the `svcs` registry)
- `@singleton`: register a singleton service (on the `svcs` registry)
## A real-life example
Here is the initialisation code of a Flask application using `flask-super`:
```python
def create_app(config: Any = None) -> Flask:
# When testing
if config:
app = Flask(__name__)
app.config.from_object(config)
# Otherwise
else:
# Not needed when called from CLI, but needed when
# called from a WSGI server
load_dotenv(verbose=True)
app = Flask(__name__)
app.config.from_prefixed_env()
finish_config(app)
init_app(app)
return app
def finish_config(app: Flask):
app.config.from_object("app.config.Config")
def init_app(app: Flask):
# First: Logging & Observability (e.g. sentry)
init_logging(app)
# Scan modules that may provide side effects
scan_package("app.models")
scan_package("app.services")
scan_package("app.controllers")
scan_package("app.cli")
# Scan 3rd-party modules
scan_package("flask_super")
# Extensions, then services
init_extensions(app)
svcs.flask.init_app(app)
register_services(app)
# Web
register_views(app)
register_controllers(app)
# Security
register_rules()
# CLI
register_commands(app)
```
## Credits
This package was created with [Cruft](https://cruft.github.io/cruft/)
and the
[abilian/cookiecutter-abilian-python](https://github.com/abilian/cookiecutter-abilian-python)
project template.
Raw data
{
"_id": null,
"home_page": "https://github.com/abilian/flask-super",
"name": "Flask-Super",
"maintainer": null,
"docs_url": null,
"requires_python": "<4,>=3.10",
"maintainer_email": null,
"keywords": null,
"author": "Abilian SAS",
"author_email": "sf@abilian.com",
"download_url": "https://files.pythonhosted.org/packages/e1/9f/aaad5310781a66ff4f4fb18661a69c90f8e218bae8d6fce6df1f8f643db1/flask_super-0.2.7.tar.gz",
"platform": null,
"description": "# Flask-Super\n\n[![image](https://img.shields.io/pypi/v/flask_super.svg)](https://pypi.python.org/pypi/flask_super)\n\n[![Documentation Status](https://readthedocs.org/projects/flask-super/badge/?version=latest)](https://flask-super.readthedocs.io/en/latest/?version=latest)\n\n> \"Any sufficiently complicated Python program contains an ad-hoc, informally-specified\n> bug-ridden slow implementation of half of the Zope Component Architecture.\" (S. Fermigier, December 2023).\n\n\n> [!WARNING]\n> Due to PyPI refusing the submission of a package called \"FLask-Plus\", the package\n> has been renamed (temporarily?) \"Flask-Super\".\n>\n> (I know this sucks. Either way, it's temporary. Stay tuned.)\n\n\n## Flask patterns and idoms\n\n- Free software: Apache Software License 2.0\n\n\n## Features\n\n- Decorator-based registration system for services (using [svcs](https://svcs.hynek.me/))\n- Powerful inspection CLI command (`flask inspect` and `flask config`).\n- Flask initialisation helpers.\n\n\n## Status\n\nThis is a preview. Expect the API to change.\n\n## Sample usage\n\n```python\n\nimport svcs\nfrom flask import Flask\nfrom flask_super import register_services\nfrom flask_super.scanner import scan_package\n\n# Assuming you have developped the proper decorators and registration logic\n# in app.lib (or any other module)\nfrom app.lib import register_routes, register_components\n\n\ndef create_app():\n app = Flask(__name__)\n\n svcs.flask.init_app(app)\n scan_package(\"app.services\")\n register_services(app)\n\n # Or just scan a package if using a framework like SQLAlchemy which\n # automatically registers classes on import\n scan_package(\"app.models\")\n\n # You may also scan custom things (e.g. models, routes, components, etc.)\n scan_package(\"app.routes\")\n register_routes(app)\n scan_package(\"app.components\")\n register_components(app)\n\n return app\n\n\napp = create_app()\n```\n\nCurrently, `flask-super` provides the following decorators:\n\n- `@service`: register a service with a per-request lifecycle (on the `svcs` registry)\n- `@singleton`: register a singleton service (on the `svcs` registry)\n\n\n## A real-life example\n\nHere is the initialisation code of a Flask application using `flask-super`:\n\n```python\ndef create_app(config: Any = None) -> Flask:\n # When testing\n if config:\n app = Flask(__name__)\n app.config.from_object(config)\n\n # Otherwise\n else:\n # Not needed when called from CLI, but needed when\n # called from a WSGI server\n load_dotenv(verbose=True)\n\n app = Flask(__name__)\n app.config.from_prefixed_env()\n\n finish_config(app)\n\n init_app(app)\n return app\n\n\ndef finish_config(app: Flask):\n app.config.from_object(\"app.config.Config\")\n\n\ndef init_app(app: Flask):\n # First: Logging & Observability (e.g. sentry)\n init_logging(app)\n\n # Scan modules that may provide side effects\n scan_package(\"app.models\")\n scan_package(\"app.services\")\n scan_package(\"app.controllers\")\n scan_package(\"app.cli\")\n\n # Scan 3rd-party modules\n scan_package(\"flask_super\")\n\n # Extensions, then services\n init_extensions(app)\n svcs.flask.init_app(app)\n register_services(app)\n\n # Web\n register_views(app)\n register_controllers(app)\n\n # Security\n register_rules()\n\n # CLI\n register_commands(app)\n```\n\n## Credits\n\nThis package was created with [Cruft](https://cruft.github.io/cruft/)\nand the\n[abilian/cookiecutter-abilian-python](https://github.com/abilian/cookiecutter-abilian-python)\nproject template.\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Patterns and idioms for Flask applications.",
"version": "0.2.7",
"project_urls": {
"Homepage": "https://github.com/abilian/flask-super"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "76e84be66da4c1ecb54694af46097e7ef84cc49f4ad28270c14992da52c13ce0",
"md5": "e4cb283f6ee0a2c063a0947cece4eb47",
"sha256": "4d5af6a560306565722ea8490f30d79f199b2f171b99e900d0407a368c375a73"
},
"downloads": -1,
"filename": "flask_super-0.2.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e4cb283f6ee0a2c063a0947cece4eb47",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4,>=3.10",
"size": 9174,
"upload_time": "2024-05-01T14:09:14",
"upload_time_iso_8601": "2024-05-01T14:09:14.855463Z",
"url": "https://files.pythonhosted.org/packages/76/e8/4be66da4c1ecb54694af46097e7ef84cc49f4ad28270c14992da52c13ce0/flask_super-0.2.7-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e19faaad5310781a66ff4f4fb18661a69c90f8e218bae8d6fce6df1f8f643db1",
"md5": "8f9c215085cf2d96a7919be91ed01fa8",
"sha256": "332ca73be362c1f97a5c44f03434dc00fe005a16d8a203d4a3253929430412f1"
},
"downloads": -1,
"filename": "flask_super-0.2.7.tar.gz",
"has_sig": false,
"md5_digest": "8f9c215085cf2d96a7919be91ed01fa8",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4,>=3.10",
"size": 9193,
"upload_time": "2024-05-01T14:09:16",
"upload_time_iso_8601": "2024-05-01T14:09:16.530747Z",
"url": "https://files.pythonhosted.org/packages/e1/9f/aaad5310781a66ff4f4fb18661a69c90f8e218bae8d6fce6df1f8f643db1/flask_super-0.2.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-01 14:09:16",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "abilian",
"github_project": "flask-super",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "flask-super"
}