nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: boto/botocore
Pull request #795 (2016-02-16 00:29:32)

NextToken should be a string, not bytes.
On python 3, the output of base64 encoding is a `bytes` object, which does not play well with the JSON encoder / decoder.

cc @jamesls @kyleknap @rayluo 


Patch:
diff --git a/botocore/paginate.py b/botocore/paginate.py
index cb631efea..510b76482 100644
--- a/botocore/paginate.py
+++ b/botocore/paginate.py
@@ -77,7 +77,7 @@ class PageIterator(object):
 
         if token_keys == dict_keys:
             self._resume_token = base64.b64encode(
-                json.dumps(value).encode('utf-8'))
+                json.dumps(value).encode('utf-8')).decode('utf-8')
         else:
             raise ValueError("Bad starting token: %s" % value)
 


Test patch:
diff --git a/tests/unit/test_paginate.py b/tests/unit/test_paginate.py
index c68e25c73..16aa3af1f 100644
--- a/tests/unit/test_paginate.py
+++ b/tests/unit/test_paginate.py
@@ -15,6 +15,7 @@ from tests import unittest
 from botocore.paginate import Paginator
 from botocore.paginate import PaginatorModel
 from botocore.exceptions import PaginationError
+from botocore.compat import six
 
 import mock
 import base64
@@ -22,7 +23,7 @@ import json
 
 
 def encode_token(token):
-    return base64.b64encode(json.dumps(token).encode('utf-8'))
+    return base64.b64encode(json.dumps(token).encode('utf-8')).decode('utf-8')
 
 
 class TestPaginatorModel(unittest.TestCase):
@@ -85,6 +86,25 @@ class TestPagination(unittest.TestCase):
                          [mock.call(), mock.call(NextToken='token1'),
                           mock.call(NextToken='token2')])
 
+    def test_next_token_is_string(self):
+        self.paginate_config = {
+            "output_token": "Marker",
+            "input_token": "Marker",
+            "result_key": "Users",
+            "limit_key": "MaxKeys",
+        }
+        self.paginator = Paginator(self.method, self.paginate_config)
+        responses = [
+            {"Users": ["User1"], "Marker": "m1"},
+            {"Users": ["User2"], "Marker": "m2"},
+            {"Users": ["User3"]}
+        ]
+        self.method.side_effect = responses
+        result = self.paginator.paginate(PaginationConfig={'MaxItems': 1})
+        result = result.build_full_result()
+        token = result.get('NextToken')
+        self.assertIsInstance(token, six.string_types)
+
     def test_any_passed_in_args_are_unmodified(self):
         responses = [{'NextToken': 'token1'},
                      {'NextToken': 'token2'},
Repository: boto/botocore
Pull request #804 (2016-02-23 20:11:05)

Don't use MD5 with s3v4
We have a function which avoids md5 when in sigv4, but forgot to include s3v4 even though we attach the function to several s3 commands.

cc @jamesls @kyleknap @rayluo 

jamesls: :shipit:

Patch:
diff --git a/botocore/handlers.py b/botocore/handlers.py
index 32d4eda48..1b8f07b9a 100644
--- a/botocore/handlers.py
+++ b/botocore/handlers.py
@@ -150,7 +150,7 @@ def _calculate_md5_from_file(fileobj):
 def conditionally_calculate_md5(params, **kwargs):
     """Only add a Content-MD5 when not using sigv4"""
     signer = kwargs['request_signer']
-    if signer.signature_version != 'v4':
+    if signer.signature_version not in ['v4', 's3v4']:
         calculate_md5(params, **kwargs)
 
 


Test patch:
diff --git a/tests/unit/test_handlers.py b/tests/unit/test_handlers.py
index aa8ef2075..bcbbf7668 100644
--- a/tests/unit/test_handlers.py
+++ b/tests/unit/test_handlers.py
@@ -521,6 +521,18 @@ class TestHandlers(BaseSessionTest):
                                              request_signer=request_signer)
         self.assertTrue('Content-MD5' not in request_dict['headers'])
 
