Merge "Enhance put_object to inform when chunk is ignored"
This commit is contained in:
commit
4f57f815b3
@ -21,6 +21,7 @@ import socket
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
import warnings
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from urllib import quote as _quote
|
from urllib import quote as _quote
|
||||||
@ -764,7 +765,7 @@ def head_object(url, token, container, name, http_conn=None):
|
|||||||
|
|
||||||
|
|
||||||
def put_object(url, token=None, container=None, name=None, contents=None,
|
def put_object(url, token=None, container=None, name=None, contents=None,
|
||||||
content_length=None, etag=None, chunk_size=65536,
|
content_length=None, etag=None, chunk_size=None,
|
||||||
content_type=None, headers=None, http_conn=None, proxy=None):
|
content_type=None, headers=None, http_conn=None, proxy=None):
|
||||||
"""
|
"""
|
||||||
Put an object
|
Put an object
|
||||||
@ -782,7 +783,9 @@ def put_object(url, token=None, container=None, name=None, contents=None,
|
|||||||
computed via the contents or chunked transfer
|
computed via the contents or chunked transfer
|
||||||
encoding will be used
|
encoding will be used
|
||||||
:param etag: etag of contents; if None, no etag will be sent
|
:param etag: etag of contents; if None, no etag will be sent
|
||||||
:param chunk_size: chunk size of data to write; default 65536
|
:param chunk_size: chunk size of data to write; it defaults to 65536;
|
||||||
|
used only if the the contents object has a 'read'
|
||||||
|
method, eg. file-like objects, ignored otherwise
|
||||||
:param content_type: value to send as content-type header; if None, no
|
:param content_type: value to send as content-type header; if None, no
|
||||||
content-type will be set (remote end will likely try
|
content-type will be set (remote end will likely try
|
||||||
to auto-detect it)
|
to auto-detect it)
|
||||||
@ -822,6 +825,8 @@ def put_object(url, token=None, container=None, name=None, contents=None,
|
|||||||
if not contents:
|
if not contents:
|
||||||
headers['Content-Length'] = '0'
|
headers['Content-Length'] = '0'
|
||||||
if hasattr(contents, 'read'):
|
if hasattr(contents, 'read'):
|
||||||
|
if chunk_size is None:
|
||||||
|
chunk_size = 65536
|
||||||
conn.putrequest('PUT', path)
|
conn.putrequest('PUT', path)
|
||||||
for header, value in headers.iteritems():
|
for header, value in headers.iteritems():
|
||||||
conn.putheader(header, value)
|
conn.putheader(header, value)
|
||||||
@ -844,6 +849,10 @@ def put_object(url, token=None, container=None, name=None, contents=None,
|
|||||||
conn.send(chunk)
|
conn.send(chunk)
|
||||||
left -= len(chunk)
|
left -= len(chunk)
|
||||||
else:
|
else:
|
||||||
|
if chunk_size is not None:
|
||||||
|
warn_msg = '%s object has no \"read\" method, ignoring chunk_size'\
|
||||||
|
% type(contents).__name__
|
||||||
|
warnings.warn(warn_msg, stacklevel=2)
|
||||||
conn.request('PUT', path, contents, headers)
|
conn.request('PUT', path, contents, headers)
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
body = resp.read()
|
body = resp.read()
|
||||||
@ -1082,7 +1091,7 @@ class Connection(object):
|
|||||||
resp_chunk_size=resp_chunk_size)
|
resp_chunk_size=resp_chunk_size)
|
||||||
|
|
||||||
def put_object(self, container, obj, contents, content_length=None,
|
def put_object(self, container, obj, contents, content_length=None,
|
||||||
etag=None, chunk_size=65536, content_type=None,
|
etag=None, chunk_size=None, content_type=None,
|
||||||
headers=None):
|
headers=None):
|
||||||
"""Wrapper for :func:`put_object`"""
|
"""Wrapper for :func:`put_object`"""
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import socket
|
import socket
|
||||||
import StringIO
|
import StringIO
|
||||||
import testtools
|
import testtools
|
||||||
|
import warnings
|
||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
|
|
||||||
# TODO: mock http connection class with more control over headers
|
# TODO: mock http connection class with more control over headers
|
||||||
@ -472,6 +473,26 @@ class TestPutObject(MockHttpTest):
|
|||||||
self.assertTrue("a-b: .x:yz mn:fg:lp" in resp.buffer[0],
|
self.assertTrue("a-b: .x:yz mn:fg:lp" in resp.buffer[0],
|
||||||
"[a-b: .x:yz mn:fg:lp] header is missing")
|
"[a-b: .x:yz mn:fg:lp] header is missing")
|
||||||
|
|
||||||
|
def test_chunk_warning(self):
|
||||||
|
conn = c.http_connection('http://www.test.com/')
|
||||||
|
file = StringIO.StringIO('asdf')
|
||||||
|
args = ('asdf', 'asdf', 'asdf', 'asdf', file)
|
||||||
|
resp = MockHttpResponse()
|
||||||
|
conn[1].getresponse = resp.fake_response
|
||||||
|
conn[1].send = resp.fake_send
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
c.put_object(*args, chunk_size=20, headers={}, http_conn=conn)
|
||||||
|
self.assertEquals(len(w), 0)
|
||||||
|
|
||||||
|
body = 'c' * 60
|
||||||
|
c.http_connection = self.fake_http_connection(200, body=body)
|
||||||
|
args = ('http://www.test.com', 'asdf', 'asdf', 'asdf', 'asdf')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
c.put_object(*args, chunk_size=20)
|
||||||
|
self.assertEquals(len(w), 1)
|
||||||
|
self.assertTrue(issubclass(w[-1].category, UserWarning))
|
||||||
|
|
||||||
|
|
||||||
def test_server_error(self):
|
def test_server_error(self):
|
||||||
body = 'c' * 60
|
body = 'c' * 60
|
||||||
c.http_connection = self.fake_http_connection(500, body=body)
|
c.http_connection = self.fake_http_connection(500, body=body)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user