This content originally appeared on DEV Community and was authored by Mateusz Charytoniuk
Intention is a Python framework designed to increase productivity when developing applications. Simplicity, productivity, and great developer experience are our primary goals.
It is based on an innovative Role-Based Services approach. (more info below).
It is async and thus performs well with IO-bound services (for example, anything that makes a lot of long-running HTTP calls to large language models or uses a lot of microservices and third-party services)—but not just those.
Try it out
Intention will take only a few minutes to set up, and it might amaze you and change how you develop apps. :)
Key Features
- Effortlessly split your project into multiple files: Intention automatically combines your project files based on the roles you assign them, making it easy to manage large projects.
- Dependency Injection: Manage your application's dependencies effortlessly with a container that holds one instance of each service, ensuring efficient resource management.
- Async-First: Intention is optimized for asynchronous programming, making it perfect for IO-bound tasks.
- Minial boilerplate: Intention adds no redundant boilerplate code. Keep your project as simple as possible.
Installation
Requirements
Linux or MacOS (should work on all Unix systems). It does not work on Windows because Intention requires the fork
multiprocessing method (which Windows does not have).
That might change in the future (see also: https://github.com/emmett-framework/granian/issues/330).
Steps
Intention works best with Poetry. Install Poetry first and follow the steps:
-
Create a new project. Invoke the command and fill in the project creation form:
poetry init my_app
-
In the project's directory (the one with the newly created
pyproject.toml
) open:
poetry shell
-
Install Intention locally in the project:
poetry add intention
-
Create your application's module:
mkdir my_app
```shell
touch my_app/__init__.py
```
-
Create the
app.py
(primary application file). That is the entire boilerplate code that Intention needs to work:
import my_app import intention intention.start(my_app).exit_after_finishing()
Invoking python ./app.py
should display something like:
usage: app.py [-h] {hello,serve} ...
Intention CLI
positional arguments:
{serve}
serve Start the app in HTTP server mode
options:
-h, --help show this help message and exit
Congratulations! You have installed the Intention project. You can continue with the next steps.
Usage
Check the demo project for basic usage.
Intention will scan your module (in this case, my_app
) for services with a role decorator and start your CLI application. That's it!
If you want to start developing something new, add a new CLI command. Use responds_to_cli
role. Add a new file in my_app/hello_command.py
(file name can be anything; it's just an example - file names and directory structure do not matter for Intention):
from intention.cli_foundation import Command
from intention.role import responds_to_cli
@responds_to_cli(
name="hello",
description="Say hello!",
)
class Hello(Command):
def respond(self) -> int:
print("Hello, World!")
return 0
You can then run it with:
python ./app.py hello
You should see:
Hello, World!
Why Intention?
Intention's unique Role-Based Services approach allows for clear and organized code. It scans your project for services decorated as roles
and automatically combines them. It takes care of all the tedious work and allows you to focus on the application architecture.
Suitable for Bigger Projects
Intention allows you to split your HTTP responders and other modules among multiple files.
You do not have to manually combine the project files. Intention treats role.*
decorators as metadata and puts them together for you.
from intention.role import responds_to_http
from intention.http import Responder, JinjaResponse
from intention.http_foundation import Request
@responds_to_http(pattern="/")
class Homepage(Responder):
async def respond(self, request: Request):
return JinjaResponse("homepage.j2")
Dependency Injection
Intention allows you to inject services into your responders and other modules.
It is possible to create service providers for more advanced use cases.
from intention.role import service_provider
from intention.service_provider.service_provider import ServiceProvider
from jinja2 import Environment, PackageLoader, select_autoescape
@service_provider(provides=Environment)
class JinjaEnvironmentServiceProvider(ServiceProvider[Environment]):
def provide(self) -> Environment:
return Environment(
auto_reload=False,
enable_async=True,
loader=PackageLoader('mymodule'),
autoescape=select_autoescape(),
)
Then, you can inject the service into your responders and other modules.
No further configuration is needed (just the type hint).
from intention.role import service
from jinja2 import Environment
@service
class MyService:
def __init__(self, env: Environment):
self.env = env
async def render_something(self):
return self.env.get_template('foo.j2').render()
Special Thanks
- Granian for creating an awesome HTTP Python runner with excellent performance
This content originally appeared on DEV Community and was authored by Mateusz Charytoniuk
Mateusz Charytoniuk | Sciencx (2024-06-18T00:22:13+00:00) Introducing Intention: A High-Performance RSGI Framework for Python. Retrieved from https://www.scien.cx/2024/06/18/introducing-intention-a-high-performance-rsgi-framework-for-python/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.