def delete(self): """Record ``DELETE`` endpoint: delete a record and return it. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPNotFound` if the record is not found. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPPreconditionFailed` if ``If-Match`` header is provided and record modified in the iterim. """ self._raise_400_if_invalid_id(self.record_id) record = self._get_record_or_404(self.record_id) self._raise_412_if_modified(record) # Retreive the last_modified information from a querystring if present. last_modified = self.request.GET.get('last_modified') if last_modified: last_modified = native_value(last_modified.strip('"')) if not isinstance(last_modified, six.integer_types): error_details = { 'name': 'last_modified', 'location': 'querystring', 'description': 'Invalid value for %s' % last_modified } raise_invalid(self.request, **error_details) # If less or equal than current record. Ignore it. if last_modified <= record[self.model.modified_field]: last_modified = None deleted = self.model.delete_record(record, last_modified=last_modified) return self.postprocess(deleted, action=ACTIONS.DELETE)
def _extract_filters(self, queryparams=None): """Extracts filters from QueryString parameters.""" if not queryparams: queryparams = self.request.GET filters = [] for param, value in queryparams.items(): param = param.strip() value = native_value(value) # Ignore specific fields if param.startswith('_') and param not in ('_since', '_to', '_before'): continue # Handle the _since specific filter. if param in ('_since', '_to', '_before'): if not isinstance(value, six.integer_types): error_details = { 'name': param, 'location': 'querystring', 'description': 'Invalid value for %s' % param } raise_invalid(self.request, **error_details) if param == '_since': operator = COMPARISON.GT else: if param == '_to': 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') send_alert(self.request, message, url) operator = COMPARISON.LT filters.append( Filter(self.collection.modified_field, value, operator) ) continue m = re.match(r'^(min|max|not|lt|gt)_(\w+)$', param) if m: keyword, field = m.groups() operator = getattr(COMPARISON, keyword.upper()) else: operator, field = COMPARISON.EQ, param if not self.is_known_field(field): error_details = { 'location': 'querystring', 'description': "Unknown filter field '{0}'".format(param) } raise_invalid(self.request, **error_details) filters.append(Filter(field, value, operator)) return filters
def _extract_filters(self, queryparams=None): """Extracts filters from QueryString parameters.""" if not queryparams: queryparams = self.request.GET filters = [] for param, value in queryparams.items(): param = param.strip() value = native_value(value) # Ignore specific fields if param.startswith('_') and param not in ('_since', '_to'): continue # Handle the _since specific filter. if param in ('_since', '_to'): if not isinstance(value, six.integer_types): error_details = { 'name': param, 'location': 'querystring', 'description': 'Invalid value for _since' } raise_invalid(self.request, **error_details) if param == '_since': operator = COMPARISON.GT else: operator = COMPARISON.LT filters.append( Filter(self.collection.modified_field, value, operator) ) continue m = re.match(r'^(min|max|not|lt|gt)_(\w+)$', param) if m: keyword, field = m.groups() operator = getattr(COMPARISON, keyword.upper()) else: operator, field = COMPARISON.EQ, param if not self.is_known_field(field): error_details = { 'location': 'querystring', 'description': "Unknown filter field '{0}'".format(param) } raise_invalid(self.request, **error_details) filters.append(Filter(field, value, operator)) return filters
def test_true_values(self): true_strings = ['True', 'on', 'true', 'yes'] true_values = [native_value(s) for s in true_strings] self.assertTrue(all(true_values))
def test_false_values(self): false_strings = ['False', 'off', 'false', 'no'] false_values = [native_value(s) for s in false_strings] self.assertFalse(any(false_values))
def test_zero_and_one_coerce_to_integers(self): self.assertEqual(native_value('1'), 1) self.assertEqual(native_value('0'), 0)
def test_float(self): self.assertEqual(native_value('3.14'), 3.14)
def test_simple_string(self): self.assertEqual(native_value('value'), 'value')
def test_integer(self): self.assertEqual(native_value('7'), 7)
def test_false_values(self): false_strings = ["False", "off", "false", "no"] false_values = [native_value(s) for s in false_strings] self.assertFalse(any(false_values))
def test_true_values(self): true_strings = ["True", "on", "true", "yes"] true_values = [native_value(s) for s in true_strings] self.assertTrue(all(true_values))
def test_simple_string(self): self.assertEqual(native_value("value"), "value")
def test_non_string_values(self): self.assertEqual(native_value(7), 7) self.assertEqual(native_value(True), True)
def _extract_filters(self, queryparams=None): """Extracts filters from QueryString parameters.""" if not queryparams: queryparams = self.request.GET filters = [] for param, paramvalue in queryparams.items(): param = param.strip() error_details = { 'name': param, 'location': 'querystring', 'description': 'Invalid value for %s' % param } # Ignore specific fields if param.startswith('_') and param not in ('_since', '_to', '_before'): continue # Handle the _since specific filter. if param in ('_since', '_to', '_before'): value = native_value(paramvalue.strip('"')) if not isinstance(value, six.integer_types): raise_invalid(self.request, **error_details) if param == '_since': operator = COMPARISON.GT else: if param == '_to': 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') send_alert(self.request, message, url) operator = COMPARISON.LT filters.append( Filter(self.model.modified_field, value, operator)) continue m = re.match(r'^(min|max|not|lt|gt|in|exclude)_(\w+)$', param) if m: keyword, field = m.groups() operator = getattr(COMPARISON, keyword.upper()) else: operator, field = COMPARISON.EQ, param if not self.is_known_field(field): error_msg = "Unknown filter field '{0}'".format(param) error_details['description'] = error_msg raise_invalid(self.request, **error_details) value = native_value(paramvalue) if operator in (COMPARISON.IN, COMPARISON.EXCLUDE): value = set([native_value(v) for v in paramvalue.split(',')]) all_integers = all( [isinstance(v, six.integer_types) for v in value]) all_strings = all( [isinstance(v, six.text_type) for v in value]) has_invalid_value = ( (field == self.model.id_field and not all_strings) or (field == self.model.modified_field and not all_integers)) if has_invalid_value: raise_invalid(self.request, **error_details) filters.append(Filter(field, value, operator)) return filters
def _extract_filters(self, queryparams=None): """Extracts filters from QueryString parameters.""" if not queryparams: queryparams = self.request.GET filters = [] for param, paramvalue in queryparams.items(): param = param.strip() error_details = { 'name': param, 'location': 'querystring', 'description': 'Invalid value for %s' % param } # Ignore specific fields if param.startswith('_') and param not in ('_since', '_to', '_before'): continue # Handle the _since specific filter. if param in ('_since', '_to', '_before'): value = native_value(paramvalue.strip('"')) if not isinstance(value, six.integer_types): raise_invalid(self.request, **error_details) if param == '_since': operator = COMPARISON.GT else: if param == '_to': 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') send_alert(self.request, message, url) operator = COMPARISON.LT filters.append( Filter(self.model.modified_field, value, operator) ) continue m = re.match(r'^(min|max|not|lt|gt|in|exclude)_(\w+)$', param) if m: keyword, field = m.groups() operator = getattr(COMPARISON, keyword.upper()) else: operator, field = COMPARISON.EQ, param if not self.is_known_field(field): error_msg = "Unknown filter field '{0}'".format(param) error_details['description'] = error_msg raise_invalid(self.request, **error_details) value = native_value(paramvalue) if operator in (COMPARISON.IN, COMPARISON.EXCLUDE): value = set([native_value(v) for v in paramvalue.split(',')]) all_integers = all([isinstance(v, six.integer_types) for v in value]) all_strings = all([isinstance(v, six.text_type) for v in value]) has_invalid_value = ( (field == self.model.id_field and not all_strings) or (field == self.model.modified_field and not all_integers) ) if has_invalid_value: raise_invalid(self.request, **error_details) filters.append(Filter(field, value, operator)) return filters