old_contents: from base64 import b64decode
  from collections import namedtuple
  
  from django.http import QueryDict
  from django.utils.translation import gettext_lazy as _
  from tastypie.exceptions import BadRequest
  
  
  LIMIT_PARAM_ERROR_MESSAGE = _("Invalid limit '{value}' provided. Please provide a positive integer.")
  
  
  def get_limit_offset(param_name, request_data, default, max_value=None):
      value = request_data.get(param_name, default)
  
      try:
          value = int(value)
      except ValueError:
          raise BadRequest(LIMIT_PARAM_ERROR_MESSAGE.format(param_name=param_name, value=value))
  
      if value <= 0:
          raise BadRequest(LIMIT_PARAM_ERROR_MESSAGE.format(param_name=param_name, value=value))
  
      if max_value:
          value = min(value, max_value)
      return value
  
  
  def sort_query(query, request_params):
      """Always order by date and ID to ensure consistent result order
      across requests.
  
      This is required for the cursor pagination.
      """
      order_by = request_params.get("order_by")
  
      if not order_by:
          order_by_args = ["date", "id"]
      else:
          if order_by not in ("date", "-date"):
              raise BadRequest(_("No matching '{field_name}' field for ordering").format(field_name=order_by))
          order_by_args = [order_by, "id"]
  
      return query.order_by(*order_by_args)
  
  
  class CursorParams(namedtuple("CursorParams", "params, domain, is_cursor")):
      def __getitem__(self, key):
          return self.params[key]
  
      def __contains__(self, key):
          return key in self.params
  
      def items(self):
          return self.params.items()
  
      def get(self, key, default=None):
          try:
              return self[key]
          except KeyError:
              return default
  
  
  def get_request_params(request):
      """Get the query params from the request. If the request is using a cursor
      decode the cursor and return those values as the query params.
      :returns: CursorParams tuple"""
      request_params = request.GET.dict()
      if 'cursor' in request_params:
          params_string = b64decode(request_params['cursor']).decode('utf-8')
          return CursorParams(
              QueryDict(params_string).dict(), request.domain, True
          )
      return CursorParams(request_params, request.domain, False)
  
new_contents: from base64 import b64decode
  from collections import namedtuple
  
  from attr import attrib, attrs
  from django.http import QueryDict
  from django.utils.translation import gettext_lazy as _
  from tastypie.exceptions import BadRequest
  
  
  LIMIT_PARAM_ERROR_MESSAGE = _("Invalid limit '{value}' provided. Please provide a positive integer.")
  
  
  def get_limit_offset(param_name, request_data, default, max_value=None):
      value = request_data.get(param_name, default)
  
      try:
          value = int(value)
      except ValueError:
          raise BadRequest(LIMIT_PARAM_ERROR_MESSAGE.format(param_name=param_name, value=value))
  
      if value <= 0:
          raise BadRequest(LIMIT_PARAM_ERROR_MESSAGE.format(param_name=param_name, value=value))
  
      if max_value:
          value = min(value, max_value)
      return value
  
  
  def sort_query(query, request_params):
      """Always order by date and ID to ensure consistent result order
      across requests.
  
      This is required for the cursor pagination.
      """
      order_by = request_params.get("order_by")
  
      if not order_by:
          order_by_args = ["date", "id"]
      else:
          if order_by not in ("date", "-date"):
              raise BadRequest(_("No matching '{field_name}' field for ordering").format(field_name=order_by))
          order_by_args = [order_by, "id"]
  
      return query.order_by(*order_by_args)
  
  
  @attrs
  class CursorParams():
      params = attrib()
      domain = attrib()
      is_cursor = attrib()
  
      def __getitem__(self, key):
          return self.params[key]
  
      def __contains__(self, key):
          return key in self.params
  
      def items(self):
          return self.params.items()
  
      def get(self, key, default=None):
          try:
              return self[key]
          except KeyError:
              return default
  
  
  def get_request_params(request):
      """Get the query params from the request. If the request is using a cursor
      decode the cursor and return those values as the query params.
      :returns: CursorParams tuple"""
      request_params = request.GET.dict()
      if 'cursor' in request_params:
          params_string = b64decode(request_params['cursor']).decode('utf-8')
          return CursorParams(
              QueryDict(params_string).dict(), request.domain, True
          )
      return CursorParams(request_params, request.domain, False)
  
subject: convert namedtuple to attrs