1# Copyright 2015 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# https://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.
13from botocore.exceptions import ClientError
14
15from boto3.s3.transfer import create_transfer_manager
16from boto3.s3.transfer import TransferConfig, S3Transfer
17from boto3.s3.transfer import ProgressCallbackInvoker
18from boto3 import utils
19
20
21def inject_s3_transfer_methods(class_attributes, **kwargs):
22    utils.inject_attribute(class_attributes, 'upload_file', upload_file)
23    utils.inject_attribute(class_attributes, 'download_file', download_file)
24    utils.inject_attribute(class_attributes, 'copy', copy)
25    utils.inject_attribute(class_attributes, 'upload_fileobj', upload_fileobj)
26    utils.inject_attribute(
27        class_attributes, 'download_fileobj', download_fileobj)
28
29
30def inject_bucket_methods(class_attributes, **kwargs):
31    utils.inject_attribute(class_attributes, 'load', bucket_load)
32    utils.inject_attribute(class_attributes, 'upload_file', bucket_upload_file)
33    utils.inject_attribute(
34        class_attributes, 'download_file', bucket_download_file)
35    utils.inject_attribute(class_attributes, 'copy', bucket_copy)
36    utils.inject_attribute(
37        class_attributes, 'upload_fileobj', bucket_upload_fileobj)
38    utils.inject_attribute(
39        class_attributes, 'download_fileobj', bucket_download_fileobj)
40
41
42def inject_object_methods(class_attributes, **kwargs):
43    utils.inject_attribute(class_attributes, 'upload_file', object_upload_file)
44    utils.inject_attribute(
45        class_attributes, 'download_file', object_download_file)
46    utils.inject_attribute(class_attributes, 'copy', object_copy)
47    utils.inject_attribute(
48        class_attributes, 'upload_fileobj', object_upload_fileobj)
49    utils.inject_attribute(
50        class_attributes, 'download_fileobj', object_download_fileobj)
51
52
53def inject_object_summary_methods(class_attributes, **kwargs):
54    utils.inject_attribute(class_attributes, 'load', object_summary_load)
55
56
57def bucket_load(self, *args, **kwargs):
58    """
59    Calls s3.Client.list_buckets() to update the attributes of the Bucket
60    resource.
61    """
62    # The docstring above is phrased this way to match what the autogenerated
63    # docs produce.
64
65    # We can't actually get the bucket's attributes from a HeadBucket,
66    # so we need to use a ListBuckets and search for our bucket.
67    # However, we may fail if we lack permissions to ListBuckets
68    # or the bucket is in another account. In which case, creation_date
69    # will be None.
70    self.meta.data = {}
71    try:
72        response = self.meta.client.list_buckets()
73        for bucket_data in response['Buckets']:
74            if bucket_data['Name'] == self.name:
75                self.meta.data = bucket_data
76                break
77    except ClientError as e:
78        if not e.response.get('Error', {}).get('Code') == 'AccessDenied':
79            raise
80
81
82def object_summary_load(self, *args, **kwargs):
83    """
84    Calls s3.Client.head_object to update the attributes of the ObjectSummary
85    resource.
86    """
87    response = self.meta.client.head_object(
88        Bucket=self.bucket_name, Key=self.key)
89    if 'ContentLength' in response:
90        response['Size'] = response.pop('ContentLength')
91    self.meta.data = response
92
93
94def upload_file(self, Filename, Bucket, Key, ExtraArgs=None,
95                Callback=None, Config=None):
96    """Upload a file to an S3 object.
97
98    Usage::
99
100        import boto3
101        s3 = boto3.resource('s3')
102        s3.meta.client.upload_file('/tmp/hello.txt', 'mybucket', 'hello.txt')
103
104    Similar behavior as S3Transfer's upload_file() method,
105    except that parameters are capitalized. Detailed examples can be found at
106    :ref:`S3Transfer's Usage <ref_s3transfer_usage>`.
107
108    :type Filename: str
109    :param Filename: The path to the file to upload.
110
111    :type Bucket: str
112    :param Bucket: The name of the bucket to upload to.
113
114    :type Key: str
115    :param Key: The name of the key to upload to.
116
117    :type ExtraArgs: dict
118    :param ExtraArgs: Extra arguments that may be passed to the
119        client operation.
120
121    :type Callback: function
122    :param Callback: A method which takes a number of bytes transferred to
123        be periodically called during the upload.
124
125    :type Config: boto3.s3.transfer.TransferConfig
126    :param Config: The transfer configuration to be used when performing the
127        transfer.
128    """
129    with S3Transfer(self, Config) as transfer:
130        return transfer.upload_file(
131            filename=Filename, bucket=Bucket, key=Key,
132            extra_args=ExtraArgs, callback=Callback)
133
134
135def download_file(self, Bucket, Key, Filename, ExtraArgs=None,
136                  Callback=None, Config=None):
137    """Download an S3 object to a file.
138
139    Usage::
140
141        import boto3
142        s3 = boto3.resource('s3')
143        s3.meta.client.download_file('mybucket', 'hello.txt', '/tmp/hello.txt')
144
145    Similar behavior as S3Transfer's download_file() method,
146    except that parameters are capitalized. Detailed examples can be found at
147    :ref:`S3Transfer's Usage <ref_s3transfer_usage>`.
148
149    :type Bucket: str
150    :param Bucket: The name of the bucket to download from.
151
152    :type Key: str
153    :param Key: The name of the key to download from.
154
155    :type Filename: str
156    :param Filename: The path to the file to download to.
157
158    :type ExtraArgs: dict
159    :param ExtraArgs: Extra arguments that may be passed to the
160        client operation.
161
162    :type Callback: function
163    :param Callback: A method which takes a number of bytes transferred to
164        be periodically called during the download.
165
166    :type Config: boto3.s3.transfer.TransferConfig
167    :param Config: The transfer configuration to be used when performing the
168        transfer.
169    """
170    with S3Transfer(self, Config) as transfer:
171        return transfer.download_file(
172            bucket=Bucket, key=Key, filename=Filename,
173            extra_args=ExtraArgs, callback=Callback)
174
175
176def bucket_upload_file(self, Filename, Key,
177                       ExtraArgs=None, Callback=None, Config=None):
178    """Upload a file to an S3 object.
179
180    Usage::
181
182        import boto3
183        s3 = boto3.resource('s3')
184        s3.Bucket('mybucket').upload_file('/tmp/hello.txt', 'hello.txt')
185
186    Similar behavior as S3Transfer's upload_file() method,
187    except that parameters are capitalized. Detailed examples can be found at
188    :ref:`S3Transfer's Usage <ref_s3transfer_usage>`.
189
190    :type Filename: str
191    :param Filename: The path to the file to upload.
192
193    :type Key: str
194    :param Key: The name of the key to upload to.
195
196    :type ExtraArgs: dict
197    :param ExtraArgs: Extra arguments that may be passed to the
198        client operation.
199
200    :type Callback: function
201    :param Callback: A method which takes a number of bytes transferred to
202        be periodically called during the upload.
203
204    :type Config: boto3.s3.transfer.TransferConfig
205    :param Config: The transfer configuration to be used when performing the
206        transfer.
207    """
208    return self.meta.client.upload_file(
209        Filename=Filename, Bucket=self.name, Key=Key,
210        ExtraArgs=ExtraArgs, Callback=Callback, Config=Config)
211
212
213def bucket_download_file(self, Key, Filename,
214                         ExtraArgs=None, Callback=None, Config=None):
215    """Download an S3 object to a file.
216
217    Usage::
218
219        import boto3
220        s3 = boto3.resource('s3')
221        s3.Bucket('mybucket').download_file('hello.txt', '/tmp/hello.txt')
222
223    Similar behavior as S3Transfer's download_file() method,
224    except that parameters are capitalized. Detailed examples can be found at
225    :ref:`S3Transfer's Usage <ref_s3transfer_usage>`.
226
227    :type Key: str
228    :param Key: The name of the key to download from.
229
230    :type Filename: str
231    :param Filename: The path to the file to download to.
232
233    :type ExtraArgs: dict
234    :param ExtraArgs: Extra arguments that may be passed to the
235        client operation.
236
237    :type Callback: function
238    :param Callback: A method which takes a number of bytes transferred to
239        be periodically called during the download.
240
241    :type Config: boto3.s3.transfer.TransferConfig
242    :param Config: The transfer configuration to be used when performing the
243        transfer.
244    """
245    return self.meta.client.download_file(
246        Bucket=self.name, Key=Key, Filename=Filename,
247        ExtraArgs=ExtraArgs, Callback=Callback, Config=Config)
248
249
250def object_upload_file(self, Filename,
251                       ExtraArgs=None, Callback=None, Config=None):
252    """Upload a file to an S3 object.
253
254    Usage::
255
256        import boto3
257        s3 = boto3.resource('s3')
258        s3.Object('mybucket', 'hello.txt').upload_file('/tmp/hello.txt')
259
260    Similar behavior as S3Transfer's upload_file() method,
261    except that parameters are capitalized. Detailed examples can be found at
262    :ref:`S3Transfer's Usage <ref_s3transfer_usage>`.
263
264    :type Filename: str
265    :param Filename: The path to the file to upload.
266
267    :type ExtraArgs: dict
268    :param ExtraArgs: Extra arguments that may be passed to the
269        client operation.
270
271    :type Callback: function
272    :param Callback: A method which takes a number of bytes transferred to
273        be periodically called during the upload.
274
275    :type Config: boto3.s3.transfer.TransferConfig
276    :param Config: The transfer configuration to be used when performing the
277        transfer.
278    """
279    return self.meta.client.upload_file(
280        Filename=Filename, Bucket=self.bucket_name, Key=self.key,
281        ExtraArgs=ExtraArgs, Callback=Callback, Config=Config)
282
283
284def object_download_file(self, Filename,
285                         ExtraArgs=None, Callback=None, Config=None):
286    """Download an S3 object to a file.
287
288    Usage::
289
290        import boto3
291        s3 = boto3.resource('s3')
292        s3.Object('mybucket', 'hello.txt').download_file('/tmp/hello.txt')
293
294    Similar behavior as S3Transfer's download_file() method,
295    except that parameters are capitalized. Detailed examples can be found at
296    :ref:`S3Transfer's Usage <ref_s3transfer_usage>`.
297
298    :type Filename: str
299    :param Filename: The path to the file to download to.
300
301    :type ExtraArgs: dict
302    :param ExtraArgs: Extra arguments that may be passed to the
303        client operation.
304
305    :type Callback: function
306    :param Callback: A method which takes a number of bytes transferred to
307        be periodically called during the download.
308
309    :type Config: boto3.s3.transfer.TransferConfig
310    :param Config: The transfer configuration to be used when performing the
311        transfer.
312    """
313    return self.meta.client.download_file(
314        Bucket=self.bucket_name, Key=self.key, Filename=Filename,
315        ExtraArgs=ExtraArgs, Callback=Callback, Config=Config)
316
317
318def copy(self, CopySource, Bucket, Key, ExtraArgs=None, Callback=None,
319         SourceClient=None, Config=None):
320    """Copy an object from one S3 location to another.
321
322    This is a managed transfer which will perform a multipart copy in
323    multiple threads if necessary.
324
325    Usage::
326
327        import boto3
328        s3 = boto3.resource('s3')
329        copy_source = {
330            'Bucket': 'mybucket',
331            'Key': 'mykey'
332        }
333        s3.meta.client.copy(copy_source, 'otherbucket', 'otherkey')
334
335    :type CopySource: dict
336    :param CopySource: The name of the source bucket, key name of the
337        source object, and optional version ID of the source object. The
338        dictionary format is:
339        ``{'Bucket': 'bucket', 'Key': 'key', 'VersionId': 'id'}``. Note
340        that the ``VersionId`` key is optional and may be omitted.
341
342    :type Bucket: str
343    :param Bucket: The name of the bucket to copy to
344
345    :type Key: str
346    :param Key: The name of the key to copy to
347
348    :type ExtraArgs: dict
349    :param ExtraArgs: Extra arguments that may be passed to the
350        client operation
351
352    :type Callback: function
353    :param Callback: A method which takes a number of bytes transferred to
354        be periodically called during the copy.
355
356    :type SourceClient: botocore or boto3 Client
357    :param SourceClient: The client to be used for operation that
358        may happen at the source object. For example, this client is
359        used for the head_object that determines the size of the copy.
360        If no client is provided, the current client is used as the client
361        for the source object.
362
363    :type Config: boto3.s3.transfer.TransferConfig
364    :param Config: The transfer configuration to be used when performing the
365        copy.
366    """
367    subscribers = None
368    if Callback is not None:
369        subscribers = [ProgressCallbackInvoker(Callback)]
370
371    config = Config
372    if config is None:
373        config = TransferConfig()
374
375    with create_transfer_manager(self, config) as manager:
376        future = manager.copy(
377            copy_source=CopySource, bucket=Bucket, key=Key,
378            extra_args=ExtraArgs, subscribers=subscribers,
379            source_client=SourceClient)
380        return future.result()
381
382
383def bucket_copy(self, CopySource, Key, ExtraArgs=None, Callback=None,
384                SourceClient=None, Config=None):
385    """Copy an object from one S3 location to an object in this bucket.
386
387    This is a managed transfer which will perform a multipart copy in
388    multiple threads if necessary.
389
390    Usage::
391
392        import boto3
393        s3 = boto3.resource('s3')
394        copy_source = {
395            'Bucket': 'mybucket',
396            'Key': 'mykey'
397        }
398        bucket = s3.Bucket('otherbucket')
399        bucket.copy(copy_source, 'otherkey')
400
401    :type CopySource: dict
402    :param CopySource: The name of the source bucket, key name of the
403        source object, and optional version ID of the source object. The
404        dictionary format is:
405        ``{'Bucket': 'bucket', 'Key': 'key', 'VersionId': 'id'}``. Note
406        that the ``VersionId`` key is optional and may be omitted.
407
408    :type Key: str
409    :param Key: The name of the key to copy to
410
411    :type ExtraArgs: dict
412    :param ExtraArgs: Extra arguments that may be passed to the
413        client operation
414
415    :type Callback: function
416    :param Callback: A method which takes a number of bytes transferred to
417        be periodically called during the copy.
418
419    :type SourceClient: botocore or boto3 Client
420    :param SourceClient: The client to be used for operation that
421        may happen at the source object. For example, this client is
422        used for the head_object that determines the size of the copy.
423        If no client is provided, the current client is used as the client
424        for the source object.
425
426    :type Config: boto3.s3.transfer.TransferConfig
427    :param Config: The transfer configuration to be used when performing the
428        copy.
429    """
430    return self.meta.client.copy(
431        CopySource=CopySource, Bucket=self.name, Key=Key, ExtraArgs=ExtraArgs,
432        Callback=Callback, SourceClient=SourceClient, Config=Config)
433
434
435def object_copy(self, CopySource, ExtraArgs=None, Callback=None,
436                SourceClient=None, Config=None):
437    """Copy an object from one S3 location to this object.
438
439    This is a managed transfer which will perform a multipart copy in
440    multiple threads if necessary.
441
442    Usage::
443
444        import boto3
445        s3 = boto3.resource('s3')
446        copy_source = {
447            'Bucket': 'mybucket',
448            'Key': 'mykey'
449        }
450        bucket = s3.Bucket('otherbucket')
451        obj = bucket.Object('otherkey')
452        obj.copy(copy_source)
453
454    :type CopySource: dict
455    :param CopySource: The name of the source bucket, key name of the
456        source object, and optional version ID of the source object. The
457        dictionary format is:
458        ``{'Bucket': 'bucket', 'Key': 'key', 'VersionId': 'id'}``. Note
459        that the ``VersionId`` key is optional and may be omitted.
460
461    :type ExtraArgs: dict
462    :param ExtraArgs: Extra arguments that may be passed to the
463        client operation
464
465    :type Callback: function
466    :param Callback: A method which takes a number of bytes transferred to
467        be periodically called during the copy.
468
469    :type SourceClient: botocore or boto3 Client
470    :param SourceClient: The client to be used for operation that
471        may happen at the source object. For example, this client is
472        used for the head_object that determines the size of the copy.
473        If no client is provided, the current client is used as the client
474        for the source object.
475
476    :type Config: boto3.s3.transfer.TransferConfig
477    :param Config: The transfer configuration to be used when performing the
478        copy.
479    """
480    return self.meta.client.copy(
481        CopySource=CopySource, Bucket=self.bucket_name, Key=self.key,
482        ExtraArgs=ExtraArgs, Callback=Callback, SourceClient=SourceClient,
483        Config=Config)
484
485
486def upload_fileobj(self, Fileobj, Bucket, Key, ExtraArgs=None,
487                   Callback=None, Config=None):
488    """Upload a file-like object to S3.
489
490    The file-like object must be in binary mode.
491
492    This is a managed transfer which will perform a multipart upload in
493    multiple threads if necessary.
494
495    Usage::
496
497        import boto3
498        s3 = boto3.client('s3')
499
500        with open('filename', 'rb') as data:
501            s3.upload_fileobj(data, 'mybucket', 'mykey')
502
503    :type Fileobj: a file-like object
504    :param Fileobj: A file-like object to upload. At a minimum, it must
505        implement the `read` method, and must return bytes.
506
507    :type Bucket: str
508    :param Bucket: The name of the bucket to upload to.
509
510    :type Key: str
511    :param Key: The name of the key to upload to.
512
513    :type ExtraArgs: dict
514    :param ExtraArgs: Extra arguments that may be passed to the
515        client operation.
516
517    :type Callback: function
518    :param Callback: A method which takes a number of bytes transferred to
519        be periodically called during the upload.
520
521    :type Config: boto3.s3.transfer.TransferConfig
522    :param Config: The transfer configuration to be used when performing the
523        upload.
524    """
525    if not hasattr(Fileobj, 'read'):
526        raise ValueError('Fileobj must implement read')
527
528    subscribers = None
529    if Callback is not None:
530        subscribers = [ProgressCallbackInvoker(Callback)]
531
532    config = Config
533    if config is None:
534        config = TransferConfig()
535
536    with create_transfer_manager(self, config) as manager:
537        future = manager.upload(
538            fileobj=Fileobj, bucket=Bucket, key=Key,
539            extra_args=ExtraArgs, subscribers=subscribers)
540        return future.result()
541
542
543def bucket_upload_fileobj(self, Fileobj, Key, ExtraArgs=None,
544                          Callback=None, Config=None):
545    """Upload a file-like object to this bucket.
546
547    The file-like object must be in binary mode.
548
549    This is a managed transfer which will perform a multipart upload in
550    multiple threads if necessary.
551
552    Usage::
553
554        import boto3
555        s3 = boto3.resource('s3')
556        bucket = s3.Bucket('mybucket')
557
558        with open('filename', 'rb') as data:
559            bucket.upload_fileobj(data, 'mykey')
560
561    :type Fileobj: a file-like object
562    :param Fileobj: A file-like object to upload. At a minimum, it must
563        implement the `read` method, and must return bytes.
564
565    :type Key: str
566    :param Key: The name of the key to upload to.
567
568    :type ExtraArgs: dict
569    :param ExtraArgs: Extra arguments that may be passed to the
570        client operation.
571
572    :type Callback: function
573    :param Callback: A method which takes a number of bytes transferred to
574        be periodically called during the upload.
575
576    :type Config: boto3.s3.transfer.TransferConfig
577    :param Config: The transfer configuration to be used when performing the
578        upload.
579    """
580    return self.meta.client.upload_fileobj(
581        Fileobj=Fileobj, Bucket=self.name, Key=Key, ExtraArgs=ExtraArgs,
582        Callback=Callback, Config=Config)
583
584
585def object_upload_fileobj(self, Fileobj, ExtraArgs=None, Callback=None,
586                          Config=None):
587    """Upload a file-like object to this object.
588
589    The file-like object must be in binary mode.
590
591    This is a managed transfer which will perform a multipart upload in
592    multiple threads if necessary.
593
594    Usage::
595
596        import boto3
597        s3 = boto3.resource('s3')
598        bucket = s3.Bucket('mybucket')
599        obj = bucket.Object('mykey')
600
601        with open('filename', 'rb') as data:
602            obj.upload_fileobj(data)
603
604    :type Fileobj: a file-like object
605    :param Fileobj: A file-like object to upload. At a minimum, it must
606        implement the `read` method, and must return bytes.
607
608    :type ExtraArgs: dict
609    :param ExtraArgs: Extra arguments that may be passed to the
610        client operation.
611
612    :type Callback: function
613    :param Callback: A method which takes a number of bytes transferred to
614        be periodically called during the upload.
615
616    :type Config: boto3.s3.transfer.TransferConfig
617    :param Config: The transfer configuration to be used when performing the
618        upload.
619    """
620    return self.meta.client.upload_fileobj(
621        Fileobj=Fileobj, Bucket=self.bucket_name, Key=self.key,
622        ExtraArgs=ExtraArgs, Callback=Callback, Config=Config)
623
624
625def download_fileobj(self, Bucket, Key, Fileobj, ExtraArgs=None,
626                     Callback=None, Config=None):
627    """Download an object from S3 to a file-like object.
628
629    The file-like object must be in binary mode.
630
631    This is a managed transfer which will perform a multipart download in
632    multiple threads if necessary.
633
634    Usage::
635
636        import boto3
637        s3 = boto3.client('s3')
638
639        with open('filename', 'wb') as data:
640            s3.download_fileobj('mybucket', 'mykey', data)
641
642    :type Bucket: str
643    :param Bucket: The name of the bucket to download from.
644
645    :type Key: str
646    :param Key: The name of the key to download from.
647
648    :type Fileobj: a file-like object
649    :param Fileobj: A file-like object to download into. At a minimum, it must
650        implement the `write` method and must accept bytes.
651
652    :type ExtraArgs: dict
653    :param ExtraArgs: Extra arguments that may be passed to the
654        client operation.
655
656    :type Callback: function
657    :param Callback: A method which takes a number of bytes transferred to
658        be periodically called during the download.
659
660    :type Config: boto3.s3.transfer.TransferConfig
661    :param Config: The transfer configuration to be used when performing the
662        download.
663    """
664    if not hasattr(Fileobj, 'write'):
665        raise ValueError('Fileobj must implement write')
666
667    subscribers = None
668    if Callback is not None:
669        subscribers = [ProgressCallbackInvoker(Callback)]
670
671    config = Config
672    if config is None:
673        config = TransferConfig()
674
675    with create_transfer_manager(self, config) as manager:
676        future = manager.download(
677            bucket=Bucket, key=Key, fileobj=Fileobj,
678            extra_args=ExtraArgs, subscribers=subscribers)
679        return future.result()
680
681
682def bucket_download_fileobj(self, Key, Fileobj, ExtraArgs=None,
683                            Callback=None, Config=None):
684    """Download an object from this bucket to a file-like-object.
685
686    The file-like object must be in binary mode.
687
688    This is a managed transfer which will perform a multipart download in
689    multiple threads if necessary.
690
691    Usage::
692
693        import boto3
694        s3 = boto3.resource('s3')
695        bucket = s3.Bucket('mybucket')
696
697        with open('filename', 'wb') as data:
698            bucket.download_fileobj('mykey', data)
699
700    :type Fileobj: a file-like object
701    :param Fileobj: A file-like object to download into. At a minimum, it must
702        implement the `write` method and must accept bytes.
703
704    :type Key: str
705    :param Key: The name of the key to download from.
706
707    :type ExtraArgs: dict
708    :param ExtraArgs: Extra arguments that may be passed to the
709        client operation.
710
711    :type Callback: function
712    :param Callback: A method which takes a number of bytes transferred to
713        be periodically called during the download.
714
715    :type Config: boto3.s3.transfer.TransferConfig
716    :param Config: The transfer configuration to be used when performing the
717        download.
718    """
719    return self.meta.client.download_fileobj(
720        Bucket=self.name, Key=Key, Fileobj=Fileobj, ExtraArgs=ExtraArgs,
721        Callback=Callback, Config=Config)
722
723
724def object_download_fileobj(self, Fileobj, ExtraArgs=None, Callback=None,
725                            Config=None):
726    """Download this object from S3 to a file-like object.
727
728    The file-like object must be in binary mode.
729
730    This is a managed transfer which will perform a multipart download in
731    multiple threads if necessary.
732
733    Usage::
734
735        import boto3
736        s3 = boto3.resource('s3')
737        bucket = s3.Bucket('mybucket')
738        obj = bucket.Object('mykey')
739
740        with open('filename', 'wb') as data:
741            obj.download_fileobj(data)
742
743    :type Fileobj: a file-like object
744    :param Fileobj: A file-like object to download into. At a minimum, it must
745        implement the `write` method and must accept bytes.
746
747    :type ExtraArgs: dict
748    :param ExtraArgs: Extra arguments that may be passed to the
749        client operation.
750
751    :type Callback: function
752    :param Callback: A method which takes a number of bytes transferred to
753        be periodically called during the download.
754
755    :type Config: boto3.s3.transfer.TransferConfig
756    :param Config: The transfer configuration to be used when performing the
757        download.
758    """
759    return self.meta.client.download_fileobj(
760        Bucket=self.bucket_name, Key=self.key, Fileobj=Fileobj,
761        ExtraArgs=ExtraArgs, Callback=Callback, Config=Config)
762