+    def test_does_not_add_md5_when_s3v4(self):
+        credentials = Credentials('key', 'secret')
+        request_signer = RequestSigner(
+            's3', 'us-east-1', 's3', 's3v4', credentials, mock.Mock())
+        request_dict = {'body': b'bar',
+                        'url': 'https://s3.us-east-1.amazonaws.com',
+                        'method': 'PUT',
+                        'headers': {}}
+        handlers.conditionally_calculate_md5(request_dict,
+                                             request_signer=request_signer)
+        self.assertTrue('Content-MD5' not in request_dict['headers'])
+
     def test_adds_md5_when_not_v4(self):
         credentials = Credentials('key', 'secret')
         request_signer = RequestSigner(
Repository: boto/botocore
Pull request #855 (2016-03-30 00:44:37)

Account for empty input shape missing
cc @kyleknap @JordonPhillips 


Patch:
diff --git a/botocore/docs/sharedexample.py b/botocore/docs/sharedexample.py
index 1d40cb771..5759a0309 100644
--- a/botocore/docs/sharedexample.py
+++ b/botocore/docs/sharedexample.py
@@ -41,7 +41,7 @@ class SharedExampleDocumenter(object):
         input_section.style.start_codeblock()
         if prefix is not None:
             input_section.write(prefix)
-        params = example['input']
+        params = example.get('input', {})
         comments = example.get('comments')
         if comments:
             comments = comments.get('input')


Test patch:
diff --git a/tests/unit/docs/test_sharedexample.py b/tests/unit/docs/test_sharedexample.py
index e9b3cba57..ccd29b980 100644
--- a/tests/unit/docs/test_sharedexample.py
+++ b/tests/unit/docs/test_sharedexample.py
@@ -176,6 +176,19 @@ class TestSharedExampleDocumenter(BaseDocsTest):
             ")"
         ])
 
+    def test_can_handle_no_input_key(self):
+        self.add_shape_to_params('foo', 'String')
+        self.documenter.document_shared_example(
+            example={},
+            prefix='foo.bar',
+            section=self.doc_structure,
+            operation_model=self.operation_model
+        )
+        self.assert_contains_lines_in_order([
+            "foo.bar(",
+            ")"
+        ])
+
     def test_unicode_string_example(self):
         self.add_shape_to_params('foo', 'String')
         self.documenter.document_shared_example(
Repository: boto/botocore
Pull request #928 (2016-05-25 16:29:48)

Add additional keys to error response
Some services return additional error keys that may be relevant
in debugging, this adds the ability to add arbitrary keys to the
stubbed error response.

cc @kyleknap @jamesls


Patch:
diff --git a/.changes/next-release/feature-Stubber.json b/.changes/next-release/feature-Stubber.json
new file mode 100644
index 000000000..995cbb05b
--- /dev/null
+++ b/.changes/next-release/feature-Stubber.json
@@ -0,0 +1,5 @@
+{
+  "category": "Stubber",
+  "description": "Allow adding additional keys to the service error response.",
+  "type": "feature"
+}
diff --git a/botocore/stub.py b/botocore/stub.py
index 3c5aa016f..38d02dd9b 100644
--- a/botocore/stub.py
+++ b/botocore/stub.py
@@ -185,7 +185,8 @@ class Stubber(object):
         self._queue.append(response)
 
     def add_client_error(self, method, service_error_code='',
-                         service_message='', http_status_code=400):
+                         service_message='', http_status_code=400,
+                         service_error_meta=None):
         """
         Adds a ``ClientError`` to the response queue.
 
@@ -202,6 +203,10 @@ class Stubber(object):
 
         :param http_status_code: The HTTP status code to return, e.g. 404, etc
         :type http_status_code: int
+
+        :param service_error_meta: Additional keys to be added to the
+            service Error
+        :type service_error_meta: dict
         """
         http_response = Response()
         http_response.status_code = http_status_code
@@ -217,6 +222,9 @@ class Stubber(object):
             }
         }
 
+        if service_error_meta is not None:
+            parsed_response['Error'].update(service_error_meta)
+
         operation_name = self.client.meta.method_to_api_mapping.get(method)
         # Note that we do not allow for expected_params while
         # adding errors into the queue yet.


Test patch:
diff --git a/tests/unit/test_stub.py b/tests/unit/test_stub.py
index 9bedb9c21..c8e84a50e 100644
--- a/tests/unit/test_stub.py
+++ b/tests/unit/test_stub.py
@@ -159,6 +159,22 @@ class TestStubber(unittest.TestCase):
         self.assertEqual(response[1]['Error']['Message'], service_message)
         self.assertEqual(response[1]['Error']['Code'], error_code)
 
+    def test_get_client_error_with_extra_keys(self):
+        error_code = "foo"
+        error_message = "bar"
+        error_meta = {
+            "Endpoint": "https://foo.bar.baz",
+        }
+        self.stubber.add_client_error(
+            'foo', error_code, error_message,
+            http_status_code=301,
+            service_error_meta=error_meta)
+        with self.stubber:
+            response = self.emit_get_response_event()
+        error = response[1]['Error']
+        self.assertIn('Endpoint', error)
+        self.assertEqual(error['Endpoint'], "https://foo.bar.baz")
+
     def test_get_response_errors_with_no_stubs(self):
         self.stubber.activate()
         with self.assertRaises(StubResponseError):
