Package restkit :: Package contrib :: Module ipython_shell
[hide private]

Source Code for Module restkit.contrib.ipython_shell

  1  # -*- coding: utf-8 - 
  2  # 
  3  # This file is part of restkit released under the MIT license.  
  4  # See the NOTICE for more information. 
  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   
28 -class Stream(StringIO):
29 - def __repr__(self):
30 return '<Stream(%s)>' % self.len
31 32
33 -class JSON(Stream):
34 - def __init__(self, value):
35 self.__value = value 36 if json: 37 Stream.__init__(self, json.dumps(value)) 38 else: 39 Stream.__init__(self, value)
40 - def __repr__(self):
41 return '<JSON(%s)>' % self.__value
42 43
44 -class Response(BaseResponse):
45 - def __str__(self, skip_body=True):
46 if self.content_length < 200 and skip_body: 47 skip_body = False 48 return BaseResponse.__str__(self, skip_body=skip_body)
49 - def __call__(self):
50 print self
51 52
53 -class Request(BaseRequest):
54 ResponseClass = Response
55 - def get_response(self, *args, **kwargs):
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
82 - def __str__(self, skip_body=True):
83 if self.content_length < 200 and skip_body: 84 skip_body = False 85 return BaseRequest.__str__(self, skip_body=skip_body)
86
87 - def __call__(self):
88 print self
89 90
91 -class ContentTypes(object):
92 _values = {}
93 - def __repr__(self):
94 return '<%s(%s)>' % (self.__class__.__name__, sorted(self._values))
95 - def __str__(self):
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
108 -class RestShell(InteractiveShellEmbed):
109 - def __init__(self, user_ns={}):
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
120 -class ShellClient(object):
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
137 - def update_ns(self, ns):
138 for k in self.methods: 139 ns[k] = self.request_meth(k) 140 stream = None 141 headers = {} 142 if self.options: 143 if self.options.input: 144 stream = Stream(open(self.options.input).read()) 145 if self.options.headers: 146 for header in self.options.headers: 147 try: 148 k, v = header.split(':') 149 headers.append((k, v)) 150 except ValueError: 151 pass 152 req = Request.blank('/') 153 req._client = self 154 del req.content_type 155 if stream: 156 req.body_file = stream 157 158 req.headers = headers 159 req.set_url(self.url) 160 ns.update( 161 Request=Request, 162 Response=Response, 163 Stream=Stream, 164 req=req, 165 stream=stream, 166 ctypes=ctypes, 167 ) 168 if json: 169 ns['JSON'] = JSON
170
171 - def request_meth(self, k):
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
203 - def help(self):
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
214 - def __repr__(self):
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