5
\$\begingroup\$

I wrotethis, which essentially acts as a single library for all possible REST services.

Here is the main file, as of alpha version 1:

import requests, jsonclass RestConsumer(object):    def __init__(self,base_url,append_json=False,**kwargs):        self.base_url = base_url        self.uriparts = []        self.append_json = append_json        self.kwargs = kwargs    def __getattr__(self,k):        if k=='spc':            return self.spc        if not k[0] == '_':            self.uriparts.append(k)        else:            if k[1:3]=='in':                self.uriparts.append(k[3:])            elif k[1:3] == 'uh':                self.uriparts.append(k.replace('_','-'))        return self    def spc(self,k):        self.uriparts.append(k)        return self    def __call__(self, **kwargs):        uri_constructed = '/'.join(self.uriparts)        self.uriparts = []        self.uri_constructed = "%s%s"%(uri_constructed,'.json') if self.append_json else uri_constructed        self.url = '/'.join([self.base_url,self.uri_constructed])        return self.get(self.url,**kwargs)    def get(self,url,**kwargs):        print url        r = requests.get(url,**kwargs)        return json.loads(r.content)    def post(self,**kwargs):        r = requests.post(**kwargs)        return json.loads(r.content)if __name__=='__main__':    from pprint import pprint    t = RestConsumer(base_url='https://api.twitter.com/1',append_json=True)    public_timeline = t.statuses.public_timeline()    pprint(public_timeline)    g = RestConsumer(base_url='https://api.github.com')    repos = g.users.kennethreitz.repos()    pprint(repos)    s = RestConsumer(base_url='http://api.stackoverflow.com/1.1')    sr = s.users.spc('55562').questions.unanswered()    pprint(sr)    sr2 = s.tags.python.spc('top-answerers').spc('all-time')()    pprint(sr2)

The rationale and usage is all explained in theREADME.

Please critique the library, the idea, implementation and shed light on alternatives.

Jamal's user avatar
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
askedJan 30, 2012 at 14:58
lprsd's user avatar
\$\endgroup\$

2 Answers2

4
\$\begingroup\$
import requests, jsonclass RestConsumer(object):    def __init__(self,base_url,append_json=False,**kwargs):        self.base_url = base_url        self.uriparts = []        self.append_json = append_json        self.kwargs = kwargs

Since you treat attributes "special", I recommend putting _ in front of these attributes so that are clearly offset.

    def __getattr__(self,k):

I recommend not using the random letterk for the name.

        if k=='spc':            return self.spc

__getattr__ only gets invoked if the attribute cannot be found. Sincespc will be found this won't ever get used.

        if not k[0] == '_':            self.uriparts.append(k)        else:            if k[1:3]=='in':                self.uriparts.append(k[3:])

What's the point of this rule?_infoo meansfoo?

            elif k[1:3] == 'uh':                self.uriparts.append(k.replace('_','-'))

uh?

        return self

I don't like the way you've implemented this. Accessing attributes modifying the object's state is deeply counter-intuitive.

    def spc(self,k):        self.uriparts.append(k)        return self

spc is not a clear name. Its hard to guess what it means.

    def __call__(self, **kwargs):        uri_constructed = '/'.join(self.uriparts)        self.uriparts = []        self.uri_constructed = "%s%s"%(uri_constructed,'.json') if self.append_json else uri_constructed        self.url = '/'.join([self.base_url,self.uri_constructed])        return self.get(self.url,**kwargs)    def get(self,url,**kwargs):        print url        r = requests.get(url,**kwargs)        return json.loads(r.content)    def post(self,**kwargs):        r = requests.post(**kwargs)        return json.loads(r.content)

get prints whilepost doesn't. Probably neither should be printing, a log facility might be useful.

The way you've designed this, some useful things won't work:

public_timeline = twitter.statuses.public_timelinewhile True:      print public_timeline()

or

user = s.users.spc(55562)print user.questions.unanswered()print user.questions.answered()

I suggest that instead of modifying the object, you return new objects. That way it will work in an intuitive manner.

Instead ofspc I suggest that you provide a__getitem__. That way you can do:

 s.users[55562].questions.unanswered()

Which I think will make it cleaner.

answeredJan 30, 2012 at 18:47
Winston Ewert's user avatar
\$\endgroup\$
2
  • \$\begingroup\$All excellent feedback. Thank you. I am modifying it now.\$\endgroup\$CommentedJan 31, 2012 at 6:47
  • \$\begingroup\$I changed it from mutating self to returning new objects. But can't figure out how to enable the last useful things you talk about.stackoverflow.com/questions/9076403/…\$\endgroup\$CommentedJan 31, 2012 at 8:37
1
\$\begingroup\$

you should include a docstring on what the program is (steal from readme "RestConsumer is a generic python wrapper for consuming JSON REST APIs" although maybe add alittle more on use).

answeredSep 22, 2012 at 13:07
Duncan's user avatar
\$\endgroup\$

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.