Repository: boto/botocore
Pull request #937 (2016-06-03 06:33:27)

Allow stubber to be used with GetBucketLocation
Right now you can't use the `Stubber` object with s3's `get_bucket_location` because it has an override that assumes a body of xml is available. This patch allows the override to be skipped where something (in this case the stubber) has already 'parsed' the response.

JordonPhillips: Looks good, but could you put in a quick unit test? Also, could you please use `scripts/new-change` to generate a changelog entry?

Patch:
diff --git a/.changes/next-release/bugfix-s3.json b/.changes/next-release/bugfix-s3.json
new file mode 100644
index 000000000..c7ec410ef
--- /dev/null
+++ b/.changes/next-release/bugfix-s3.json
@@ -0,0 +1,5 @@
+{
+  "category": "s3",
+  "description": "Make the stubber work with get_bucket_location",
+  "type": "bugfix"
+}
diff --git a/botocore/handlers.py b/botocore/handlers.py
index 42a61158f..f6ef9f0cd 100644
--- a/botocore/handlers.py
+++ b/botocore/handlers.py
@@ -424,6 +424,9 @@ def parse_get_bucket_location(parsed, http_response, **kwargs):
     # The "parsed" passed in only has the ResponseMetadata
     # filled out.  This handler will fill in the LocationConstraint
     # value.
+    if 'LocationConstraint' in parsed:
+        # Response already set - a stub?
+        return
     response_body = http_response.content
     parser = xml.etree.cElementTree.XMLParser(
         target=xml.etree.cElementTree.TreeBuilder(),


Test patch:
diff --git a/tests/unit/test_handlers.py b/tests/unit/test_handlers.py
index 1256e8e24..5fd117b00 100644
--- a/tests/unit/test_handlers.py
+++ b/tests/unit/test_handlers.py
@@ -610,6 +610,13 @@ class TestHandlers(BaseSessionTest):
         handlers.decode_list_object(parsed, context=context)
         self.assertEqual(parsed['Delimiter'], u'\xe7\xf6s% asd\x08 c')
 
+    def test_get_bucket_location_optional(self):
+        # This handler should no-op if another hook (i.e. stubber) has already
+        # filled in response
+        response = {"LocationConstraint": "eu-west-1"}
+        handlers.parse_get_bucket_location(response, None),
+        self.assertEqual(response["LocationConstraint"], "eu-west-1")
+
 
 class TestConvertStringBodyToFileLikeObject(BaseSessionTest):
     def assert_converts_to_file_like_object_with_bytes(self, body, body_bytes):
Repository: boto/botocore
Pull request #975 (2016-07-06 09:41:25)

allow bytearray in calculating md5 from bytes
Passing `bytearray` to S3 multipart upload fails when calculating md5. Having the below code, it fails w/o the modification.
https://gist.github.com/foobarna/913a84136a4357bbdc4112c924c0c41e

https://docs.python.org/2/whatsnew/2.6.html#pep-3112-byte-literals



Patch:
diff --git a/botocore/handlers.py b/botocore/handlers.py
index d5b5e993f..431b08af4 100644
--- a/botocore/handlers.py
+++ b/botocore/handlers.py
@@ -130,7 +130,7 @@ def calculate_md5(params, **kwargs):
     request_dict = params
     if request_dict['body'] and 'Content-MD5' not in params['headers']:
         body = request_dict['body']
-        if isinstance(body, bytes):
+        if isinstance(body, (bytes, bytearray)):
             binary_md5 = _calculate_md5_from_bytes(body)
         else:
             binary_md5 = _calculate_md5_from_file(body)


Test patch:
diff --git a/tests/unit/test_handlers.py b/tests/unit/test_handlers.py
index dcec9f240..79ee4c066 100644
--- a/tests/unit/test_handlers.py
+++ b/tests/unit/test_handlers.py
@@ -866,6 +866,17 @@ class TestAddMD5(BaseMD5Test):
             request_dict['headers']['Content-MD5'],
             'OFj2IjCsPJFfMAxmQxLGPw==')
 
+    def test_add_md5_with_bytearray_object(self):
+        request_dict = {
+            'body': bytearray(b'foobar'),
+            'headers': {}
+        }
+        self.md5_digest.return_value = b'8X\xf6"0\xac<\x91_0\x0cfC\x12\xc6?'
+        handlers.calculate_md5(request_dict)
+        self.assertEqual(
+            request_dict['headers']['Content-MD5'],
+            'OFj2IjCsPJFfMAxmQxLGPw==')
+
 
 class TestParameterAlias(unittest.TestCase):
     def setUp(self):