So I adapted urllib2 as suggested by answers to another question:
class HttpRequest(urllib2.Request):
  def __init__(self, *args, **kwargs):
    self._method = kwargs.pop('method', 'GET')
    urllib2.Request.__init__(self, *args, **kwargs)
  def get_method(self):
    return self._method
and it works nicely for PUT with JSON:
req = HttpRequest(url=url, method='PUT', 
    data=json.dumps(metadata))
response = urllib2.urlopen(req)
but it fails with data= binary data (partial stacktrace below):
  File "c:\appl\python\2.7.2\lib\urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "c:\appl\python\2.7.2\lib\urllib2.py", line 394, in open
    response = self._open(req, data)
  File "c:\appl\python\2.7.2\lib\urllib2.py", line 412, in _open
    '_open', req)
  File "c:\appl\python\2.7.2\lib\urllib2.py", line 372, in _call_chain
    result = func(*args)
  File "c:\appl\python\2.7.2\lib\urllib2.py", line 1199, in http_open
    return self.do_open(httplib.HTTPConnection, req)
  File "c:\appl\python\2.7.2\lib\urllib2.py", line 1168, in do_open
    h.request(req.get_method(), req.get_selector(), req.data, headers)
  File "c:\appl\python\2.7.2\lib\httplib.py", line 955, in request
    self._send_request(method, url, body, headers)
  File "c:\appl\python\2.7.2\lib\httplib.py", line 989, in _send_request
    self.endheaders(body)
  File "c:\appl\python\2.7.2\lib\httplib.py", line 951, in endheaders
    self._send_output(message_body)
  File "c:\appl\python\2.7.2\lib\httplib.py", line 809, in _send_output
    msg += message_body
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 10: ordinal
 not in range(128)
Is there a way I can fix this?
 
     
     
     
    