question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Create bottle.py module decorator, to ease subclassing

See original GitHub issue

Currently in bottle, the @route decorator is a Bottle instance attribute, making it harder to subclass, as following code will not work, as not syntaxically correct:

import bottle

class App(bottle.Bottle):
    @self.route('/there')   # <--- wrong syntax!
    def some_func(self): pass

So, considering some different options, and trying not to go down the bottleCBV route that seems quite weird to me, I setup a workaround in a personal project (see here), which sums up as follows:

import inspect
import bottle

def route(path: str, method: str = 'GET')
    """Decorate a method, to track it for later routing."""
    def wrapper(func):
        func.route = (path, method)
        return func
   return wrapper

class BottleApp(bottle.Bottle):
    """A parent class, taking care of setting-up the routing."""
    def __init__(*args, **kwargs):
        super().__init__(*args, **kwargs)
        self.set_routes()

    def set_routes(self):
        for meth in inspect(self, predicate=inspect.ismethod):
            if hasattr(meth, 'route'):
               # and now the magic happens
               self.route(path=meth.route.path, method=meth.route.method, callback=meth)

With just this, we can now subclass in a lean way:

class MyApp(BottleApp):
    """A class, that can be run by a WSGI server, that can bear its own attributes."""
    @route(path='/users')
    def users(self):
        return self.whatever

I’d be happy to propose a Pull Request to integrate this, what do you think about this?

Some comments and thoughts:

  • The @route module decorator may use different attribute names, and could also consider a list of acceptable methods. Hooks shall also be considered, I’ve worked around this already;
  • I would put set_routes method to bottle.Bottle class directly.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
defnullcommented, Apr 25, 2020

There are some attempts to implement such a base class (or other ways to create bottle apps) around, if you look for them. The reusability-pattern I have seen the most is to just create the application within a function:

def create_app(**settings):
    app = bottle.Bottle()
    ...
    return app

A base-class could add a lot of metaclass-magic to the mix, for example, inject specialized decorators to be used at declatarion-time or make sure the final class is callable. But I’m not sure if that really helps. Explicit is better than implicit, after all.

0reactions
josephernestcommented, Oct 31, 2022

@defnull, what would be a simple and recommended way to create a class for an application? (which builds the Bottle object and starts it)
Here is an old question about this: Bottle framework and OOP, using method instead of function, I would be interested about the “canonical way”, blessed by the creator of the library 😃

I was thinking about something like:

import bottle

class App:
    def __init__(self, port=80):
        self.app = bottle.Bottle()
        self.port = port

    def setup_routes(self):
        @self.app.route("/foo")
        def foo():
            return("foo")

        @self.app.route("/bar")
        def bar():
            return("bar")

    def start(self):
        self.app.run(port=self.port)

a = App()
a.setup_routes()
a.start()

PS: I noted the fact that it’s not a good idea to subclass bottle.Bottle (in your previous comment).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Tutorial — Bottle 0.13-dev documentation
For the sake of simplicity, most examples in this tutorial use a module-level route() decorator to define routes. This adds routes to a...
Read more >
Bottle framework and OOP, using method instead of function
route, attr) will not work as intended; you want bottle.route(attr.route)(attr) (because bottle.route() is a decorator, which returns a callable, which then ...
Read more >
bottle/bottle.py at master · bottlepy/bottle - GitHub
bottle.py is a fast and simple micro-framework for python web-applications. ... INFO: Some server adapters need to monkey-patch std-lib modules before they.
Read more >
Python Multithreading Tutorial: Subclassing Thread - 2020
To create our own thread in Python, we'll want to make our class to work as a thread. For this, we should subclass...
Read more >
Logging Cookbook — Python 3.11.1 documentation
import logging # create logger module_logger = logging. ... while not arg['stop']: logging.debug('Hi from myfunc') time.sleep(0.5) def main(): logging.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found