hugapi / hug

Embrace the APIs of the future. Hug aims to make developing APIs as simple as possible, but no simpler.
MIT License
6.86k stars 387 forks source link

Can hug decorate non trivial classes ? #822

Open Annakan opened 5 years ago

Annakan commented 5 years ago

i have this simple API class

@hug.object.http_methods('/infosets')
class InfosetCollection:

    def __init__(self, infoset_store):
        self.infoset_store = infoset_store

    def get(self, req, resp):
        # we need to retrieve all the infosets available
        return self.infoset_store.list()

    def post(self, req, resp):
        infoset = req.data
        return self.infoset_store.save(infoset=infoset)

where infoset_store is the real manager of the infoset resource.

Of course Hug choke on this since it tries to create instances of infosetCollection without any infoset_store.

Is there a clean way out of this to decorate "real" classes that are not just a bunch of stateless methods ?

A global is not an option, globals lead to premature creation of resources, side effects at import time and all manners of evil. The current class allows me to inject an infoset_store for tests, delay configuration of infoset_store till it is really needed and a lot of other good things.

I looked into a few examples and saw the use of directive but will this not quick the ball just one step further into the directive that would also need to access a global or eagerly load its configuration ?

Is there a solution for Hug to create its API class instances later than at 'import/init" time, pass a factory function that would be called once when the API is used or take control of the instance creation ?

Thanks a lot for your time and the HUG project.

jay-tyler commented 5 years ago

Could the issue be rephrased as "is there a way to maintain internal state" in hug?

Supporting classes with arbitrary args and kwargs is potentially problematic, i.e. how would those call dependencies get "published" and "threaded through" the rest of the call stack?

This is an API problem that's been solved in other frameworks. One of the most well known is pytest's fixtures, which are nullary callables, or callables that ultimately depend on nullary callables. We'd probably prefer solutions that maintain a functional closure based on nullary callable(s).

FYI We have an ongoing effort to try to figure out what v3 of hug is going to look like, and there's a relevant conversation here that you'd be welcome to participate in.

@timothycrosley Would better know what the current capabilities for maintaining internal state are. If we don't have an equivalent of "call once" in the current directive system, I think I could give you a slightly hacky functional workaround.