prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Remove colander deprecations
  ```
  /home/mathieu/Code/Mozilla/kinto/.venv/lib/python3.6/site-packages/cornice/validators/_colander.py:110: DeprecationWarning: Setting schema to a class is deprecated.  Set schema to an instance instead.
    schema = _ensure_instantiated(schema)
  ```
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `kinto/core/views/batch.py`
  Content:
  ```
  1 import logging
  2 
  3 import colander
  4 from cornice.validators import colander_validator
  5 from pyramid import httpexceptions
  6 from pyramid.security import NO_PERMISSION_REQUIRED
  7 
  8 from kinto.core import errors
  9 from kinto.core import Service
  10 from kinto.core.errors import ErrorSchema
  11 from kinto.core.utils import merge_dicts, build_request, build_response
  12 from kinto.core.resource.viewset import CONTENT_TYPES
  13 
  14 
  15 subrequest_logger = logging.getLogger('subrequest.summary')
  16 
  17 valid_http_method = colander.OneOf(('GET', 'HEAD', 'DELETE', 'TRACE',
  18                                     'POST', 'PUT', 'PATCH'))
  19 
  20 
  21 def string_values(node, cstruct):
  22     """Validate that a ``colander.Mapping`` only has strings in its values.
  23 
  24     .. warning::
  25 
  26         Should be associated to a ``colander.Mapping`` schema node.
  27     """
  28     are_strings = [isinstance(v, str) for v in cstruct.values()]
  29     if not all(are_strings):
  30         error_msg = '{} contains non string value'.format(cstruct)
  31         raise colander.Invalid(node, error_msg)
  32 
  33 
  34 class BatchRequestSchema(colander.MappingSchema):
  35     method = colander.SchemaNode(colander.String(),
  36                                  validator=valid_http_method,
  37                                  missing=colander.drop)
  38     path = colander.SchemaNode(colander.String(),
  39                                validator=colander.Regex('^/'))
  40     headers = colander.SchemaNode(colander.Mapping(unknown='preserve'),
  41                                   validator=string_values,
  42                                   missing=colander.drop)
  43     body = colander.SchemaNode(colander.Mapping(unknown='preserve'),
  44                                missing=colander.drop)
  45 
  46     @staticmethod
  47     def schema_type():
  48         return colander.Mapping(unknown='raise')
  49 
  50 
  51 class BatchPayloadSchema(colander.MappingSchema):
  52     defaults = BatchRequestSchema(missing=colander.drop).clone()
  53     requests = colander.SchemaNode(colander.Sequence(),
  54                                    BatchRequestSchema())
  55 
  56     @staticmethod
  57     def schema_type():
  58         return colander.Mapping(unknown='raise')
  59 
  60     def __init__(self, *args, **kwargs):
  61         super().__init__(*args, **kwargs)
  62         # On defaults, path is not mandatory.
  63         self.get('defaults').get('path').missing = colander.drop
  64 
  65     def deserialize(self, cstruct=colander.null):
  66         """Preprocess received data to carefully merge defaults.
  67         """
  68         if cstruct is not colander.null:
  69             defaults = cstruct.get('defaults')
  70             requests = cstruct.get('requests')
  71             if isinstance(defaults, dict) and isinstance(requests, list):
  72                 for request in requests:
  73                     if isinstance(request, dict):
  74                         merge_dicts(request, defaults)
  75         return super().deserialize(cstruct)
  76 
  77 
  78 class BatchRequest(colander.MappingSchema):
  79     body = BatchPayloadSchema()
  80 
  81 
  82 class BatchResponseSchema(colander.MappingSchema):
  83     status = colander.SchemaNode(colander.Integer())
  84     path = colander.SchemaNode(colander.String())
  85     headers = colander.SchemaNode(colander.Mapping(unknown='preserve'),
  86                                   validator=string_values,
  87                                   missing=colander.drop)
  88     body = colander.SchemaNode(colander.Mapping(unknown='preserve'),
  89                                missing=colander.drop)
  90 
  91 
  92 class BatchResponseBodySchema(colander.MappingSchema):
  93     responses = colander.SequenceSchema(BatchResponseSchema(missing=colander.drop))
  94 
  95 
  96 class BatchResponse(colander.MappingSchema):
  97     body = BatchResponseBodySchema()
  98 
  99 
  100 class ErrorResponseSchema(colander.MappingSchema):
  101     body = ErrorSchema()
  102 
  103 
  104 batch_responses = {
  105     '200': BatchResponse(description='Return a list of operation responses.'),
  106     '400': ErrorResponseSchema(description='The request was badly formatted.'),
  107     'default': ErrorResponseSchema(description='an unknown error occurred.')
  108 }
  109 
  110 batch = Service(name='batch', path='/batch',
  111                 description='Batch operations')
  112 
  113 
  114 @batch.post(schema=BatchRequest,
  115             validators=(colander_validator,),
  116             content_type=CONTENT_TYPES,
  117             permission=NO_PERMISSION_REQUIRED,
  118             tags=['Batch'], operation_id='batch',
  119             response_schemas=batch_responses)
  120 def post_batch(request):
  121     requests = request.validated['body']['requests']
  122 
  123     request.log_context(batch_size=len(requests))
  124 
  125     limit = request.registry.settings['batch_max_requests']
  126     if limit and len(requests) > int(limit):
  127         error_msg = 'Number of requests is limited to {}'.format(limit)
  128         request.errors.add('body', 'requests', error_msg)
  129         return
  130 
  131     if any([batch.path in req['path'] for req in requests]):
  132         error_msg = 'Recursive call on {} endpoint is forbidden.'.format(batch.path)
  133         request.errors.add('body', 'requests', error_msg)
  134         return
  135 
  136     responses = []
  137 
  138     for subrequest_spec in requests:
  139         subrequest = build_request(request, subrequest_spec)
  140 
  141         log_context = {**request.log_context(),
  142                        'path': subrequest.path,
  143                        'method': subrequest.method}
  144         try:
  145             # Invoke subrequest without individual transaction.
  146             resp, subrequest = request.follow_subrequest(subrequest,
  147                                                          use_tweens=False)
  148         except httpexceptions.HTTPException as e:
  149             # Since some request in the batch failed, we need to stop the parent request
  150             # through Pyramid's transaction manager. 5XX errors are already caught by
  151             # pyramid_tm's commit_veto
  152             # https://github.com/Kinto/kinto/issues/624
  153             if e.status_code == 409:
  154                 request.tm.abort()
  155 
  156             if e.content_type == 'application/json':
  157                 resp = e
  158             else:
  159                 # JSONify raw Pyramid errors.
  160                 resp = errors.http_error(e)
  161 
  162         subrequest_logger.info('subrequest.summary', extra=log_context)
  163 
  164         dict_resp = build_response(resp, subrequest)
  165         responses.append(dict_resp)
  166 
  167     return {
  168         'responses': responses
  169     }
  170
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/kinto/core/views/batch.py b/kinto/core/views/batch.py
  --- a/kinto/core/views/batch.py
  +++ b/kinto/core/views/batch.py
  @@ -111,7 +111,7 @@
                   description='Batch operations')
   
   
  -@batch.post(schema=BatchRequest,
  +@batch.post(schema=BatchRequest(),
               validators=(colander_validator,),
               content_type=CONTENT_TYPES,
               permission=NO_PERMISSION_REQUIRED,
  
verification_info: {"golden_diff": "diff --git a/kinto/core/views/batch.py b/kinto/core/views/batch.py\n--- a/kinto/core/views/batch.py\n+++ b/kinto/core/views/batch.py\n@@ -111,7 +111,7 @@\n                 description='Batch operations')\n \n \n-@batch.post(schema=BatchRequest,\n+@batch.post(schema=BatchRequest(),\n             validators=(colander_validator,),\n             content_type=CONTENT_TYPES,\n             permission=NO_PERMISSION_REQUIRED,\n", "issue": "Remove colander deprecations\n```\r\n/home/mathieu/Code/Mozilla/kinto/.venv/lib/python3.6/site-packages/cornice/validators/_colander.py:110: DeprecationWarning: Setting schema to a class is deprecated.  Set schema to an instance instead.\r\n  schema = _ensure_instantiated(schema)\r\n```\n", "before_files": [{"content": "import logging\n\nimport colander\nfrom cornice.validators import colander_validator\nfrom pyramid import httpexceptions\nfrom pyramid.security import NO_PERMISSION_REQUIRED\n\nfrom kinto.core import errors\nfrom kinto.core import Service\nfrom kinto.core.errors import ErrorSchema\nfrom kinto.core.utils import merge_dicts, build_request, build_response\nfrom kinto.core.resource.viewset import CONTENT_TYPES\n\n\nsubrequest_logger = logging.getLogger('subrequest.summary')\n\nvalid_http_method = colander.OneOf(('GET', 'HEAD', 'DELETE', 'TRACE',\n                                    'POST', 'PUT', 'PATCH'))\n\n\ndef string_values(node, cstruct):\n    \"\"\"Validate that a ``colander.Mapping`` only has strings in its values.\n\n    .. warning::\n\n        Should be associated to a ``colander.Mapping`` schema node.\n    \"\"\"\n    are_strings = [isinstance(v, str) for v in cstruct.values()]\n    if not all(are_strings):\n        error_msg = '{} contains non string value'.format(cstruct)\n        raise colander.Invalid(node, error_msg)\n\n\nclass BatchRequestSchema(colander.MappingSchema):\n    method = colander.SchemaNode(colander.String(),\n                                 validator=valid_http_method,\n                                 missing=colander.drop)\n    path = colander.SchemaNode(colander.String(),\n                               validator=colander.Regex('^/'))\n    headers = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                                  validator=string_values,\n                                  missing=colander.drop)\n    body = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                               missing=colander.drop)\n\n    @staticmethod\n    def schema_type():\n        return colander.Mapping(unknown='raise')\n\n\nclass BatchPayloadSchema(colander.MappingSchema):\n    defaults = BatchRequestSchema(missing=colander.drop).clone()\n    requests = colander.SchemaNode(colander.Sequence(),\n                                   BatchRequestSchema())\n\n    @staticmethod\n    def schema_type():\n        return colander.Mapping(unknown='raise')\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        # On defaults, path is not mandatory.\n        self.get('defaults').get('path').missing = colander.drop\n\n    def deserialize(self, cstruct=colander.null):\n        \"\"\"Preprocess received data to carefully merge defaults.\n        \"\"\"\n        if cstruct is not colander.null:\n            defaults = cstruct.get('defaults')\n            requests = cstruct.get('requests')\n            if isinstance(defaults, dict) and isinstance(requests, list):\n                for request in requests:\n                    if isinstance(request, dict):\n                        merge_dicts(request, defaults)\n        return super().deserialize(cstruct)\n\n\nclass BatchRequest(colander.MappingSchema):\n    body = BatchPayloadSchema()\n\n\nclass BatchResponseSchema(colander.MappingSchema):\n    status = colander.SchemaNode(colander.Integer())\n    path = colander.SchemaNode(colander.String())\n    headers = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                                  validator=string_values,\n                                  missing=colander.drop)\n    body = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                               missing=colander.drop)\n\n\nclass BatchResponseBodySchema(colander.MappingSchema):\n    responses = colander.SequenceSchema(BatchResponseSchema(missing=colander.drop))\n\n\nclass BatchResponse(colander.MappingSchema):\n    body = BatchResponseBodySchema()\n\n\nclass ErrorResponseSchema(colander.MappingSchema):\n    body = ErrorSchema()\n\n\nbatch_responses = {\n    '200': BatchResponse(description='Return a list of operation responses.'),\n    '400': ErrorResponseSchema(description='The request was badly formatted.'),\n    'default': ErrorResponseSchema(description='an unknown error occurred.')\n}\n\nbatch = Service(name='batch', path='/batch',\n                description='Batch operations')\n\n\n@batch.post(schema=BatchRequest,\n            validators=(colander_validator,),\n            content_type=CONTENT_TYPES,\n            permission=NO_PERMISSION_REQUIRED,\n            tags=['Batch'], operation_id='batch',\n            response_schemas=batch_responses)\ndef post_batch(request):\n    requests = request.validated['body']['requests']\n\n    request.log_context(batch_size=len(requests))\n\n    limit = request.registry.settings['batch_max_requests']\n    if limit and len(requests) > int(limit):\n        error_msg = 'Number of requests is limited to {}'.format(limit)\n        request.errors.add('body', 'requests', error_msg)\n        return\n\n    if any([batch.path in req['path'] for req in requests]):\n        error_msg = 'Recursive call on {} endpoint is forbidden.'.format(batch.path)\n        request.errors.add('body', 'requests', error_msg)\n        return\n\n    responses = []\n\n    for subrequest_spec in requests:\n        subrequest = build_request(request, subrequest_spec)\n\n        log_context = {**request.log_context(),\n                       'path': subrequest.path,\n                       'method': subrequest.method}\n        try:\n            # Invoke subrequest without individual transaction.\n            resp, subrequest = request.follow_subrequest(subrequest,\n                                                         use_tweens=False)\n        except httpexceptions.HTTPException as e:\n            # Since some request in the batch failed, we need to stop the parent request\n            # through Pyramid's transaction manager. 5XX errors are already caught by\n            # pyramid_tm's commit_veto\n            # https://github.com/Kinto/kinto/issues/624\n            if e.status_code == 409:\n                request.tm.abort()\n\n            if e.content_type == 'application/json':\n                resp = e\n            else:\n                # JSONify raw Pyramid errors.\n                resp = errors.http_error(e)\n\n        subrequest_logger.info('subrequest.summary', extra=log_context)\n\n        dict_resp = build_response(resp, subrequest)\n        responses.append(dict_resp)\n\n    return {\n        'responses': responses\n    }\n", "path": "kinto/core/views/batch.py"}], "after_files": [{"content": "import logging\n\nimport colander\nfrom cornice.validators import colander_validator\nfrom pyramid import httpexceptions\nfrom pyramid.security import NO_PERMISSION_REQUIRED\n\nfrom kinto.core import errors\nfrom kinto.core import Service\nfrom kinto.core.errors import ErrorSchema\nfrom kinto.core.utils import merge_dicts, build_request, build_response\nfrom kinto.core.resource.viewset import CONTENT_TYPES\n\n\nsubrequest_logger = logging.getLogger('subrequest.summary')\n\nvalid_http_method = colander.OneOf(('GET', 'HEAD', 'DELETE', 'TRACE',\n                                    'POST', 'PUT', 'PATCH'))\n\n\ndef string_values(node, cstruct):\n    \"\"\"Validate that a ``colander.Mapping`` only has strings in its values.\n\n    .. warning::\n\n        Should be associated to a ``colander.Mapping`` schema node.\n    \"\"\"\n    are_strings = [isinstance(v, str) for v in cstruct.values()]\n    if not all(are_strings):\n        error_msg = '{} contains non string value'.format(cstruct)\n        raise colander.Invalid(node, error_msg)\n\n\nclass BatchRequestSchema(colander.MappingSchema):\n    method = colander.SchemaNode(colander.String(),\n                                 validator=valid_http_method,\n                                 missing=colander.drop)\n    path = colander.SchemaNode(colander.String(),\n                               validator=colander.Regex('^/'))\n    headers = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                                  validator=string_values,\n                                  missing=colander.drop)\n    body = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                               missing=colander.drop)\n\n    @staticmethod\n    def schema_type():\n        return colander.Mapping(unknown='raise')\n\n\nclass BatchPayloadSchema(colander.MappingSchema):\n    defaults = BatchRequestSchema(missing=colander.drop).clone()\n    requests = colander.SchemaNode(colander.Sequence(),\n                                   BatchRequestSchema())\n\n    @staticmethod\n    def schema_type():\n        return colander.Mapping(unknown='raise')\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        # On defaults, path is not mandatory.\n        self.get('defaults').get('path').missing = colander.drop\n\n    def deserialize(self, cstruct=colander.null):\n        \"\"\"Preprocess received data to carefully merge defaults.\n        \"\"\"\n        if cstruct is not colander.null:\n            defaults = cstruct.get('defaults')\n            requests = cstruct.get('requests')\n            if isinstance(defaults, dict) and isinstance(requests, list):\n                for request in requests:\n                    if isinstance(request, dict):\n                        merge_dicts(request, defaults)\n        return super().deserialize(cstruct)\n\n\nclass BatchRequest(colander.MappingSchema):\n    body = BatchPayloadSchema()\n\n\nclass BatchResponseSchema(colander.MappingSchema):\n    status = colander.SchemaNode(colander.Integer())\n    path = colander.SchemaNode(colander.String())\n    headers = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                                  validator=string_values,\n                                  missing=colander.drop)\n    body = colander.SchemaNode(colander.Mapping(unknown='preserve'),\n                               missing=colander.drop)\n\n\nclass BatchResponseBodySchema(colander.MappingSchema):\n    responses = colander.SequenceSchema(BatchResponseSchema(missing=colander.drop))\n\n\nclass BatchResponse(colander.MappingSchema):\n    body = BatchResponseBodySchema()\n\n\nclass ErrorResponseSchema(colander.MappingSchema):\n    body = ErrorSchema()\n\n\nbatch_responses = {\n    '200': BatchResponse(description='Return a list of operation responses.'),\n    '400': ErrorResponseSchema(description='The request was badly formatted.'),\n    'default': ErrorResponseSchema(description='an unknown error occurred.')\n}\n\nbatch = Service(name='batch', path='/batch',\n                description='Batch operations')\n\n\n@batch.post(schema=BatchRequest(),\n            validators=(colander_validator,),\n            content_type=CONTENT_TYPES,\n            permission=NO_PERMISSION_REQUIRED,\n            tags=['Batch'], operation_id='batch',\n            response_schemas=batch_responses)\ndef post_batch(request):\n    requests = request.validated['body']['requests']\n\n    request.log_context(batch_size=len(requests))\n\n    limit = request.registry.settings['batch_max_requests']\n    if limit and len(requests) > int(limit):\n        error_msg = 'Number of requests is limited to {}'.format(limit)\n        request.errors.add('body', 'requests', error_msg)\n        return\n\n    if any([batch.path in req['path'] for req in requests]):\n        error_msg = 'Recursive call on {} endpoint is forbidden.'.format(batch.path)\n        request.errors.add('body', 'requests', error_msg)\n        return\n\n    responses = []\n\n    for subrequest_spec in requests:\n        subrequest = build_request(request, subrequest_spec)\n\n        log_context = {**request.log_context(),\n                       'path': subrequest.path,\n                       'method': subrequest.method}\n        try:\n            # Invoke subrequest without individual transaction.\n            resp, subrequest = request.follow_subrequest(subrequest,\n                                                         use_tweens=False)\n        except httpexceptions.HTTPException as e:\n            # Since some request in the batch failed, we need to stop the parent request\n            # through Pyramid's transaction manager. 5XX errors are already caught by\n            # pyramid_tm's commit_veto\n            # https://github.com/Kinto/kinto/issues/624\n            if e.status_code == 409:\n                request.tm.abort()\n\n            if e.content_type == 'application/json':\n                resp = e\n            else:\n                # JSONify raw Pyramid errors.\n                resp = errors.http_error(e)\n\n        subrequest_logger.info('subrequest.summary', extra=log_context)\n\n        dict_resp = build_response(resp, subrequest)\n        responses.append(dict_resp)\n\n    return {\n        'responses': responses\n    }\n", "path": "kinto/core/views/batch.py"}]}