1# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/
2#
3# Permission is hereby granted, free of charge, to any person obtaining a
4# copy of this software and associated documentation files (the
5# "Software"), to deal in the Software without restriction, including
6# without limitation the rights to use, copy, modify, merge, publish, dis-
7# tribute, sublicense, and/or sell copies of the Software, and to permit
8# persons to whom the Software is furnished to do so, subject to the fol-
9# lowing conditions:
10#
11# The above copyright notice and this permission notice shall be included
12# in all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20# IN THE SOFTWARE.
21
22from boto.compat import urllib, six
23
24def bucket_lister(bucket, prefix='', delimiter='', marker='', headers=None,
25                  encoding_type=None):
26    """
27    A generator function for listing keys in a bucket.
28    """
29    more_results = True
30    k = None
31    while more_results:
32        rs = bucket.get_all_keys(prefix=prefix, marker=marker,
33                                 delimiter=delimiter, headers=headers,
34                                 encoding_type=encoding_type)
35        for k in rs:
36            yield k
37        if k:
38            marker = rs.next_marker or k.name
39        if marker and encoding_type == "url":
40            if isinstance(marker, six.text_type):
41                marker = marker.encode('utf-8')
42            marker = urllib.parse.unquote(marker)
43        more_results= rs.is_truncated
44
45class BucketListResultSet(object):
46    """
47    A resultset for listing keys within a bucket.  Uses the bucket_lister
48    generator function and implements the iterator interface.  This
49    transparently handles the results paging from S3 so even if you have
50    many thousands of keys within the bucket you can iterate over all
51    keys in a reasonably efficient manner.
52    """
53
54    def __init__(self, bucket=None, prefix='', delimiter='', marker='',
55                 headers=None, encoding_type=None):
56        self.bucket = bucket
57        self.prefix = prefix
58        self.delimiter = delimiter
59        self.marker = marker
60        self.headers = headers
61        self.encoding_type = encoding_type
62
63    def __iter__(self):
64        return bucket_lister(self.bucket, prefix=self.prefix,
65                             delimiter=self.delimiter, marker=self.marker,
66                             headers=self.headers,
67                             encoding_type=self.encoding_type)
68
69def versioned_bucket_lister(bucket, prefix='', delimiter='',
70                            key_marker='', version_id_marker='', headers=None,
71                            encoding_type=None):
72    """
73    A generator function for listing versions in a bucket.
74    """
75    more_results = True
76    k = None
77    while more_results:
78        rs = bucket.get_all_versions(prefix=prefix, key_marker=key_marker,
79                                     version_id_marker=version_id_marker,
80                                     delimiter=delimiter, headers=headers,
81                                     max_keys=999, encoding_type=encoding_type)
82        for k in rs:
83            yield k
84        key_marker = rs.next_key_marker
85        version_id_marker = rs.next_version_id_marker
86        more_results= rs.is_truncated
87
88class VersionedBucketListResultSet(object):
89    """
90    A resultset for listing versions within a bucket.  Uses the bucket_lister
91    generator function and implements the iterator interface.  This
92    transparently handles the results paging from S3 so even if you have
93    many thousands of keys within the bucket you can iterate over all
94    keys in a reasonably efficient manner.
95    """
96
97    def __init__(self, bucket=None, prefix='', delimiter='', key_marker='',
98                 version_id_marker='', headers=None, encoding_type=None):
99        self.bucket = bucket
100        self.prefix = prefix
101        self.delimiter = delimiter
102        self.key_marker = key_marker
103        self.version_id_marker = version_id_marker
104        self.headers = headers
105        self.encoding_type = encoding_type
106
107    def __iter__(self):
108        return versioned_bucket_lister(self.bucket, prefix=self.prefix,
109                                       delimiter=self.delimiter,
110                                       key_marker=self.key_marker,
111                                       version_id_marker=self.version_id_marker,
112                                       headers=self.headers,
113                                       encoding_type=self.encoding_type)
114
115def multipart_upload_lister(bucket, key_marker='',
116                            upload_id_marker='',
117                            headers=None, encoding_type=None):
118    """
119    A generator function for listing multipart uploads in a bucket.
120    """
121    more_results = True
122    k = None
123    while more_results:
124        rs = bucket.get_all_multipart_uploads(key_marker=key_marker,
125                                              upload_id_marker=upload_id_marker,
126                                              headers=headers,
127                                              encoding_type=encoding_type)
128        for k in rs:
129            yield k
130        key_marker = rs.next_key_marker
131        upload_id_marker = rs.next_upload_id_marker
132        more_results= rs.is_truncated
133
134class MultiPartUploadListResultSet(object):
135    """
136    A resultset for listing multipart uploads within a bucket.
137    Uses the multipart_upload_lister generator function and
138    implements the iterator interface.  This
139    transparently handles the results paging from S3 so even if you have
140    many thousands of uploads within the bucket you can iterate over all
141    keys in a reasonably efficient manner.
142    """
143    def __init__(self, bucket=None, key_marker='',
144                 upload_id_marker='', headers=None, encoding_type=None):
145        self.bucket = bucket
146        self.key_marker = key_marker
147        self.upload_id_marker = upload_id_marker
148        self.headers = headers
149        self.encoding_type = encoding_type
150
151    def __iter__(self):
152        return multipart_upload_lister(self.bucket,
153                                       key_marker=self.key_marker,
154                                       upload_id_marker=self.upload_id_marker,
155                                       headers=self.headers,
156                                       encoding_type=self.encoding_type)
157