Merge lp:~jameinel/bzr/2.1.0b2-471193-st-and-chk-map into lp:bzr
- 2.1.0b2-471193-st-and-chk-map
- Merge into bzr.dev
Proposed by
John A Meinel
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | not available | ||||
Proposed branch: | lp:~jameinel/bzr/2.1.0b2-471193-st-and-chk-map | ||||
Merge into: | lp:bzr | ||||
Diff against target: |
565 lines 10 files modified
NEWS (+12/-3) bzrlib/chk_map.py (+3/-3) bzrlib/help_topics/en/debug-flags.txt (+1/-0) bzrlib/plugins/launchpad/__init__.py (+12/-23) bzrlib/plugins/launchpad/lp_registration.py (+25/-4) bzrlib/plugins/launchpad/test_lp_directory.py (+144/-1) bzrlib/static_tuple.py (+17/-0) bzrlib/tests/test__static_tuple.py (+26/-0) bzrlib/tests/test_http.py (+55/-1) bzrlib/transport/http/_urllib2_wrappers.py (+19/-7) |
||||
To merge this branch: | bzr merge lp:~jameinel/bzr/2.1.0b2-471193-st-and-chk-map | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vincent Ladeuil | Approve | ||
Review via email: mp+14309@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote : | # |
Revision history for this message
Vincent Ladeuil (vila) wrote : | # |
Don't forget to land in 2.1.0b2 and not bzr.dev !
The long term intent being to get rid of expect_
please say so in the doc string.
Also, you may want to mail bzr.dev users about setting the flag in their bazaar.conf
debug_flags defaults.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'NEWS' |
2 | --- NEWS 2009-11-01 05:41:57 +0000 |
3 | +++ NEWS 2009-11-02 18:26:13 +0000 |
4 | @@ -101,9 +101,10 @@ |
5 | |
6 | Key highlights in this release are: improved handling of |
7 | failures-during-cleanup for commit, fixing a long-standing bug with |
8 | -``bzr+http`` and shared repositories, and a new StaticTuple datatype, |
9 | -allowing us to reduce memory consumption (50%) and garbage collector |
10 | -overhead (40% faster) for many operations. |
11 | +``bzr+http`` and shared repositories, all ``lp:`` urls to be resolved |
12 | +behind proxies, and a new StaticTuple datatype, allowing us to reduce |
13 | +memory consumption (50%) and garbage collector overhead (40% faster) for |
14 | +many operations. |
15 | |
16 | Bug Fixes |
17 | ********* |
18 | @@ -116,6 +117,14 @@ |
19 | they do occur. This fixes some causes of ``TooManyConcurrentRequests`` |
20 | and similar errors. (Andrew Bennetts, #429747, #243391) |
21 | |
22 | +* Launchpad urls can now be resolved from behind proxies. |
23 | + (Gordon Tyler, Vincent Ladeuil, #198920) |
24 | + |
25 | +* Reduce the strictness for StaticTuple, instead add a debug flag |
26 | + ``-Dstatic_tuple`` which will change apis to be strict and raise errors. |
27 | + This way, most users won't see failures, but developers can improve |
28 | + internals. (John Arbash Meinel, #471193) |
29 | + |
30 | * TreeTransform.adjust_path updates the limbo paths of descendants of adjusted |
31 | files. (Aaron Bentley) |
32 | |
33 | |
34 | === modified file 'bzrlib/chk_map.py' |
35 | --- bzrlib/chk_map.py 2009-10-23 18:46:03 +0000 |
36 | +++ bzrlib/chk_map.py 2009-11-02 18:26:13 +0000 |
37 | @@ -50,6 +50,7 @@ |
38 | lru_cache, |
39 | osutils, |
40 | registry, |
41 | + static_tuple, |
42 | trace, |
43 | ) |
44 | from bzrlib.static_tuple import StaticTuple |
45 | @@ -720,6 +721,7 @@ |
46 | :param bytes: The bytes of the node. |
47 | :param key: The key that the serialised node has. |
48 | """ |
49 | + key = static_tuple.expect_static_tuple(key) |
50 | return _deserialise_leaf_node(bytes, key, |
51 | search_key_func=search_key_func) |
52 | |
53 | @@ -1018,9 +1020,7 @@ |
54 | :param key: The key that the serialised node has. |
55 | :return: An InternalNode instance. |
56 | """ |
57 | - if type(key) is not StaticTuple: |
58 | - raise AssertionError('deserialise should be called with a' |
59 | - ' StaticTuple not %s' % (type(key),)) |
60 | + key = static_tuple.expect_static_tuple(key) |
61 | return _deserialise_internal_node(bytes, key, |
62 | search_key_func=search_key_func) |
63 | |
64 | |
65 | === modified file 'bzrlib/help_topics/en/debug-flags.txt' |
66 | --- bzrlib/help_topics/en/debug-flags.txt 2009-10-07 08:19:19 +0000 |
67 | +++ bzrlib/help_topics/en/debug-flags.txt 2009-11-02 18:26:13 +0000 |
68 | @@ -30,6 +30,7 @@ |
69 | -Drelock Emit a message every time a branch or repository object is |
70 | unlocked then relocked the same way. |
71 | -Dsftp Trace SFTP internals. |
72 | +-Dstatic_tuple Error when a tuple is used where a StaticTuple is expected |
73 | -Dstream Trace fetch streams. |
74 | -Dstrict_locks Trace when OS locks are potentially used in a non-portable |
75 | manner. |
76 | |
77 | === modified file 'bzrlib/plugins/launchpad/__init__.py' |
78 | --- bzrlib/plugins/launchpad/__init__.py 2009-07-06 13:00:23 +0000 |
79 | +++ bzrlib/plugins/launchpad/__init__.py 2009-11-02 18:26:13 +0000 |
80 | @@ -262,30 +262,19 @@ |
81 | _register_directory() |
82 | |
83 | |
84 | -def test_suite(): |
85 | - """Called by bzrlib to fetch tests for this plugin""" |
86 | - from unittest import TestSuite, TestLoader |
87 | - from bzrlib.plugins.launchpad import ( |
88 | - test_account, |
89 | - test_lp_directory, |
90 | - test_lp_login, |
91 | - test_lp_open, |
92 | - test_lp_service, |
93 | - test_register, |
94 | - ) |
95 | +def load_tests(basic_tests, module, loader): |
96 | + testmod_names = [ |
97 | + 'test_account', |
98 | + 'test_register', |
99 | + 'test_lp_directory', |
100 | + 'test_lp_login', |
101 | + 'test_lp_open', |
102 | + 'test_lp_service', |
103 | + ] |
104 | + basic_tests.addTest(loader.loadTestsFromModuleNames( |
105 | + ["%s.%s" % (__name__, tmn) for tmn in testmod_names])) |
106 | + return basic_tests |
107 | |
108 | - loader = TestLoader() |
109 | - suite = TestSuite() |
110 | - for module in [ |
111 | - test_account, |
112 | - test_register, |
113 | - test_lp_directory, |
114 | - test_lp_login, |
115 | - test_lp_open, |
116 | - test_lp_service, |
117 | - ]: |
118 | - suite.addTests(loader.loadTestsFromModule(module)) |
119 | - return suite |
120 | |
121 | _launchpad_help = """Integration with Launchpad.net |
122 | |
123 | |
124 | === modified file 'bzrlib/plugins/launchpad/lp_registration.py' |
125 | --- bzrlib/plugins/launchpad/lp_registration.py 2009-07-04 16:22:16 +0000 |
126 | +++ bzrlib/plugins/launchpad/lp_registration.py 2009-11-02 18:26:13 +0000 |
127 | @@ -31,6 +31,7 @@ |
128 | errors, |
129 | __version__ as _bzrlib_version, |
130 | ) |
131 | +from bzrlib.transport.http import _urllib2_wrappers |
132 | |
133 | # for testing, do |
134 | ''' |
135 | @@ -53,6 +54,29 @@ |
136 | errors.BzrError.__init__(self, url=url) |
137 | |
138 | |
139 | +class XMLRPCTransport(xmlrpclib.Transport): |
140 | + |
141 | + def __init__(self, scheme, use_datetime=0): |
142 | + xmlrpclib.Transport.__init__(self, use_datetime=use_datetime) |
143 | + self._scheme = scheme |
144 | + self._opener = _urllib2_wrappers.Opener() |
145 | + self.verbose = 0 |
146 | + |
147 | + def request(self, host, handler, request_body, verbose=0): |
148 | + self.verbose = verbose |
149 | + url = self._scheme + "://" + host + handler |
150 | + request = _urllib2_wrappers.Request("POST", url, request_body) |
151 | + # FIXME: _urllib2_wrappers will override user-agent with its own |
152 | + # request.add_header("User-Agent", self.user_agent) |
153 | + request.add_header("Content-Type", "text/xml") |
154 | + |
155 | + response = self._opener.open(request) |
156 | + if response.code != 200: |
157 | + raise xmlrpclib.ProtocolError(host + handler, response.code, |
158 | + response.msg, response.info()) |
159 | + return self.parse_response(response) |
160 | + |
161 | + |
162 | class LaunchpadService(object): |
163 | """A service to talk to Launchpad via XMLRPC. |
164 | |
165 | @@ -90,10 +114,7 @@ |
166 | self._lp_instance = lp_instance |
167 | if transport is None: |
168 | uri_type = urllib.splittype(self.service_url)[0] |
169 | - if uri_type == 'https': |
170 | - transport = xmlrpclib.SafeTransport() |
171 | - else: |
172 | - transport = xmlrpclib.Transport() |
173 | + transport = XMLRPCTransport(uri_type) |
174 | transport.user_agent = 'bzr/%s (xmlrpclib/%s)' \ |
175 | % (_bzrlib_version, xmlrpclib.__version__) |
176 | self.transport = transport |
177 | |
178 | === modified file 'bzrlib/plugins/launchpad/test_lp_directory.py' |
179 | --- bzrlib/plugins/launchpad/test_lp_directory.py 2009-03-23 14:59:43 +0000 |
180 | +++ bzrlib/plugins/launchpad/test_lp_directory.py 2009-11-02 18:26:13 +0000 |
181 | @@ -16,10 +16,12 @@ |
182 | |
183 | """Tests for directory lookup through Launchpad.net""" |
184 | |
185 | +import os |
186 | import xmlrpclib |
187 | |
188 | from bzrlib import ( |
189 | errors, |
190 | + tests, |
191 | ) |
192 | from bzrlib.branch import Branch |
193 | from bzrlib.directory_service import directories |
194 | @@ -28,10 +30,38 @@ |
195 | TestCaseWithMemoryTransport |
196 | ) |
197 | from bzrlib.transport import get_transport |
198 | -from bzrlib.plugins.launchpad import _register_directory |
199 | +from bzrlib.plugins.launchpad import ( |
200 | + _register_directory, |
201 | + lp_registration, |
202 | + ) |
203 | from bzrlib.plugins.launchpad.lp_directory import ( |
204 | LaunchpadDirectory) |
205 | from bzrlib.plugins.launchpad.account import get_lp_login |
206 | +from bzrlib.tests import ( |
207 | + http_server, |
208 | + http_utils, |
209 | + ) |
210 | + |
211 | + |
212 | +def load_tests(standard_tests, module, loader): |
213 | + result = loader.suiteClass() |
214 | + t_tests, remaining_tests = tests.split_suite_by_condition( |
215 | + standard_tests, tests.condition_isinstance(( |
216 | + TestXMLRPCTransport, |
217 | + ))) |
218 | + transport_scenarios = [ |
219 | + ('http', dict(server_class=PreCannedHTTPServer,)), |
220 | + ] |
221 | + if tests.HTTPSServerFeature.available(): |
222 | + transport_scenarios.append( |
223 | + ('https', dict(server_class=PreCannedHTTPSServer,)), |
224 | + ) |
225 | + tests.multiply_tests(t_tests, transport_scenarios, result) |
226 | + |
227 | + # No parametrization for the remaining tests |
228 | + result.addTests(remaining_tests) |
229 | + |
230 | + return result |
231 | |
232 | |
233 | class FakeResolveFactory(object): |
234 | @@ -190,3 +220,116 @@ |
235 | transport = get_transport('lp:///apt') |
236 | branch = Branch.open_from_transport(transport) |
237 | self.assertEqual(target_branch.base, branch.base) |
238 | + |
239 | + |
240 | +class PredefinedRequestHandler(http_server.TestingHTTPRequestHandler): |
241 | + """Request handler for a unique and pre-defined request. |
242 | + |
243 | + The only thing we care about here is that we receive a connection. But |
244 | + since we want to dialog with a real http client, we have to send it correct |
245 | + responses. |
246 | + |
247 | + We expect to receive a *single* request nothing more (and we won't even |
248 | + check what request it is), the tests will recognize us from our response. |
249 | + """ |
250 | + |
251 | + def handle_one_request(self): |
252 | + tcs = self.server.test_case_server |
253 | + requestline = self.rfile.readline() |
254 | + headers = self.MessageClass(self.rfile, 0) |
255 | + if requestline.startswith('POST'): |
256 | + # The body should be a single line (or we don't know where it ends |
257 | + # and we don't want to issue a blocking read) |
258 | + body = self.rfile.readline() |
259 | + |
260 | + self.wfile.write(tcs.canned_response) |
261 | + |
262 | + |
263 | +class PreCannedServerMixin(object): |
264 | + |
265 | + def __init__(self): |
266 | + super(PreCannedServerMixin, self).__init__( |
267 | + request_handler=PredefinedRequestHandler) |
268 | + # Bytes read and written by the server |
269 | + self.bytes_read = 0 |
270 | + self.bytes_written = 0 |
271 | + self.canned_response = None |
272 | + |
273 | + |
274 | +class PreCannedHTTPServer(PreCannedServerMixin, http_server.HttpServer): |
275 | + pass |
276 | + |
277 | + |
278 | +if tests.HTTPSServerFeature.available(): |
279 | + from bzrlib.tests import https_server |
280 | + class PreCannedHTTPSServer(PreCannedServerMixin, https_server.HTTPSServer): |
281 | + pass |
282 | + |
283 | + |
284 | +class TestXMLRPCTransport(tests.TestCase): |
285 | + |
286 | + # set by load_tests |
287 | + server_class = None |
288 | + |
289 | + def setUp(self): |
290 | + tests.TestCase.setUp(self) |
291 | + self.server = self.server_class() |
292 | + self.server.setUp() |
293 | + # Ensure we don't clobber env |
294 | + self._captureVar('BZR_LP_XMLRPC_URL', None) |
295 | + |
296 | + def tearDown(self): |
297 | + self.server.tearDown() |
298 | + tests.TestCase.tearDown(self) |
299 | + |
300 | + def set_canned_response(self, server, path): |
301 | + response_format = '''HTTP/1.1 200 OK\r |
302 | +Date: Tue, 11 Jul 2006 04:32:56 GMT\r |
303 | +Server: Apache/2.0.54 (Fedora)\r |
304 | +Last-Modified: Sun, 23 Apr 2006 19:35:20 GMT\r |
305 | +ETag: "56691-23-38e9ae00"\r |
306 | +Accept-Ranges: bytes\r |
307 | +Content-Length: %(length)d\r |
308 | +Connection: close\r |
309 | +Content-Type: text/plain; charset=UTF-8\r |
310 | +\r |
311 | +<?xml version='1.0'?> |
312 | +<methodResponse> |
313 | +<params> |
314 | +<param> |
315 | +<value><struct> |
316 | +<member> |
317 | +<name>urls</name> |
318 | +<value><array><data> |
319 | +<value><string>bzr+ssh://bazaar.launchpad.net/%(path)s</string></value> |
320 | +<value><string>http://bazaar.launchpad.net/%(path)s</string></value> |
321 | +</data></array></value> |
322 | +</member> |
323 | +</struct></value> |
324 | +</param> |
325 | +</params> |
326 | +</methodResponse> |
327 | +''' |
328 | + length = 334 + 2 * len(path) |
329 | + server.canned_response = response_format % dict(length=length, |
330 | + path=path) |
331 | + |
332 | + def do_request(self, server_url): |
333 | + os.environ['BZR_LP_XMLRPC_URL'] = self.server.get_url() |
334 | + service = lp_registration.LaunchpadService() |
335 | + resolve = lp_registration.ResolveLaunchpadPathRequest('bzr') |
336 | + result = resolve.submit(service) |
337 | + return result |
338 | + |
339 | + def test_direct_request(self): |
340 | + self.set_canned_response(self.server, '~bzr-pqm/bzr/bzr.dev') |
341 | + result = self.do_request(self.server.get_url()) |
342 | + urls = result.get('urls', None) |
343 | + self.assertIsNot(None, urls) |
344 | + self.assertEquals( |
345 | + ['bzr+ssh://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev', |
346 | + 'http://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev'], |
347 | + urls) |
348 | + # FIXME: we need to test with a real proxy, I can't find a way so simulate |
349 | + # CONNECT without leaving one server hanging the test :-/ Since that maybe |
350 | + # related to the leaking tests problems, I'll punt for now -- vila 20091030 |
351 | |
352 | === modified file 'bzrlib/static_tuple.py' |
353 | --- bzrlib/static_tuple.py 2009-10-12 20:02:27 +0000 |
354 | +++ bzrlib/static_tuple.py 2009-11-02 18:26:13 +0000 |
355 | @@ -16,6 +16,8 @@ |
356 | |
357 | """Interface thunk for a StaticTuple implementation.""" |
358 | |
359 | +from bzrlib import debug |
360 | + |
361 | try: |
362 | from bzrlib._static_tuple_c import StaticTuple |
363 | except ImportError, e: |
364 | @@ -23,3 +25,18 @@ |
365 | osutils.failed_to_load_extension(e) |
366 | from bzrlib._static_tuple_py import StaticTuple |
367 | |
368 | + |
369 | +def expect_static_tuple(obj): |
370 | + """Check if the passed object is a StaticTuple. |
371 | + |
372 | + Cast it if necessary, but if the 'static_tuple' debug flag is set, raise an |
373 | + error instead. |
374 | + |
375 | + As apis are improved, we will probably eventually stop calling this as it |
376 | + adds overhead we shouldn't need. |
377 | + """ |
378 | + if 'static_tuple' not in debug.debug_flags: |
379 | + return StaticTuple.from_sequence(obj) |
380 | + if type(obj) is not StaticTuple: |
381 | + raise TypeError('We expected a StaticTuple not a %s' % (type(obj),)) |
382 | + return obj |
383 | |
384 | === modified file 'bzrlib/tests/test__static_tuple.py' |
385 | --- bzrlib/tests/test__static_tuple.py 2009-10-27 14:07:16 +0000 |
386 | +++ bzrlib/tests/test__static_tuple.py 2009-11-02 18:26:13 +0000 |
387 | @@ -22,6 +22,7 @@ |
388 | |
389 | from bzrlib import ( |
390 | _static_tuple_py, |
391 | + debug, |
392 | errors, |
393 | osutils, |
394 | static_tuple, |
395 | @@ -620,3 +621,28 @@ |
396 | return |
397 | self.assertIs(static_tuple.StaticTuple, |
398 | self.module.StaticTuple) |
399 | + |
400 | + |
401 | +class TestEnsureStaticTuple(tests.TestCase): |
402 | + |
403 | + def test_is_static_tuple(self): |
404 | + st = static_tuple.StaticTuple('foo') |
405 | + st2 = static_tuple.expect_static_tuple(st) |
406 | + self.assertIs(st, st2) |
407 | + |
408 | + def test_is_tuple(self): |
409 | + t = ('foo',) |
410 | + st = static_tuple.expect_static_tuple(t) |
411 | + self.assertIsInstance(st, static_tuple.StaticTuple) |
412 | + self.assertEqual(t, st) |
413 | + |
414 | + def test_flagged_is_static_tuple(self): |
415 | + debug.debug_flags.add('static_tuple') |
416 | + st = static_tuple.StaticTuple('foo') |
417 | + st2 = static_tuple.expect_static_tuple(st) |
418 | + self.assertIs(st, st2) |
419 | + |
420 | + def test_flagged_is_tuple(self): |
421 | + debug.debug_flags.add('static_tuple') |
422 | + t = ('foo',) |
423 | + self.assertRaises(TypeError, static_tuple.expect_static_tuple, t) |
424 | |
425 | === modified file 'bzrlib/tests/test_http.py' |
426 | --- bzrlib/tests/test_http.py 2009-09-17 11:54:41 +0000 |
427 | +++ bzrlib/tests/test_http.py 2009-11-02 18:26:13 +0000 |
428 | @@ -1956,7 +1956,7 @@ |
429 | pass |
430 | |
431 | |
432 | -class TestActivity(tests.TestCase): |
433 | +class TestActivityMixin(object): |
434 | """Test socket activity reporting. |
435 | |
436 | We use a special purpose server to control the bytes sent and received and |
437 | @@ -2100,3 +2100,57 @@ |
438 | code, f = t._post('abc def end-of-body\n') |
439 | self.assertEqual('lalala whatever as long as itsssss\n', f.read()) |
440 | self.assertActivitiesMatch() |
441 | + |
442 | + |
443 | +class TestActivity(tests.TestCase, TestActivityMixin): |
444 | + |
445 | + def setUp(self): |
446 | + tests.TestCase.setUp(self) |
447 | + self.server = self._activity_server(self._protocol_version) |
448 | + self.server.setUp() |
449 | + self.activities = {} |
450 | + def report_activity(t, bytes, direction): |
451 | + count = self.activities.get(direction, 0) |
452 | + count += bytes |
453 | + self.activities[direction] = count |
454 | + |
455 | + # We override at class level because constructors may propagate the |
456 | + # bound method and render instance overriding ineffective (an |
457 | + # alternative would be to define a specific ui factory instead...) |
458 | + self.orig_report_activity = self._transport._report_activity |
459 | + self._transport._report_activity = report_activity |
460 | + |
461 | + def tearDown(self): |
462 | + self._transport._report_activity = self.orig_report_activity |
463 | + self.server.tearDown() |
464 | + tests.TestCase.tearDown(self) |
465 | + |
466 | + |
467 | +class TestNoReportActivity(tests.TestCase, TestActivityMixin): |
468 | + |
469 | + def setUp(self): |
470 | + tests.TestCase.setUp(self) |
471 | + # Unlike TestActivity, we are really testing ReportingFileSocket and |
472 | + # ReportingSocket, so we don't need all the parametrization. Since |
473 | + # ReportingFileSocket and ReportingSocket are wrappers, it's easier to |
474 | + # test them through their use by the transport than directly (that's a |
475 | + # bit less clean but far more simpler and effective). |
476 | + self.server = ActivityHTTPServer('HTTP/1.1') |
477 | + self._transport=_urllib.HttpTransport_urllib |
478 | + |
479 | + self.server.setUp() |
480 | + |
481 | + # We override at class level because constructors may propagate the |
482 | + # bound method and render instance overriding ineffective (an |
483 | + # alternative would be to define a specific ui factory instead...) |
484 | + self.orig_report_activity = self._transport._report_activity |
485 | + self._transport._report_activity = None |
486 | + |
487 | + def tearDown(self): |
488 | + self._transport._report_activity = self.orig_report_activity |
489 | + self.server.tearDown() |
490 | + tests.TestCase.tearDown(self) |
491 | + |
492 | + def assertActivitiesMatch(self): |
493 | + # Nothing to check here |
494 | + pass |
495 | |
496 | === modified file 'bzrlib/transport/http/_urllib2_wrappers.py' |
497 | --- bzrlib/transport/http/_urllib2_wrappers.py 2009-08-19 16:33:39 +0000 |
498 | +++ bzrlib/transport/http/_urllib2_wrappers.py 2009-11-02 18:26:13 +0000 |
499 | @@ -80,10 +80,13 @@ |
500 | self.filesock = filesock |
501 | self._report_activity = report_activity |
502 | |
503 | + def report_activity(self, size, direction): |
504 | + if self._report_activity: |
505 | + self._report_activity(size, direction) |
506 | |
507 | def read(self, size=1): |
508 | s = self.filesock.read(size) |
509 | - self._report_activity(len(s), 'read') |
510 | + self.report_activity(len(s), 'read') |
511 | return s |
512 | |
513 | def readline(self): |
514 | @@ -93,7 +96,7 @@ |
515 | # don't *need* the size parameter we'll stay with readline(self) |
516 | # -- vila 20090209 |
517 | s = self.filesock.readline() |
518 | - self._report_activity(len(s), 'read') |
519 | + self.report_activity(len(s), 'read') |
520 | return s |
521 | |
522 | def __getattr__(self, name): |
523 | @@ -106,13 +109,17 @@ |
524 | self.sock = sock |
525 | self._report_activity = report_activity |
526 | |
527 | + def report_activity(self, size, direction): |
528 | + if self._report_activity: |
529 | + self._report_activity(size, direction) |
530 | + |
531 | def sendall(self, s, *args): |
532 | self.sock.sendall(s, *args) |
533 | - self._report_activity(len(s), 'write') |
534 | + self.report_activity(len(s), 'write') |
535 | |
536 | def recv(self, *args): |
537 | s = self.sock.recv(*args) |
538 | - self._report_activity(len(s), 'read') |
539 | + self.report_activity(len(s), 'read') |
540 | return s |
541 | |
542 | def makefile(self, mode='r', bufsize=-1): |
543 | @@ -219,8 +226,7 @@ |
544 | # we want to warn. But not below a given thresold. |
545 | _range_warning_thresold = 1024 * 1024 |
546 | |
547 | - def __init__(self, |
548 | - report_activity=None): |
549 | + def __init__(self, report_activity=None): |
550 | self._response = None |
551 | self._report_activity = report_activity |
552 | self._ranges_received_whole_file = None |
553 | @@ -360,7 +366,13 @@ |
554 | |
555 | def set_proxy(self, proxy, type): |
556 | """Set the proxy and remember the proxied host.""" |
557 | - self.proxied_host = self.get_host() |
558 | + # We need to set the default port ourselves way before it gets set |
559 | + # in the HTTP[S]Connection object at build time. |
560 | + if self.type == 'https': |
561 | + conn_class = HTTPSConnection |
562 | + else: |
563 | + conn_class = HTTPConnection |
564 | + self.proxied_host = '%s:%s' % (self.get_host(), conn_class.default_port) |
565 | urllib2.Request.set_proxy(self, proxy, type) |
566 | |
567 |
This fixes a critical bug for the 2.1.0b2 series.
Basically, there are some code paths by-which regular tuples can end up where we may not want them. We *could* change all of our apis to auto-cast, but that will end up negating the performance advantage. (As then you have 2 objects a tuple *and* a StaticTuple, referring to the same things.)
However, we need a migration strategy. So for now, I'm adding a debug flag that I can set, similar to '-Dhpss'. When set, I chose to cause an exception rather than just printing a traceback. We can change our minds later.