Table of contents
1.
Introduction
2.
Common Use Cases in Bottle Framework 
2.1.
Keeping Track of Sessions 
2.2.
Debugging with Style: Debugging Middleware
2.3.
Unit Testing Bottle Applications
2.4.
Functional Testing of Bottle Application
2.5.
Embedding other WSGI Applications
2.6.
Ignore Trailing Slashes
2.7.
Keep Alive Request 
2.8.
GZIP Compression in Bottle 
2.9.
Using the Hooks Plugin                   
2.10.
Using Bottle with Heroku
3.
Frequently Asked Questions
3.1.
What is Bottle API?
3.2.
Is Bottle an MVC framework?
3.3.
Explain WSGI in Python.
3.4.
Why do I require WSGI?
3.5.
Bottle or Flask, which is better?
4.
Conclusion
Last Updated: Mar 27, 2024
Medium

How to Deal with Common Use Cases in Bottle Framework - Python

Author Ishita mishra
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

You might wonder, "Why did the Bottle framework become popular among web developers?" 

The Bottle web framework has a 4% market share among Python web frameworks and is ranked fifth in popularity. It is excellent for rapid development, personal web applications, and prototyping. 

Common Use Cases in the Bottle Framework

Read the following article to understand how to deal with Common Use Cases in the Bottle Framework in Python. 

Common Use Cases in Bottle Framework 

This is a collection of code samples and Common Use Cases in the Bottle Framework.

Keeping Track of Sessions 

Due to the lack of a recommended method, there is no built-in support for sessions (in a micro framework). You could either utilize beaker middleware with a suitable backend or write it yourself, depending on the circumstances and environment. An illustration of a beaker session with a file-based backend in this Common Use Cases in the Bottle Framework is shown below:

import bottle
from beaker.middleware import SessionMiddleware
session_opts = {
    'session.type': 'file',
    'session.cookie_expires': 300,
    'session.data_dir': './data',
    'session.auto': True
}
app = SessionMiddleware(bottle.app(), session_opts)

@bottle.route('/test')
def test():
  s = bottle.request.environ.get('beaker.session')
  s['test'] = s.get('test',0) + 1
  s.save()
  return 'Test counter: %d' % s['test']
bottle.run(app=app)


Caution⚠️ SessionMiddleware from Beaker is not thread-safe. One of the updates may be lost if two requests edit the same session simultaneously. Sessions should be handled as a read-only store after their initial populating. Consider using an actual database instead of session middleware packages if you frequently update sessions and don't want to lose any updates in this Common Use Cases in the Bottle Framework.

Debugging with Style: Debugging Middleware

Bottle catches any Exceptions raised in your app code to prevent the failure of your WSGI server.  You can disable this behavior if the built-in debug() mode is insufficient, and you require exceptions to propagate to a debugging middleware:
 

import bottle
app = bottle.app()
app.catchall = False                  #Most bottle exceptions are raised again.
myapp = DebuggingMiddleware(app)      #Replace it with a middleware of your choosing (see below)
bottle.run(app=myapp)

 

Now that your middleware can handle the rest, Bottle only catches its exceptions (HTTPErrorHTTPResponse, and BottleException).

The werkzeug and paste libraries have fairly powerful WSGI middleware for debugging. Take a look at werkzeug.debug.DebuggedApplication for paste and werkzeug in paste.evalexception.middleware.EvalException  when trying to paste. Please do not use them in production because they allow you to inspect the stack and even run Python code inside the stack context.

Unit Testing Bottle Applications

A WSGI environment is typically not operating during unit testing against methods defined in your web application’s Common Use Cases in the Bottle Framework.

An easy illustration with Nose:

import bottle
@bottle.route('/')
def index():
    return 'Hello'
if __name__ == '__main__':
    bottle.run()

 

A test script:

import mywebapp
def test_webapp_index():
    assert mywebapp.index() == 'Hello'

 

Only index() is tested in the example; the Bottle route() method is never used.

You can use Boddle to simulate bottle.request if the code being tested needs access to it:

 import bottle
@bottle.route('/')
def index():
    return 'HELLO %s!' % bottle.request.params['name']


A test script:

import mywebapp
from boddle import boddle
def test_webapp_index():
    with boddle(params={'name':'CodingNinjas'}):
        assert mywebapp.index() == 'HELLO CodingNinjas'

Functional Testing of Bottle Application

One of the most frequent Common Use Cases in the Bottle Framework can be used with any HTTP-based testing system. However, some testing frameworks have a closer relationship with WSGI and offer the ability to call WSGI apps in a controlled environment with tracebacks and full access to debugging tools. An excellent place to begin is by Testing the tools for WSGI.

Functional Testing

An illustration using WebTest and Nose:

  from webtest import TestApp
import mywebapp
def test_functional_login_logout():
    app = TestApp(mywebapp.app)
    app.post('/login', {'user': 'foo', 'pass': 'bar'})    #recieve cookie by logging in
    assert app.get('/admin').status == '200 OK'           # successfully retrieve a page.
    assert app.get('/logout').status_code == 200          # logout
    app.reset()                                           # Set the cookie down

# attempt to obtain the same page in vain
    assert app.get('/admin', expect_errors=True).status == '401 Unauthorized error'
Functional Testing of Bottle Framework

Embedding other WSGI Applications

You can access other WSGI applications from within your bottle and let the bottle operate as pseudo-middleware. At the same time, this is not the recommended method (you should use middleware in front of the bottle to do this). Here's an illustration of this Common Use Cases in the Bottle Framework:

  from bottle import request, response, route
    subproject = SomeWSGIApplication()
    
    @route('/subproject/<subpath:re:.*>', method='ANY')
    def call_wsgi(subpath):
        new_environ = request.environ.copy()
        new_environ['SCRIPT_NAME'] = new_environ.get('SCRIPT_NAME','') + '/subproject'
        new_environ['PATH_INFO'] = '/' + subpath
        def start_response(status, headerlist):
            response.status = int(status.split()[0])
            for key, value in headerlist:
                response.add_header(key, value)
        return app(new_environ, start_response)


