We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
S3 - RequestTimeout during large files
I'm trying to upload a large file (9 GB) and getting a RequestTimeout error using `aws s3 mv ...`

I haven't fully tested it yet, but it seems like if I run the command over and over it will eventually work.

Here's the debug log from a failed attempt: https://s3.amazonaws.com/nimbus-public/s3_backup.log

I'll post back if I determine that retrying the command several times works or not.

aws version: aws-cli/1.1.2 Python/2.7.3 Windows/2008ServerR2


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `awscli/customizations/s3/utils.py`
Content:
```
1 # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"). You
4 # may not use this file except in compliance with the License. A copy of
5 # the License is located at
6 #
7 #     http://aws.amazon.com/apache2.0/
8 #
9 # or in the "license" file accompanying this file. This file is
10 # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11 # ANY KIND, either express or implied. See the License for the specific
12 # language governing permissions and limitations under the License.
13 from datetime import datetime
14 import mimetypes
15 import hashlib
16 import math
17 import os
18 import sys
19 from functools import partial
20 
21 from six import PY3
22 from six.moves import queue as Queue
23 from dateutil.tz import tzlocal
24 
25 from awscli.customizations.s3.constants import QUEUE_TIMEOUT_WAIT, \
26     MAX_PARTS, MAX_SINGLE_UPLOAD_SIZE
27 
28 
29 class MD5Error(Exception):
30     """
31     Exception for md5's that do not match.
32     """
33     pass
34 
35 
36 class NoBlockQueue(Queue.Queue):
37     """
38     This queue ensures that joining does not block interrupt signals.
39     It also contains a threading event ``interrupt`` that breaks the
40     while loop if signaled.  The ``interrupt`` signal is optional.
41     If left out, this should act like a normal queue.
42     """
43     def __init__(self, interrupt=None, maxsize=0):
44         Queue.Queue.__init__(self, maxsize=maxsize)
45         self.interrupt = interrupt
46 
47     def join(self):
48         self.all_tasks_done.acquire()
49         try:
50             while self.unfinished_tasks:
51                 if self.interrupt and self.interrupt.isSet():
52                     break
53                 self.all_tasks_done.wait(QUEUE_TIMEOUT_WAIT)
54         finally:
55             self.all_tasks_done.release()
56 
57 
58 def find_bucket_key(s3_path):
59     """
60     This is a helper function that given an s3 path such that the path is of
61     the form: bucket/key
62     It will return the bucket and the key represented by the s3 path
63     """
64     s3_components = s3_path.split('/')
65     bucket = s3_components[0]
66     s3_key = ""
67     if len(s3_components) > 1:
68         s3_key = '/'.join(s3_components[1:])
69     return bucket, s3_key
70 
71 
72 def get_file_stat(path):
73     """
74     This is a helper function that given a local path return the size of
75     the file in bytes and time of last modification.
76     """
77     stats = os.stat(path)
78     update_time = datetime.fromtimestamp(stats.st_mtime, tzlocal())
79     return stats.st_size, update_time
80 
81 
82 def check_etag(etag, fileobj):
83     """
84     This fucntion checks the etag and the md5 checksum to ensure no
85     data was corrupted upon transfer.
86     """
87     get_chunk = partial(fileobj.read, 1024 * 1024)
88     m = hashlib.md5()
89     for chunk in iter(get_chunk, b''):
90         m.update(chunk)
91     if '-' not in etag:
92         if etag != m.hexdigest():
93             raise MD5Error
94 
95 
96 def check_error(response_data):
97     """
98     A helper function that prints out the error message recieved in the
99     response_data and raises an error when there is an error.
100     """
101     if response_data:
102         if 'Errors' in response_data:
103             errors = response_data['Errors']
104             for error in errors:
105                 raise Exception("Error: %s\n" % error['Message'])
106 
107 
108 def operate(service, cmd, kwargs):
109     """
110     A helper function that universally calls any command by taking in the
111     service, name of the command, and any additional parameters required in
112     the call.
113     """
114     operation = service.get_operation(cmd)
115     http_response, response_data = operation.call(**kwargs)
116     check_error(response_data)
117     return response_data, http_response
118 
119 
120 def find_chunksize(size, current_chunksize):
121     """
122     The purpose of this function is determine a chunksize so that
123     the number of parts in a multipart upload is not greater than
124     the ``MAX_PARTS``.  If the ``chunksize`` is greater than
125     ``MAX_SINGLE_UPLOAD_SIZE`` it returns ``MAX_SINGLE_UPLOAD_SIZE``.
126     """
127     chunksize = current_chunksize
128     num_parts = int(math.ceil(size / float(chunksize)))
129     while num_parts > MAX_PARTS:
130         chunksize *= 2
131         num_parts = int(math.ceil(size / float(chunksize)))
132     if chunksize > MAX_SINGLE_UPLOAD_SIZE:
133         return MAX_SINGLE_UPLOAD_SIZE
134     else:
135         return chunksize
136 
137 
138 class MultiCounter(object):
139     """
140     This class is used as a way to keep track of how many multipart
141     operations are in progress.  It also is used to track how many
142     part operations are occuring.
143     """
144     def __init__(self):
145         self.count = 0
146 
147 
148 def uni_print(statement):
149     """
150     This function is used to properly write unicode to stdout.  It
151     ensures that the proper encoding is used if the statement is
152     not in a version type of string.  The initial check is to
153     allow if ``sys.stdout`` does not use an encoding
154     """
155     encoding = getattr(sys.stdout, 'encoding', None)
156     if encoding is not None and not PY3:
157         sys.stdout.write(statement.encode(sys.stdout.encoding))
158     else:
159         try:
160             sys.stdout.write(statement)
161         except UnicodeEncodeError:
162             # Some file like objects like cStringIO will
163             # try to decode as ascii.  Interestingly enough
164             # this works with a normal StringIO.
165             sys.stdout.write(statement.encode('utf-8'))
166 
167 
168 def guess_content_type(filename):
169     """Given a filename, guess it's content type.
170 
171     If the type cannot be guessed, a value of None is returned.
172     """
173     return mimetypes.guess_type(filename)[0]
174 
175 
176 def relative_path(filename, start=os.path.curdir):
177     """Cross platform relative path of a filename.
178 
179     If no relative path can be calculated (i.e different
180     drives on Windows), then instead of raising a ValueError,
181     the absolute path is returned.
182 
183     """
184     try:
185         dirname, basename = os.path.split(filename)
186         relative_dir = os.path.relpath(dirname, start)
187         return os.path.join(relative_dir, basename)
188     except ValueError:
189         return os.path.abspath(filename)
190 
191 
192 class ReadFileChunk(object):
193     def __init__(self, filename, start_byte, size):
194         self._filename = filename
195         self._start_byte = start_byte
196         self._fileobj = open(self._filename, 'rb')
197         self._size = self._calculate_file_size(self._fileobj, requested_size=size,
198                                                start_byte=start_byte)
199         self._fileobj.seek(self._start_byte)
200         self._amount_read = 0
201 
202     def _calculate_file_size(self, fileobj, requested_size, start_byte):
203         actual_file_size = os.fstat(fileobj.fileno()).st_size
204         max_chunk_size = actual_file_size - start_byte
205         return min(max_chunk_size, requested_size)
206 
207     def read(self, amount=None):
208         if amount is None:
209             remaining = self._size - self._amount_read
210             data = self._fileobj.read(remaining)
211             self._amount_read += remaining
212             return data
213         else:
214             actual_amount = min(self._size - self._amount_read, amount)
215             data = self._fileobj.read(actual_amount)
216             self._amount_read += actual_amount
217             return data
218 
219     def close(self):
220         self._fileobj.close()
221 
222     def __len__(self):
223         # __len__ is defined because requests will try to determine the length
224         # of the stream to set a content length.  In the normal case
225         # of the file it will just stat the file, but we need to change that
226         # behavior.  By providing a __len__, requests will use that instead
227         # of stat'ing the file.
228         return self._size
229 
230     def __enter__(self):
231         return self
232 
233     def __exit__(self, *args, **kwargs):
234         self._fileobj.close()
235 
236     def __iter__(self):
237         # This is a workaround for http://bugs.python.org/issue17575
238         # Basically httplib will try to iterate over the contents, even
239         # if its a file like object.  This wasn't noticed because we've
240         # already exhausted the stream so iterating over the file immediately
241         # steps, which is what we're simulating here.
242         return iter([])
243
```
--- 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()

