1from __future__ import unicode_literals 2 3import logging 4 5from rbtools.api.decode import decode_response 6from rbtools.api.factory import create_resource 7from rbtools.api.request import HttpRequest, ReviewBoardServer 8from rbtools.api.transport import Transport 9 10 11class SyncTransport(Transport): 12 """A synchronous transport layer for the API client. 13 14 The file provided in cookie_file is used to store and retrieve 15 the authentication cookies for the API. 16 17 The optional agent parameter can be used to specify a custom 18 User-Agent string for the API. If not provided, the default 19 RBTools User-Agent will be used. 20 21 The optional session can be used to specify an 'rbsessionid' 22 to use when authenticating with reviewboard. 23 """ 24 def __init__(self, url, cookie_file=None, username=None, password=None, 25 api_token=None, agent=None, session=None, disable_proxy=False, 26 auth_callback=None, otp_token_callback=None, 27 verify_ssl=True, allow_caching=True, 28 cache_location=None, in_memory_cache=False, 29 save_cookies=True, ext_auth_cookies=None, 30 ca_certs=None, client_key=None, client_cert=None, 31 *args, **kwargs): 32 super(SyncTransport, self).__init__(url, *args, **kwargs) 33 self.allow_caching = allow_caching 34 self.cache_location = cache_location 35 self.in_memory_cache = in_memory_cache 36 self.server = ReviewBoardServer( 37 self.url, 38 cookie_file=cookie_file, 39 username=username, 40 password=password, 41 api_token=api_token, 42 session=session, 43 disable_proxy=disable_proxy, 44 auth_callback=auth_callback, 45 otp_token_callback=otp_token_callback, 46 verify_ssl=verify_ssl, 47 save_cookies=save_cookies, 48 ext_auth_cookies=ext_auth_cookies, 49 ca_certs=ca_certs, 50 client_key=client_key, 51 client_cert=client_cert) 52 53 def get_root(self): 54 return self._execute_request(HttpRequest(self.server.url)) 55 56 def get_path(self, path, *args, **kwargs): 57 if not path.endswith('/'): 58 path = path + '/' 59 60 if path.startswith('/'): 61 path = path[1:] 62 63 return self._execute_request( 64 HttpRequest(self.server.url + path, query_args=kwargs)) 65 66 def get_url(self, url, *args, **kwargs): 67 if not url.endswith('/'): 68 url = url + '/' 69 70 return self._execute_request(HttpRequest(url, query_args=kwargs)) 71 72 def login(self, username, password): 73 self.server.login(username, password) 74 75 def logout(self): 76 self.server.logout() 77 78 def execute_request_method(self, method, *args, **kwargs): 79 request = method(*args, **kwargs) 80 81 if isinstance(request, HttpRequest): 82 return self._execute_request(request) 83 84 return request 85 86 def _execute_request(self, request): 87 """Execute an HTTPRequest and construct a resource from the payload""" 88 logging.debug('Making HTTP %s request to %s', 89 request.method, request.url) 90 91 rsp = self.server.make_request(request) 92 info = rsp.info() 93 mime_type = info['Content-Type'] 94 item_content_type = info.get('Item-Content-Type', None) 95 96 if request.method == 'DELETE': 97 # DELETE calls don't return any data. Everything else should. 98 return None 99 else: 100 payload = rsp.read() 101 payload = decode_response(payload, mime_type) 102 103 return create_resource(self, payload, request.url, 104 mime_type=mime_type, 105 item_mime_type=item_content_type) 106 107 def enable_cache(self): 108 """Enable caching for all future HTTP requests. 109 110 The cache will be created at the default location if none is provided. 111 112 If the in_memory parameter is True, the cache will be created in memory 113 instead of on disk. This overrides the cache_location parameter. 114 """ 115 if self.allow_caching: 116 self.server.enable_cache(cache_location=self.cache_location, 117 in_memory=self.in_memory_cache) 118 119 def __repr__(self): 120 return '<%s(url=%r, cookie_file=%r, agent=%r)>' % ( 121 self.__class__.__name__, 122 self.url, 123 self.server.cookie_file, 124 self.server.agent) 125