def test_delete_a_record_update_collection_timestamp(self): collection_resp = self.app.get(self.collection_url, headers=self.headers) old_timestamp = int( decode_header(json.loads(collection_resp.headers['ETag']))) self.app.delete(self.record_url, headers=self.headers, status=200) collection_resp = self.app.get(self.collection_url, headers=self.headers) new_timestamp = int( decode_header(json.loads(collection_resp.headers['ETag']))) assert old_timestamp < new_timestamp
def _raise_412_if_modified(self, record=None): """Raise 412 if current timestamp is superior to the one specified in headers. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPPreconditionFailed` """ if_match = self.request.headers.get('If-Match') if_none_match = self.request.headers.get('If-None-Match') if not if_match and not if_none_match: return if_match = decode_header(if_match) if if_match else None if record and if_none_match and decode_header(if_none_match) == '*': if record.get(self.model.deleted_field, False): # Tombstones should not prevent creation. return modified_since = -1 # Always raise. elif if_match: try: if not (if_match[0] == if_match[-1] == '"'): raise ValueError() modified_since = int(if_match[1:-1]) except (IndexError, ValueError): message = ("Invalid value for If-Match. The value should " "be integer between double quotes.") error_details = { 'location': 'headers', 'description': message } raise_invalid(self.request, **error_details) else: # In case _raise_304_if_not_modified() did not raise. return if record: current_timestamp = record[self.model.modified_field] else: current_timestamp = self.model.timestamp() if current_timestamp > modified_since: error_msg = 'Resource was modified meanwhile' details = {'existing': record} if record else {} response = http_error(HTTPPreconditionFailed(), errno=ERRORS.MODIFIED_MEANWHILE, message=error_msg, details=details) self._add_timestamp_header(response, timestamp=current_timestamp) raise response
def test_create_a_record_update_collection_timestamp(self): collection_resp = self.app.get(self.collection_url, headers=self.headers) old_timestamp = int( decode_header(json.loads(collection_resp.headers['ETag']))) self.app.post_json(self.collection_url, MINIMALIST_RECORD, headers=self.headers, status=201) collection_resp = self.app.get(self.collection_url, headers=self.headers) new_timestamp = int( decode_header(json.loads(collection_resp.headers['ETag']))) assert old_timestamp < new_timestamp
def _raise_412_if_modified(self, record=None): """Raise 412 if current timestamp is superior to the one specified in headers. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPPreconditionFailed` """ if_match = self.request.headers.get('If-Match') if_none_match = self.request.headers.get('If-None-Match') if not if_match and not if_none_match: return if_match = decode_header(if_match) if if_match else None if record and if_none_match and decode_header(if_none_match) == '*': if record.get(self.model.deleted_field, False): # Tombstones should not prevent creation. return modified_since = -1 # Always raise. elif if_match: try: if not (if_match[0] == if_match[-1] == '"'): raise ValueError() modified_since = int(if_match[1:-1]) except (IndexError, ValueError): message = ("Invalid value for If-Match. The value should " "be integer between double quotes.") error_details = {'location': 'headers', 'description': message} raise_invalid(self.request, **error_details) else: # In case _raise_304_if_not_modified() did not raise. return if record: current_timestamp = record[self.model.modified_field] else: current_timestamp = self.model.timestamp() if current_timestamp > modified_since: error_msg = 'Resource was modified meanwhile' details = {'existing': record} if record else {} response = http_error(HTTPPreconditionFailed(), errno=ERRORS.MODIFIED_MEANWHILE, message=error_msg, details=details) self._add_timestamp_header(response, timestamp=current_timestamp) raise response
def _raise_304_if_not_modified(self, record=None): """Raise 304 if current timestamp is inferior to the one specified in headers. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPNotModified` """ if_none_match = self.request.headers.get('If-None-Match') if not if_none_match: return if_none_match = decode_header(if_none_match) try: if not (if_none_match[0] == if_none_match[-1] == '"'): raise ValueError() modified_since = int(if_none_match[1:-1]) except (IndexError, ValueError): if if_none_match == '*': return error_details = { 'location': 'headers', 'description': "Invalid value for If-None-Match" } raise_invalid(self.request, **error_details) if record: current_timestamp = record[self.model.modified_field] else: current_timestamp = self.model.timestamp() if current_timestamp <= modified_since: response = HTTPNotModified() self._add_timestamp_header(response, timestamp=current_timestamp) raise response
def test_filter_with__to_return_an_alert_header(self): self.resource.request.GET = {'_to': '3'} self.resource.collection_get() self.assertIn('Alert', self.resource.request.response.headers) alert = self.resource.request.response.headers['Alert'] self.assertDictEqual( decode_header(json.loads(alert)), { 'code': 'soft-eol', 'message': ('_to is now deprecated, ' 'you should use _before instead'), 'url': ('http://cliquet.rtfd.org/en/2.4.0/api/resource' '.html#list-of-available-url-parameters') })
def test_returns_an_unicode__string_if_passed_bytes_and_encoding(self): entry = 'Rémy'.encode('latin-1') value = decode_header(entry, 'latin-1') self.assertEqual(type(value), six.text_type)
def test_returns_an_unicode__string_if_passed_bytes(self): entry = 'Toto'.encode('utf-8') value = decode_header(entry) self.assertEqual(type(value), six.text_type)
def verify_alert_header(self, request, expected): self.assertIn('Alert', request.response.headers) alert = request.response.headers['Alert'] self.assertDictEqual(decode_header(json.loads(alert)), expected)
def verify_alert_header(self, request, expected): self.assertIn('Alert', request.response.headers) alert = request.response.headers['Alert'] self.assertDictEqual( decode_header(json.loads(alert)), expected)
def test_returns_an_unicode_string_if_passed_a_string(self): entry = 'Toto' value = decode_header(entry) self.assertEqual(entry, value)