← Back to team overview

ladon-dev-team team mailing list archive

Re: REST implementation

 

Hi Jacob.

Thanks for your review and comments. Yes, regarding the request I just
didn't found a way to parse it. I'm fully agree on idea that the interface
just obtain the args from dispatcher. So, I can propose another way. We can
introduce some HttpRequest object which will be instantiated by a
dispatcher and then passed to an interfaces. This object will handle all
request parsing stuff. Then each interface can use that part which is
required. What is your opinion?

Best regards,
Mike

2012/10/24 Jakob Simon-Gaarde <jakobsg@xxxxxxxxx>

> For now I have a few comments on the alterations to BaseInterface. I'm not
> all the way through yet, I want to take some testruns :-)
> a
> To be honest I iike your code-style and productivity level - I just need
> to know we are keeping the Ladon ideology, which I regretfully havent put
> into precise words yet :-)
>
> Here are my comments:
>
> interfaces.base.BaseInterface:
>
> def allowed_http_methods()
> good solution, that part is solved kind of hackish in wsgi_application
>
> def parse_request()
> I can see why you want to parse environ. I'm not saying it shouldn't be
> and I have been there trying to make the right decision
> ultimately I chose to keep wsgi and interfaces separated completely for
> simplicity. So the rule until now has been that the
> dispatcher should be the layer between wsgi and interfaces. I know this
> can easilly become a religious discussion - why not have
> the data where you need it (and the end-user gets that) on the other hand
> you can easilly destroy a frameworks presumptions
> if you let too much freedom into the way you develope modules. So - I
> would prefer that the info you need is passed on in a
> controlled fashion so it is clear between the dispatcher and interfaces
> which info is available.
> I don't know if that was a good explanation nor that i hit the nail on the
> head, but it's my experience that you have to be careful
> at these kind of decisions cause they can backfire. In your case all you
> need is the 'QUERY_STRING' and 'REQUEST_METHOD'. Probably
> the query-string is your case should be converted to the request_body
> argument (on !POST requests) and the REQUEST_METHOD shold be
> passed as an extra controlled argument to parse_request.
> If you think I am putting too much energy in this point I can understand,
> call it a gut-feeling :-)
>
>
>
> 2012/10/23 Jakob Simon-Gaarde <jakobsg@xxxxxxxxx>
>
>> 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 <mikhus@xxxxxxxxx>
>>
>>> 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 <jakobsg@xxxxxxxxx>
>>>
>>>> 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 <jakobsg@xxxxxxxxx>
>>>>
>>>>> 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 <mikhus@xxxxxxxxx>
>>>>>
>>>>>> 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 <jakobsg@xxxxxxxxx>
>>>>>>
>>>>>>>  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 <mikhus@xxxxxxxxx>
>>>>>>>
>>>>>>>> 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 <jakobsg@xxxxxxxxx>
>>>>>>>>
>>>>>>>>> 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 <mikhus@xxxxxxxxx>
>>>>>>>>>
>>>>>>>>>> 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 <jakobsg@xxxxxxxxx>
>>>>>>>>>>
>>>>>>>>>>> My first question about your RESTful implementation is, why are
>>>>>>>>>>> you not implementing it as a protocol?
>>>>>>>>>>>
>>>>>>>>>>> / Jakob
>>>>>>>>>>>
>>>>>>>>>>> 2012/10/22 Jakob Simon-Gaarde <jakobsg@xxxxxxxxx>
>>>>>>>>>>>
>>>>>>>>>>>> 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 <jakobsg@xxxxxxxxx>
>>>>>>>>>>>>
>>>>>>>>>>>>> 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 <jakobsg@xxxxxxxxx>
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Hi Mike
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Looking into this now, you will have my reply today :-)
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> / Jakob
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 2012/10/22 Mykhailo Stadnyk <mikhus@xxxxxxxxx>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> 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 <jakobsg@xxxxxxxxx>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Interesting :-)
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I'll look at it later - we must make sure that it doesn't
>>>>>>>>>>>>>>>> break anything.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> 2012/10/22 Mykhailo Stadnyk <mikhus@xxxxxxxxx>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> 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     : ladon-dev-team@xxxxxxxxxxxxxxxxxxx
>>>>>>> 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     : ladon-dev-team@xxxxxxxxxxxxxxxxxxx
>>>> 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     : ladon-dev-team@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~ladon-dev-team
> More help   : https://help.launchpad.net/ListHelp
>
>

References