1# Copyright 2016 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.
13from functools import lru_cache
14
15from s3transfer.compat import accepts_kwargs
16from s3transfer.exceptions import InvalidSubscriberMethodError
17
18
19class BaseSubscriber:
20 """The base subscriber class
21
22 It is recommended that all subscriber implementations subclass and then
23 override the subscription methods (i.e. on_{subsribe_type}() methods).
24 """
25
26 VALID_SUBSCRIBER_TYPES = ['queued', 'progress', 'done']
27
28 def __new__(cls, *args, **kwargs):
29 cls._validate_subscriber_methods()
30 return super().__new__(cls)
31
32 @classmethod
33 @lru_cache
34 def _validate_subscriber_methods(cls):
35 for subscriber_type in cls.VALID_SUBSCRIBER_TYPES:
36 subscriber_method = getattr(cls, 'on_' + subscriber_type)
37 if not callable(subscriber_method):
38 raise InvalidSubscriberMethodError(
39 f'Subscriber method {subscriber_method} must be callable.'
40 )
41
42 if not accepts_kwargs(subscriber_method):
43 raise InvalidSubscriberMethodError(
44 f'Subscriber method {subscriber_method} must accept keyword '
45 'arguments (**kwargs)'
46 )
47
48 def on_queued(self, future, **kwargs):
49 """Callback to be invoked when transfer request gets queued
50
51 This callback can be useful for:
52
53 * Keeping track of how many transfers have been requested
54 * Providing the expected transfer size through
55 future.meta.provide_transfer_size() so a HeadObject would not
56 need to be made for copies and downloads.
57
58 :type future: s3transfer.futures.TransferFuture
59 :param future: The TransferFuture representing the requested transfer.
60 """
61 pass
62
63 def on_progress(self, future, bytes_transferred, **kwargs):
64 """Callback to be invoked when progress is made on transfer
65
66 This callback can be useful for:
67
68 * Recording and displaying progress
69
70 :type future: s3transfer.futures.TransferFuture
71 :param future: The TransferFuture representing the requested transfer.
72
73 :type bytes_transferred: int
74 :param bytes_transferred: The number of bytes transferred for that
75 invocation of the callback. Note that a negative amount can be
76 provided, which usually indicates that an in-progress request
77 needed to be retried and thus progress was rewound.
78 """
79 pass
80
81 def on_done(self, future, **kwargs):
82 """Callback to be invoked once a transfer is done
83
84 This callback can be useful for:
85
86 * Recording and displaying whether the transfer succeeded or
87 failed using future.result()
88 * Running some task after the transfer completed like changing
89 the last modified time of a downloaded file.
90
91 :type future: s3transfer.futures.TransferFuture
92 :param future: The TransferFuture representing the requested transfer.
93 """
94 pass