Once more, it is not advised to implement subprojects in this manner. It is just present because many people requested it to demonstrate how bottle maps to WSGI.

Ignore Trailing Slashes

It is one of the most Common Use Cases in the Bottle Framework. Both /example and /example/ are distinct routes in Bottle. The following two @route decorators can be added to treat both URLs equally:

        @route('/test')
@route('/test/')
def test(): return 'Slash? no?'


A WSGI middleware that removes trailing slashes from all URLs should be added:

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)
app = bottle.app()
myapp = StripPathMiddleware(app)
bottle.run(app=myapp)


Alternatively, provide a before_request hook to remove the trailing slashes:

@hook('before_request')
def strip_path():
    request.environ['PATH_INFO'] = request.environ['PATH_INFO'].rstrip('/')


Footnote📝  Since they are Take a look at <http://www.ietf.org/rfc/rfc3986.txt>.

Keep Alive Request 

When used with the response header "Connection: keep-alive," specific "push" techniques, such as XHR multipart, require the ability to write response data without terminating the connection. Although WSGI does not naturally support this behavior, Bottle still allows it by utilizing the gevent async framework. The following sample can be used with either the paste HTTP server or the gevent HTTP server. To operate the paste server, change server='gevent' to server='paste':

  from gevent import monkey; monkey.patch_all()
import gevent
from bottle import route, run
@route('/stream')
def stream():
    yield 'BEGIN'
    gevent.sleep(3)
    yield 'MID'
    gevent.sleep(5)
    yield 'END'
run(host='0.0.0.0', port=8080, server='gevent')


When you visit http://localhost:8080/stream, the words "START," "MIDDLE," and "END" should appear one after the other (rather than waiting 8 seconds to see them all at once).

GZIP Compression in Bottle 

Gzip compression, is a Common Use Cases in the Bottle Framework that speeds up websites by condensing static resources (such as CSS and JS files) during a request. Supporting Gzip compression is complicated because several corner cases constantly arise. An appropriate Gzip implementation must:

⭐ Be quick while compressing on the fly.

⭐ For browsers without Support, avoid compressing.

⭐ Do not compress already compressed files (images, videos).

⭐ Dynamic files shouldn't be compressed.

⭐ Support for two distinct compression techniques (gzip and deflate).

⭐ Files that don't change regularly should be cached.

⭐ If one of the files changed despite this, de-validate the cache.

⭐ Be careful the cache doesn't grow too large.

⭐ Avoid caching small files since on-the-fly compression is faster than a disc seek.

The Bottle project advises that the WSGI server that Bottle runs on top of handle Gzip compression best due to these needs. GzipFilter middleware is offered by WSGI servers like CherryPy and can be used to do this.

Using the Hooks Plugin                   

For instance, you may enable Cross-Origin Resource Sharing for the information provided by all of your URLs by using the hook decorator and a callback function:

Using the Hooks Plugin
from bottle import hook, response, route
@hook('after_request')
def enable_cors():
    response.headers['Access-Control-Allow-Origin'] = '*'
@route('/foo')
def say_foo():
    return 'foo!'
@route('/bar')
def say_bar():
    return {'type': 'friendly', 'content': 'HELLO'}


Additionally, you may use before_request to do a task before each function is invoked.

Using Bottle with Heroku

Python applications can now be executed on Heroku architecture's well-known cloud application platform. The Write Your App section of the Getting Started with Python on Heroku/Cedar guide has been replaced with Bottle-specific code in this recipe, which is based on the Heroku Quickstart:

 import os
from bottle import route, run
@route("/")
def hello_world():
    return "Hello World"
run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))


Using the os.environ dictionary, Heroku's app stack passes the port on which the application must listen for requests in this Common Use Cases in the Bottle Framework.

You can also practice with the help of Online Python Compiler

Frequently Asked Questions

What is Bottle API?

The Bottle is a Python-based, lightweight, WSGI micro web framework. Except for the Python Standard Library, it is delivered as a single file module.

Is Bottle an MVC framework?

Like most frameworks, Bottle uses a variation of the MVC design pattern.

Explain WSGI in Python.

The Web Server Gateway Interface is a direct calling convention used by web servers to route requests to frameworks created in the Python programming language.

Why do I require WSGI?

WSGI makes Python Web Applications portable across many web servers without requiring additional setups on NGINX, Apache, or other web servers.

Bottle or Flask, which is better?

Flask can accommodate many functionalities and provides good support through tutorials or online groups. Whereas if you have to finish a project quickly, Bottle works best as a framework.

Conclusion

This blog has extensively covered all the Common Use Cases in the Bottle Framework in Python and how to deal with them with the help of code snippets and appropriate examples. Read the articles, the 19 best Python frameworksFlask in Python, and Django in Python if you want to delve deeper into the various frameworks of Python.

Be Curious with Coding Ninjas Image

Refer to our Guided Path on Coding Ninjas Studio to upskill yourself in Data Structures and AlgorithmsCompetitive ProgrammingJavaScriptSystem DesignMachine learning, and many more! If you want to increase your competency in coding, you should check out the mock test series and participate in the contests organized on Coding Ninjas Studio!

Nevertheless, you may consider our paid courses to give your career an edge over others!

Do upvote our blogs if you find them helpful and engaging!

Happy Learning, Ninjas!!

Thankyou Image
Live masterclass