Sure, I think I'm an adequate :) I also just would like to find the best solution. I told - it's just a proposal, and I made some thoughts on it, just share them with you. Finally, our goal the same - to provide the best solution to the end-user. BTW, I just don't know how to provide service description - it's something out of the existing standards. That's why I was asking in the past - what to do with that?
Mike 2012/10/23 Jakob Simon-Gaarde <[email protected]> > Hi Mike > > I hope you understand that I'm not rejecting your proposal at all :-) just > throwing balls in the air and alternative suggestions so we can reach the > best solution. Tonight I am gonna review your branch in more detail and > give you some feedback. > > Earlier you mentioned that all you really need to describe the restful > service is a list of objects. I don't entirely agree with this unless that > list also contains object info ie. attribute names and types. > > > / Jakob > > 2012/10/23 Mykhailo Stadnyk <[email protected]> > >> Initially I was supposed to implement in some kind of way, but just using >> the class-level decorator. But! It is too strict and not as flexible as >> could be. >> I told already taht I imagine that exposing RESTful methods might be a >> bit more flexible. Let's imagine that I already have some SOAP service >> which is easily could map to REST by exposing the methods (assuming that >> SOAP service is "almost RESTful", but all I need is to expose to HTTP GET >> not a single method but several). You can look at, for example, JAX-WS - >> the REST implementation is something like in my proposal. You put TOO >> strict constraints for the REST service, mine is more flexible. I propose >> to developer to decide what does he want to do with his service (he might >> want to have 2 POST, 5 GET, 1 PUT and no DELETE HTTP methods exposed for >> concrete service object). This mapping could be easily done by matching the >> arguments passed through an HTTP, so the rule is a following: >> 1. If you have several methods exposed to the same type of HTTP request, >> which method to call is determined by matching the bypassed HTTP params and >> the service method arguments >> 2. REST is not RPC, so you can not tell which method to call by name, >> but we can call different methods relying on their signatures >> >> 1,2 - the same but with different words. >> >> Regards, >> Mike >> >> 2012/10/23 Jakob Simon-Gaarde <[email protected]> >> >>> Let's try to define the end-user result, and then discuss the >>> implementation afterwards. >>> >>> In the following I have defined a very simple type as a case we can >>> collaborate through. >>> >>> Maybe we have an object called Client that needs to be RESTful. I think >>> the nicest thing to do would be to SubClass LadonType (ie. >>> RESTfulLadonType) which has some virtual methods: >>> >>> class Client(RESTfulLadonType): >>> >>> uid = PORTABLE_STRING >>> name = PORTABLE_STRING >>> account = PORTABLE_STRING >>> credit = bool >>> >>> def get(self,id): >>> pass >>> >>> def put(self,id): >>> pass >>> >>> def delete(self,id): >>> pass >>> >>> Ladon sees right away that some og the objects used in the Service class >>> are RESTful and adds restful to the list of protocols. >>> Your turn! >>> >>> / Jakob >>> >>> >>> >>> 2012/10/23 Jakob Simon-Gaarde <[email protected]> >>> >>>> I knew this already :-) And that's not nessesarilly a bad thing, >>>> depending on what you are developing. I just think we need to think through >>>> how to implement it in Ladon. Since you have enjoyed using Ladon until now, >>>> you probably already know that I am a hugh fan of end-user simplicity. >>>> >>>> And since REST is strictly object-oriented, I really think we should be >>>> looking at decorating the LadonType instead of methods. I haven't thought >>>> it all the way through yet, but I'm almost sure that would be the place to >>>> do it. >>>> >>>> >>>> / Jakob >>>> >>>> >>>> 2012/10/23 Mykhailo Stadnyk <[email protected]> >>>> >>>>> Exacly! REST is a constraint to objects by design! You've caught it. >>>>> But it's good principal for data-oriented services with no overhead by any >>>>> top-level protocol. It's a principal of building RESTful services. And >>>>> will >>>>> be good if Ladon will support it >>>>> >>>>> 2012/10/23 Jakob Simon-Gaarde <[email protected]> >>>>> >>>>>> But, I think I know what you mean. It's the fact that it utilizes >>>>>> all HTTP methods that makes you say that REST is in the HTTP protocol. I >>>>>> just don't nessesarily find that this is very revolutionary. It's more >>>>>> of a >>>>>> constraint, cause you are limited to objects by design. >>>>>> >>>>>> / Jakob >>>>>> >>>>>> >>>>>> 2012/10/23 Mykhailo Stadnyk <[email protected]> >>>>>> >>>>>>> For REST HTTP is not underlying level but the protocol itself. In >>>>>>> terms of REST design of service is known, so all you need is just to >>>>>>> describe a list of objects. And then for each object there is 4 >>>>>>> operations >>>>>>> you are able to perform Create (HTTP PUT), Read (HTTP GET), Update (HTTP >>>>>>> POST) and Delete (HTTP DELETE). That's why in terms of REST you do not >>>>>>> need >>>>>>> the description. You have only URLs each representing the object you >>>>>>> can do >>>>>>> direct HTTP requests and you have no overhead of having some top-level >>>>>>> protocol, etc. That's why I said that REST is HTTP, because there is >>>>>>> nothing on top of HTTP in REST. And there is nothing to describe, only >>>>>>> the >>>>>>> object URLs. >>>>>>> >>>>>>> It means that RESTful service architecture is not as flexible as >>>>>>> SOAP, so if you, as developer decided to create RESTful service it means >>>>>>> that you already chosen the service architecture. It also means that not >>>>>>> every SOAP service can be RESTful, but RESTful service could be >>>>>>> delivered >>>>>>> with SOAP. >>>>>>> So you, as developer MUST decide first if you are building a RESTful >>>>>>> service, if so - go ahead, make it and Ladon give you benefit to deliver >>>>>>> your RESTful service throug varius different supported protocols. >>>>>>> >>>>>>> Again. You CAN deliver RESTful service throug >>>>>>> SOAP/XML-RPC/JSON-WSP/etc. But you CAN NOT deliver abstract >>>>>>> SOAP/XML-RPC/JSON-WSP service through REST if it wasn't designed as >>>>>>> RESTful >>>>>>> >>>>>>> In my implementation I've tried to make everything with maximum >>>>>>> flexibility, so each RESTFul service could have more than 4 CRUD >>>>>>> methods, >>>>>>> for each HTTP request method you can have as many service methods as you >>>>>>> need if the service methods have different signatures (arguments) >>>>>>> >>>>>>> like >>>>>>> >>>>>>> class Service: >>>>>>> @restfulize(method="GET") >>>>>>> def get_one_record( r_id): >>>>>>> pass >>>>>>> @restfulize(method="GET") >>>>>>> def get_last_record( r_time): >>>>>>> pass >>>>>>> @restfulize(method="GET") >>>>>>> def get_all_records(): >>>>>>> pass >>>>>>> @restfulize(method="GET") >>>>>>> def get_filtered_records( filters): >>>>>>> pass >>>>>>> >>>>>>> As you see in this example 4 service methods are bind to HTTP GET >>>>>>> method. Depending of parameters bypassed through HTTP I try to determine >>>>>>> which method to call, but from terms of protocol you always do >>>>>>> >>>>>>> GET >>>>>>> /Service/rest?filters['name']=*bla&filters['another_key']=somevalue >>>>>>> HTTP/1.1 >>>>>>> Host: yourservice.com >>>>>>> ... >>>>>>> >>>>>>> The same for other HTTP methods. You can have 2 different methods >>>>>>> for POST, for example for User service example you may have split User >>>>>>> data >>>>>>> update and user password update, etc.. >>>>>>> >>>>>>> Or maybe your service may not provide some methods. Like you create >>>>>>> the public read-only service, so you don't provide PUT/POST/DELETE >>>>>>> >>>>>>> P.S. REST does not provide the way do bypass which service method to >>>>>>> call by name. REST is not RPC. You have only the Resource, it's URL and >>>>>>> 4 >>>>>>> operations. It is REST. >>>>>>> >>>>>>> Best regards, >>>>>>> Mike >>>>>>> >>>>>>> >>>>>>> 2012/10/23 Jakob Simon-Gaarde <[email protected]> >>>>>>> >>>>>>>> Everything in Ladon is HTTP :-) >>>>>>>> >>>>>>>> But HTTP is just the underlying protocol, and under that is a >>>>>>>> transport protocol etc. >>>>>>>> >>>>>>>> When I am talking about protocol in Ladon I mean service protocols >>>>>>>> like soap, json-wsp and soon json-rpc which are also protocols. I >>>>>>>> would put >>>>>>>> REST at this level aswell. >>>>>>>> >>>>>>>> I haven't really used REST before, but from what I can see it is >>>>>>>> nothing more than another service protocol which utilizes the HTTP >>>>>>>> standard >>>>>>>> a bit more, like using PUT,POST,GET,DELETE methods. Also it looks like >>>>>>>> there is not so much constraint on how parameters are passed so they >>>>>>>> can be >>>>>>>> JSON or XML or query-string. >>>>>>>> >>>>>>>> I don't like that there is no service description format for REST >>>>>>>> services. That is kind of a key feature in Ladon, that all supported >>>>>>>> protocols should be able to describe themselves. >>>>>>>> >>>>>>>> >>>>>>>> / Jakob >>>>>>>> >>>>>>>> 2012/10/22 Mykhailo Stadnyk <[email protected]> >>>>>>>> >>>>>>>>> What do you mean? >>>>>>>>> >>>>>>>>> Actually REST is HTTP in terms of protocol, so what do I need to >>>>>>>>> implement? Maybe you can explain me more detailed your thought. >>>>>>>>> >>>>>>>>> Best regards, >>>>>>>>> Mike >>>>>>>>> >>>>>>>>> 2012/10/22 Jakob Simon-Gaarde <[email protected]> >>>>>>>>> >>>>>>>>>> My first question about your RESTful implementation is, why are >>>>>>>>>> you not implementing it as a protocol? >>>>>>>>>> >>>>>>>>>> / Jakob >>>>>>>>>> >>>>>>>>>> 2012/10/22 Jakob Simon-Gaarde <[email protected]> >>>>>>>>>> >>>>>>>>>>> Just a remark about the package name tracepyd. That might be an >>>>>>>>>>> unfortunate package name, cause on that odd platform called Windows >>>>>>>>>>> pyd-files are binary python modules. Just a remark :-) >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> 2012/10/22 Jakob Simon-Gaarde <[email protected]> >>>>>>>>>>> >>>>>>>>>>>> Hi Mike. >>>>>>>>>>>> >>>>>>>>>>>> Let's talk about tracepyd first, does it solve this bug: >>>>>>>>>>>> >>>>>>>>>>>> https://bugs.launchpad.net/ladon/+bug/877727 >>>>>>>>>>>> >>>>>>>>>>>> rpclib has a terribly ugly solution for this, as you can see in >>>>>>>>>>>> the bug, and we want to be better than rpclib :-) >>>>>>>>>>>> >>>>>>>>>>>> / Jakob >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> 2012/10/22 Jakob Simon-Gaarde <[email protected]> >>>>>>>>>>>> >>>>>>>>>>>>> Hi Mike >>>>>>>>>>>>> >>>>>>>>>>>>> Looking into this now, you will have my reply today :-) >>>>>>>>>>>>> >>>>>>>>>>>>> / Jakob >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> 2012/10/22 Mykhailo Stadnyk <[email protected]> >>>>>>>>>>>>> >>>>>>>>>>>>>> Currently it's an experimental feature which is not ready to >>>>>>>>>>>>>> be integrated. I didn't test it at all (keep working on it). >>>>>>>>>>>>>> >>>>>>>>>>>>>> So here is my personal road-map for this feature: >>>>>>>>>>>>>> 1. Resolve problem with decorators dependencies (something >>>>>>>>>>>>>> I described in previous message) >>>>>>>>>>>>>> 2. Write tests and test the functionality >>>>>>>>>>>>>> 3. I've not checked how does it deal with requests >>>>>>>>>>>>>> containing multipart boundaries and binary data >>>>>>>>>>>>>> 4. Not sure what to do with service description (currently >>>>>>>>>>>>>> I've just removed, but have an idea we can use it to describe >>>>>>>>>>>>>> service any >>>>>>>>>>>>>> way, even as long as REST does not specify this) >>>>>>>>>>>>>> 5. Write documentation/examples >>>>>>>>>>>>>> >>>>>>>>>>>>>> But I'm stuck on issue #1. I want to know: >>>>>>>>>>>>>> * do you agree to add dependency in Ladon to tracepyd module >>>>>>>>>>>>>> or not? >>>>>>>>>>>>>> * If not - do you agree to include tracepyd's implementation >>>>>>>>>>>>>> into Ladon (not as dependency, but to place it somewhere in >>>>>>>>>>>>>> tools)? >>>>>>>>>>>>>> * If not - do you agree to modify @ladonize decorator >>>>>>>>>>>>>> functionality to add extra-params for REST (for me its ugly). >>>>>>>>>>>>>> * If not - which ideas do you have then? :) >>>>>>>>>>>>>> >>>>>>>>>>>>>> I'd like to suggest to add dependency to tracepyd. Currently >>>>>>>>>>>>>> I have a version locally which works fine, so I can publish this >>>>>>>>>>>>>> solution >>>>>>>>>>>>>> to my branch to let you see. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thank you in advance for your time and advice, >>>>>>>>>>>>>> Mike >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> 2012/10/22 Jakob Simon-Gaarde <[email protected]> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Interesting :-) >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I'll look at it later - we must make sure that it doesn't >>>>>>>>>>>>>>> break anything. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> 2012/10/22 Mykhailo Stadnyk <[email protected]> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Hi Jacob. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> As I told I'm trying to implement RESTful services support >>>>>>>>>>>>>>>> by Ladon. The basic functionality is implemented - you can >>>>>>>>>>>>>>>> check my branch: >>>>>>>>>>>>>>>> lp:~mikhus/ladon/rest<https://code.launchpad.net/~mikhus/ladon/rest> >>>>>>>>>>>>>>>> to >>>>>>>>>>>>>>>> see how does it work. Here is an example of RESTful service >>>>>>>>>>>>>>>> you may run to >>>>>>>>>>>>>>>> see: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> from ladon.ladonizer import ladonize, restfulize >>>>>>>>>>>>>>>> from ladon.compat import PORTABLE_STRING >>>>>>>>>>>>>>>> from ladon.types.ladontype import LadonType >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> class User(LadonType): >>>>>>>>>>>>>>>> name = PORTABLE_STRING >>>>>>>>>>>>>>>> email = PORTABLE_STRING >>>>>>>>>>>>>>>> passwd = PORTABLE_STRING >>>>>>>>>>>>>>>> def __init__(): >>>>>>>>>>>>>>>> self.name = "" >>>>>>>>>>>>>>>> self.email = "" >>>>>>>>>>>>>>>> self.passwd = "" >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> class UserService( object) : >>>>>>>>>>>>>>>> @restfulize(method="PUT") >>>>>>>>>>>>>>>> @ladonize(str, str, str, rtype=User) >>>>>>>>>>>>>>>> def newUser( self, u_name, u_email, u_passwd) : >>>>>>>>>>>>>>>> user = User() # where User is LadonType object >>>>>>>>>>>>>>>> user.name = u_name >>>>>>>>>>>>>>>> user.email = u_email >>>>>>>>>>>>>>>> user.passwd = u_passwd >>>>>>>>>>>>>>>> return user >>>>>>>>>>>>>>>> @restfulize(method="GET") >>>>>>>>>>>>>>>> @ladonize(int, rtype=[User]) >>>>>>>>>>>>>>>> def getUser(self, u_id) : >>>>>>>>>>>>>>>> return User() >>>>>>>>>>>>>>>> @restfulize(method="GET") >>>>>>>>>>>>>>>> @ladonize(int, rtype=[User]) >>>>>>>>>>>>>>>> def getUsers(self) : >>>>>>>>>>>>>>>> return [User(), User(), User()] >>>>>>>>>>>>>>>> @restfulize(method="POST") >>>>>>>>>>>>>>>> @ladonize(int, str, str, str, rtype=User) >>>>>>>>>>>>>>>> def updUser( self, u_id, u_name, u_email, u_passwd): >>>>>>>>>>>>>>>> user = User() >>>>>>>>>>>>>>>> user.name = u_name >>>>>>>>>>>>>>>> user.email = u_email >>>>>>>>>>>>>>>> user.passwd = u_passwd >>>>>>>>>>>>>>>> return user >>>>>>>>>>>>>>>> @restfulize(method="DELETE") >>>>>>>>>>>>>>>> @ladonize(int, rtype=bool) >>>>>>>>>>>>>>>> def delUser( self, u_id) : >>>>>>>>>>>>>>>> return True >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> By the way, there is at least one issue I don't know how to >>>>>>>>>>>>>>>> solve better, so I want your advice. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> As you see I've implemented specific decorator to mark >>>>>>>>>>>>>>>> service methods as RESTful. It's @restfulize decorator. The >>>>>>>>>>>>>>>> problem that it >>>>>>>>>>>>>>>> is implemented now as: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> def restfulize( *dargs, **dkwargs): >>>>>>>>>>>>>>>> def decorator(fn): >>>>>>>>>>>>>>>> * minfo = fn._ladon_method_info* >>>>>>>>>>>>>>>> if 'method' in dkwargs: >>>>>>>>>>>>>>>> if not minfo.restfulize( **dkwargs): >>>>>>>>>>>>>>>> raise RestfulMethodConfigMismatch( fn.func_name) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> return fn # returns ladonized method >>>>>>>>>>>>>>>> return decorator >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The problem is highlighted with bold. Will be good to make >>>>>>>>>>>>>>>> this decorator independent of what @ladonize defined in it's >>>>>>>>>>>>>>>> private props. >>>>>>>>>>>>>>>> But, as far as "fn" here is a reference to ladon's "injector" >>>>>>>>>>>>>>>> function I >>>>>>>>>>>>>>>> have no way to determine correctly which real method in which >>>>>>>>>>>>>>>> class is >>>>>>>>>>>>>>>> decorated. It means that in such case I have no way to extract >>>>>>>>>>>>>>>> LadonMethodInfo associated to "fn" in other way but >>>>>>>>>>>>>>>> implemented for the >>>>>>>>>>>>>>>> moment. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The real problem is when I want to override @ladonize >>>>>>>>>>>>>>>> decorator. In this case @resftulize becomes nonoperational >>>>>>>>>>>>>>>> because I loose >>>>>>>>>>>>>>>> reference to "_ladon_method_info" and means that I should take >>>>>>>>>>>>>>>> care to >>>>>>>>>>>>>>>> bypass all the existing private properties in 3-d party >>>>>>>>>>>>>>>> override >>>>>>>>>>>>>>>> implementation, which is not good at all. So I want to have >>>>>>>>>>>>>>>> @restfulize and >>>>>>>>>>>>>>>> @ladonize implemented without hard dependency between them. >>>>>>>>>>>>>>>> Via global_service_collection() it's possible to do but you >>>>>>>>>>>>>>>> need to determine real method function in some way. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> So I see the following ways to fix it: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 1. Via decorator registry (Here we solved such kind of >>>>>>>>>>>>>>>> problem by creating DecoratorRegistry (I've published it as >>>>>>>>>>>>>>>> http://pypi.python.org/pypi/tracepyd)) >>>>>>>>>>>>>>>> 2. By adding REST functionality to @ladonize decorator >>>>>>>>>>>>>>>> itself, to have something like: >>>>>>>>>>>>>>>> @ladonize(PORTABLE_STRING, rtype=[PORTABLE_STRING], *rest={ >>>>>>>>>>>>>>>> "method" : "GET", "produces": "XML" }*) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Maybe you can point me to some other ideas you know how to >>>>>>>>>>>>>>>> resolve such kind of problem. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Best regards, >>>>>>>>>>>>>>>> Mike >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>> Med venlig hilsen / Best regards >>>>>>>>>>>>>>> Jakob Simon-Gaarde >>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> -- >>>>>>>>>>>>> Med venlig hilsen / Best regards >>>>>>>>>>>>> Jakob Simon-Gaarde >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> Med venlig hilsen / Best regards >>>>>>>>>>>> Jakob Simon-Gaarde >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> Med venlig hilsen / Best regards >>>>>>>>>>> Jakob Simon-Gaarde >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> Med venlig hilsen / Best regards >>>>>>>>>> Jakob Simon-Gaarde >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> Med venlig hilsen / Best regards >>>>>>>> Jakob Simon-Gaarde >>>>>>>> >>>>>>> >>>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> Med venlig hilsen / Best regards >>>>>> Jakob Simon-Gaarde >>>>>> >>>>>> -- >>>>>> Mailing list: https://launchpad.net/~ladon-dev-team >>>>>> Post to : [email protected] >>>>>> Unsubscribe : https://launchpad.net/~ladon-dev-team >>>>>> More help : https://help.launchpad.net/ListHelp >>>>>> >>>>>> >>>>> >>>> >>>> >>>> -- >>>> Med venlig hilsen / Best regards >>>> Jakob Simon-Gaarde >>>> >>> >>> >>> >>> -- >>> Med venlig hilsen / Best regards >>> Jakob Simon-Gaarde >>> >>> -- >>> Mailing list: https://launchpad.net/~ladon-dev-team >>> Post to : [email protected] >>> Unsubscribe : https://launchpad.net/~ladon-dev-team >>> More help : https://help.launchpad.net/ListHelp >>> >>> >> > > > -- > Med venlig hilsen / Best regards > Jakob Simon-Gaarde > > -- > Mailing list: https://launchpad.net/~ladon-dev-team > Post to : [email protected] > Unsubscribe : https://launchpad.net/~ladon-dev-team > More help : https://help.launchpad.net/ListHelp > >
-- Mailing list: https://launchpad.net/~ladon-dev-team Post to : [email protected] Unsubscribe : https://launchpad.net/~ladon-dev-team More help : https://help.launchpad.net/ListHelp

