Merge lp:~djfroofy/txaws/newagent-767205 into lp:txaws
- newagent-767205
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Duncan McGreggor |
Approved revision: | 144 |
Merged at revision: | 144 |
Proposed branch: | lp:~djfroofy/txaws/newagent-767205 |
Merge into: | lp:txaws |
Prerequisite: | lp:~djfroofy/txaws/modernize-924459 |
Diff against target: |
564 lines (+137/-52) 3 files modified
txaws/client/base.py (+3/-1) txaws/s3/client.py (+49/-25) txaws/s3/tests/test_client.py (+85/-26) |
To merge this branch: | bzr merge lp:~djfroofy/txaws/newagent-767205 |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Duncan McGreggor | Approve | ||
Drew Smathers | Needs Resubmitting | ||
Robert Collins | Abstain | ||
Review via email: mp+93312@code.launchpad.net |
Commit message
Description of the change
Robert Collins (lifeless) : | # |
Daira Hopwood (daira) wrote : | # |
Thanks, will review tomorrow.
Daira Hopwood (daira) wrote : | # |
Sorry for the delay. Looks good to me.
Just a minor style nit: some of the code indents parameters to after the '(', and some only by 4 spaces. E.g.
{{{
def __init__(self, creds=None, endpoint=None, query_factory=None,
}}}
vs
{{{
def __init__(self, creds=None, endpoint=None, query_factory=None,
receiver_
}}}
The former is more readable.
Zooko Wilcox-O'Hearn (zooko) wrote : | # |
Okay, if david-sarah reviewed it and said "Looks good to me", then the branch ought to be merged. Who has authority do that?
Duncan McGreggor (oubiwann) wrote : | # |
On Thu, Apr 12, 2012 at 5:02 PM, Zooko Wilcox-O'Hearn <email address hidden> wrote:
> Okay, if david-sarah reviewed it and said "Looks good to me", then the branch ought to be merged. Who has authority do that?
I'll take a look...
d
Duncan McGreggor (oubiwann) wrote : | # |
On Fri, Apr 13, 2012 at 12:43 AM, Duncan McGreggor <email address hidden> wrote:
> On Thu, Apr 12, 2012 at 5:02 PM, Zooko Wilcox-O'Hearn <email address hidden> wrote:
>> Okay, if david-sarah reviewed it and said "Looks good to me", then the branch ought to be merged. Who has authority do that?
>
> I'll take a look...
Okay, I just took a look. Looks like a review comment I left earlier
(needs fixing) hasn't been addressed by the author (unless I'm missing
something?).
Once that's either done or discussed, we can move this puppy forward :-)
Drew Smathers (djfroofy) wrote : | # |
> This change looks good to me at first glance (reading the diff on the merge
> proposal; I haven't branched the code yet). In particular, the amz_headers
> functionality is much-needed.
>
> Drew, I don't see anything about the new web client usage, only headers and
> body producer. Is that coming in a future change?
>
Ok, so I had to remember myself while staring at the diff. The code for agent is in the prerequisite branch: lp:~djfroofy/txaws/modernize-924459
> At the risk of being a total pain in the ass, here's what I would recommend:
>
No, no worries.
> 1) split out the headers changes into a new branch, and attach it to bug
> #972432.
#972432 must be a duplicate of #640098; the amz_headers argument has been merged already. To summarize what this diff is adding: Support for plugging in Body Producers and Receivers in s3.client (this is made possible by: lp:~djfroofy/txaws/modernize-924459).
There are actually no changes related to headers in this patch. Rather, I'm adding receiver_factory as __init__() argument to S3Client and body_producer as argument to regular S3 api calls.
Cutting to the point, I think #972432 needs to be reviewed first.
> 2) create a new bug for the body producer/receiver factory feature, split that
> code out, and attach it to there in its own branch.
That was in the scope of #972432
> 3) do the work on the new agent in this branch and this ticket (bug #767205).
Again: #972432 is where that functionality is.
Drew Smathers (djfroofy) wrote : | # |
> Sorry for the delay. Looks good to me.
>
> Just a minor style nit: some of the code indents parameters to after the '(',
> and some only by 4 spaces. E.g.
> {{{
> def __init__(self, creds=None, endpoint=None, query_factory=None,
> parser=None, receiver_
> }}}
> vs
> {{{
> def __init__(self, creds=None, endpoint=None, query_factory=None,
> receiver_
> }}}
> The former is more readable.
Yes, I agree and will address this.
- 144. By Drew Smathers
-
param indentation style fix [f=767205]
Drew Smathers (djfroofy) wrote : | # |
Ok style fixes pushed to branch.
Duncan McGreggor (oubiwann) wrote : | # |
On Sat, Apr 14, 2012 at 12:28 PM, Drew Smathers
<email address hidden> wrote:
>> This change looks good to me at first glance (reading the diff on the merge
>> proposal; I haven't branched the code yet). In particular, the amz_headers
>> functionality is much-needed.
>>
>> Drew, I don't see anything about the new web client usage, only headers and
>> body producer. Is that coming in a future change?
>>
>
> Ok, so I had to remember myself while staring at the diff. The code for agent is in the prerequisite branch: lp:~djfroofy/txaws/modernize-924459
>
>
>> At the risk of being a total pain in the ass, here's what I would recommend:
>>
>
> No, no worries.
>
>> 1) split out the headers changes into a new branch, and attach it to bug
>> #972432.
>
> #972432 must be a duplicate of #640098; the amz_headers argument has been merged already. To summarize what this diff is adding: Support for plugging in Body Producers and Receivers in s3.client (this is made possible by: lp:~djfroofy/txaws/modernize-924459).
>
> There are actually no changes related to headers in this patch. Rather, I'm adding receiver_factory as __init__() argument to S3Client and body_producer as argument to regular S3 api calls.
>
> Cutting to the point, I think #972432 needs to be reviewed first.
>
>> 2) create a new bug for the body producer/receiver factory feature, split that
>> code out, and attach it to there in its own branch.
>
> That was in the scope of #972432
>
>> 3) do the work on the new agent in this branch and this ticket (bug #767205).
>
> Again: #972432 is where that functionality is.
> --
> https:/
> You are reviewing the proposed merge of lp:~djfroofy/txaws/newagent-767205 into lp:txaws.
Thanks for catching me up, Drew -- this is good stuff.
I'm going to be in the air tomorrow, on the way to the OpenStack
design summit and conference, but will branch all the code and check
out the associated tickets, to make sure I haven't missed anything.
Regardless, it looks like we've got a pending merge on our hands. This
code should land in trunk within a day or two...
Thanks again!
Duncan McGreggor (oubiwann) wrote : | # |
On Sat, Apr 14, 2012 at 12:28 PM, Drew Smathers
<email address hidden> wrote:
>>
>> 1) split out the headers changes into a new branch, and attach it to bug
>> #972432.
>
> #972432 must be a duplicate of #640098; the amz_headers argument has been merged already. To summarize what this diff is adding: Support for plugging in Body Producers and Receivers in s3.client (this is made possible by: lp:~djfroofy/txaws/modernize-924459).
>
> There are actually no changes related to headers in this patch. Rather, I'm adding receiver_factory as __init__() argument to S3Client and body_producer as argument to regular S3 api calls.
>
> Cutting to the point, I think #972432 needs to be reviewed first.
Do you mean bug #924459? (since bug #972432 is a duplicate of bug #640098 ...)
>> 2) create a new bug for the body producer/receiver factory feature, split that
>> code out, and attach it to there in its own branch.
>
> That was in the scope of #972432
It looks like you mean bug #640098?
More soon...
Drew Smathers (djfroofy) wrote : | # |
> On Sat, Apr 14, 2012 at 12:28 PM, Drew Smathers
> <email address hidden> wrote:
> >>
> >> 1) split out the headers changes into a new branch, and attach it to bug
> >> #972432.
> >
> > #972432 must be a duplicate of #640098; the amz_headers argument has been
> merged already. To summarize what this diff is adding: Support for plugging
> in Body Producers and Receivers in s3.client (this is made possible by:
> lp:~djfroofy/txaws/modernize-924459).
> >
> > There are actually no changes related to headers in this patch. Rather, I'm
> adding receiver_factory as __init__() argument to S3Client and body_producer
> as argument to regular S3 api calls.
> >
> > Cutting to the point, I think #972432 needs to be reviewed first.
>
> Do you mean bug #924459? (since bug #972432 is a duplicate of bug #640098 ...)
>
> >> 2) create a new bug for the body producer/receiver factory feature, split
> that
> >> code out, and attach it to there in its own branch.
> >
> > That was in the scope of #972432
>
> It looks like you mean bug #640098?
No, another typo, but I meant bug #924459. This has underlying support for the producer/receiver factory supports. This current ticket then just exposes that underlying support in s3 APIs.
Drew Smathers (djfroofy) wrote : | # |
> On Sat, Apr 14, 2012 at 12:28 PM, Drew Smathers
> <email address hidden> wrote:
> >>
> >> 1) split out the headers changes into a new branch, and attach it to bug
> >> #972432.
> >
> > #972432 must be a duplicate of #640098; the amz_headers argument has been
> merged already. To summarize what this diff is adding: Support for plugging
> in Body Producers and Receivers in s3.client (this is made possible by:
> lp:~djfroofy/txaws/modernize-924459).
> >
> > There are actually no changes related to headers in this patch. Rather, I'm
> adding receiver_factory as __init__() argument to S3Client and body_producer
> as argument to regular S3 api calls.
> >
> > Cutting to the point, I think #972432 needs to be reviewed first.
>
> Do you mean bug #924459? (since bug #972432 is a duplicate of bug #640098 ...)
>
Yes, this was a typo.
Drew Smathers (djfroofy) wrote : | # |
> Merge away!
Hi Duncan, am I the one who is supposed to do the merge, or does this need to be done by another developer?
Duncan McGreggor (oubiwann) wrote : | # |
On Fri, May 11, 2012 at 1:19 PM, Drew Smathers
<email address hidden> wrote:
>> Merge away!
>
> Hi Duncan, am I the one who is supposed to do the merge, or does this need to be done by another developer?
Yes! I've just added you to the team -- given your contributions (and
god-like patience!), I think that's more than reasonable :-)
You'll want to do the obvious (merge trunk into your branches, check
for conflicts, push, etc.), but you should be all set!
Let us know if you run into any problems.
d
Preview Diff
1 | === modified file 'txaws/client/base.py' |
2 | --- txaws/client/base.py 2012-04-14 16:36:18 +0000 |
3 | +++ txaws/client/base.py 2012-04-14 16:36:18 +0000 |
4 | @@ -74,9 +74,10 @@ |
5 | @param query_factory: The class or function that produces a query |
6 | object for making requests to the EC2 service. |
7 | @param parser: A parser object for parsing responses from the EC2 service. |
8 | + @param receiver_factory: Factory for receiving responses from EC2 service. |
9 | """ |
10 | def __init__(self, creds=None, endpoint=None, query_factory=None, |
11 | - parser=None): |
12 | + parser=None, receiver_factory=None): |
13 | if creds is None: |
14 | creds = AWSCredentials() |
15 | if endpoint is None: |
16 | @@ -84,6 +85,7 @@ |
17 | self.creds = creds |
18 | self.endpoint = endpoint |
19 | self.query_factory = query_factory |
20 | + self.receiver_factory = receiver_factory |
21 | self.parser = parser |
22 | |
23 | class StreamingError(Exception): |
24 | |
25 | === modified file 'txaws/s3/client.py' |
26 | --- txaws/s3/client.py 2012-01-28 00:39:00 +0000 |
27 | +++ txaws/s3/client.py 2012-04-14 16:36:18 +0000 |
28 | @@ -74,10 +74,12 @@ |
29 | class S3Client(BaseClient): |
30 | """A client for S3.""" |
31 | |
32 | - def __init__(self, creds=None, endpoint=None, query_factory=None): |
33 | + def __init__(self, creds=None, endpoint=None, query_factory=None, |
34 | + receiver_factory=None): |
35 | if query_factory is None: |
36 | query_factory = Query |
37 | - super(S3Client, self).__init__(creds, endpoint, query_factory) |
38 | + super(S3Client, self).__init__(creds, endpoint, query_factory, |
39 | + receiver_factory=receiver_factory) |
40 | |
41 | def list_buckets(self): |
42 | """ |
43 | @@ -87,7 +89,8 @@ |
44 | the request. |
45 | """ |
46 | query = self.query_factory( |
47 | - action="GET", creds=self.creds, endpoint=self.endpoint) |
48 | + action="GET", creds=self.creds, endpoint=self.endpoint, |
49 | + receiver_factory=self.receiver_factory) |
50 | d = query.submit() |
51 | return d.addCallback(self._parse_list_buckets) |
52 | |
53 | @@ -131,7 +134,7 @@ |
54 | """ |
55 | query = self.query_factory( |
56 | action="GET", creds=self.creds, endpoint=self.endpoint, |
57 | - bucket=bucket) |
58 | + bucket=bucket, receiver_factory=self.receiver_factory) |
59 | d = query.submit() |
60 | return d.addCallback(self._parse_get_bucket) |
61 | |
62 | @@ -174,7 +177,8 @@ |
63 | """ |
64 | query = self.query_factory(action="GET", creds=self.creds, |
65 | endpoint=self.endpoint, bucket=bucket, |
66 | - object_name="?location") |
67 | + object_name="?location", |
68 | + receiver_factory=self.receiver_factory) |
69 | d = query.submit() |
70 | return d.addCallback(self._parse_bucket_location) |
71 | |
72 | @@ -193,7 +197,8 @@ |
73 | """ |
74 | query = self.query_factory( |
75 | action='GET', creds=self.creds, endpoint=self.endpoint, |
76 | - bucket=bucket, object_name='?lifecycle') |
77 | + bucket=bucket, object_name='?lifecycle', |
78 | + receiver_factory=self.receiver_factory) |
79 | return query.submit().addCallback(self._parse_lifecycle_config) |
80 | |
81 | def _parse_lifecycle_config(self, xml_bytes): |
82 | @@ -221,7 +226,8 @@ |
83 | """ |
84 | query = self.query_factory( |
85 | action='GET', creds=self.creds, endpoint=self.endpoint, |
86 | - bucket=bucket, object_name='?website') |
87 | + bucket=bucket, object_name='?website', |
88 | + receiver_factory=self.receiver_factory) |
89 | return query.submit().addCallback(self._parse_website_config) |
90 | |
91 | def _parse_website_config(self, xml_bytes): |
92 | @@ -242,7 +248,8 @@ |
93 | """ |
94 | query = self.query_factory( |
95 | action='GET', creds=self.creds, endpoint=self.endpoint, |
96 | - bucket=bucket, object_name='?notification') |
97 | + bucket=bucket, object_name='?notification', |
98 | + receiver_factory=self.receiver_factory) |
99 | return query.submit().addCallback(self._parse_notification_config) |
100 | |
101 | def _parse_notification_config(self, xml_bytes): |
102 | @@ -262,7 +269,8 @@ |
103 | """ |
104 | query = self.query_factory( |
105 | action='GET', creds=self.creds, endpoint=self.endpoint, |
106 | - bucket=bucket, object_name='?versioning') |
107 | + bucket=bucket, object_name='?versioning', |
108 | + receiver_factory=self.receiver_factory) |
109 | return query.submit().addCallback(self._parse_versioning_config) |
110 | |
111 | def _parse_versioning_config(self, xml_bytes): |
112 | @@ -279,7 +287,8 @@ |
113 | """ |
114 | query = self.query_factory( |
115 | action='GET', creds=self.creds, endpoint=self.endpoint, |
116 | - bucket=bucket, object_name='?acl') |
117 | + bucket=bucket, object_name='?acl', |
118 | + receiver_factory=self.receiver_factory) |
119 | return query.submit().addCallback(self._parse_acl) |
120 | |
121 | def put_bucket_acl(self, bucket, access_control_policy): |
122 | @@ -289,7 +298,8 @@ |
123 | data = access_control_policy.to_xml() |
124 | query = self.query_factory( |
125 | action='PUT', creds=self.creds, endpoint=self.endpoint, |
126 | - bucket=bucket, object_name='?acl', data=data) |
127 | + bucket=bucket, object_name='?acl', data=data, |
128 | + receiver_factory=self.receiver_factory) |
129 | return query.submit().addCallback(self._parse_acl) |
130 | |
131 | def _parse_acl(self, xml_bytes): |
132 | @@ -299,8 +309,8 @@ |
133 | """ |
134 | return AccessControlPolicy.from_xml(xml_bytes) |
135 | |
136 | - def put_object(self, bucket, object_name, data, content_type=None, |
137 | - metadata={}, amz_headers={}): |
138 | + def put_object(self, bucket, object_name, data=None, content_type=None, |
139 | + metadata={}, amz_headers={}, body_producer=None): |
140 | """ |
141 | Put an object in a bucket. |
142 | |
143 | @@ -318,7 +328,8 @@ |
144 | action="PUT", creds=self.creds, endpoint=self.endpoint, |
145 | bucket=bucket, object_name=object_name, data=data, |
146 | content_type=content_type, metadata=metadata, |
147 | - amz_headers=amz_headers) |
148 | + amz_headers=amz_headers, body_producer=body_producer, |
149 | + receiver_factory=self.receiver_factory) |
150 | return query.submit() |
151 | |
152 | def copy_object(self, source_bucket, source_object_name, dest_bucket=None, |
153 | @@ -344,7 +355,8 @@ |
154 | query = self.query_factory( |
155 | action="PUT", creds=self.creds, endpoint=self.endpoint, |
156 | bucket=dest_bucket, object_name=dest_object_name, |
157 | - metadata=metadata, amz_headers=amz_headers) |
158 | + metadata=metadata, amz_headers=amz_headers, |
159 | + receiver_factory=self.receiver_factory) |
160 | return query.submit() |
161 | |
162 | def get_object(self, bucket, object_name): |
163 | @@ -353,7 +365,8 @@ |
164 | """ |
165 | query = self.query_factory( |
166 | action="GET", creds=self.creds, endpoint=self.endpoint, |
167 | - bucket=bucket, object_name=object_name) |
168 | + bucket=bucket, object_name=object_name, |
169 | + receiver_factory=self.receiver_factory) |
170 | return query.submit() |
171 | |
172 | def head_object(self, bucket, object_name): |
173 | @@ -384,7 +397,8 @@ |
174 | data = access_control_policy.to_xml() |
175 | query = self.query_factory( |
176 | action='PUT', creds=self.creds, endpoint=self.endpoint, |
177 | - bucket=bucket, object_name='%s?acl' % object_name, data=data) |
178 | + bucket=bucket, object_name='%s?acl' % object_name, data=data, |
179 | + receiver_factory=self.receiver_factory) |
180 | return query.submit().addCallback(self._parse_acl) |
181 | |
182 | def get_object_acl(self, bucket, object_name): |
183 | @@ -393,7 +407,8 @@ |
184 | """ |
185 | query = self.query_factory( |
186 | action='GET', creds=self.creds, endpoint=self.endpoint, |
187 | - bucket=bucket, object_name='%s?acl' % object_name) |
188 | + bucket=bucket, object_name='%s?acl' % object_name, |
189 | + receiver_factory=self.receiver_factory) |
190 | return query.submit().addCallback(self._parse_acl) |
191 | |
192 | def put_request_payment(self, bucket, payer): |
193 | @@ -407,7 +422,8 @@ |
194 | data = RequestPayment(payer).to_xml() |
195 | query = self.query_factory( |
196 | action="PUT", creds=self.creds, endpoint=self.endpoint, |
197 | - bucket=bucket, object_name="?requestPayment", data=data) |
198 | + bucket=bucket, object_name="?requestPayment", data=data, |
199 | + receiver_factory=self.receiver_factory) |
200 | return query.submit() |
201 | |
202 | def get_request_payment(self, bucket): |
203 | @@ -419,7 +435,8 @@ |
204 | """ |
205 | query = self.query_factory( |
206 | action="GET", creds=self.creds, endpoint=self.endpoint, |
207 | - bucket=bucket, object_name="?requestPayment") |
208 | + bucket=bucket, object_name="?requestPayment", |
209 | + receiver_factory=self.receiver_factory) |
210 | return query.submit().addCallback(self._parse_get_request_payment) |
211 | |
212 | def _parse_get_request_payment(self, xml_bytes): |
213 | @@ -434,12 +451,13 @@ |
214 | """A query for submission to the S3 service.""" |
215 | |
216 | def __init__(self, bucket=None, object_name=None, data="", |
217 | - content_type=None, metadata={}, amz_headers={}, *args, |
218 | - **kwargs): |
219 | + content_type=None, metadata={}, amz_headers={}, |
220 | + body_producer=None, *args, **kwargs): |
221 | super(Query, self).__init__(*args, **kwargs) |
222 | self.bucket = bucket |
223 | self.object_name = object_name |
224 | self.data = data |
225 | + self.body_producer = body_producer |
226 | self.content_type = content_type |
227 | self.metadata = metadata |
228 | self.amz_headers = amz_headers |
229 | @@ -463,9 +481,14 @@ |
230 | """ |
231 | Build the list of headers needed in order to perform S3 operations. |
232 | """ |
233 | - headers = {"Content-Length": len(self.data), |
234 | - "Content-MD5": calculate_md5(self.data), |
235 | + if self.body_producer: |
236 | + content_length = self.body_producer.length |
237 | + else: |
238 | + content_length = len(self.data) |
239 | + headers = {"Content-Length": content_length, |
240 | "Date": self.date} |
241 | + if self.body_producer is None: |
242 | + headers["Content-MD5"] = calculate_md5(self.data) |
243 | for key, value in self.metadata.iteritems(): |
244 | headers["x-amz-meta-" + key] = value |
245 | for key, value in self.amz_headers.iteritems(): |
246 | @@ -529,5 +552,6 @@ |
247 | self.endpoint, self.bucket, self.object_name) |
248 | d = self.get_page( |
249 | url_context.get_url(), method=self.action, postdata=self.data, |
250 | - headers=self.get_headers()) |
251 | + headers=self.get_headers(), body_producer=self.body_producer, |
252 | + receiver_factory=self.receiver_factory) |
253 | return d.addErrback(s3_error_wrapper) |
254 | |
255 | === modified file 'txaws/s3/tests/test_client.py' |
256 | --- txaws/s3/tests/test_client.py 2012-01-28 00:44:53 +0000 |
257 | +++ txaws/s3/tests/test_client.py 2012-04-14 16:36:18 +0000 |
258 | @@ -10,6 +10,7 @@ |
259 | s3clientSkip = None |
260 | from txaws.s3.acls import AccessControlPolicy |
261 | from txaws.s3.model import RequestPayment |
262 | +from txaws.testing.producers import StringBodyProducer |
263 | from txaws.service import AWSServiceEndpoint |
264 | from txaws.testing import payload |
265 | from txaws.testing.base import TXAWSTestCase |
266 | @@ -100,7 +101,8 @@ |
267 | |
268 | class StubQuery(client.Query): |
269 | |
270 | - def __init__(query, action, creds, endpoint): |
271 | + def __init__(query, action, creds, endpoint, |
272 | + body_producer=None, receiver_factory=None): |
273 | super(StubQuery, query).__init__( |
274 | action=action, creds=creds) |
275 | self.assertEquals(action, "GET") |
276 | @@ -134,7 +136,8 @@ |
277 | |
278 | class StubQuery(client.Query): |
279 | |
280 | - def __init__(query, action, creds, endpoint, bucket=None): |
281 | + def __init__(query, action, creds, endpoint, bucket=None, |
282 | + body_producer=None, receiver_factory=None): |
283 | super(StubQuery, query).__init__( |
284 | action=action, creds=creds, bucket=bucket) |
285 | self.assertEquals(action, "PUT") |
286 | @@ -156,7 +159,8 @@ |
287 | |
288 | class StubQuery(client.Query): |
289 | |
290 | - def __init__(query, action, creds, endpoint, bucket=None): |
291 | + def __init__(query, action, creds, endpoint, bucket=None, |
292 | + body_producer=None, receiver_factory=None): |
293 | super(StubQuery, query).__init__( |
294 | action=action, creds=creds, bucket=bucket) |
295 | self.assertEquals(action, "GET") |
296 | @@ -208,7 +212,8 @@ |
297 | class StubQuery(client.Query): |
298 | |
299 | def __init__(query, action, creds, endpoint, bucket=None, |
300 | - object_name=None): |
301 | + object_name=None, body_producer=None, |
302 | + receiver_factory=None): |
303 | super(StubQuery, query).__init__(action=action, creds=creds, |
304 | bucket=bucket, |
305 | object_name=object_name) |
306 | @@ -243,7 +248,8 @@ |
307 | class StubQuery(client.Query): |
308 | |
309 | def __init__(query, action, creds, endpoint, bucket=None, |
310 | - object_name=None): |
311 | + object_name=None, body_producer=None, |
312 | + receiver_factory=None): |
313 | super(StubQuery, query).__init__(action=action, creds=creds, |
314 | bucket=bucket, |
315 | object_name=object_name) |
316 | @@ -284,7 +290,8 @@ |
317 | class StubQuery(client.Query): |
318 | |
319 | def __init__(query, action, creds, endpoint, bucket=None, |
320 | - object_name=None): |
321 | + object_name=None, body_producer=None, |
322 | + receiver_factory=None): |
323 | super(StubQuery, query).__init__(action=action, creds=creds, |
324 | bucket=bucket, |
325 | object_name=object_name) |
326 | @@ -323,7 +330,8 @@ |
327 | class StubQuery(client.Query): |
328 | |
329 | def __init__(query, action, creds, endpoint, bucket=None, |
330 | - object_name=None): |
331 | + object_name=None, body_producer=None, |
332 | + receiver_factory=None): |
333 | super(StubQuery, query).__init__(action=action, creds=creds, |
334 | bucket=bucket, |
335 | object_name=object_name) |
336 | @@ -360,7 +368,8 @@ |
337 | class StubQuery(client.Query): |
338 | |
339 | def __init__(query, action, creds, endpoint, bucket=None, |
340 | - object_name=None): |
341 | + object_name=None, body_producer=None, |
342 | + receiver_factory=None): |
343 | super(StubQuery, query).__init__(action=action, creds=creds, |
344 | bucket=bucket, |
345 | object_name=object_name) |
346 | @@ -396,7 +405,8 @@ |
347 | class StubQuery(client.Query): |
348 | |
349 | def __init__(query, action, creds, endpoint, bucket=None, |
350 | - object_name=None): |
351 | + object_name=None, body_producer=None, |
352 | + receiver_factory=None): |
353 | super(StubQuery, query).__init__(action=action, creds=creds, |
354 | bucket=bucket, |
355 | object_name=object_name) |
356 | @@ -433,7 +443,8 @@ |
357 | class StubQuery(client.Query): |
358 | |
359 | def __init__(query, action, creds, endpoint, bucket=None, |
360 | - object_name=None): |
361 | + object_name=None, body_producer=None, |
362 | + receiver_factory=None): |
363 | super(StubQuery, query).__init__(action=action, creds=creds, |
364 | bucket=bucket, |
365 | object_name=object_name) |
366 | @@ -473,7 +484,8 @@ |
367 | class StubQuery(client.Query): |
368 | |
369 | def __init__(query, action, creds, endpoint, bucket=None, |
370 | - object_name=None): |
371 | + object_name=None, body_producer=None, |
372 | + receiver_factory=None): |
373 | super(StubQuery, query).__init__(action=action, creds=creds, |
374 | bucket=bucket, |
375 | object_name=object_name) |
376 | @@ -509,7 +521,8 @@ |
377 | class StubQuery(client.Query): |
378 | |
379 | def __init__(query, action, creds, endpoint, bucket=None, |
380 | - object_name=None): |
381 | + object_name=None, body_producer=None, |
382 | + receiver_factory=None): |
383 | super(StubQuery, query).__init__(action=action, creds=creds, |
384 | bucket=bucket, |
385 | object_name=object_name) |
386 | @@ -546,7 +559,8 @@ |
387 | class StubQuery(client.Query): |
388 | |
389 | def __init__(query, action, creds, endpoint, bucket=None, |
390 | - object_name=None): |
391 | + object_name=None, body_producer=None, |
392 | + receiver_factory=None): |
393 | super(StubQuery, query).__init__(action=action, creds=creds, |
394 | bucket=bucket, |
395 | object_name=object_name) |
396 | @@ -576,7 +590,8 @@ |
397 | |
398 | class StubQuery(client.Query): |
399 | |
400 | - def __init__(query, action, creds, endpoint, bucket=None): |
401 | + def __init__(query, action, creds, endpoint, bucket=None, |
402 | + body_producer=None, receiver_factory=None): |
403 | super(StubQuery, query).__init__( |
404 | action=action, creds=creds, bucket=bucket) |
405 | self.assertEquals(action, "DELETE") |
406 | @@ -599,7 +614,8 @@ |
407 | class StubQuery(client.Query): |
408 | |
409 | def __init__(query, action, creds, endpoint, bucket=None, |
410 | - object_name=None, data=""): |
411 | + object_name=None, data="", body_producer=None, |
412 | + receiver_factory=None): |
413 | super(StubQuery, query).__init__(action=action, creds=creds, |
414 | bucket=bucket, |
415 | object_name=object_name, |
416 | @@ -630,7 +646,8 @@ |
417 | class StubQuery(client.Query): |
418 | |
419 | def __init__(query, action, creds, endpoint, bucket=None, |
420 | - object_name=None, data=""): |
421 | + object_name=None, data="", receiver_factory=None, |
422 | + body_producer=None): |
423 | super(StubQuery, query).__init__(action=action, creds=creds, |
424 | bucket=bucket, |
425 | object_name=object_name, |
426 | @@ -665,7 +682,7 @@ |
427 | |
428 | def __init__(query, action, creds, endpoint, bucket=None, |
429 | object_name=None, data=None, content_type=None, |
430 | - metadata=None): |
431 | + metadata=None, body_producer=None, receiver_factory=None): |
432 | super(StubQuery, query).__init__( |
433 | action=action, creds=creds, bucket=bucket, |
434 | object_name=object_name, data=data, |
435 | @@ -701,7 +718,7 @@ |
436 | |
437 | def __init__(query, action, creds, endpoint, bucket=None, |
438 | object_name=None, data=None, content_type=None, |
439 | - metadata=None): |
440 | + metadata=None, body_producer=None, receiver_factory=None): |
441 | super(StubQuery, query).__init__( |
442 | action=action, creds=creds, bucket=bucket, |
443 | object_name=object_name, data=data, |
444 | @@ -730,7 +747,8 @@ |
445 | |
446 | def __init__(query, action, creds, endpoint, bucket=None, |
447 | object_name=None, data=None, content_type=None, |
448 | - metadata=None, amz_headers=None): |
449 | + metadata=None, amz_headers=None, body_producer=None, |
450 | + receiver_factory=None): |
451 | super(StubQuery, query).__init__( |
452 | action=action, creds=creds, bucket=bucket, |
453 | object_name=object_name, data=data, |
454 | @@ -756,6 +774,42 @@ |
455 | metadata={"key": "some meta data"}, |
456 | amz_headers={"acl": "public-read"}) |
457 | |
458 | + def test_put_object_with_custom_body_producer(self): |
459 | + |
460 | + class StubQuery(client.Query): |
461 | + |
462 | + def __init__(query, action, creds, endpoint, bucket=None, |
463 | + object_name=None, data=None, content_type=None, |
464 | + metadata=None, amz_headers=None, body_producer=None, |
465 | + receiver_factory=None): |
466 | + super(StubQuery, query).__init__( |
467 | + action=action, creds=creds, bucket=bucket, |
468 | + object_name=object_name, data=data, |
469 | + content_type=content_type, metadata=metadata, |
470 | + amz_headers=amz_headers, body_producer=body_producer) |
471 | + self.assertEqual(action, "PUT") |
472 | + self.assertEqual(creds.access_key, "foo") |
473 | + self.assertEqual(creds.secret_key, "bar") |
474 | + self.assertEqual(query.bucket, "mybucket") |
475 | + self.assertEqual(query.object_name, "objectname") |
476 | + self.assertEqual(query.content_type, "text/plain") |
477 | + self.assertEqual(query.metadata, {"key": "some meta data"}) |
478 | + self.assertEqual(query.amz_headers, {"acl": "public-read"}) |
479 | + self.assertIdentical(body_producer, string_producer) |
480 | + |
481 | + def submit(query): |
482 | + return succeed(None) |
483 | + |
484 | + |
485 | + string_producer = StringBodyProducer("some data") |
486 | + creds = AWSCredentials("foo", "bar") |
487 | + s3 = client.S3Client(creds, query_factory=StubQuery) |
488 | + return s3.put_object("mybucket", "objectname", |
489 | + content_type="text/plain", |
490 | + metadata={"key": "some meta data"}, |
491 | + amz_headers={"acl": "public-read"}, |
492 | + body_producer=string_producer) |
493 | + |
494 | def test_copy_object(self): |
495 | """ |
496 | L{S3Client.copy_object} creates a L{Query} to copy an object from one |
497 | @@ -766,7 +820,8 @@ |
498 | |
499 | def __init__(query, action, creds, endpoint, bucket=None, |
500 | object_name=None, data=None, content_type=None, |
501 | - metadata=None, amz_headers=None): |
502 | + metadata=None, amz_headers=None, body_producer=None, |
503 | + receiver_factory=None): |
504 | super(StubQuery, query).__init__( |
505 | action=action, creds=creds, bucket=bucket, |
506 | object_name=object_name, data=data, |
507 | @@ -798,7 +853,8 @@ |
508 | |
509 | def __init__(query, action, creds, endpoint, bucket=None, |
510 | object_name=None, data=None, content_type=None, |
511 | - metadata=None, amz_headers=None): |
512 | + metadata=None, amz_headers=None, body_producer=None, |
513 | + receiver_factory=None): |
514 | super(StubQuery, query).__init__( |
515 | action=action, creds=creds, bucket=bucket, |
516 | object_name=object_name, data=data, |
517 | @@ -822,7 +878,7 @@ |
518 | |
519 | def __init__(query, action, creds, endpoint, bucket=None, |
520 | object_name=None, data=None, content_type=None, |
521 | - metadata=None): |
522 | + metadata=None, body_producer=None, receiver_factory=None): |
523 | super(StubQuery, query).__init__( |
524 | action=action, creds=creds, bucket=bucket, |
525 | object_name=object_name, data=data, |
526 | @@ -846,7 +902,7 @@ |
527 | |
528 | def __init__(query, action, creds, endpoint, bucket=None, |
529 | object_name=None, data=None, content_type=None, |
530 | - metadata=None): |
531 | + metadata=None, body_producer=None, receiver_factory=None): |
532 | super(StubQuery, query).__init__( |
533 | action=action, creds=creds, bucket=bucket, |
534 | object_name=object_name, data=data, |
535 | @@ -869,7 +925,8 @@ |
536 | class StubQuery(client.Query): |
537 | |
538 | def __init__(query, action, creds, endpoint, bucket=None, |
539 | - object_name=None, data=""): |
540 | + object_name=None, data="", body_producer=None, |
541 | + receiver_factory=None): |
542 | super(StubQuery, query).__init__(action=action, creds=creds, |
543 | bucket=bucket, |
544 | object_name=object_name, |
545 | @@ -902,7 +959,8 @@ |
546 | class StubQuery(client.Query): |
547 | |
548 | def __init__(query, action, creds, endpoint, bucket=None, |
549 | - object_name=None, data=""): |
550 | + object_name=None, data="", body_producer=None, |
551 | + receiver_factory=None): |
552 | super(StubQuery, query).__init__(action=action, creds=creds, |
553 | bucket=bucket, |
554 | object_name=object_name, |
555 | @@ -1077,7 +1135,8 @@ |
556 | """ |
557 | class StubQuery(client.Query): |
558 | |
559 | - def __init__(query, action, creds, endpoint, bucket): |
560 | + def __init__(query, action, creds, endpoint, bucket, |
561 | + body_producer=None, receiver_factory=None): |
562 | super(StubQuery, query).__init__( |
563 | action=action, creds=creds, bucket=bucket) |
564 | self.assertEquals(action, "GET") |
This change looks good to me at first glance (reading the diff on the merge proposal; I haven't branched the code yet). In particular, the amz_headers functionality is much-needed.
Drew, I don't see anything about the new web client usage, only headers and body producer. Is that coming in a future change?
At the risk of being a total pain in the ass, here's what I would recommend:
1) split out the headers changes into a new branch, and attach it to bug #972432.
2) create a new bug for the body producer/receiver factory feature, split that code out, and attach it to there in its own branch.
3) do the work on the new agent in this branch and this ticket (bug #767205).