Commit 8b78b996 authored by Jeremy Hylton's avatar Jeremy Hylton

Fix [ #465502 ] urllib2: urlopen unicode problem

When checking for strings use,
!         if isinstance(uri, (types.StringType, types.UnicodeType)):

Also get rid of some dodgy code that tried to guess whether attributes
were callable or not.
parent 2f6a0b00
...@@ -89,6 +89,7 @@ f = urllib2.urlopen('http://www.python.org/') ...@@ -89,6 +89,7 @@ f = urllib2.urlopen('http://www.python.org/')
import socket import socket
import httplib import httplib
import inspect
import re import re
import base64 import base64
import types import types
...@@ -252,7 +253,7 @@ class OpenerDirector: ...@@ -252,7 +253,7 @@ class OpenerDirector:
def add_handler(self, handler): def add_handler(self, handler):
added = 0 added = 0
for meth in get_methods(handler): for meth in dir(handler):
if meth[-5:] == '_open': if meth[-5:] == '_open':
protocol = meth[:-5] protocol = meth[:-5]
if self.handle_open.has_key(protocol): if self.handle_open.has_key(protocol):
...@@ -303,7 +304,7 @@ class OpenerDirector: ...@@ -303,7 +304,7 @@ class OpenerDirector:
def open(self, fullurl, data=None): def open(self, fullurl, data=None):
# accept a URL or a Request object # accept a URL or a Request object
if isinstance(fullurl, types.StringType): if isinstance(fullurl, (types.StringType, types.UnicodeType)):
req = Request(fullurl, data) req = Request(fullurl, data)
else: else:
req = fullurl req = fullurl
...@@ -346,34 +347,6 @@ class OpenerDirector: ...@@ -346,34 +347,6 @@ class OpenerDirector:
args = (dict, 'default', 'http_error_default') + orig_args args = (dict, 'default', 'http_error_default') + orig_args
return self._call_chain(*args) return self._call_chain(*args)
def is_callable(obj):
# not quite like builtin callable (which I didn't know existed),
# not entirely sure it needs to be different
if type(obj) in (types.BuiltinFunctionType,
types.BuiltinMethodType, types.LambdaType,
types.MethodType):
return 1
if isinstance(obj, types.InstanceType):
return hasattr(obj, '__call__')
return 0
def get_methods(inst):
methods = {}
classes = []
classes.append(inst.__class__)
while classes:
klass = classes[0]
del classes[0]
classes = classes + list(klass.__bases__)
for name in dir(klass):
attr = getattr(klass, name)
if isinstance(attr, types.UnboundMethodType):
methods[name] = 1
for name in dir(inst):
if is_callable(getattr(inst, name)):
methods[name] = 1
return methods.keys()
# XXX probably also want an abstract factory that knows things like # XXX probably also want an abstract factory that knows things like
# the fact that a ProxyHandler needs to get inserted first. # the fact that a ProxyHandler needs to get inserted first.
# would also know when it makes sense to skip a superclass in favor of # would also know when it makes sense to skip a superclass in favor of
...@@ -399,12 +372,11 @@ def build_opener(*handlers): ...@@ -399,12 +372,11 @@ def build_opener(*handlers):
skip = [] skip = []
for klass in default_classes: for klass in default_classes:
for check in handlers: for check in handlers:
if isinstance(check, types.ClassType): if inspect.isclass(check):
if issubclass(check, klass): if issubclass(check, klass):
skip.append(klass) skip.append(klass)
elif isinstance(check, types.InstanceType): elif isinstance(check, klass):
if isinstance(check, klass): skip.append(klass)
skip.append(klass)
for klass in skip: for klass in skip:
default_classes.remove(klass) default_classes.remove(klass)
...@@ -412,7 +384,7 @@ def build_opener(*handlers): ...@@ -412,7 +384,7 @@ def build_opener(*handlers):
opener.add_handler(klass()) opener.add_handler(klass())
for h in handlers: for h in handlers:
if isinstance(h, types.ClassType): if inspect.isclass(h):
h = h() h = h()
opener.add_handler(h) opener.add_handler(h)
return opener return opener
...@@ -545,7 +517,7 @@ class HTTPPasswordMgr: ...@@ -545,7 +517,7 @@ class HTTPPasswordMgr:
def add_password(self, realm, uri, user, passwd): def add_password(self, realm, uri, user, passwd):
# uri could be a single URI or a sequence # uri could be a single URI or a sequence
if isinstance(uri, types.StringType): if isinstance(uri, (types.StringType, types.UnicodeType)):
uri = [uri] uri = [uri]
uri = tuple(map(self.reduce_uri, uri)) uri = tuple(map(self.reduce_uri, uri))
if not self.passwd.has_key(realm): if not self.passwd.has_key(realm):
...@@ -1067,7 +1039,7 @@ class OpenerFactory: ...@@ -1067,7 +1039,7 @@ class OpenerFactory:
def build_opener(self): def build_opener(self):
opener = OpenerDirector() opener = OpenerDirector()
for ph in self.proxy_handlers: for ph in self.proxy_handlers:
if isinstance(ph, types.ClassType): if inspect.isclass(ph):
ph = ph() ph = ph()
opener.add_handler(ph) opener.add_handler(ph)
...@@ -1088,49 +1060,46 @@ if __name__ == "__main__": ...@@ -1088,49 +1060,46 @@ if __name__ == "__main__":
'file:/etc/passwd', 'file:/etc/passwd',
'file://nonsensename/etc/passwd', 'file://nonsensename/etc/passwd',
'ftp://www.python.org/pub/tmp/httplib.py', 'ftp://www.python.org/pub/python/misc/sousa.au',
'ftp://www.python.org/pub/tmp/imageop.c',
'ftp://www.python.org/pub/tmp/blat', 'ftp://www.python.org/pub/tmp/blat',
'http://www.espn.com/', # redirect 'http://www.espn.com/', # redirect
'http://www.python.org/Spanish/Inquistion/', 'http://www.python.org/Spanish/Inquistion/',
('http://grail.cnri.reston.va.us/cgi-bin/faqw.py', ('http://www.python.org/cgi-bin/faqw.py',
'query=pythonistas&querytype=simple&casefold=yes&req=search'), 'query=pythonistas&querytype=simple&casefold=yes&req=search'),
'http://www.python.org/', 'http://www.python.org/',
'ftp://prep.ai.mit.edu/welcome.msg', 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC/research-reports/00README-Legal-Rules-Regs',
'ftp://www.python.org/pub/tmp/figure.prn',
'ftp://www.python.org/pub/tmp/interp.pl',
'http://checkproxy.cnri.reston.va.us/test/test.html',
] ]
if localhost is not None: ## if localhost is not None:
urls = urls + [ ## urls = urls + [
'file://%s/etc/passwd' % localhost, ## 'file://%s/etc/passwd' % localhost,
'http://%s/simple/' % localhost, ## 'http://%s/simple/' % localhost,
'http://%s/digest/' % localhost, ## 'http://%s/digest/' % localhost,
'http://%s/not/found.h' % localhost, ## 'http://%s/not/found.h' % localhost,
] ## ]
bauth = HTTPBasicAuthHandler() ## bauth = HTTPBasicAuthHandler()
bauth.add_password('basic_test_realm', localhost, 'jhylton', ## bauth.add_password('basic_test_realm', localhost, 'jhylton',
'password') ## 'password')
dauth = HTTPDigestAuthHandler() ## dauth = HTTPDigestAuthHandler()
dauth.add_password('digest_test_realm', localhost, 'jhylton', ## dauth.add_password('digest_test_realm', localhost, 'jhylton',
'password') ## 'password')
cfh = CacheFTPHandler() cfh = CacheFTPHandler()
cfh.setTimeout(1) cfh.setTimeout(1)
# XXX try out some custom proxy objects too! ## # XXX try out some custom proxy objects too!
def at_cnri(req): ## def at_cnri(req):
host = req.get_host() ## host = req.get_host()
print host ## print host
if host[-18:] == '.cnri.reston.va.us': ## if host[-18:] == '.cnri.reston.va.us':
return 1 ## return 1
p = CustomProxy('http', at_cnri, 'proxy.cnri.reston.va.us') ## p = CustomProxy('http', at_cnri, 'proxy.cnri.reston.va.us')
ph = CustomProxyHandler(p) ## ph = CustomProxyHandler(p)
#install_opener(build_opener(dauth, bauth, cfh, GopherHandler, ph)) ## install_opener(build_opener(dauth, bauth, cfh, GopherHandler, ph))
install_opener(build_opener(cfh, GopherHandler))
for url in urls: for url in urls:
if isinstance(url, types.TupleType): if isinstance(url, types.TupleType):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment