Search code examples
pythonflasksqlalchemyflask-sqlalchemypython-decorators

Apply try/except to multiple Python class definitions


is there a way to apply try/except logic to multiple class definitions without a try/except in every definition?

For example, instead of:

def test_table(tablename):
    return Table(tablename, db.metadata, Column('id', Integer, primary_key=True))

class User(db.Model):
    try:
        __table__ = db.metadata.tables['user']
        __bind_key__ = 'secondary'
        # More attrs...
    except KeyError:
        __table__ = test_table('user')


class Policy(db.Model):
    try:
        __table__ = db.metadata.tables['policy']
        __bind_key__ = 'secondary'
        # More attrs...
    except KeyError:
        __table__ = test_table('policy')

I could apply logic with a decorator like:

@if_no_metadata_use_default('user')
class User(db.Model):
        __table__ = db.metadata.tables['user']
        __bind_key__ = 'secondary'
        # More attrs...

@if_no_metadata_use_default('policy')
class Policy(db.Model):
    __table__ = db.metadata.tables['policy']
    __bind_key__ = 'secondary'
    # More attrs...

Solution

  • This might not be a good practice in general since it really decreases your code readablity, but you can create an exception_wrapper decorator like this:

    def exception_wrapper(func):
        def run(exception, on_exception, *args, **kwargs):
            try:
                return func(*args, **kwargs)
            except exception:
                on_exception()
    
        return run
    
    
    def on_exception():
        pass
    
    
    @exception_wrapper
    def f(a, b):
        if a < b:
            raise NotImplementedError
        return a + b
    
    
    print(f(NotImplementedError, on_exception, 10, 2))
    

    Again, I'm against using this kind of wrappers for exceptions since they will make your life harder in the long run, but it's up to you!