Giter Site home page Giter Site logo

Comments (8)

timothycrosley avatar timothycrosley commented on May 20, 2024

Hi @kostasdizas,

Thanks for reporting this! There are some round-about ways to work around it, but I think it should be fixed within the project itself so that you can attach hug routes to methods without modification. Ill work on getting a fix up soon.

Thanks!

~Timothy

from hug.

timothycrosley avatar timothycrosley commented on May 20, 2024

Actually, thinking about it some more - I think I need better background on what you're trying to accomplish.
You can easily make hug "ignore" the self parameter by providing a default value:

class API(object):

    @hug.call()
    def hello_world(self=None):
        return "Hello World!"

api_instance = API()
assert api_instance.hello_world.interface
assert api_instance.hello_world()
assert hug.test.get(api, '/hello_world').data == "Hello World!"

Or you could wrap the method in the staticmethod decorator and it wouldn't require self at all. But, I'm assuming that since the API call is a method on an object that you want the API call to have access to that object and it's methods / properties. The problem being that hug cant know what instance of the object you want, if you're attaching to a class definition. So another way to accomplish the above, if you want it to actually have self defined:

class API(object):

    def hello_world(self):
        return "Hello World!"

api_instance = API()

@hug.call()
def hello_world():
    return api_instance.hello_world()

I've going ahead and written tests to verify both of these methods work here:
https://github.com/timothycrosley/hug/pull/83/files#diff-8107272ea49a7ea4505985b05542ce00R45

And I've insured that the auto-documenter wont document that an exposed API call takes a 'self' argument.

Let me know if this solves your issue, or if there is a more robust framework level solution that would help.

Thanks!

~Timothy

from hug.

kostasdizas avatar kostasdizas commented on May 20, 2024

Hello Timothy,
I was actually trying two things at the same time. In the beginning I was only trying to group together similar endpoints, more specifically CRUD operations for a specific model. It worked like a charm:

class BlogEndpoints():

    base = "blog"
    model = Blog

    @hug.get(["/{0}".format(base), "/{0}/{{id}}".format(base)])
    def get(id:int=None):
        result = __class__.model.get(id) if id else __class__.model.get()
        return result

    @hug.post("/{0}/new".format(base))
    def add(title:str, content:str):
        __class__.model.create(title=title, content=content)
        return "ok"

    @hug.put(["/{0}".format(base), "/{0}/{{id}}".format(base)])
    def edit(id:int, title:str, content:str):
        x = __class__.model.update(id).values(title, content)
        return "ok"

    @hug.delete(["/{0}".format(base), "/{0}/{{id}}".format(base)])
    def delete(id:int):
        __class__.model.delete(id)
        return "ok"

Here's my sample code including pseudo access to the model.
Secondly, I wanted to create something more abstract that can be inherited, and essentially automate the process of creating those basic endpoints. I've experimented with different things and decided to just use a method that registers all the endpoints.

...
def __init__(self, base, model):
    self.base = base
    self.model = model

def register_endpoints(self):
    hug.get(["/{}".format(self.base), "/{}/{{id}}".format(self.base)] )(self.get)
    hug.post("/{}/new".format(self.base))(self.add)
    hug.put(["/{}".format(self.base), "/{}/{{id}}".format(self.base)] )(self.edit)
    hug.delete(["/{}".format(self.base), "/{}/{{id}}".format(self.base)] )(self.delete)
...

This sort of works but the hug.call decorator won't accept class methods. I get an error saying:

AttributeError: 'method' object has no attribute 'interface'

All in all I'm pretty pleased with the first method, but it involves a lot of code repetition. Using self=None can work but limits the flexibility of the method since it cannot access any class variables. I'll keep working on it and see how far I can take it. Ideally I want to get to the point where you only need this to create the CRUD endpoints:

class BlogEndpoints(hugCRUD):
    base = "blog"
    model = Blog

from hug.

timothycrosley avatar timothycrosley commented on May 20, 2024

@kostasdizas,

Thanks for adding these useful usage scenarios, I certainly see merit in your initial register_endpoints approach. I'll go ahead and implement support for that approach now and if in the future you think of more clean ways to implement the re-use you want let me know, and I'll try to implement them as well (or certainly accept a pull-request if you have time). I'll try to get a new release out ASAP that implements this feature.

Thanks!

~Timothy

from hug.

timothycrosley avatar timothycrosley commented on May 20, 2024

I just released version 1.6.0 which has built-in support for attaching hug routes to methods

Thanks!

~Timothy

from hug.

kostasdizas avatar kostasdizas commented on May 20, 2024

Hey @timothycrosley,

I've created a small module called hugpee that automatically does what I described above. It's in its early stages and only supports peewee models for the time being. I'd greatly appreciate your comments and suggestions on this.

Kostas

from hug.

timothycrosley avatar timothycrosley commented on May 20, 2024

@kostasdizas,

Haven't had a great deal of time to look at it yet, but on the surface it looks great! Once I release a new version of hug that includes all the features hugpee is dependent on, and you feel okay with hugpee itself - I'll go ahead and link it on the main repo. Hopefully I'll have some more time to look at hugpee tonight.

Thanks!

~Timothy

from hug.

tgalery avatar tgalery commented on May 20, 2024

@timothycrosley Any updates on this ? I quite like hug and have been using for a project but it lacks features related to exposing CRUD operations on models (at the moment we have to expose certain routs for each operation we want and add the code manually). I'm also using pewee, so hugpee sounds like a good call. However, if one doesn't use this module, what would be a good way to best expose a models CRUD operations ?

from hug.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.