```

diff --git a/awscli/customizations/s3/utils.py b/awscli/customizations/s3/utils.py
--- a/awscli/customizations/s3/utils.py
+++ b/awscli/customizations/s3/utils.py
@@ -216,6 +216,10 @@
             self._amount_read += actual_amount
             return data
 
+    def seek(self, where):
+        self._fileobj.seek(self._start_byte + where)
+        self._amount_read = where
+
     def close(self):
         self._fileobj.close()

{"golden_diff": "diff --git a/awscli/customizations/s3/utils.py b/awscli/customizations/s3/utils.py\n--- a/awscli/customizations/s3/utils.py\n+++ b/awscli/customizations/s3/utils.py\n@@ -216,6 +216,10 @@\n             self._amount_read += actual_amount\n             return data\n \n+    def seek(self, where):\n+        self._fileobj.seek(self._start_byte + where)\n+        self._amount_read = where\n+\n     def close(self):\n         self._fileobj.close()\n", "issue": "S3 - RequestTimeout during large files\nI'm trying to upload a large file (9 GB) and getting a RequestTimeout error using `aws s3 mv ...`\n\nI haven't fully tested it yet, but it seems like if I run the command over and over it will eventually work.\n\nHere's the debug log from a failed attempt: https://s3.amazonaws.com/nimbus-public/s3_backup.log\n\nI'll post back if I determine that retrying the command several times works or not.\n\naws version: aws-cli/1.1.2 Python/2.7.3 Windows/2008ServerR2\n\n", "before_files": [{"content": "# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nfrom datetime import datetime\nimport mimetypes\nimport hashlib\nimport math\nimport os\nimport sys\nfrom functools import partial\n\nfrom six import PY3\nfrom six.moves import queue as Queue\nfrom dateutil.tz import tzlocal\n\nfrom awscli.customizations.s3.constants import QUEUE_TIMEOUT_WAIT, \\\n    MAX_PARTS, MAX_SINGLE_UPLOAD_SIZE\n\n\nclass MD5Error(Exception):\n    \"\"\"\n    Exception for md5's that do not match.\n    \"\"\"\n    pass\n\n\nclass NoBlockQueue(Queue.Queue):\n    \"\"\"\n    This queue ensures that joining does not block interrupt signals.\n    It also contains a threading event ``interrupt`` that breaks the\n    while loop if signaled.  The ``interrupt`` signal is optional.\n    If left out, this should act like a normal queue.\n    \"\"\"\n    def __init__(self, interrupt=None, maxsize=0):\n        Queue.Queue.__init__(self, maxsize=maxsize)\n        self.interrupt = interrupt\n\n    def join(self):\n        self.all_tasks_done.acquire()\n        try:\n            while self.unfinished_tasks:\n                if self.interrupt and self.interrupt.isSet():\n                    break\n                self.all_tasks_done.wait(QUEUE_TIMEOUT_WAIT)\n        finally:\n            self.all_tasks_done.release()\n\n\ndef find_bucket_key(s3_path):\n    \"\"\"\n    This is a helper function that given an s3 path such that the path is of\n    the form: bucket/key\n    It will return the bucket and the key represented by the s3 path\n    \"\"\"\n    s3_components = s3_path.split('/')\n    bucket = s3_components[0]\n    s3_key = \"\"\n    if len(s3_components) > 1:\n        s3_key = '/'.join(s3_components[1:])\n    return bucket, s3_key\n\n\ndef get_file_stat(path):\n    \"\"\"\n    This is a helper function that given a local path return the size of\n    the file in bytes and time of last modification.\n    \"\"\"\n    stats = os.stat(path)\n    update_time = datetime.fromtimestamp(stats.st_mtime, tzlocal())\n    return stats.st_size, update_time\n\n\ndef check_etag(etag, fileobj):\n    \"\"\"\n    This fucntion checks the etag and the md5 checksum to ensure no\n    data was corrupted upon transfer.\n    \"\"\"\n    get_chunk = partial(fileobj.read, 1024 * 1024)\n    m = hashlib.md5()\n    for chunk in iter(get_chunk, b''):\n        m.update(chunk)\n    if '-' not in etag:\n        if etag != m.hexdigest():\n            raise MD5Error\n\n\ndef check_error(response_data):\n    \"\"\"\n    A helper function that prints out the error message recieved in the\n    response_data and raises an error when there is an error.\n    \"\"\"\n    if response_data:\n        if 'Errors' in response_data:\n            errors = response_data['Errors']\n            for error in errors:\n                raise Exception(\"Error: %s\\n\" % error['Message'])\n\n\ndef operate(service, cmd, kwargs):\n    \"\"\"\n    A helper function that universally calls any command by taking in the\n    service, name of the command, and any additional parameters required in\n    the call.\n    \"\"\"\n    operation = service.get_operation(cmd)\n    http_response, response_data = operation.call(**kwargs)\n    check_error(response_data)\n    return response_data, http_response\n\n\ndef find_chunksize(size, current_chunksize):\n    \"\"\"\n    The purpose of this function is determine a chunksize so that\n    the number of parts in a multipart upload is not greater than\n    the ``MAX_PARTS``.  If the ``chunksize`` is greater than\n    ``MAX_SINGLE_UPLOAD_SIZE`` it returns ``MAX_SINGLE_UPLOAD_SIZE``.\n    \"\"\"\n    chunksize = current_chunksize\n    num_parts = int(math.ceil(size / float(chunksize)))\n    while num_parts > MAX_PARTS:\n        chunksize *= 2\n        num_parts = int(math.ceil(size / float(chunksize)))\n    if chunksize > MAX_SINGLE_UPLOAD_SIZE:\n        return MAX_SINGLE_UPLOAD_SIZE\n    else:\n        return chunksize\n\n\nclass MultiCounter(object):\n    \"\"\"\n    This class is used as a way to keep track of how many multipart\n    operations are in progress.  It also is used to track how many\n    part operations are occuring.\n    \"\"\"\n    def __init__(self):\n        self.count = 0\n\n\ndef uni_print(statement):\n    \"\"\"\n    This function is used to properly write unicode to stdout.  It\n    ensures that the proper encoding is used if the statement is\n    not in a version type of string.  The initial check is to\n    allow if ``sys.stdout`` does not use an encoding\n    \"\"\"\n    encoding = getattr(sys.stdout, 'encoding', None)\n    if encoding is not None and not PY3:\n        sys.stdout.write(statement.encode(sys.stdout.encoding))\n    else:\n        try:\n            sys.stdout.write(statement)\n        except UnicodeEncodeError:\n            # Some file like objects like cStringIO will\n            # try to decode as ascii.  Interestingly enough\n            # this works with a normal StringIO.\n            sys.stdout.write(statement.encode('utf-8'))\n\n\ndef guess_content_type(filename):\n    \"\"\"Given a filename, guess it's content type.\n\n    If the type cannot be guessed, a value of None is returned.\n    \"\"\"\n    return mimetypes.guess_type(filename)[0]\n\n\ndef relative_path(filename, start=os.path.curdir):\n    \"\"\"Cross platform relative path of a filename.\n\n    If no relative path can be calculated (i.e different\n    drives on Windows), then instead of raising a ValueError,\n    the absolute path is returned.\n\n    \"\"\"\n    try:\n        dirname, basename = os.path.split(filename)\n        relative_dir = os.path.relpath(dirname, start)\n        return os.path.join(relative_dir, basename)\n    except ValueError:\n        return os.path.abspath(filename)\n\n\nclass ReadFileChunk(object):\n    def __init__(self, filename, start_byte, size):\n        self._filename = filename\n        self._start_byte = start_byte\n        self._fileobj = open(self._filename, 'rb')\n        self._size = self._calculate_file_size(self._fileobj, requested_size=size,\n                                               start_byte=start_byte)\n        self._fileobj.seek(self._start_byte)\n        self._amount_read = 0\n\n    def _calculate_file_size(self, fileobj, requested_size, start_byte):\n        actual_file_size = os.fstat(fileobj.fileno()).st_size\n        max_chunk_size = actual_file_size - start_byte\n        return min(max_chunk_size, requested_size)\n\n    def read(self, amount=None):\n        if amount is None:\n            remaining = self._size - self._amount_read\n            data = self._fileobj.read(remaining)\n            self._amount_read += remaining\n            return data\n        else:\n            actual_amount = min(self._size - self._amount_read, amount)\n            data = self._fileobj.read(actual_amount)\n            self._amount_read += actual_amount\n            return data\n\n    def close(self):\n        self._fileobj.close()\n\n    def __len__(self):\n        # __len__ is defined because requests will try to determine the length\n        # of the stream to set a content length.  In the normal case\n        # of the file it will just stat the file, but we need to change that\n        # behavior.  By providing a __len__, requests will use that instead\n        # of stat'ing the file.\n        return self._size\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args, **kwargs):\n        self._fileobj.close()\n\n    def __iter__(self):\n        # This is a workaround for http://bugs.python.org/issue17575\n        # Basically httplib will try to iterate over the contents, even\n        # if its a file like object.  This wasn't noticed because we've\n        # already exhausted the stream so iterating over the file immediately\n        # steps, which is what we're simulating here.\n        return iter([])\n", "path": "awscli/customizations/s3/utils.py"}], "after_files": [{"content": "# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nfrom datetime import datetime\nimport mimetypes\nimport hashlib\nimport math\nimport os\nimport sys\nfrom functools import partial\n\nfrom six import PY3\nfrom six.moves import queue as Queue\nfrom dateutil.tz import tzlocal\n\nfrom awscli.customizations.s3.constants import QUEUE_TIMEOUT_WAIT, \\\n    MAX_PARTS, MAX_SINGLE_UPLOAD_SIZE\n\n\nclass MD5Error(Exception):\n    \"\"\"\n    Exception for md5's that do not match.\n    \"\"\"\n    pass\n\n\nclass NoBlockQueue(Queue.Queue):\n    \"\"\"\n    This queue ensures that joining does not block interrupt signals.\n    It also contains a threading event ``interrupt`` that breaks the\n    while loop if signaled.  The ``interrupt`` signal is optional.\n    If left out, this should act like a normal queue.\n    \"\"\"\n    def __init__(self, interrupt=None, maxsize=0):\n        Queue.Queue.__init__(self, maxsize=maxsize)\n        self.interrupt = interrupt\n\n    def join(self):\n        self.all_tasks_done.acquire()\n        try:\n            while self.unfinished_tasks:\n                if self.interrupt and self.interrupt.isSet():\n                    break\n                self.all_tasks_done.wait(QUEUE_TIMEOUT_WAIT)\n        finally:\n            self.all_tasks_done.release()\n\n\ndef find_bucket_key(s3_path):\n    \"\"\"\n    This is a helper function that given an s3 path such that the path is of\n    the form: bucket/key\n    It will return the bucket and the key represented by the s3 path\n    \"\"\"\n    s3_components = s3_path.split('/')\n    bucket = s3_components[0]\n    s3_key = \"\"\n    if len(s3_components) > 1:\n        s3_key = '/'.join(s3_components[1:])\n    return bucket, s3_key\n\n\ndef get_file_stat(path):\n    \"\"\"\n    This is a helper function that given a local path return the size of\n    the file in bytes and time of last modification.\n    \"\"\"\n    stats = os.stat(path)\n    update_time = datetime.fromtimestamp(stats.st_mtime, tzlocal())\n    return stats.st_size, update_time\n\n\ndef check_etag(etag, fileobj):\n    \"\"\"\n    This fucntion checks the etag and the md5 checksum to ensure no\n    data was corrupted upon transfer.\n    \"\"\"\n    get_chunk = partial(fileobj.read, 1024 * 1024)\n    m = hashlib.md5()\n    for chunk in iter(get_chunk, b''):\n        m.update(chunk)\n    if '-' not in etag:\n        if etag != m.hexdigest():\n            raise MD5Error\n\n\ndef check_error(response_data):\n    \"\"\"\n    A helper function that prints out the error message recieved in the\n    response_data and raises an error when there is an error.\n    \"\"\"\n    if response_data:\n        if 'Errors' in response_data:\n            errors = response_data['Errors']\n            for error in errors:\n                raise Exception(\"Error: %s\\n\" % error['Message'])\n\n\ndef operate(service, cmd, kwargs):\n    \"\"\"\n    A helper function that universally calls any command by taking in the\n    service, name of the command, and any additional parameters required in\n    the call.\n    \"\"\"\n    operation = service.get_operation(cmd)\n    http_response, response_data = operation.call(**kwargs)\n    check_error(response_data)\n    return response_data, http_response\n\n\ndef find_chunksize(size, current_chunksize):\n    \"\"\"\n    The purpose of this function is determine a chunksize so that\n    the number of parts in a multipart upload is not greater than\n    the ``MAX_PARTS``.  If the ``chunksize`` is greater than\n    ``MAX_SINGLE_UPLOAD_SIZE`` it returns ``MAX_SINGLE_UPLOAD_SIZE``.\n    \"\"\"\n    chunksize = current_chunksize\n    num_parts = int(math.ceil(size / float(chunksize)))\n    while num_parts > MAX_PARTS:\n        chunksize *= 2\n        num_parts = int(math.ceil(size / float(chunksize)))\n    if chunksize > MAX_SINGLE_UPLOAD_SIZE:\n        return MAX_SINGLE_UPLOAD_SIZE\n    else:\n        return chunksize\n\n\nclass MultiCounter(object):\n    \"\"\"\n    This class is used as a way to keep track of how many multipart\n    operations are in progress.  It also is used to track how many\n    part operations are occuring.\n    \"\"\"\n    def __init__(self):\n        self.count = 0\n\n\ndef uni_print(statement):\n    \"\"\"\n    This function is used to properly write unicode to stdout.  It\n    ensures that the proper encoding is used if the statement is\n    not in a version type of string.  The initial check is to\n    allow if ``sys.stdout`` does not use an encoding\n    \"\"\"\n    encoding = getattr(sys.stdout, 'encoding', None)\n    if encoding is not None and not PY3:\n        sys.stdout.write(statement.encode(sys.stdout.encoding))\n    else:\n        try:\n            sys.stdout.write(statement)\n        except UnicodeEncodeError:\n            # Some file like objects like cStringIO will\n            # try to decode as ascii.  Interestingly enough\n            # this works with a normal StringIO.\n            sys.stdout.write(statement.encode('utf-8'))\n\n\ndef guess_content_type(filename):\n    \"\"\"Given a filename, guess it's content type.\n\n    If the type cannot be guessed, a value of None is returned.\n    \"\"\"\n    return mimetypes.guess_type(filename)[0]\n\n\ndef relative_path(filename, start=os.path.curdir):\n    \"\"\"Cross platform relative path of a filename.\n\n    If no relative path can be calculated (i.e different\n    drives on Windows), then instead of raising a ValueError,\n    the absolute path is returned.\n\n    \"\"\"\n    try:\n        dirname, basename = os.path.split(filename)\n        relative_dir = os.path.relpath(dirname, start)\n        return os.path.join(relative_dir, basename)\n    except ValueError:\n        return os.path.abspath(filename)\n\n\nclass ReadFileChunk(object):\n    def __init__(self, filename, start_byte, size):\n        self._filename = filename\n        self._start_byte = start_byte\n        self._fileobj = open(self._filename, 'rb')\n        self._size = self._calculate_file_size(self._fileobj, requested_size=size,\n                                               start_byte=start_byte)\n        self._fileobj.seek(self._start_byte)\n        self._amount_read = 0\n\n    def _calculate_file_size(self, fileobj, requested_size, start_byte):\n        actual_file_size = os.fstat(fileobj.fileno()).st_size\n        max_chunk_size = actual_file_size - start_byte\n        return min(max_chunk_size, requested_size)\n\n    def read(self, amount=None):\n        if amount is None:\n            remaining = self._size - self._amount_read\n            data = self._fileobj.read(remaining)\n            self._amount_read += remaining\n            return data\n        else:\n            actual_amount = min(self._size - self._amount_read, amount)\n            data = self._fileobj.read(actual_amount)\n            self._amount_read += actual_amount\n            return data\n\n    def seek(self, where):\n        self._fileobj.seek(self._start_byte + where)\n        self._amount_read = where\n\n    def close(self):\n        self._fileobj.close()\n\n    def __len__(self):\n        # __len__ is defined because requests will try to determine the length\n        # of the stream to set a content length.  In the normal case\n        # of the file it will just stat the file, but we need to change that\n        # behavior.  By providing a __len__, requests will use that instead\n        # of stat'ing the file.\n        return self._size\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args, **kwargs):\n        self._fileobj.close()\n\n    def __iter__(self):\n        # This is a workaround for http://bugs.python.org/issue17575\n        # Basically httplib will try to iterate over the contents, even\n        # if its a file like object.  This wasn't noticed because we've\n        # already exhausted the stream so iterating over the file immediately\n        # steps, which is what we're simulating here.\n        return iter([])\n", "path": "awscli/customizations/s3/utils.py"}]}