1
2
3
4
5
6 from StringIO import StringIO
7 import urlparse
8
9 try:
10 from IPython.config.loader import Config
11 from IPython.frontend.terminal.embed import InteractiveShellEmbed
12 except ImportError:
13 raise ImportError('IPython (http://pypi.python.org/pypi/ipython) >=0.11' +\
14 'is required.')
15
16 try:
17 import webob
18 except ImportError:
19 raise ImportError('webob (http://pythonpaste.org/webob/) is required.')
20
21 from webob import Response as BaseResponse
22
23 from restkit import __version__
24 from restkit.contrib.console import common_indent, json
25 from restkit.contrib.webob_api import Request as BaseRequest
26
27
30 return '<Stream(%s)>' % self.len
31
32
41 return '<JSON(%s)>' % self.__value
42
43
51
52
54 ResponseClass = Response
56 url = self.url
57 stream = None
58 for a in args:
59 if isinstance(a, Stream):
60 stream = a
61 a.seek(0)
62 continue
63 elif isinstance(a, basestring):
64 if a.startswith('http'):
65 url = a
66 elif a.startswith('/'):
67 url = a
68
69 self.set_url(url)
70
71 if stream:
72 self.body_file = stream
73 self.content_length = stream.len
74 if self.method == 'GET' and kwargs:
75 for k, v in kwargs.items():
76 self.GET[k] = v
77 elif self.method == 'POST' and kwargs:
78 for k, v in kwargs.items():
79 self.GET[k] = v
80 return BaseRequest.get_response(self)
81
86
89
90
91 -class ContentTypes(object):
92 _values = {}
94 return '<%s(%s)>' % (self.__class__.__name__, sorted(self._values))
96 return '\n'.join(['%-20.20s: %s' % h for h in \
97 sorted(self._value.items())])
98
99
100 ctypes = ContentTypes()
101 for k in common_indent:
102 attr = k.replace('/', '_').replace('+', '_')
103 ctypes._values[attr] = attr
104 ctypes.__dict__[attr] = k
105 del k, attr
106
107
110
111 cfg = Config()
112 shell_config = cfg.InteractiveShellEmbed
113 shell_config.prompt_in1 = '\C_Blue\#) \C_Greenrestcli\$ '
114
115 super(RestShell, self).__init__(config = cfg,
116 banner1= 'restkit shell %s' % __version__,
117 exit_msg="quit restcli shell", user_ns=user_ns)
118
119
121 methods = dict(
122 get='[req|url|path_info], **query_string',
123 post='[req|url|path_info], [Stream()|**query_string_body]',
124 head='[req|url|path_info], **query_string',
125 put='[req|url|path_info], stream',
126 delete='[req|url|path_info]')
127
128 - def __init__(self, url='/', options=None, **kwargs):
129 self.options = options
130 self.url = url or '/'
131 self.ns = {}
132 self.shell = RestShell(user_ns=self.ns)
133 self.update_ns(self.ns)
134 self.help()
135 self.shell(header='', global_ns={}, local_ns={})
136
170
172 def req(*args, **kwargs):
173 resp = self.request(k.upper(), *args, **kwargs)
174 self.shell.user_ns.update(dict(resp=resp))
175
176 print resp
177 return resp
178 req.func_name = k
179 req.__name__ = k
180 req.__doc__ = """send a HTTP %s""" % k.upper()
181 return req
182
183 - def request(self, meth, *args, **kwargs):
184 """forward to restkit.request"""
185 req = None
186 for a in args:
187 if isinstance(a, Request):
188 req = a
189 args = [a for a in args if a is not req]
190 break
191 if req is None:
192 req = self.shell.user_ns.get('req')
193 if not isinstance(req, Request):
194 req = Request.blank('/')
195 del req.content_type
196 req.method = meth
197
198 req.set_url(self.url)
199 resp = req.get_response(*args, **kwargs)
200 self.url = req.url
201 return resp
202
204 ns = self.ns.copy()
205 methods = ''
206 for k in sorted(self.methods):
207 args = self.methods[k]
208 doc = ' >>> %s(%s)' % (k, args)
209 methods += '%-65.65s # send a HTTP %s\n' % (doc, k)
210 ns['methods'] = methods
211 print HELP.strip() % ns
212 print ''
213
215 return '<shellclient>'
216
217
218 -def main(*args, **kwargs):
219 for a in args:
220 if a.startswith('http://'):
221 kwargs['url'] = a
222 ShellClient(**kwargs)
223
224
225 HELP = """
226 restkit shell
227 =============
228
229 HTTP Methods
230 ------------
231
232 %(methods)s
233 Helpers
234 -------
235
236 >>> req # request to play with. By default http methods will use this one
237 %(req)r
238
239 >>> stream # Stream() instance if you specified a -i in command line
240 %(stream)r
241
242 >>> ctypes # Content-Types helper with headers properties
243 %(ctypes)r
244 """
245
246 if __name__ == '__main__':
247 import sys
248 main(*sys.argv[1:])
249