Path: csiph.com!eternal-september.org!feeder.eternal-september.org!border1.nntp.ams1.giganews.com!nntp.giganews.com!newsfeed.xs4all.nl!newsfeed8.news.xs4all.nl!nzpost1.xs4all.net!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'python,': 0.02; 'api.': 0.04; 'true,': 0.04; 'classes,': 0.05; 'attributes': 0.07; 'classes.': 0.07; 'dependency': 0.07; 'api': 0.09; 'here?': 0.09; 'http,': 0.09; 'lookup': 0.09; 'objects.': 0.09; 'subject:Writing': 0.09; 'subject:module': 0.09; 'python': 0.10; 'files.': 0.13; 'skip:f 30': 0.15; 'credential': 0.16; 'forth.': 0.16; 'handle,': 0.16; 'instantiate': 0.16; 'received:172.18.0': 0.16; 'subject:api': 0.16; 'up*': 0.16; 'attribute': 0.18; 'basically': 0.18; 'pointer': 0.18; 'python?': 0.18; '(not': 0.20; 'to:name:python-list@python.org': 0.20; 'to:2**1': 0.21; 'aspect': 0.22; 'object.': 0.22; 'referring': 0.22; 'code.': 0.23; 'header :In-Reply-To:1': 0.24; 'example': 0.26; '(which': 0.26; 'rest': 0.26; 'separate': 0.27; 'this.': 0.28; 'skip:( 20': 0.28; 'fine': 0.28; 'looks': 0.29; 'container': 0.29; 'credentials': 0.29; 'queue': 0.29; 'use?': 0.29; 'workaround': 0.29; 'objects': 0.29; 'creating': 0.30; 'call.': 0.30; 'certainly': 0.30; 'query': 0.30; 'another': 0.32; 'especially': 0.32; 'holds': 0.32; 'point': 0.33; 'problem': 0.33; 'foo': 0.33; 'http': 0.33; 'correctly': 0.34; 'except': 0.34; 'handle': 0.34; 'skip:d 20': 0.34; 'add': 0.34; 'that,': 0.34; 'gets': 0.35; 'gives': 0.35; 'so,': 0.35; 'instance': 0.35; 'programming.': 0.35; 'protocol': 0.35; 'knowledge': 0.35; 'quite': 0.35; 'something': 0.35; 'remote': 0.35; 'but': 0.36; 'skip:i 20': 0.36; 'should': 0.36; 'created': 0.36; 'possible': 0.36; 'to:addr:python-list': 0.36; 'subject:: ': 0.37; 'being': 0.37; 'thanks': 0.37; 'starting': 0.37; 'itself': 0.38; 'does': 0.39; "didn't": 0.39; 'build': 0.40; 'to:addr:python.org': 0.40; 'where': 0.40; 'called': 0.40; 'ever': 0.60; 'provide': 0.61; 'here.': 0.62; 'making': 0.62; 'here': 0.66; 'stated': 0.70; 'services.': 0.72; 'facilities': 0.72; 'insight,': 0.84; 'lacks': 0.84; 'glad': 0.87; 'capability': 0.91; 'sorry.': 0.91; 'tough': 0.95 X-Authority-Analysis: v=2.1 cv=NrEbCZpJ c=1 sm=1 tr=0 a=g3mLq75WYuDrh3Lt0JSDww==:117 a=g3mLq75WYuDrh3Lt0JSDww==:17 a=QC7fh9NfAAAA:8 a=5pFAO2ZBLFIA:10 a=8nJEP1OIZ-IA:10 a=ff-B7xzCdYMA:10 a=elzRbq9_KkDnFw5NdbwA:9 a=wPNLvfGTeEIA:10 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.activenetwerx.com X-Spam-Level: * X-Spam-Status: No, score=1.3 required=5.0 tests=RDNS_NONE autolearn=no autolearn_force=no version=3.4.0 From: "Joseph L. Casale" To: "Sven R. Kunze" , "python-list@python.org" Subject: Re: Writing a module to abstract a REST api Thread-Topic: Writing a module to abstract a REST api Thread-Index: AQHQ8VdKzAS7nkl7nU2AayZu81Yu155BmmuAgADNE1WAAI/JAP//2Vfo Date: Fri, 18 Sep 2015 21:43:13 +0000 References: <1b35c9c9b6864d7bb9bf11e0e3cb98ca@exch.activenetwerx.com>, <55FB2A8F.9050501@mail.de> <1442590107897.9135@activenetwerx.com>,<55FC4F34.2030800@mail.de> In-Reply-To: <55FC4F34.2030800@mail.de> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [72.29.233.193] Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-CMAE-Envelope: MS4wfLb2NEVg2YM4+lhKHdbn7p/M11LQo1hOGD77w+KvRKxnCMoGlfhQO/FdC2dSdLesZn01xKDZK/UsZF/kigvKU+k08TZPc8T5RI1BVr6J08nLM4o3uJ7betGWqrSnsbitxrT/UeI6n6mCsRjJn4YQfksMl42mijRjrPOWkWcdtAQTusAB6r0pZpFqdHyyEyTSDg== X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 92 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1442612605 news.xs4all.nl 23844 [2001:888:2000:d::a6]:45827 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:96839 Hi Sven,=0A= =0A= >> The problem now comes from the following:=0A= >>=0A= >> # foo now contains a handle to the remote api.=0A= >> foo =3D InstanceOfApiWrapper()=0A= >=0A= > Is it necessary to have an instance of that API? Just curiosity here.=0A= =0A= Not always but often as the pattern here might rely on a handle=0A= to a c types based api handle for example which might be a pointer=0A= or it may hold a session with credentials and state (not for REST of course= ).=0A= =0A= >> # queues is a container of Queue classes.=0A= >> queues =3D foo.get_queues()=0A= >>=0A= >> queue =3D queues[0]=0A= >> queue.delete()=0A= >=0A= > Alright. I see you want to have concrete classes, so you work with HTTP= =0A= > like you would do with SOAP-bases web services.=0A= =0A= Yup.=0A= =0A= > I actually was referring to the self-expanding capability of REST=0A= > (please note, REST is not HTTP, HTTP is one protocol that can be use to= =0A= > build an REST-ful API). It's basically like: you query a resource which= =0A= > holds an link to another resource which you then you query by following= =0A= > that link and so on and so forth. So, all what you need for REST is one= =0A= > starting point to explore the resource graph.=0A= =0A= Well that is true, but what of the credential object that gets created=0A= with the instance of InstanceOfApiWrapper? You are certainly right=0A= in that the instance of Queue being REST based will always have all=0A= it needs to perform the functions, it just lacks the credentials.=0A= =0A= >> In this case its possible for foo (InstanceOfApiWrapper) to inject a ref= erence=0A= >> to itself so the delete() can actually make the call.=0A= >>=0A= >> # I want to create a queue from scratch...=0A= >> disparate_queue =3D Queue(x, y, z)=0A= >> # Now what happens? No handle to an api?=0A= >> disparate_queue.delete()=0A= >=0A= > I don't see an issue here. Looks quite readable.=0A= =0A= Well, what credentials does .delete() use? I should have actually stated=0A= that, sorry.=0A= =0A= >> An alternative is:=0A= >> foo.delete_queue(disparate_queue)=0A= >>=0A= >> That's not a pattern I prefer, what facilities in Python provide for a w= orkaround=0A= >> here?=0A= >=0A= > You always can add attributes to objects. So, add something like an=0A= > __api__ attribute (which nobody would ever use except you when creating= =0A= > these queue objects in "get_queues").=0A= =0A= This is where I am going, but how do you perform dependency injection=0A= in Python? =0A= =0A= > It's perfectly fine to add a "secret" API instance to the object. It's=0A= > called aspect-oriented programming. You remove the aspect of how to=0A= > correctly manage an API instance and put that knowledge into a separate= =0A= > piece of code. *thumbs up*=0A= =0A= Yea, I am glad you agree:) Its a model I certainly subscribe to. I just don= 't=0A= know how to make the disparate case "know" of the foo instance when=0A= foo didn't instantiate it (which gives the injection opportunity).=0A= =0A= That foo instance also serves of a starting point to make the GET type quer= ies.=0A= =0A= How would you go about making disparate case lookup a handle, especially=0A= when I insist on placing all the objects in their files. I know, tough to d= o in=0A= Python, but its what I am used to.=0A= =0A= Thanks a lot for the knowledge and insight, I greatly appreciate this.=0A= jlc=