Comments (8)
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.
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.
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.
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.
I just released version 1.6.0
which has built-in support for attaching hug routes to methods
Thanks!
~Timothy
from hug.
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.
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.
@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)
- TypeError: __call__() missing 1 required positional argument: 'context'
- Splitting APIs over multiple files
- zsh: command not found: hug HOT 1
- How to configure a service?
- Bug: dashed versions of valid command line arguments fail silently
- Add exception in not_found router
- Missing explicit python 3.8 compatibility from release note.
- GET endpoints not working when using prefixes in @hug.object.urls
- Tag the source
- Remove pinning
- pytest-runner not required HOT 1
- distutils has been deprecated in Python 3.10 HOT 1
- Is this project abandoned? HOT 8
- Unexpected conversion during a requests.post() operation
- TypeError: gather() got an unexpected keyword argument 'loop' HOT 2
- CORS Middleware help
- Exception handler: Why find a potential handler doesn't exit the loop
- Implementation bugs for exception catching!
- FYI: cgi module is deprecated in Python 3.11, will be removed in 3.13
- Could you please clarify this deprecation warning?! HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hug.