Bottle Documentation

repository·master·Indexed 27 days ago

https://github.com/bottlepy/bottle

Bottle is a fast, simple, and lightweight WSGI micro web-framework for Python, distributed as a single-file module with no external dependencies beyond the Python Standard Library. It provides tools for routing via decorators, request and response handling, plugin support, application hooks, and static file serving. It includes a built-in development server and supports various server adapters such as wsgiref, waitress, and gunicorn.

Tokens
24.6K
Snippets
65
Records
137
Agent score
91%

What's inside Bottle

  1. Overview of Bottle features

    master

    Bottle is a fast, simple, and lightweight WSGI micro web-framework for Python. Key features include:

    • Routing: Mapping requests to function calls with support for clean and dynamic URLs.
    • Templates: A fast built-in template engine with support for external engines like mako, jinja2, and cheetah.
    • Utilities: Easy access to HTTP features such as form data, file uploads, cookies, and headers.
    • Server: Includes a built-in development server and adapters for WSGI-capable servers like gunicorn, paste, or cheroot.
  2. Explore 3rd Party Plugins for Bottle

    master

    Bottle supports a variety of third-party plugins to extend its core functionality, including integrations for databases, authentication, caching, and more.

    Common categories of plugins include:

    • Databases/ORMs: Bottle-Sqlalchemy, Bottle-Mongo, Bottle-Redis, Bottle-Sqlite, Macaron (SQLite ORM), and Bottle-Web2pydal.
    • Authentication/Security: Bottle-Cork (AuthN/AuthZ), Bottle-OAuthlib (OAuth2.0), bottle-jwt, and bottlejwt.
    • Caching/Sessions: Bottle-Beaker (Session/Caching via WSGI Middleware) and Bottle-Memcache.
    • Utilities: Bottle-Cors-plugin (CORS), Bottle-Flash (Flash messages), Bottle-Servefiles (Static files), and Bottle-Werkzeug (Advanced debugging/Request objects).
    • Collections: Bottle-Extras is a meta-package used to install a collection of Bottle plugins.

    Note: These plugins are maintained by third parties and are not part of the official Bottle project.

  3. Create a 'Hello World' application

    master

    You can create a basic web application by using the route decorator to map URLs to functions, the template function to render HTML, and the run function to start the built-in development server.

    from bottle import route, run, template
    
    @route('/hello/<name>')
    def index(name):
        return template('<b>Hello {{name}}</b>!', name=name)
    
    run(host='localhost', port=8080)
  4. Implement WebSockets with gevent-websocket

    master

    To support bidirectional WebSockets in Bottle, use the gevent-websocket package and its WebSocketHandler.

    1. Access the WebSocket object via request.environ.get('wsgi.websocket').
    2. Use a loop to receive() messages and send() responses.
    3. Catch WebSocketError to detect when the client closes the connection.
    4. Run the application using gevent.pywsgi.WSGIServer with the WebSocketHandler class.
    from bottle import request, Bottle, abort
    from gevent.pywsgi import WSGIServer
    from geventwebsocket import WebSocketError
    from geventwebsocket.handler import WebSocketHandler
    
    app = Bottle()
    
    @app.route('/websocket')
    def handle_websocket():
        wsock = request.environ.get('wsgi.websocket')
        if not wsock:
            abort(400, 'Expected WebSocket request.')
    
        while True:
            try:
                message = wsock.receive()
                wsock.send("Your message was: %r" % message)
            except WebSocketError:
                break
    
    server = WSGIServer(("0.0.0.0", 8080), app,
                        handler_class=WebSocketHandler)
    server.serve_forever()
  5. Simulate asynchronous event callbacks using gevent.queue

    master

    In standard asynchronous frameworks, you use callbacks to write to a socket. In Bottle (WSGI), you must return an iterable. To bridge this, use gevent.queue.Queue as your body iterable.

    1. Create a gevent.queue.Queue().
    2. Pass the queue's .put method as a callback to your async worker.
    3. Signal the end of the stream by putting StopIteration into the queue.
    4. Return the queue object from your route handler.
    @route('/fetch')
    def fetch():
        body = gevent.queue.Queue()
        worker = SomeAsyncWorker()
        worker.on_data(body.put)
        worker.on_finish(lambda: body.put(StopIteration))
        worker.start()
        return body
  6. Install Bottle and set up a virtual environment

    master

    To install Bottle following Python best practices, create a virtual environment (venv), activate it, and use pip to install the bottle package. Bottle has no dependencies other than Python itself.

    Note on Python Versions: This tutorial assumes Python 3.10 or newer. If using Python 3.8 or 3.9, you must replace match statements with if-elif-else cascades. If using Python 2.7, you must replace f-strings with standard string formatting methods.

    python -m venv bottle_venv
    cd bottle_venv
    #for Linux & MacOS
    source bin/activate
    #for Windows
    .\Scripts\activate
    pip3 install bottle
  7. Manage documentation translations via Transifex

    master

    The Bottle documentation uses Transifex for translation workflows. If you have modified the documentation, you can push new messages to Transifex using make push. To update your local translation files with the latest changes from the platform, use make pull.

    Note: Both make push and make pull require a Transifex manager account. For actual translation work, you can use a standard Transifex user account at https://www.transifex.com/bottle.

  8. Configure plugins via constructors or Bottle.config

    master

    Plugins can be configured in two primary ways:

    1. Constructor Parameters: Pass configuration directly when instantiating the plugin (e.g., database connection strings).
    2. Bottle.config: Newer plugins can read values from the Bottle.config dictionary. This allows for easier deployment overrides and runtime changes.

    Note: Plugin authors can also inspect route parameters (including custom ones) to change behavior dynamically (e.g., a database plugin starting a transaction if a route accepts a db keyword).

  9. Understand Bottle versioning and release behavior

    master

    Bottle uses a major.minor.patch versioning scheme that does not strictly follow SemVer. Understanding these rules helps you manage updates:

    • Major Release (x.0): Significant milestones that change core design and break backward compatibility. Application code changes are likely required.
    • Minor Release (x.y): New APIs or backward-incompatible behavior changes. Usually designed to be backward compatible for at least one minor release, but you may see deprecation warnings.
    • Patches (x.y.z): Bug-fixes and security patches that do not change APIs or behavior. These are safe to update immediately.
    • Pre-Release Versions: Marked with rc (e.g., 0.13.4rc1). These are API-stable but intended for testing, not production.
  10. Clone the Bottle development repository

    master

    You can obtain the Bottle source code via Git or by downloading source archives. For active development, cloning the repository is recommended.

    git clone git://github.com/bottlepy/bottle.git
    # or
    git clone https://github.com/bottlepy/bottle.git
  11. Handle HTML Form POST data

    master

    When a form is submitted via POST, the data is stored in request.forms. Ensure your HTML form uses method="post".

    from bottle import route, request
    
    @route('/login', method='POST')
    def do_login():
        username = request.forms.username
        password = request.forms.password
        if check_login(username, password):
            return "<p>Your login information was correct.</p>"
        else:
            return "<p>Login failed.</p>"
  12. Handle trailing slashes in routes

    master

    In Bottle, /example and /example/ are distinct routes. To treat them identically, you can use one of three methods:

    1. Multiple Decorators: Add both @route('/path') and @route('/path/') to the function.
    2. WSGI Middleware: Use a middleware to strip trailing slashes from PATH_INFO before it reaches Bottle.
    3. before_request Hook: Use a Bottle hook to modify the request path.
    # Option 1: Multiple decorators
    @route('/test')
    @route('/test/')
    def test(): return 'Slash? no?'
    
    # Option 2: WSGI Middleware
    class StripPathMiddleware(object):
      def __init__(self, app):
        self.app = app
      def __call__(self, e, h):
        e['PATH_INFO'] = e['PATH_INFO'].rstrip('/')
        return self.app(e,h)
    
    # Option 3: before_request hook
    @hook('before_request')
    def strip_path():
        request['PATH_INFO'] = request['PATH_INFO'].rstrip('/')