datafolklabs / cement

Application Framework for Python
http://builtoncement.com
BSD 3-Clause "New" or "Revised" License
1.23k stars 118 forks source link

Extra building block utilities #541

Open Skarlett opened 5 years ago

Skarlett commented 5 years ago

Cement Issue Reporting and Feature Requests

System Information

Adds a Utility to create parameterized decorators, and uses this to build a fallback decorator, in turn with the framework creates a throw and catch ability without much underlying code.

import cement.utils.misc

def save_my_code():
  return "did this instead"

@cement.utils.misc.fallback([save_my_code])
def failure():
  raise Exception("Oops!")

print(failure())  # "did this instead"
derks commented 5 years ago

@Skarlett this is an interesting concept. Have you considered a pre_close hook for this purpose? If you try/except properly around app.run(), then app.close() should always be called, which inturn calls the pre_close and post_close hooks allowing for application/plugin/extension cleanup.

Just wondering if you considered that, and how/if this feature differs significantly?

Skarlett commented 5 years ago

I looked into the feature, and was satisfied with its most use cases, though the addition I've added adds another layer of flexibility on top of hooks (possible more too - depends how creative you are).

from cement import App
from cement.utils.misc import fallback

def  fallback_hook(app):
  pass
​
@fallback([fallback_hook, ...])
def my_hook_function(app):
    # do something with app
    pass
​
class MyApp(App):
    class Meta:
        label = 'myapp'
        hooks = [
            ('pre_setup', my_hook_function),
        ]

The only difference is this abstracts a try/except and assumes the next item to attempt, and automatically returns it in its place. (Edit otherwises throws RuntimeException)

This idea was to supplement hooks with fallback features, but allowing it to still be used anywhere if desired by the developer.