Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/alecthomas/waffle
Waffle - A Dependency-Injection-based application framework for Python
https://github.com/alecthomas/waffle
Last synced: 16 days ago
JSON representation
Waffle - A Dependency-Injection-based application framework for Python
- Host: GitHub
- URL: https://github.com/alecthomas/waffle
- Owner: alecthomas
- Created: 2013-06-06T17:01:41.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2024-01-01T17:12:26.000Z (11 months ago)
- Last Synced: 2024-10-10T16:06:15.234Z (about 1 month ago)
- Language: Python
- Size: 343 KB
- Stars: 5
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Waffle - A Dependency-Injection-based Python Application Framework
Waffle provides common functionality for bootstrapping an application using [Injector](https://github.com/alecthomas/injector).
The general approach used by the Injector modules in Waffle is to use flags to configure the behaviour of objects exported by the modules. The flag defaults can (and sometimes must) be overridden by the `@main` decorator or `run()` function.
For example, `waffle.redis.RedisModule` relies on the flag `--redis_server` to connect to a Redis server, which defaults to `localhost:6379:0`. To configure and use the Redis module you might do something like this:
```python
from waffle import main@main(redis_server='redis.domain.com:6379:1')
def main(injector):
redis = injector.get(Redis)
```Waffle provides:
1. Command line flag parsing via argh.
2. Injection of flags.
3. Construction of the injector.
4. A bunch of modules that provide different integration: Redis, SQLAlchemy, Flask, logging, etc.## Examples
### A bare bones application
```python
from waffle import main@main
def main():
print 'Hello world'
```### Injecting modules
A slightly more complex example injecting the logging module:
```python
from waffle import LoggingModule, main@main(debug=True)
@modules(LoggingModule)
def main():
...
````@main` should be the last statements in the module.
### A full example web server with database
This example illustrates several aspects of Waffle:
- How to set defaults for flags by passing the flags as keyword arguments to either `main()` or `run()`.
- The use of the convenience Injector modules `AppModules` and `WebModules`, which install commonly used modules for applications and web applications, respectively. See [below](#available-modules) for details.- Use of the `@transaction` decorator to wrap requests in an SQLAlchemy transaction.
```python
from injector import inject
from sqlalchemy import Column, Stringfrom waffle import AppModules, WebModules, \
Model, WebApplication, routes, main, modules, route, \
transaction, csrf_exemptclass KeyValue(Model):
key = Column(String, primary_key=True)
value = Column(String)@route('/')
@transaction
def index():
return [(kv.key, kv.value) for kv in KeyValue.query.all()]@route('/')
@transaction
@csrf_exempt
def get_or_create(request, key):
kv = KeyValue.query.filter_by(key=key).all()
if kv:
kv = kv[0]
if request.method == 'POST':
if kv:
kv.value = request.data
else:
kv = KeyValue(key=key, value=request.data)
kv.save()
return {'status': 'OK'}return {'key': kv.key, 'value': kv.value}
@main(database_uri='sqlite:///:memory:', static_root='./static/',
template_root='./templates/')
@modules(AppModules, WebModules)
@inject(app=WebApplication)
def main(app):
app.serve(port=8081, use_reloader=False)```
## Available modules
### waffle.common.AppModules (composite)
Installs `waffle.db.DatabaseModule` and `waffle.db.LoggingModule`.
### waffle.web.common.WebModules (composite)
Installs `waffle.web.clastic.WebModule`, `waffle.web.db.DatabaseSessionModule`, `waffle.web.template.TemplateModule` and `waffle.web.csrf.CsrfModule`.
### waffle.db.DatabaseModule
Configure SQLAlchemy to work with injection.
Binds a configured SQLAlchemy `Session` to the injector.
```python
from sqlalchemy.orm import String
from sqlalchemy.orm.session import Session
from waffle import DatabaseModule, Base, main, modulesclass KeyValue(Base):
key = String()
value = String()@main(database_uri='sqlite:///tmp/test.db')
@modules(DatabaseModule)
def main(injector):
session = injector.get(Session)
...
```### waffle.log.LoggingModule
Configures some default basic logging.
Binds the key `LogLevel` to the specified log level.
### waffle.devel.DevelModule
A module that binds the gevent `BackdoorServer`, allowing the developer to attach to a Python shell in the application.
Use like so:
```python
injector.get(BackdoorServer).start()
```### waffle.web.clastic.WebModule
Integrates [Clastic](https://github.com/mahmoud/clastic) through an injector module. This is the core module for providing web application support.
### waffle.web.db.DatabaseSessionModule
A module that manages DB session lifecycle in HTTP requests. This basically resets the session at the end of each request.
### waffle.web.template.TemplateModule
A module that provides template loading and the ability for separate modules to contribute to the global template rendering context. Useful for eg. adding global debug variables, etc.
To contribute to global template context:
```python
binder.multibind(TemplateContext, to={
'debug': debug,
})
```### waffle.web.csrf.CsrfModule
Enable CSRF support in templates.
### waffle.redis.RedisModule
Provides a Redis client configured by flags:
```python
from redis import Redis@inject(redis=Redis)
def get(redis):
return redis.get('some_key')
```