def test_create_http_exception(self): """Test that create_http_exception creates specific exceptions.""" for code, (cls_name, cls_parent) in gcs_errors.http_errors.items(): exc = gcs_errors.create_http_exception(code, mock.sentinel.message) self.assertEqual(code, exc.code) self.assertTrue(isinstance(exc, getattr(gcs_errors, cls_name))) self.assertEqual(mock.sentinel.message, exc.message)
def _get_data(self, size, begin=0): if not size: return '' end = begin + size - 1 headers = {'Authorization': self._credentials.authorization, 'Range': 'bytes=%d-%d' % (begin, end)} params = {'alt': 'media'} r = requests.get(self._location, params=params, headers=headers) expected = (requests.codes.ok, requests.codes.partial_content, requests.codes.requested_range_not_satisfiable) if r.status_code not in expected: raise errors.create_http_exception( r.status_code, 'Error reading object %s in bucket %s: %s-%s' % (self.name, self.bucket, r.status_code, r.content)) if r.status_code == requests.codes.requested_range_not_satisfiable: return ('', True) content_range = r.headers.get('Content-Range') total_size = None if content_range: try: total_size = int(content_range.split('/')[-1]) eof = total_size <= begin + len(r.content) self.size = total_size except Exception: eof = len(r.content) < size if total_size is None: eof = len(r.content) < size return (r.content, eof)
def _open(self): safe_bucket = requests.utils.quote(self.bucket, safe='') safe_name = requests.utils.quote(self.name, safe='') if self._is_readable(): self._location = self._URL % (safe_bucket, safe_name) params = {'fields': 'size', 'generation': self._generation} headers = {'Authorization': self._credentials.authorization} r = requests.get(self._location, params=params, headers=headers) if r.status_code == requests.codes.ok: try: self.size = int(json.loads(r.content)['size']) except Exception as exc: raise errors.Error('Bad data returned by GCS %s' % exc) else: self.size = 0 initial_url = self._URL_UPLOAD % safe_bucket params = {'uploadType': 'resumable', 'name': self.name} headers = {'x-goog-resumable': 'start', 'Authorization': self._credentials.authorization, 'Content-type': 'application/octet-stream'} r = requests.post(initial_url, params=params, headers=headers) if r.status_code == requests.codes.ok: self._location = r.headers['Location'] if r.status_code != requests.codes.ok: raise errors.create_http_exception( r.status_code, 'Error opening object %s in bucket %s: %s-%s' % (self.name, self.bucket, r.status_code, r.content)) self.closed = False
def _send_data(self, data, begin=0, finalize=False): if not (data or finalize): return if not data: size = self.size data_range = 'bytes */%s' % size else: end = begin + len(data) - 1 size = self.size if finalize else '*' data_range = 'bytes %s-%s/%s' % (begin, end, size) headers = {'Authorization': self._credentials.authorization, 'Content-Range': data_range} r = requests.put(self._location, data=data, headers=headers) if size == '*': expected = requests.codes.resume_incomplete else: expected = requests.codes.ok if r.status_code != expected: raise errors.create_http_exception( r.status_code, 'Error writting to object %s in bucket %s: %s-%s' % (self.name, self.bucket, r.status_code, r.content))
def _get_data(self, size, begin=0): if not size: return '' end = begin + size - 1 headers = { 'Authorization': self._credentials.authorization, 'Range': 'bytes=%d-%d' % (begin, end) } params = {'alt': 'media'} r = requests.get(self._location, params=params, headers=headers) expected = (requests.codes.ok, requests.codes.partial_content, requests.codes.requested_range_not_satisfiable) if r.status_code not in expected: raise errors.create_http_exception( r.status_code, 'Error reading object %s in bucket %s: %s-%s' % (self.name, self.bucket, r.status_code, r.content)) if r.status_code == requests.codes.requested_range_not_satisfiable: return ('', True) content_range = r.headers.get('Content-Range') total_size = None if content_range: try: total_size = int(content_range.split('/')[-1]) eof = total_size <= begin + len(r.content) self.size = total_size except Exception: eof = len(r.content) < size if total_size is None: eof = len(r.content) < size return (r.content, eof)
def _request(self, op='GET', headers=None, body=None, parse=False, ok=(requests.codes.ok, ), url=None, format_url=True, **params): """Request actions on a GCS resource. :param op: Operation to perform (GET, PUT, POST, HEAD, DELETE). :type op: six.string_types :param headers: Headers to send in the request. Authentication will be added. :type headers: dict :param body: Body to send in the request. :type body: Dictionary, bytes or file-like object. :param parse: If we want to check that response body is JSON. :type parse: bool :param ok: Response status codes to consider as OK. :type ok: Iterable of integer numbers :param url: Alternative url to use :type url: six.string_types :param format_url: If we want provided url to be formatted with params :type format_url: bool :param params: All params to send as URL params in the request. :returns: requests.Request :""" headers = {} if not headers else headers.copy() headers['Authorization'] = self._credentials.authorization if not url: url = self._URL if format_url: format_args = { x: requests.utils.quote(six.text_type(getattr(self, x)), safe='') for x in self._required_attributes } url = url.format(**format_args) r = requests.request(op, url, params=params, headers=headers, json=body) if r.status_code not in ok: raise gcs_errors.create_http_exception(r.status_code, r.content) if parse: try: r.json() except Exception: raise gcs_errors.Error('GCS response is not JSON: %s' % r.content) return r
def _send_data(self, data, begin=0, finalize=False): if not (data or finalize): return if not data: size = self.size data_range = 'bytes */%s' % size else: end = begin + len(data) - 1 size = self.size if finalize else '*' data_range = 'bytes %s-%s/%s' % (begin, end, size) headers = { 'Authorization': self._credentials.authorization, 'Content-Range': data_range } r = requests.put(self._location, data=data, headers=headers) if size == '*': expected = requests.codes.resume_incomplete else: expected = requests.codes.ok if r.status_code != expected: raise errors.create_http_exception( r.status_code, 'Error writting to object %s in bucket %s: %s-%s' % (self.name, self.bucket, r.status_code, r.content))
def _open(self): safe_bucket = requests.utils.quote(self.bucket, safe='') safe_name = requests.utils.quote(self.name, safe='') if self._is_readable(): self._location = self._URL % (safe_bucket, safe_name) params = {'fields': 'size', 'generation': self._generation} headers = {'Authorization': self._credentials.authorization} r = requests.get(self._location, params=params, headers=headers) if r.status_code == requests.codes.ok: try: self.size = int(json.loads(r.content)['size']) except Exception as exc: raise errors.Error('Bad data returned by GCS %s' % exc) else: self.size = 0 initial_url = self._URL_UPLOAD % safe_bucket params = {'uploadType': 'resumable', 'name': self.name} headers = { 'x-goog-resumable': 'start', 'Authorization': self._credentials.authorization, 'Content-type': 'application/octet-stream' } r = requests.post(initial_url, params=params, headers=headers) if r.status_code == requests.codes.ok: self._location = r.headers['Location'] if r.status_code != requests.codes.ok: raise errors.create_http_exception( r.status_code, 'Error opening object %s in bucket %s: %s-%s' % (self.name, self.bucket, r.status_code, r.content)) self.closed = False
def test_create_http_exception_non_int_code(self): """Test create_http_exception creates exceptions from non int codes.""" for code, (cls_name, cls_parent) in gcs_errors.http_errors.items(): exc = gcs_errors.create_http_exception('code', mock.sentinel.message) self.assertEqual('code', exc.code) self.assertIs(gcs_errors.Http, type(exc)) self.assertEqual(mock.sentinel.message, exc.message)
def _request(self, op='GET', headers=None, body=None, parse=False, ok=(requests.codes.ok,), url=None, format_url=True, **params): """Request actions on a GCS resource. :param op: Operation to perform (GET, PUT, POST, HEAD, DELETE). :type op: six.string_types :param headers: Headers to send in the request. Authentication will be added. :type headers: dict :param body: Body to send in the request. :type body: Dictionary, bytes or file-like object. :param parse: If we want to check that response body is JSON. :type parse: bool :param ok: Response status codes to consider as OK. :type ok: Iterable of integer numbers :param url: Alternative url to use :type url: six.string_types :param format_url: If we want provided url to be formatted with params :type format_url: bool :param params: All params to send as URL params in the request. :returns: requests.Request :""" headers = {} if not headers else headers.copy() headers['Authorization'] = self._credentials.authorization if not url: url = self._URL if format_url: format_args = { x: requests.utils.quote(six.text_type(getattr(self, x)), safe='') for x in self._required_attributes} url = url.format(**format_args) r = requests.request(op, url, params=params, headers=headers, json=body) if r.status_code not in ok: raise gcs_errors.create_http_exception(r.status_code, r.content) if parse: try: r.json() except Exception: raise gcs_errors.Error('GCS response is not JSON: %s' % r.content) return r
def test_create_http_exception_non_specific(self): """Test create_http_exception creates non specific exceptions.""" exc = gcs_errors.create_http_exception(1, mock.sentinel.message) self.assertEqual(1, exc.code) self.assertIs(gcs_errors.Http, type(exc)) self.assertEqual(mock.sentinel.message, exc.message)