You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(107) |
Dec
(67) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(76) |
Feb
(125) |
Mar
(72) |
Apr
(13) |
May
(18) |
Jun
(12) |
Jul
(129) |
Aug
(47) |
Sep
(1) |
Oct
(36) |
Nov
(128) |
Dec
(124) |
2002 |
Jan
(59) |
Feb
|
Mar
(14) |
Apr
(14) |
May
(72) |
Jun
(9) |
Jul
(3) |
Aug
(5) |
Sep
(18) |
Oct
(65) |
Nov
(28) |
Dec
(12) |
2003 |
Jan
(10) |
Feb
(2) |
Mar
(4) |
Apr
(33) |
May
(21) |
Jun
(9) |
Jul
(29) |
Aug
(34) |
Sep
(4) |
Oct
(8) |
Nov
(15) |
Dec
(4) |
2004 |
Jan
(26) |
Feb
(12) |
Mar
(11) |
Apr
(9) |
May
(7) |
Jun
|
Jul
(5) |
Aug
|
Sep
(3) |
Oct
(7) |
Nov
(1) |
Dec
(10) |
2005 |
Jan
(2) |
Feb
(72) |
Mar
(16) |
Apr
(39) |
May
(48) |
Jun
(97) |
Jul
(57) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(100) |
Dec
(24) |
2006 |
Jan
(15) |
Feb
(34) |
Mar
(33) |
Apr
(31) |
May
(79) |
Jun
(64) |
Jul
(41) |
Aug
(64) |
Sep
(31) |
Oct
(46) |
Nov
(55) |
Dec
(37) |
2007 |
Jan
(32) |
Feb
(61) |
Mar
(11) |
Apr
(58) |
May
(46) |
Jun
(30) |
Jul
(94) |
Aug
(93) |
Sep
(86) |
Oct
(69) |
Nov
(125) |
Dec
(177) |
2008 |
Jan
(169) |
Feb
(97) |
Mar
(74) |
Apr
(113) |
May
(120) |
Jun
(334) |
Jul
(215) |
Aug
(237) |
Sep
(72) |
Oct
(189) |
Nov
(126) |
Dec
(160) |
2009 |
Jan
(180) |
Feb
(45) |
Mar
(98) |
Apr
(140) |
May
(151) |
Jun
(71) |
Jul
(107) |
Aug
(119) |
Sep
(73) |
Oct
(121) |
Nov
(14) |
Dec
(6) |
2010 |
Jan
(13) |
Feb
(9) |
Mar
(10) |
Apr
(64) |
May
(3) |
Jun
(16) |
Jul
(7) |
Aug
(23) |
Sep
(17) |
Oct
(37) |
Nov
(5) |
Dec
(8) |
2011 |
Jan
(10) |
Feb
(11) |
Mar
(77) |
Apr
(11) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <pj...@us...> - 2009-05-27 03:30:05
|
Revision: 6394 http://jython.svn.sourceforge.net/jython/?rev=6394&view=rev Author: pjenvey Date: 2009-05-27 03:29:59 +0000 (Wed, 27 May 2009) Log Message: ----------- don't hardcode posixpath Modified Paths: -------------- trunk/jython/Lib/test/test_import_jy.py Modified: trunk/jython/Lib/test/test_import_jy.py =================================================================== --- trunk/jython/Lib/test/test_import_jy.py 2009-05-27 02:50:23 UTC (rev 6393) +++ trunk/jython/Lib/test/test_import_jy.py 2009-05-27 03:29:59 UTC (rev 6394) @@ -98,16 +98,18 @@ class OverrideBuiltinsImportTestCase(unittest.TestCase): def test_override(self): + modname = os.path.__name__ tests = [ ("import os.path" , "('os.path', None, -1, 'os')" ), ("import os.path as path2", "('os.path', None, -1, 'os')" ), - ("from os.path import *" , "('os.path', ('*',), -1, 'posixpath')"), + ("from os.path import *" , + "('os.path', ('*',), -1, '%s')" % modname), ("from os.path import join", - "('os.path', ('join',), -1, 'posixpath')"), + "('os.path', ('join',), -1, '%s')" % modname), ("from os.path import join as join2", - "('os.path', ('join',), -1, 'posixpath')"), + "('os.path', ('join',), -1, '%s')" % modname), ("from os.path import join as join2, split as split2", - "('os.path', ('join', 'split'), -1, 'posixpath')"), + "('os.path', ('join', 'split'), -1, '%s')" % modname), ] import sys This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-27 02:50:24
|
Revision: 6393 http://jython.svn.sourceforge.net/jython/?rev=6393&view=rev Author: pjenvey Date: 2009-05-27 02:50:23 +0000 (Wed, 27 May 2009) Log Message: ----------- add jython windows check Modified Paths: -------------- trunk/jython/Lib/urllib.py Modified: trunk/jython/Lib/urllib.py =================================================================== --- trunk/jython/Lib/urllib.py 2009-05-27 02:49:43 UTC (rev 6392) +++ trunk/jython/Lib/urllib.py 2009-05-27 02:50:23 UTC (rev 6393) @@ -44,7 +44,7 @@ # Helper for non-unix systems if os.name == 'mac': from macurl2path import url2pathname, pathname2url -elif os.name == 'nt': +elif os.name == 'nt' or sys.platform.startswith('java') and os._name == 'nt': from nturl2path import url2pathname, pathname2url elif os.name == 'riscos': from rourl2path import url2pathname, pathname2url This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-27 02:49:47
|
Revision: 6392 http://jython.svn.sourceforge.net/jython/?rev=6392&view=rev Author: pjenvey Date: 2009-05-27 02:49:43 +0000 (Wed, 27 May 2009) Log Message: ----------- from: http://svn.python.org/projects/python/branches/release25-maint/Lib/urllib.py@54377 Added Paths: ----------- trunk/jython/Lib/urllib.py Added: trunk/jython/Lib/urllib.py =================================================================== --- trunk/jython/Lib/urllib.py (rev 0) +++ trunk/jython/Lib/urllib.py 2009-05-27 02:49:43 UTC (rev 6392) @@ -0,0 +1,1538 @@ +"""Open an arbitrary URL. + +See the following document for more info on URLs: +"Names and Addresses, URIs, URLs, URNs, URCs", at +http://www.w3.org/pub/WWW/Addressing/Overview.html + +See also the HTTP spec (from which the error codes are derived): +"HTTP - Hypertext Transfer Protocol", at +http://www.w3.org/pub/WWW/Protocols/ + +Related standards and specs: +- RFC1808: the "relative URL" spec. (authoritative status) +- RFC1738 - the "URL standard". (authoritative status) +- RFC1630 - the "URI spec". (informational status) + +The object returned by URLopener().open(file) will differ per +protocol. All you know is that is has methods read(), readline(), +readlines(), fileno(), close() and info(). The read*(), fileno() +and close() methods work like those of open files. +The info() method returns a mimetools.Message object which can be +used to query various info about the object, if available. +(mimetools.Message objects are queried with the getheader() method.) +""" + +import string +import socket +import os +import time +import sys +from urlparse import urljoin as basejoin + +__all__ = ["urlopen", "URLopener", "FancyURLopener", "urlretrieve", + "urlcleanup", "quote", "quote_plus", "unquote", "unquote_plus", + "urlencode", "url2pathname", "pathname2url", "splittag", + "localhost", "thishost", "ftperrors", "basejoin", "unwrap", + "splittype", "splithost", "splituser", "splitpasswd", "splitport", + "splitnport", "splitquery", "splitattr", "splitvalue", + "splitgophertype", "getproxies"] + +__version__ = '1.17' # XXX This version is not always updated :-( + +MAXFTPCACHE = 10 # Trim the ftp cache beyond this size + +# Helper for non-unix systems +if os.name == 'mac': + from macurl2path import url2pathname, pathname2url +elif os.name == 'nt': + from nturl2path import url2pathname, pathname2url +elif os.name == 'riscos': + from rourl2path import url2pathname, pathname2url +else: + def url2pathname(pathname): + """OS-specific conversion from a relative URL of the 'file' scheme + to a file system path; not recommended for general use.""" + return unquote(pathname) + + def pathname2url(pathname): + """OS-specific conversion from a file system path to a relative URL + of the 'file' scheme; not recommended for general use.""" + return quote(pathname) + +# This really consists of two pieces: +# (1) a class which handles opening of all sorts of URLs +# (plus assorted utilities etc.) +# (2) a set of functions for parsing URLs +# XXX Should these be separated out into different modules? + + +# Shortcut for basic usage +_urlopener = None +def urlopen(url, data=None, proxies=None): + """urlopen(url [, data]) -> open file-like object""" + global _urlopener + if proxies is not None: + opener = FancyURLopener(proxies=proxies) + elif not _urlopener: + opener = FancyURLopener() + _urlopener = opener + else: + opener = _urlopener + if data is None: + return opener.open(url) + else: + return opener.open(url, data) +def urlretrieve(url, filename=None, reporthook=None, data=None): + global _urlopener + if not _urlopener: + _urlopener = FancyURLopener() + return _urlopener.retrieve(url, filename, reporthook, data) +def urlcleanup(): + if _urlopener: + _urlopener.cleanup() + +# exception raised when downloaded size does not match content-length +class ContentTooShortError(IOError): + def __init__(self, message, content): + IOError.__init__(self, message) + self.content = content + +ftpcache = {} +class URLopener: + """Class to open URLs. + This is a class rather than just a subroutine because we may need + more than one set of global protocol-specific options. + Note -- this is a base class for those who don't want the + automatic handling of errors type 302 (relocated) and 401 + (authorization needed).""" + + __tempfiles = None + + version = "Python-urllib/%s" % __version__ + + # Constructor + def __init__(self, proxies=None, **x509): + if proxies is None: + proxies = getproxies() + assert hasattr(proxies, 'has_key'), "proxies must be a mapping" + self.proxies = proxies + self.key_file = x509.get('key_file') + self.cert_file = x509.get('cert_file') + self.addheaders = [('User-Agent', self.version)] + self.__tempfiles = [] + self.__unlink = os.unlink # See cleanup() + self.tempcache = None + # Undocumented feature: if you assign {} to tempcache, + # it is used to cache files retrieved with + # self.retrieve(). This is not enabled by default + # since it does not work for changing documents (and I + # haven't got the logic to check expiration headers + # yet). + self.ftpcache = ftpcache + # Undocumented feature: you can use a different + # ftp cache by assigning to the .ftpcache member; + # in case you want logically independent URL openers + # XXX This is not threadsafe. Bah. + + def __del__(self): + self.close() + + def close(self): + self.cleanup() + + def cleanup(self): + # This code sometimes runs when the rest of this module + # has already been deleted, so it can't use any globals + # or import anything. + if self.__tempfiles: + for file in self.__tempfiles: + try: + self.__unlink(file) + except OSError: + pass + del self.__tempfiles[:] + if self.tempcache: + self.tempcache.clear() + + def addheader(self, *args): + """Add a header to be used by the HTTP interface only + e.g. u.addheader('Accept', 'sound/basic')""" + self.addheaders.append(args) + + # External interface + def open(self, fullurl, data=None): + """Use URLopener().open(file) instead of open(file, 'r').""" + fullurl = unwrap(toBytes(fullurl)) + if self.tempcache and fullurl in self.tempcache: + filename, headers = self.tempcache[fullurl] + fp = open(filename, 'rb') + return addinfourl(fp, headers, fullurl) + urltype, url = splittype(fullurl) + if not urltype: + urltype = 'file' + if urltype in self.proxies: + proxy = self.proxies[urltype] + urltype, proxyhost = splittype(proxy) + host, selector = splithost(proxyhost) + url = (host, fullurl) # Signal special case to open_*() + else: + proxy = None + name = 'open_' + urltype + self.type = urltype + name = name.replace('-', '_') + if not hasattr(self, name): + if proxy: + return self.open_unknown_proxy(proxy, fullurl, data) + else: + return self.open_unknown(fullurl, data) + try: + if data is None: + return getattr(self, name)(url) + else: + return getattr(self, name)(url, data) + except socket.error, msg: + raise IOError, ('socket error', msg), sys.exc_info()[2] + + def open_unknown(self, fullurl, data=None): + """Overridable interface to open unknown URL type.""" + type, url = splittype(fullurl) + raise IOError, ('url error', 'unknown url type', type) + + def open_unknown_proxy(self, proxy, fullurl, data=None): + """Overridable interface to open unknown URL type.""" + type, url = splittype(fullurl) + raise IOError, ('url error', 'invalid proxy for %s' % type, proxy) + + # External interface + def retrieve(self, url, filename=None, reporthook=None, data=None): + """retrieve(url) returns (filename, headers) for a local object + or (tempfilename, headers) for a remote object.""" + url = unwrap(toBytes(url)) + if self.tempcache and url in self.tempcache: + return self.tempcache[url] + type, url1 = splittype(url) + if filename is None and (not type or type == 'file'): + try: + fp = self.open_local_file(url1) + hdrs = fp.info() + del fp + return url2pathname(splithost(url1)[1]), hdrs + except IOError, msg: + pass + fp = self.open(url, data) + headers = fp.info() + if filename: + tfp = open(filename, 'wb') + else: + import tempfile + garbage, path = splittype(url) + garbage, path = splithost(path or "") + path, garbage = splitquery(path or "") + path, garbage = splitattr(path or "") + suffix = os.path.splitext(path)[1] + (fd, filename) = tempfile.mkstemp(suffix) + self.__tempfiles.append(filename) + tfp = os.fdopen(fd, 'wb') + result = filename, headers + if self.tempcache is not None: + self.tempcache[url] = result + bs = 1024*8 + size = -1 + read = 0 + blocknum = 0 + if reporthook: + if "content-length" in headers: + size = int(headers["Content-Length"]) + reporthook(blocknum, bs, size) + while 1: + block = fp.read(bs) + if block == "": + break + read += len(block) + tfp.write(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, bs, size) + fp.close() + tfp.close() + del fp + del tfp + + # raise exception if actual size does not match content-length header + if size >= 0 and read < size: + raise ContentTooShortError("retrieval incomplete: got only %i out " + "of %i bytes" % (read, size), result) + + return result + + # Each method named open_<type> knows how to open that type of URL + + def open_http(self, url, data=None): + """Use HTTP protocol.""" + import httplib + user_passwd = None + proxy_passwd= None + if isinstance(url, str): + host, selector = splithost(url) + if host: + user_passwd, host = splituser(host) + host = unquote(host) + realhost = host + else: + host, selector = url + # check whether the proxy contains authorization information + proxy_passwd, host = splituser(host) + # now we proceed with the url we want to obtain + urltype, rest = splittype(selector) + url = rest + user_passwd = None + if urltype.lower() != 'http': + realhost = None + else: + realhost, rest = splithost(rest) + if realhost: + user_passwd, realhost = splituser(realhost) + if user_passwd: + selector = "%s://%s%s" % (urltype, realhost, rest) + if proxy_bypass(realhost): + host = realhost + + #print "proxy via http:", host, selector + if not host: raise IOError, ('http error', 'no host given') + + if proxy_passwd: + import base64 + proxy_auth = base64.b64encode(proxy_passwd).strip() + else: + proxy_auth = None + + if user_passwd: + import base64 + auth = base64.b64encode(user_passwd).strip() + else: + auth = None + h = httplib.HTTP(host) + if data is not None: + h.putrequest('POST', selector) + h.putheader('Content-Type', 'application/x-www-form-urlencoded') + h.putheader('Content-Length', '%d' % len(data)) + else: + h.putrequest('GET', selector) + if proxy_auth: h.putheader('Proxy-Authorization', 'Basic %s' % proxy_auth) + if auth: h.putheader('Authorization', 'Basic %s' % auth) + if realhost: h.putheader('Host', realhost) + for args in self.addheaders: h.putheader(*args) + h.endheaders() + if data is not None: + h.send(data) + errcode, errmsg, headers = h.getreply() + if errcode == -1: + # something went wrong with the HTTP status line + raise IOError, ('http protocol error', 0, + 'got a bad status line', None) + fp = h.getfile() + if errcode == 200: + return addinfourl(fp, headers, "http:" + url) + else: + if data is None: + return self.http_error(url, fp, errcode, errmsg, headers) + else: + return self.http_error(url, fp, errcode, errmsg, headers, data) + + def http_error(self, url, fp, errcode, errmsg, headers, data=None): + """Handle http errors. + Derived class can override this, or provide specific handlers + named http_error_DDD where DDD is the 3-digit error code.""" + # First check if there's a specific handler for this error + name = 'http_error_%d' % errcode + if hasattr(self, name): + method = getattr(self, name) + if data is None: + result = method(url, fp, errcode, errmsg, headers) + else: + result = method(url, fp, errcode, errmsg, headers, data) + if result: return result + return self.http_error_default(url, fp, errcode, errmsg, headers) + + def http_error_default(self, url, fp, errcode, errmsg, headers): + """Default error handler: close the connection and raise IOError.""" + void = fp.read() + fp.close() + raise IOError, ('http error', errcode, errmsg, headers) + + if hasattr(socket, "ssl"): + def open_https(self, url, data=None): + """Use HTTPS protocol.""" + import httplib + user_passwd = None + proxy_passwd = None + if isinstance(url, str): + host, selector = splithost(url) + if host: + user_passwd, host = splituser(host) + host = unquote(host) + realhost = host + else: + host, selector = url + # here, we determine, whether the proxy contains authorization information + proxy_passwd, host = splituser(host) + urltype, rest = splittype(selector) + url = rest + user_passwd = None + if urltype.lower() != 'https': + realhost = None + else: + realhost, rest = splithost(rest) + if realhost: + user_passwd, realhost = splituser(realhost) + if user_passwd: + selector = "%s://%s%s" % (urltype, realhost, rest) + #print "proxy via https:", host, selector + if not host: raise IOError, ('https error', 'no host given') + if proxy_passwd: + import base64 + proxy_auth = base64.b64encode(proxy_passwd).strip() + else: + proxy_auth = None + if user_passwd: + import base64 + auth = base64.b64encode(user_passwd).strip() + else: + auth = None + h = httplib.HTTPS(host, 0, + key_file=self.key_file, + cert_file=self.cert_file) + if data is not None: + h.putrequest('POST', selector) + h.putheader('Content-Type', + 'application/x-www-form-urlencoded') + h.putheader('Content-Length', '%d' % len(data)) + else: + h.putrequest('GET', selector) + if proxy_auth: h.putheader('Proxy-Authorization', 'Basic %s' % proxy_auth) + if auth: h.putheader('Authorization', 'Basic %s' % auth) + if realhost: h.putheader('Host', realhost) + for args in self.addheaders: h.putheader(*args) + h.endheaders() + if data is not None: + h.send(data) + errcode, errmsg, headers = h.getreply() + if errcode == -1: + # something went wrong with the HTTP status line + raise IOError, ('http protocol error', 0, + 'got a bad status line', None) + fp = h.getfile() + if errcode == 200: + return addinfourl(fp, headers, "https:" + url) + else: + if data is None: + return self.http_error(url, fp, errcode, errmsg, headers) + else: + return self.http_error(url, fp, errcode, errmsg, headers, + data) + + def open_gopher(self, url): + """Use Gopher protocol.""" + if not isinstance(url, str): + raise IOError, ('gopher error', 'proxy support for gopher protocol currently not implemented') + import gopherlib + host, selector = splithost(url) + if not host: raise IOError, ('gopher error', 'no host given') + host = unquote(host) + type, selector = splitgophertype(selector) + selector, query = splitquery(selector) + selector = unquote(selector) + if query: + query = unquote(query) + fp = gopherlib.send_query(selector, query, host) + else: + fp = gopherlib.send_selector(selector, host) + return addinfourl(fp, noheaders(), "gopher:" + url) + + def open_file(self, url): + """Use local file or FTP depending on form of URL.""" + if not isinstance(url, str): + raise IOError, ('file error', 'proxy support for file protocol currently not implemented') + if url[:2] == '//' and url[2:3] != '/' and url[2:12].lower() != 'localhost/': + return self.open_ftp(url) + else: + return self.open_local_file(url) + + def open_local_file(self, url): + """Use local file.""" + import mimetypes, mimetools, email.Utils + try: + from cStringIO import StringIO + except ImportError: + from StringIO import StringIO + host, file = splithost(url) + localname = url2pathname(file) + try: + stats = os.stat(localname) + except OSError, e: + raise IOError(e.errno, e.strerror, e.filename) + size = stats.st_size + modified = email.Utils.formatdate(stats.st_mtime, usegmt=True) + mtype = mimetypes.guess_type(url)[0] + headers = mimetools.Message(StringIO( + 'Content-Type: %s\nContent-Length: %d\nLast-modified: %s\n' % + (mtype or 'text/plain', size, modified))) + if not host: + urlfile = file + if file[:1] == '/': + urlfile = 'file://' + file + return addinfourl(open(localname, 'rb'), + headers, urlfile) + host, port = splitport(host) + if not port \ + and socket.gethostbyname(host) in (localhost(), thishost()): + urlfile = file + if file[:1] == '/': + urlfile = 'file://' + file + return addinfourl(open(localname, 'rb'), + headers, urlfile) + raise IOError, ('local file error', 'not on local host') + + def open_ftp(self, url): + """Use FTP protocol.""" + if not isinstance(url, str): + raise IOError, ('ftp error', 'proxy support for ftp protocol currently not implemented') + import mimetypes, mimetools + try: + from cStringIO import StringIO + except ImportError: + from StringIO import StringIO + host, path = splithost(url) + if not host: raise IOError, ('ftp error', 'no host given') + host, port = splitport(host) + user, host = splituser(host) + if user: user, passwd = splitpasswd(user) + else: passwd = None + host = unquote(host) + user = unquote(user or '') + passwd = unquote(passwd or '') + host = socket.gethostbyname(host) + if not port: + import ftplib + port = ftplib.FTP_PORT + else: + port = int(port) + path, attrs = splitattr(path) + path = unquote(path) + dirs = path.split('/') + dirs, file = dirs[:-1], dirs[-1] + if dirs and not dirs[0]: dirs = dirs[1:] + if dirs and not dirs[0]: dirs[0] = '/' + key = user, host, port, '/'.join(dirs) + # XXX thread unsafe! + if len(self.ftpcache) > MAXFTPCACHE: + # Prune the cache, rather arbitrarily + for k in self.ftpcache.keys(): + if k != key: + v = self.ftpcache[k] + del self.ftpcache[k] + v.close() + try: + if not key in self.ftpcache: + self.ftpcache[key] = \ + ftpwrapper(user, passwd, host, port, dirs) + if not file: type = 'D' + else: type = 'I' + for attr in attrs: + attr, value = splitvalue(attr) + if attr.lower() == 'type' and \ + value in ('a', 'A', 'i', 'I', 'd', 'D'): + type = value.upper() + (fp, retrlen) = self.ftpcache[key].retrfile(file, type) + mtype = mimetypes.guess_type("ftp:" + url)[0] + headers = "" + if mtype: + headers += "Content-Type: %s\n" % mtype + if retrlen is not None and retrlen >= 0: + headers += "Content-Length: %d\n" % retrlen + headers = mimetools.Message(StringIO(headers)) + return addinfourl(fp, headers, "ftp:" + url) + except ftperrors(), msg: + raise IOError, ('ftp error', msg), sys.exc_info()[2] + + def open_data(self, url, data=None): + """Use "data" URL.""" + if not isinstance(url, str): + raise IOError, ('data error', 'proxy support for data protocol currently not implemented') + # ignore POSTed data + # + # syntax of data URLs: + # dataurl := "data:" [ mediatype ] [ ";base64" ] "," data + # mediatype := [ type "/" subtype ] *( ";" parameter ) + # data := *urlchar + # parameter := attribute "=" value + import mimetools + try: + from cStringIO import StringIO + except ImportError: + from StringIO import StringIO + try: + [type, data] = url.split(',', 1) + except ValueError: + raise IOError, ('data error', 'bad data URL') + if not type: + type = 'text/plain;charset=US-ASCII' + semi = type.rfind(';') + if semi >= 0 and '=' not in type[semi:]: + encoding = type[semi+1:] + type = type[:semi] + else: + encoding = '' + msg = [] + msg.append('Date: %s'%time.strftime('%a, %d %b %Y %T GMT', + time.gmtime(time.time()))) + msg.append('Content-type: %s' % type) + if encoding == 'base64': + import base64 + data = base64.decodestring(data) + else: + data = unquote(data) + msg.append('Content-Length: %d' % len(data)) + msg.append('') + msg.append(data) + msg = '\n'.join(msg) + f = StringIO(msg) + headers = mimetools.Message(f, 0) + #f.fileno = None # needed for addinfourl + return addinfourl(f, headers, url) + + +class FancyURLopener(URLopener): + """Derived class with handlers for errors we can handle (perhaps).""" + + def __init__(self, *args, **kwargs): + URLopener.__init__(self, *args, **kwargs) + self.auth_cache = {} + self.tries = 0 + self.maxtries = 10 + + def http_error_default(self, url, fp, errcode, errmsg, headers): + """Default error handling -- don't raise an exception.""" + return addinfourl(fp, headers, "http:" + url) + + def http_error_302(self, url, fp, errcode, errmsg, headers, data=None): + """Error 302 -- relocated (temporarily).""" + self.tries += 1 + if self.maxtries and self.tries >= self.maxtries: + if hasattr(self, "http_error_500"): + meth = self.http_error_500 + else: + meth = self.http_error_default + self.tries = 0 + return meth(url, fp, 500, + "Internal Server Error: Redirect Recursion", headers) + result = self.redirect_internal(url, fp, errcode, errmsg, headers, + data) + self.tries = 0 + return result + + def redirect_internal(self, url, fp, errcode, errmsg, headers, data): + if 'location' in headers: + newurl = headers['location'] + elif 'uri' in headers: + newurl = headers['uri'] + else: + return + void = fp.read() + fp.close() + # In case the server sent a relative URL, join with original: + newurl = basejoin(self.type + ":" + url, newurl) + return self.open(newurl) + + def http_error_301(self, url, fp, errcode, errmsg, headers, data=None): + """Error 301 -- also relocated (permanently).""" + return self.http_error_302(url, fp, errcode, errmsg, headers, data) + + def http_error_303(self, url, fp, errcode, errmsg, headers, data=None): + """Error 303 -- also relocated (essentially identical to 302).""" + return self.http_error_302(url, fp, errcode, errmsg, headers, data) + + def http_error_307(self, url, fp, errcode, errmsg, headers, data=None): + """Error 307 -- relocated, but turn POST into error.""" + if data is None: + return self.http_error_302(url, fp, errcode, errmsg, headers, data) + else: + return self.http_error_default(url, fp, errcode, errmsg, headers) + + def http_error_401(self, url, fp, errcode, errmsg, headers, data=None): + """Error 401 -- authentication required. + This function supports Basic authentication only.""" + if not 'www-authenticate' in headers: + URLopener.http_error_default(self, url, fp, + errcode, errmsg, headers) + stuff = headers['www-authenticate'] + import re + match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff) + if not match: + URLopener.http_error_default(self, url, fp, + errcode, errmsg, headers) + scheme, realm = match.groups() + if scheme.lower() != 'basic': + URLopener.http_error_default(self, url, fp, + errcode, errmsg, headers) + name = 'retry_' + self.type + '_basic_auth' + if data is None: + return getattr(self,name)(url, realm) + else: + return getattr(self,name)(url, realm, data) + + def http_error_407(self, url, fp, errcode, errmsg, headers, data=None): + """Error 407 -- proxy authentication required. + This function supports Basic authentication only.""" + if not 'proxy-authenticate' in headers: + URLopener.http_error_default(self, url, fp, + errcode, errmsg, headers) + stuff = headers['proxy-authenticate'] + import re + match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff) + if not match: + URLopener.http_error_default(self, url, fp, + errcode, errmsg, headers) + scheme, realm = match.groups() + if scheme.lower() != 'basic': + URLopener.http_error_default(self, url, fp, + errcode, errmsg, headers) + name = 'retry_proxy_' + self.type + '_basic_auth' + if data is None: + return getattr(self,name)(url, realm) + else: + return getattr(self,name)(url, realm, data) + + def retry_proxy_http_basic_auth(self, url, realm, data=None): + host, selector = splithost(url) + newurl = 'http://' + host + selector + proxy = self.proxies['http'] + urltype, proxyhost = splittype(proxy) + proxyhost, proxyselector = splithost(proxyhost) + i = proxyhost.find('@') + 1 + proxyhost = proxyhost[i:] + user, passwd = self.get_user_passwd(proxyhost, realm, i) + if not (user or passwd): return None + proxyhost = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + proxyhost + self.proxies['http'] = 'http://' + proxyhost + proxyselector + if data is None: + return self.open(newurl) + else: + return self.open(newurl, data) + + def retry_proxy_https_basic_auth(self, url, realm, data=None): + host, selector = splithost(url) + newurl = 'https://' + host + selector + proxy = self.proxies['https'] + urltype, proxyhost = splittype(proxy) + proxyhost, proxyselector = splithost(proxyhost) + i = proxyhost.find('@') + 1 + proxyhost = proxyhost[i:] + user, passwd = self.get_user_passwd(proxyhost, realm, i) + if not (user or passwd): return None + proxyhost = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + proxyhost + self.proxies['https'] = 'https://' + proxyhost + proxyselector + if data is None: + return self.open(newurl) + else: + return self.open(newurl, data) + + def retry_http_basic_auth(self, url, realm, data=None): + host, selector = splithost(url) + i = host.find('@') + 1 + host = host[i:] + user, passwd = self.get_user_passwd(host, realm, i) + if not (user or passwd): return None + host = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + host + newurl = 'http://' + host + selector + if data is None: + return self.open(newurl) + else: + return self.open(newurl, data) + + def retry_https_basic_auth(self, url, realm, data=None): + host, selector = splithost(url) + i = host.find('@') + 1 + host = host[i:] + user, passwd = self.get_user_passwd(host, realm, i) + if not (user or passwd): return None + host = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + host + newurl = 'https://' + host + selector + if data is None: + return self.open(newurl) + else: + return self.open(newurl, data) + + def get_user_passwd(self, host, realm, clear_cache = 0): + key = realm + '@' + host.lower() + if key in self.auth_cache: + if clear_cache: + del self.auth_cache[key] + else: + return self.auth_cache[key] + user, passwd = self.prompt_user_passwd(host, realm) + if user or passwd: self.auth_cache[key] = (user, passwd) + return user, passwd + + def prompt_user_passwd(self, host, realm): + """Override this in a GUI environment!""" + import getpass + try: + user = raw_input("Enter username for %s at %s: " % (realm, + host)) + passwd = getpass.getpass("Enter password for %s in %s at %s: " % + (user, realm, host)) + return user, passwd + except KeyboardInterrupt: + print + return None, None + + +# Utility functions + +_localhost = None +def localhost(): + """Return the IP address of the magic hostname 'localhost'.""" + global _localhost + if _localhost is None: + _localhost = socket.gethostbyname('localhost') + return _localhost + +_thishost = None +def thishost(): + """Return the IP address of the current host.""" + global _thishost + if _thishost is None: + _thishost = socket.gethostbyname(socket.gethostname()) + return _thishost + +_ftperrors = None +def ftperrors(): + """Return the set of errors raised by the FTP class.""" + global _ftperrors + if _ftperrors is None: + import ftplib + _ftperrors = ftplib.all_errors + return _ftperrors + +_noheaders = None +def noheaders(): + """Return an empty mimetools.Message object.""" + global _noheaders + if _noheaders is None: + import mimetools + try: + from cStringIO import StringIO + except ImportError: + from StringIO import StringIO + _noheaders = mimetools.Message(StringIO(), 0) + _noheaders.fp.close() # Recycle file descriptor + return _noheaders + + +# Utility classes + +class ftpwrapper: + """Class used by open_ftp() for cache of open FTP connections.""" + + def __init__(self, user, passwd, host, port, dirs): + self.user = user + self.passwd = passwd + self.host = host + self.port = port + self.dirs = dirs + self.init() + + def init(self): + import ftplib + self.busy = 0 + self.ftp = ftplib.FTP() + self.ftp.connect(self.host, self.port) + self.ftp.login(self.user, self.passwd) + for dir in self.dirs: + self.ftp.cwd(dir) + + def retrfile(self, file, type): + import ftplib + self.endtransfer() + if type in ('d', 'D'): cmd = 'TYPE A'; isdir = 1 + else: cmd = 'TYPE ' + type; isdir = 0 + try: + self.ftp.voidcmd(cmd) + except ftplib.all_errors: + self.init() + self.ftp.voidcmd(cmd) + conn = None + if file and not isdir: + # Try to retrieve as a file + try: + cmd = 'RETR ' + file + conn = self.ftp.ntransfercmd(cmd) + except ftplib.error_perm, reason: + if str(reason)[:3] != '550': + raise IOError, ('ftp error', reason), sys.exc_info()[2] + if not conn: + # Set transfer mode to ASCII! + self.ftp.voidcmd('TYPE A') + # Try a directory listing + if file: cmd = 'LIST ' + file + else: cmd = 'LIST' + conn = self.ftp.ntransfercmd(cmd) + self.busy = 1 + # Pass back both a suitably decorated object and a retrieval length + return (addclosehook(conn[0].makefile('rb'), + self.endtransfer), conn[1]) + def endtransfer(self): + if not self.busy: + return + self.busy = 0 + try: + self.ftp.voidresp() + except ftperrors(): + pass + + def close(self): + self.endtransfer() + try: + self.ftp.close() + except ftperrors(): + pass + +class addbase: + """Base class for addinfo and addclosehook.""" + + def __init__(self, fp): + self.fp = fp + self.read = self.fp.read + self.readline = self.fp.readline + if hasattr(self.fp, "readlines"): self.readlines = self.fp.readlines + if hasattr(self.fp, "fileno"): + self.fileno = self.fp.fileno + else: + self.fileno = lambda: None + if hasattr(self.fp, "__iter__"): + self.__iter__ = self.fp.__iter__ + if hasattr(self.fp, "next"): + self.next = self.fp.next + + def __repr__(self): + return '<%s at %r whose fp = %r>' % (self.__class__.__name__, + id(self), self.fp) + + def close(self): + self.read = None + self.readline = None + self.readlines = None + self.fileno = None + if self.fp: self.fp.close() + self.fp = None + +class addclosehook(addbase): + """Class to add a close hook to an open file.""" + + def __init__(self, fp, closehook, *hookargs): + addbase.__init__(self, fp) + self.closehook = closehook + self.hookargs = hookargs + + def close(self): + addbase.close(self) + if self.closehook: + self.closehook(*self.hookargs) + self.closehook = None + self.hookargs = None + +class addinfo(addbase): + """class to add an info() method to an open file.""" + + def __init__(self, fp, headers): + addbase.__init__(self, fp) + self.headers = headers + + def info(self): + return self.headers + +class addinfourl(addbase): + """class to add info() and geturl() methods to an open file.""" + + def __init__(self, fp, headers, url): + addbase.__init__(self, fp) + self.headers = headers + self.url = url + + def info(self): + return self.headers + + def geturl(self): + return self.url + + +# Utilities to parse URLs (most of these return None for missing parts): +# unwrap('<URL:type://host/path>') --> 'type://host/path' +# splittype('type:opaquestring') --> 'type', 'opaquestring' +# splithost('//host[:port]/path') --> 'host[:port]', '/path' +# splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]' +# splitpasswd('user:passwd') -> 'user', 'passwd' +# splitport('host:port') --> 'host', 'port' +# splitquery('/path?query') --> '/path', 'query' +# splittag('/path#tag') --> '/path', 'tag' +# splitattr('/path;attr1=value1;attr2=value2;...') -> +# '/path', ['attr1=value1', 'attr2=value2', ...] +# splitvalue('attr=value') --> 'attr', 'value' +# splitgophertype('/Xselector') --> 'X', 'selector' +# unquote('abc%20def') -> 'abc def' +# quote('abc def') -> 'abc%20def') + +try: + unicode +except NameError: + def _is_unicode(x): + return 0 +else: + def _is_unicode(x): + return isinstance(x, unicode) + +def toBytes(url): + """toBytes(u"URL") --> 'URL'.""" + # Most URL schemes require ASCII. If that changes, the conversion + # can be relaxed + if _is_unicode(url): + try: + url = url.encode("ASCII") + except UnicodeError: + raise UnicodeError("URL " + repr(url) + + " contains non-ASCII characters") + return url + +def unwrap(url): + """unwrap('<URL:type://host/path>') --> 'type://host/path'.""" + url = url.strip() + if url[:1] == '<' and url[-1:] == '>': + url = url[1:-1].strip() + if url[:4] == 'URL:': url = url[4:].strip() + return url + +_typeprog = None +def splittype(url): + """splittype('type:opaquestring') --> 'type', 'opaquestring'.""" + global _typeprog + if _typeprog is None: + import re + _typeprog = re.compile('^([^/:]+):') + + match = _typeprog.match(url) + if match: + scheme = match.group(1) + return scheme.lower(), url[len(scheme) + 1:] + return None, url + +_hostprog = None +def splithost(url): + """splithost('//host[:port]/path') --> 'host[:port]', '/path'.""" + global _hostprog + if _hostprog is None: + import re + _hostprog = re.compile('^//([^/?]*)(.*)$') + + match = _hostprog.match(url) + if match: return match.group(1, 2) + return None, url + +_userprog = None +def splituser(host): + """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" + global _userprog + if _userprog is None: + import re + _userprog = re.compile('^(.*)@(.*)$') + + match = _userprog.match(host) + if match: return map(unquote, match.group(1, 2)) + return None, host + +_passwdprog = None +def splitpasswd(user): + """splitpasswd('user:passwd') -> 'user', 'passwd'.""" + global _passwdprog + if _passwdprog is None: + import re + _passwdprog = re.compile('^([^:]*):(.*)$') + + match = _passwdprog.match(user) + if match: return match.group(1, 2) + return user, None + +# splittag('/path#tag') --> '/path', 'tag' +_portprog = None +def splitport(host): + """splitport('host:port') --> 'host', 'port'.""" + global _portprog + if _portprog is None: + import re + _portprog = re.compile('^(.*):([0-9]+)$') + + match = _portprog.match(host) + if match: return match.group(1, 2) + return host, None + +_nportprog = None +def splitnport(host, defport=-1): + """Split host and port, returning numeric port. + Return given default port if no ':' found; defaults to -1. + Return numerical port if a valid number are found after ':'. + Return None if ':' but not a valid number.""" + global _nportprog + if _nportprog is None: + import re + _nportprog = re.compile('^(.*):(.*)$') + + match = _nportprog.match(host) + if match: + host, port = match.group(1, 2) + try: + if not port: raise ValueError, "no digits" + nport = int(port) + except ValueError: + nport = None + return host, nport + return host, defport + +_queryprog = None +def splitquery(url): + """splitquery('/path?query') --> '/path', 'query'.""" + global _queryprog + if _queryprog is None: + import re + _queryprog = re.compile('^(.*)\?([^?]*)$') + + match = _queryprog.match(url) + if match: return match.group(1, 2) + return url, None + +_tagprog = None +def splittag(url): + """splittag('/path#tag') --> '/path', 'tag'.""" + global _tagprog + if _tagprog is None: + import re + _tagprog = re.compile('^(.*)#([^#]*)$') + + match = _tagprog.match(url) + if match: return match.group(1, 2) + return url, None + +def splitattr(url): + """splitattr('/path;attr1=value1;attr2=value2;...') -> + '/path', ['attr1=value1', 'attr2=value2', ...].""" + words = url.split(';') + return words[0], words[1:] + +_valueprog = None +def splitvalue(attr): + """splitvalue('attr=value') --> 'attr', 'value'.""" + global _valueprog + if _valueprog is None: + import re + _valueprog = re.compile('^([^=]*)=(.*)$') + + match = _valueprog.match(attr) + if match: return match.group(1, 2) + return attr, None + +def splitgophertype(selector): + """splitgophertype('/Xselector') --> 'X', 'selector'.""" + if selector[:1] == '/' and selector[1:2]: + return selector[1], selector[2:] + return None, selector + +_hextochr = dict(('%02x' % i, chr(i)) for i in range(256)) +_hextochr.update(('%02X' % i, chr(i)) for i in range(256)) + +def unquote(s): + """unquote('abc%20def') -> 'abc def'.""" + res = s.split('%') + for i in xrange(1, len(res)): + item = res[i] + try: + res[i] = _hextochr[item[:2]] + item[2:] + except KeyError: + res[i] = '%' + item + except UnicodeDecodeError: + res[i] = unichr(int(item[:2], 16)) + item[2:] + return "".join(res) + +def unquote_plus(s): + """unquote('%7e/abc+def') -> '~/abc def'""" + s = s.replace('+', ' ') + return unquote(s) + +always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789' '_.-') +_safemaps = {} + +def quote(s, safe = '/'): + """quote('abc def') -> 'abc%20def' + + Each part of a URL, e.g. the path info, the query, etc., has a + different set of reserved characters that must be quoted. + + RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists + the following reserved characters. + + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + "$" | "," + + Each of these characters is reserved in some component of a URL, + but not necessarily in all of them. + + By default, the quote function is intended for quoting the path + section of a URL. Thus, it will not encode '/'. This character + is reserved, but in typical usage the quote function is being + called on a path where the existing slash characters are used as + reserved characters. + """ + cachekey = (safe, always_safe) + try: + safe_map = _safemaps[cachekey] + except KeyError: + safe += always_safe + safe_map = {} + for i in range(256): + c = chr(i) + safe_map[c] = (c in safe) and c or ('%%%02X' % i) + _safemaps[cachekey] = safe_map + res = map(safe_map.__getitem__, s) + return ''.join(res) + +def quote_plus(s, safe = ''): + """Quote the query fragment of a URL; replacing ' ' with '+'""" + if ' ' in s: + s = quote(s, safe + ' ') + return s.replace(' ', '+') + return quote(s, safe) + +def urlencode(query,doseq=0): + """Encode a sequence of two-element tuples or dictionary into a URL query string. + + If any values in the query arg are sequences and doseq is true, each + sequence element is converted to a separate parameter. + + If the query arg is a sequence of two-element tuples, the order of the + parameters in the output will match the order of parameters in the + input. + """ + + if hasattr(query,"items"): + # mapping objects + query = query.items() + else: + # it's a bother at times that strings and string-like objects are + # sequences... + try: + # non-sequence items should not work with len() + # non-empty strings will fail this + if len(query) and not isinstance(query[0], tuple): + raise TypeError + # zero-length sequences of all types will get here and succeed, + # but that's a minor nit - since the original implementation + # allowed empty dicts that type of behavior probably should be + # preserved for consistency + except TypeError: + ty,va,tb = sys.exc_info() + raise TypeError, "not a valid non-string sequence or mapping object", tb + + l = [] + if not doseq: + # preserve old behavior + for k, v in query: + k = quote_plus(str(k)) + v = quote_plus(str(v)) + l.append(k + '=' + v) + else: + for k, v in query: + k = quote_plus(str(k)) + if isinstance(v, str): + v = quote_plus(v) + l.append(k + '=' + v) + elif _is_unicode(v): + # is there a reasonable way to convert to ASCII? + # encode generates a string, but "replace" or "ignore" + # lose information and "strict" can raise UnicodeError + v = quote_plus(v.encode("ASCII","replace")) + l.append(k + '=' + v) + else: + try: + # is this a sufficient test for sequence-ness? + x = len(v) + except TypeError: + # not a sequence + v = quote_plus(str(v)) + l.append(k + '=' + v) + else: + # loop over the sequence + for elt in v: + l.append(k + '=' + quote_plus(str(elt))) + return '&'.join(l) + +# Proxy handling +def getproxies_environment(): + """Return a dictionary of scheme -> proxy server URL mappings. + + Scan the environment for variables named <scheme>_proxy; + this seems to be the standard convention. If you need a + different way, you can pass a proxies dictionary to the + [Fancy]URLopener constructor. + + """ + proxies = {} + for name, value in os.environ.items(): + name = name.lower() + if value and name[-6:] == '_proxy': + proxies[name[:-6]] = value + return proxies + +if sys.platform == 'darwin': + def getproxies_internetconfig(): + """Return a dictionary of scheme -> proxy server URL mappings. + + By convention the mac uses Internet Config to store + proxies. An HTTP proxy, for instance, is stored under + the HttpProxy key. + + """ + try: + import ic + except ImportError: + return {} + + try: + config = ic.IC() + except ic.error: + return {} + proxies = {} + # HTTP: + if 'UseHTTPProxy' in config and config['UseHTTPProxy']: + try: + value = config['HTTPProxyHost'] + except ic.error: + pass + else: + proxies['http'] = 'http://%s' % value + # FTP: XXXX To be done. + # Gopher: XXXX To be done. + return proxies + + def proxy_bypass(x): + return 0 + + def getproxies(): + return getproxies_environment() or getproxies_internetconfig() + +elif os.name == 'nt': + def getproxies_registry(): + """Return a dictionary of scheme -> proxy server URL mappings. + + Win32 uses the registry to store proxies. + + """ + proxies = {} + try: + import _winreg + except ImportError: + # Std module, so should be around - but you never know! + return proxies + try: + internetSettings = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, + r'Software\Microsoft\Windows\CurrentVersion\Internet Settings') + proxyEnable = _winreg.QueryValueEx(internetSettings, + 'ProxyEnable')[0] + if proxyEnable: + # Returned as Unicode but problems if not converted to ASCII + proxyServer = str(_winreg.QueryValueEx(internetSettings, + 'ProxyServer')[0]) + if '=' in proxyServer: + # Per-protocol settings + for p in proxyServer.split(';'): + protocol, address = p.split('=', 1) + # See if address has a type:// prefix + import re + if not re.match('^([^/:]+)://', address): + address = '%s://%s' % (protocol, address) + proxies[protocol] = address + else: + # Use one setting for all protocols + if proxyServer[:5] == 'http:': + proxies['http'] = proxyServer + else: + proxies['http'] = 'http://%s' % proxyServer + proxies['ftp'] = 'ftp://%s' % proxyServer + internetSettings.Close() + except (WindowsError, ValueError, TypeError): + # Either registry key not found etc, or the value in an + # unexpected format. + # proxies already set up to be empty so nothing to do + pass + return proxies + + def getproxies(): + """Return a dictionary of scheme -> proxy server URL mappings. + + Returns settings gathered from the environment, if specified, + or the registry. + + """ + return getproxies_environment() or getproxies_registry() + + def proxy_bypass(host): + try: + import _winreg + import re + except ImportError: + # Std modules, so should be around - but you never know! + return 0 + try: + internetSettings = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, + r'Software\Microsoft\Windows\CurrentVersion\Internet Settings') + proxyEnable = _winreg.QueryValueEx(internetSettings, + 'ProxyEnable')[0] + proxyOverride = str(_winreg.QueryValueEx(internetSettings, + 'ProxyOverride')[0]) + # ^^^^ Returned as Unicode but problems if not converted to ASCII + except WindowsError: + return 0 + if not proxyEnable or not proxyOverride: + return 0 + # try to make a host list from name and IP address. + rawHost, port = splitport(host) + host = [rawHost] + try: + addr = socket.gethostbyname(rawHost) + if addr != rawHost: + host.append(addr) + except socket.error: + pass + try: + fqdn = socket.getfqdn(rawHost) + if fqdn != rawHost: + host.append(fqdn) + except socket.error: + pass + # make a check value list from the registry entry: replace the + # '<local>' string by the localhost entry and the corresponding + # canonical entry. + proxyOverride = proxyOverride.split(';') + i = 0 + while i < len(proxyOverride): + if proxyOverride[i] == '<local>': + proxyOverride[i:i+1] = ['localhost', + '127.0.0.1', + socket.gethostname(), + socket.gethostbyname( + socket.gethostname())] + i += 1 + # print proxyOverride + # now check if we match one of the registry values. + for test in proxyOverride: + test = test.replace(".", r"\.") # mask dots + test = test.replace("*", r".*") # change glob sequence + test = test.replace("?", r".") # change glob char + for val in host: + # print "%s <--> %s" %( test, val ) + if re.match(test, val, re.I): + return 1 + return 0 + +else: + # By default use environment variables + getproxies = getproxies_environment + + def proxy_bypass(host): + return 0 + +# Test and time quote() and unquote() +def test1(): + s = '' + for i in range(256): s = s + chr(i) + s = s*4 + t0 = time.time() + qs = quote(s) + uqs = unquote(qs) + t1 = time.time() + if uqs != s: + print 'Wrong!' + print repr(s) + print repr(qs) + print repr(uqs) + print round(t1 - t0, 3), 'sec' + + +def reporthook(blocknum, blocksize, totalsize): + # Report during remote transfers + print "Block number: %d, Block size: %d, Total size: %d" % ( + blocknum, blocksize, totalsize) + +# Test program +def test(args=[]): + if not args: + args = [ + '/etc/passwd', + 'file:/etc/passwd', + 'file://localhost/etc/passwd', + 'ftp://ftp.gnu.org/pub/README', +## 'gopher://gopher.micro.umn.edu/1/', + 'http://www.python.org/index.html', + ] + if hasattr(URLopener, "open_https"): + args.append('https://synergy.as.cmu.edu/~geek/') + try: + for url in args: + print '-'*10, url, '-'*10 + fn, h = urlretrieve(url, None, reporthook) + print fn + if h: + print '======' + for k in h.keys(): print k + ':', h[k] + print '======' + fp = open(fn, 'rb') + data = fp.read() + del fp + if '\r' in data: + table = string.maketrans("", "") + data = data.translate(table, "\r") + print data + fn, h = None, None + print '-'*40 + finally: + urlcleanup() + +def main(): + import getopt, sys + try: + opts, args = getopt.getopt(sys.argv[1:], "th") + except getopt.error, msg: + print msg + print "Use -h for help" + return + t = 0 + for o, a in opts: + if o == '-t': + t = t + 1 + if o == '-h': + print "Usage: python urllib.py [-t] [url ...]" + print "-t runs self-test;", + print "otherwise, contents of urls are printed" + return + if t: + if t > 1: + test1() + test(args) + else: + if not args: + print "Use -h for help" + for url in args: + print urlopen(url).read(), + +# Run test program when run as a script +if __name__ == '__main__': + main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-27 02:43:23
|
Revision: 6391 http://jython.svn.sourceforge.net/jython/?rev=6391&view=rev Author: pjenvey Date: 2009-05-27 02:43:21 +0000 (Wed, 27 May 2009) Log Message: ----------- windows test fixes: o help test_ftruncate w/ an extra fsync o handle ':' in the test_sax.test_expat_locator_withinfo url o recompile test_java_subclasses' class files and write them in binary mode in hopes this satisifies the buildbot env o regrtest typo Modified Paths: -------------- trunk/jython/Lib/test/regrtest.py trunk/jython/Lib/test/test_fileno.py trunk/jython/Lib/test/test_java_subclasses.py trunk/jython/Lib/test/test_sax.py Modified: trunk/jython/Lib/test/regrtest.py =================================================================== --- trunk/jython/Lib/test/regrtest.py 2009-05-27 02:42:18 UTC (rev 6390) +++ trunk/jython/Lib/test/regrtest.py 2009-05-27 02:43:21 UTC (rev 6391) @@ -1533,7 +1533,7 @@ if test_support.is_jython: if os._name != 'posix': self.expected.update([ - 'test_grb', 'test_mhlib', 'test_posix', 'test_pwd', + 'test_grp', 'test_mhlib', 'test_posix', 'test_pwd', 'test_signal']) self.valid = True Modified: trunk/jython/Lib/test/test_fileno.py =================================================================== --- trunk/jython/Lib/test/test_fileno.py 2009-05-27 02:42:18 UTC (rev 6390) +++ trunk/jython/Lib/test/test_fileno.py 2009-05-27 02:43:21 UTC (rev 6391) @@ -24,6 +24,7 @@ def test_ftruncate(self): self.fp.write('jython filenos') self.fp.flush() + os.fsync(self.fd) self.assertEqual(os.path.getsize(self.filename), 14) os.ftruncate(self.fd, 8) self.assertEqual(os.path.getsize(self.filename), 8) Modified: trunk/jython/Lib/test/test_java_subclasses.py =================================================================== --- trunk/jython/Lib/test/test_java_subclasses.py 2009-05-27 02:42:18 UTC (rev 6390) +++ trunk/jython/Lib/test/test_java_subclasses.py 2009-05-27 02:43:21 UTC (rev 6391) @@ -248,7 +248,7 @@ Checks for http://jython.org/bugs/1861985 ''' def setUp(self): - out = open('Abstract.class', 'w') + out = open('Abstract.class', 'wb') out.write(ABSTRACT_CLASS) out.close() self.orig_syspath = sys.path[:] @@ -277,13 +277,12 @@ """ # The following is the correspoding bytecode for ContextAbstract compiled with javac 1.5 # Needs to be named differently than Abstract above so the class loader won't just use it -CONTEXT_ABSTRACT = '''\ -eJxdjr1uwjAUhc8lbgIh/AVegA0YQJ1BlRBSp6gdWrE7wQKjEEvBVH0tFip14AF4KMQ17YSHc3yu -vuPry/X3DOAZ3RACrRAe2gE6AWKCP9OFti8EbzBcEsTCrBShlehCvR12qSo/ZZrzJE5MJvOlLLXL -/0NhN3pP6CQLU1j1befp3pYys1N+d6fsxqwI4Yc5lJl61a7QewDHW/klIzzBjxDB58UPAKHtkEku -i/XkPd2qzIo+/1/AnQrIdVkDTlN2Yq+NfkCjEyrHO1JlbXLF3QV7lbXGKfqDEaIOCHL7ORMad7J5 -A7yvPDQ= -'''.decode('base64').decode('zlib') +CONTEXT_ABSTRACT = """\ +eJxdTsEOwVAQnK2n1aq2Bz/ghgNxF4lInIQDcX9tX6jQJvWI33IhcfABPkrs69EedjKzM7v7+b7e +AEaIPAj4HmpoOQgchAR7nOWZnhBq3d6WIGZFqgjhIsvV8nKKVbmR8ZEV+6T0vkgJ3rq4lImaZ0Zt +z4pcq5uexmddykQPDvIqfdRh+3Bh86I/AyEyluFR5rvhKj6oRIsO/yNgygKZLHeHWY+RGN3+E9R/ +wLozITS4BxwxdsHYgBBkrlVTr9KbP6qaLFc= +""".decode('base64').decode('zlib') class ContextClassloaderTest(unittest.TestCase): '''Classes on the context classloader should be importable and subclassable. Modified: trunk/jython/Lib/test/test_sax.py =================================================================== --- trunk/jython/Lib/test/test_sax.py 2009-05-27 02:42:18 UTC (rev 6390) +++ trunk/jython/Lib/test/test_sax.py 2009-05-27 02:43:21 UTC (rev 6391) @@ -479,9 +479,8 @@ # replace the backslashes with forward testfile = testfile.replace('\\', '/') - # XXX: may not match getSystemId when the filename contains funky - # characters (like ':') - expected = urllib.quote(testfile) + # urllib.quote isn't the exact encoder (e.g. ':' isn't escaped) + expected = urllib.quote(testfile).replace('%3A', ':') return xmlgen.location.getSystemId().endswith(expected) and \ xmlgen.location.getPublicId() is None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-27 02:42:24
|
Revision: 6390 http://jython.svn.sourceforge.net/jython/?rev=6390&view=rev Author: pjenvey Date: 2009-05-27 02:42:18 +0000 (Wed, 27 May 2009) Log Message: ----------- o fix file repr w/ windows paths and unicode o remove no longer needed test_repr workarounds Modified Paths: -------------- trunk/jython/Lib/test/test_repr.py trunk/jython/src/org/python/core/PyFile.java Modified: trunk/jython/Lib/test/test_repr.py =================================================================== --- trunk/jython/Lib/test/test_repr.py 2009-05-27 01:47:54 UTC (rev 6389) +++ trunk/jython/Lib/test/test_repr.py 2009-05-27 02:42:18 UTC (rev 6390) @@ -130,13 +130,10 @@ def test_file(self): fp = open(unittest.__file__) self.failUnless(repr(fp).startswith( - # XXX: Jython doesn't use hex ids - # "<open file '%s', mode 'r' at 0x" % unittest.__file__)) - "<open file '%s', mode 'r' at " % unittest.__file__)) + "<open file '%s', mode 'r' at 0x" % unittest.__file__)) fp.close() self.failUnless(repr(fp).startswith( - # "<closed file '%s', mode 'r' at 0x" % unittest.__file__)) - "<closed file '%s', mode 'r' at " % unittest.__file__)) + "<closed file '%s', mode 'r' at 0x" % unittest.__file__)) def test_lambda(self): self.failUnless(repr(lambda x: x).startswith( @@ -149,8 +146,7 @@ eq(repr(hash), '<built-in function hash>') # Methods self.failUnless(repr(''.split).startswith( - # '<built-in method split of str object at 0x')) - '<built-in method split of str object at ')) + '<built-in method split of str object at 0x')) def test_xrange(self): import warnings @@ -197,11 +193,9 @@ class C: def foo(cls): pass x = staticmethod(C.foo) - #self.failUnless(repr(x).startswith('<staticmethod object at 0x')) - self.failUnless(repr(x).startswith('<staticmethod object at ')) + self.failUnless(repr(x).startswith('<staticmethod object at 0x')) x = classmethod(C.foo) - #self.failUnless(repr(x).startswith('<classmethod object at 0x')) - self.failUnless(repr(x).startswith('<classmethod object at ')) + self.failUnless(repr(x).startswith('<classmethod object at 0x')) def test_unsortable(self): # Repr.repr() used to call sorted() on sets, frozensets and dicts @@ -283,8 +277,7 @@ from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import bar # Module name may be prefixed with "test.", depending on how run. self.failUnless(repr(bar.bar).startswith( - # "<class %s.bar at 0x" % bar.__name__)) - "<class %s.bar at " % bar.__name__)) + "<class %s.bar at 0x" % bar.__name__)) def test_instance(self): touch(os.path.join(self.subpkgname, 'baz'+os.extsep+'py'), '''\ @@ -294,8 +287,7 @@ from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz ibaz = baz.baz() self.failUnless(repr(ibaz).startswith( - # "<%s.baz instance at 0x" % baz.__name__)) - "<%s.baz instance at " % baz.__name__)) + "<%s.baz instance at 0x" % baz.__name__)) def test_method(self): eq = self.assertEquals @@ -310,8 +302,7 @@ # Bound method next iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() self.failUnless(repr(iqux.amethod).startswith( - # '<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa instance at 0x' \ - '<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa instance at ' \ + '<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa instance at 0x' \ % (qux.__name__,) )) def test_builtin_function(self): Modified: trunk/jython/src/org/python/core/PyFile.java =================================================================== --- trunk/jython/src/org/python/core/PyFile.java 2009-05-27 01:47:54 UTC (rev 6389) +++ trunk/jython/src/org/python/core/PyFile.java 2009-05-27 02:42:18 UTC (rev 6390) @@ -493,20 +493,13 @@ @ExposedMethod(names = {"__str__", "__repr__"}, doc = BuiltinDocs.file___str___doc) final String file_toString() { - StringBuilder s = new StringBuilder("<"); - if (file.closed()) { - s.append("closed "); - } else { - s.append("open "); + String state = file.closed() ? "closed" : "open"; + String id = Py.idstr(this); + if (name instanceof PyUnicode) { + String escapedName = PyString.encode_UnicodeEscape(name.toString(), false); + return String.format("<%s file u'%s', mode '%s' at %s>", state, escapedName, mode, id); } - s.append("file "); - s.append(name.__repr__()); - s.append(", mode '"); - s.append(mode); - s.append("' at "); - s.append(Py.idstr(this)); - s.append(">"); - return s.toString(); + return String.format("<%s file '%s', mode '%s' at %s>", state, name, mode, id); } public String toString() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-27 02:22:31
|
Revision: 6388 http://jython.svn.sourceforge.net/jython/?rev=6388&view=rev Author: pjenvey Date: 2009-05-27 01:46:25 +0000 (Wed, 27 May 2009) Log Message: ----------- solaris test fixes: o apply test_socket bsd setsockopt workaround and then some o extra_collect the particularly garbagey test_scope test twice Modified Paths: -------------- trunk/jython/Lib/test/test_scope.py trunk/jython/Lib/test/test_socket.py Modified: trunk/jython/Lib/test/test_scope.py =================================================================== --- trunk/jython/Lib/test/test_scope.py 2009-05-26 21:57:38 UTC (rev 6387) +++ trunk/jython/Lib/test/test_scope.py 2009-05-27 01:46:25 UTC (rev 6388) @@ -438,6 +438,8 @@ if is_jython: from test_weakref import extra_collect extra_collect() + # A lot of garbage + extra_collect() vereq(Foo.count, 0) print "17. class and global" Modified: trunk/jython/Lib/test/test_socket.py =================================================================== --- trunk/jython/Lib/test/test_socket.py 2009-05-26 21:57:38 UTC (rev 6387) +++ trunk/jython/Lib/test/test_socket.py 2009-05-27 01:46:25 UTC (rev 6388) @@ -23,6 +23,7 @@ EIGHT_BIT_MSG = 'Bh\xed Al\xe1in \xd3 Cinn\xe9ide anseo\n' os_name = platform.java_ver()[3][0] is_bsd = os_name == 'Mac OS X' or 'BSD' in os_name +is_solaris = os_name == 'SunOS' try: True @@ -535,8 +536,11 @@ for expected_value in values: sock.setsockopt(level, option, expected_value) retrieved_value = sock.getsockopt(level, option) - self.failUnlessEqual(retrieved_value, expected_value, \ - "Retrieved option(%s, %s) value %s != %s(value set)" % (level, option, retrieved_value, expected_value)) + msg = "Retrieved option(%s, %s) value %s != %s(value set)" % (level, option, retrieved_value, expected_value) + if is_solaris and option == socket.SO_RCVBUF: + self.assert_(retrieved_value >= expected_value, msg) + else: + self.failUnlessEqual(retrieved_value, expected_value, msg) def _testUDPOption(self, level, option, values): try: @@ -565,8 +569,8 @@ sock.bind( (HOST, PORT+1) ) sock.connect( (HOST, PORT) ) msg = "Option value '%s'='%s' did not propagate to implementation socket" % (option, values[-1]) - if is_bsd and option in (socket.SO_RCVBUF, socket.SO_SNDBUF): - # XXX: there's no guarantee that bufsize will be the + if ((is_bsd or is_solaris) and option in (socket.SO_RCVBUF, socket.SO_SNDBUF)): + # NOTE: there's no guarantee that bufsize will be the # exact setsockopt value, particularly after # establishing a connection. seems it will be *at least* # the values we test (which are rather small) on @@ -587,8 +591,12 @@ # now bind and listen on the socket i.e. cause the implementation socket to be created sock.bind( (HOST, PORT) ) sock.listen(50) - self.failUnlessEqual(sock.getsockopt(level, option), values[-1], \ - "Option value '(%s,%s)'='%s' did not propagate to implementation socket" % (level, option, values[-1])) + msg = "Option value '(%s,%s)'='%s' did not propagate to implementation socket" % (level, option, values[-1]) + if is_solaris and option == socket.SO_RCVBUF: + # NOTE: see similar bsd/solaris workaround above + self.assert_(sock.getsockopt(level, option) >= values[-1], msg) + else: + self.failUnlessEqual(sock.getsockopt(level, option), values[-1], msg) self._testSetAndGetOption(sock, level, option, values) finally: sock.close() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-27 02:22:26
|
Revision: 6389 http://jython.svn.sourceforge.net/jython/?rev=6389&view=rev Author: pjenvey Date: 2009-05-27 01:47:54 +0000 (Wed, 27 May 2009) Log Message: ----------- test_dircache thinko, add more windows regrtest skips Modified Paths: -------------- trunk/jython/Lib/test/regrtest.py trunk/jython/Lib/test/test_dircache.py Modified: trunk/jython/Lib/test/regrtest.py =================================================================== --- trunk/jython/Lib/test/regrtest.py 2009-05-27 01:46:25 UTC (rev 6388) +++ trunk/jython/Lib/test/regrtest.py 2009-05-27 01:47:54 UTC (rev 6389) @@ -1532,7 +1532,9 @@ if test_support.is_jython: if os._name != 'posix': - self.expected.update(['test_mhlib', 'test_signal']) + self.expected.update([ + 'test_grb', 'test_mhlib', 'test_posix', 'test_pwd', + 'test_signal']) self.valid = True Modified: trunk/jython/Lib/test/test_dircache.py =================================================================== --- trunk/jython/Lib/test/test_dircache.py 2009-05-27 01:46:25 UTC (rev 6388) +++ trunk/jython/Lib/test/test_dircache.py 2009-05-27 01:47:54 UTC (rev 6389) @@ -44,8 +44,8 @@ # That is, this test can't possibly work under Windows -- dircache # is only good for capturing a one-shot snapshot there. - if (sys.platform[:3] not in ('win', 'os2') or - (is_jython and os._name != 'nt')): + if (sys.platform[:3] not in ('win', 'os2') and + (not is_jython or os._name != 'nt')): # Sadly, dircache has the same granularity as stat.mtime, and so # can't notice any changes that occurred within 1 sec of the last # time it examined a directory. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 21:57:40
|
Revision: 6387 http://jython.svn.sourceforge.net/jython/?rev=6387&view=rev Author: pjenvey Date: 2009-05-26 21:57:38 +0000 (Tue, 26 May 2009) Log Message: ----------- abspath relative $PRG symlinks so sys.executable can work. fix from jruby thanks Roland Walter fixes #1357 Modified Paths: -------------- trunk/jython/NEWS trunk/jython/src/shell/jython Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2009-05-26 19:46:24 UTC (rev 6386) +++ trunk/jython/NEWS 2009-05-26 21:57:38 UTC (rev 6387) @@ -1,5 +1,9 @@ Jython NEWS +Jython 2.5.0 + Bugs fixed + - [ 1357 ] no sys.executable when script runner is a relative link + Jython 2.5.0 rc3 Bugs fixed - [ 1344 ] setName semantics of threading.Thread different to CPython Modified: trunk/jython/src/shell/jython =================================================================== --- trunk/jython/src/shell/jython 2009-05-26 19:46:24 UTC (rev 6386) +++ trunk/jython/src/shell/jython 2009-05-26 21:57:38 UTC (rev 6387) @@ -29,7 +29,11 @@ ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '.*/.*' > /dev/null; then - PRG="$link" + if expr "$link" : '^/' > /dev/null; then + PRG="$link" + else + PRG="`dirname ${PRG}`/${link}" + fi else PRG="`dirname $PRG`/$link" fi This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-05-26 19:47:24
|
Revision: 6386 http://jython.svn.sourceforge.net/jython/?rev=6386&view=rev Author: fwierzbicki Date: 2009-05-26 19:46:24 +0000 (Tue, 26 May 2009) Log Message: ----------- tag rc3 Added Paths: ----------- tags/Release_2_5rc3/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-05-26 19:45:33
|
Revision: 6385 http://jython.svn.sourceforge.net/jython/?rev=6385&view=rev Author: fwierzbicki Date: 2009-05-26 19:44:21 +0000 (Tue, 26 May 2009) Log Message: ----------- RC3 numbering Modified Paths: -------------- trunk/jython/NEWS trunk/jython/README.txt trunk/jython/build.xml Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2009-05-26 19:24:16 UTC (rev 6384) +++ trunk/jython/NEWS 2009-05-26 19:44:21 UTC (rev 6385) @@ -1,12 +1,12 @@ Jython NEWS -Jython 2.5.0 +Jython 2.5.0 rc3 Bugs fixed - [ 1344 ] setName semantics of threading.Thread different to CPython - Fixed JLine console on cygwin - [ 1348 ] muti-threaded issue, maybe threads cannot exit -Jython 2.5.0 a0 - rc1 +Jython 2.5.0 a0 - rc2 Bugs fixed (new numbering due to move to Roundup) - [ 1188 ] Patch against trunk to handle SecurityExceptions - [ 1271 ] Bean property accessors in derived class overide methods in base class Modified: trunk/jython/README.txt =================================================================== --- trunk/jython/README.txt 2009-05-26 19:24:16 UTC (rev 6384) +++ trunk/jython/README.txt 2009-05-26 19:44:21 UTC (rev 6385) @@ -1,15 +1,9 @@ -Welcome to Jython 2.5rc2 +Welcome to Jython 2.5rc3 ======================== -This is the second release candidate of the 2.5 version of Jython (about 10 -minutes after the first). It fixes a windows bug with our jline support on -windows. Below is the RC1 notes: +This is the third release candidate of the 2.5 version of Jython. It partially +fixes JLine on Cygwin and some threading issues. -It contains bug fixes and polish since the last beta. One especially nice bit -of polish is that jline is enabled by default now, and so using up and down -arrows should work out of the box. If no major bugs are found this release -will get re-labled and released as the production version of 2.5.0. - The release was compiled on Mac OS X with JDK 5 and requires JDK 5 to run. Please try this out and report any bugs at http://bugs.jython.org. Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2009-05-26 19:24:16 UTC (rev 6384) +++ trunk/jython/build.xml 2009-05-26 19:44:21 UTC (rev 6385) @@ -187,13 +187,13 @@ <property name="PY_RELEASE_LEVEL_SNAPSHOT" value="170"/> <!-- 0xAA --> <!-- The current version info --> - <property name="jython.version" value="2.5rc2+"/> - <property name="jython.version.noplus" value="2.5rc2"/> + <property name="jython.version" value="2.5rc3+"/> + <property name="jython.version.noplus" value="2.5rc3"/> <property name="jython.major_version" value="2"/> <property name="jython.minor_version" value="5"/> <property name="jython.micro_version" value="0"/> <property name="jython.release_level" value="${PY_RELEASE_LEVEL_GAMMA}"/> - <property name="jython.release_serial" value="2"/> + <property name="jython.release_serial" value="3"/> <condition property="do.snapshot.build"> <isset property="snapshot.revision" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fwi...@us...> - 2009-05-26 19:26:58
|
Revision: 6384 http://jython.svn.sourceforge.net/jython/?rev=6384&view=rev Author: fwierzbicki Date: 2009-05-26 19:24:16 +0000 (Tue, 26 May 2009) Log Message: ----------- Change build target for maven. Modified Paths: -------------- trunk/jython/maven/build.xml Modified: trunk/jython/maven/build.xml =================================================================== --- trunk/jython/maven/build.xml 2009-05-26 07:46:39 UTC (rev 6383) +++ trunk/jython/maven/build.xml 2009-05-26 19:24:16 UTC (rev 6384) @@ -153,6 +153,6 @@ </target> <target name="build-jython" depends="clean"> - <ant antfile="build.xml" target="developer-build"/> + <ant antfile="build.xml" target="jar-complete"/> </target> </project> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 07:46:49
|
Revision: 6383 http://jython.svn.sourceforge.net/jython/?rev=6383&view=rev Author: pjenvey Date: 2009-05-26 07:46:39 +0000 (Tue, 26 May 2009) Log Message: ----------- more testing on Windows fixes Modified Paths: -------------- trunk/jython/Lib/test/check_for_initializer_in_syspath.py trunk/jython/Lib/test/test_marshal.py trunk/jython/Lib/test/test_tarfile.py Modified: trunk/jython/Lib/test/check_for_initializer_in_syspath.py =================================================================== --- trunk/jython/Lib/test/check_for_initializer_in_syspath.py 2009-05-26 07:00:22 UTC (rev 6382) +++ trunk/jython/Lib/test/check_for_initializer_in_syspath.py 2009-05-26 07:46:39 UTC (rev 6383) @@ -1,2 +1,4 @@ +import os import sys -assert "/from_SyspathAppendingInitializer_with_love" in sys.path +path = os.path.abspath("/from_SyspathAppendingInitializer_with_love") +assert path in sys.path Modified: trunk/jython/Lib/test/test_marshal.py =================================================================== --- trunk/jython/Lib/test/test_marshal.py 2009-05-26 07:00:22 UTC (rev 6382) +++ trunk/jython/Lib/test/test_marshal.py 2009-05-26 07:46:39 UTC (rev 6383) @@ -16,7 +16,7 @@ with open(test_support.TESTFN, "wb") as test_file: marshal.dump(item, test_file) with open(test_support.TESTFN, "rb") as test_file: - got = marshal.load(file(test_support.TESTFN, "rb")) #, debug=True) + got = marshal.load(test_file) return got Modified: trunk/jython/Lib/test/test_tarfile.py =================================================================== --- trunk/jython/Lib/test/test_tarfile.py 2009-05-26 07:00:22 UTC (rev 6382) +++ trunk/jython/Lib/test/test_tarfile.py 2009-05-26 07:46:39 UTC (rev 6383) @@ -200,7 +200,8 @@ def test_extractall(self): # Test if extractall() correctly restores directory permissions # and times (see issue1735). - if sys.platform == "win32": + if (sys.platform == "win32" or + test_support.is_jython and os._name == 'nt'): # Win32 has no support for utime() on directories or # fine grained permissions. return @@ -275,6 +276,9 @@ def setUp(self): self.tar = tarfile.open(tarname(self.comp), self.mode) + def tearDown(self): + self.tar.close() + class ReadDetectFileobjTest(ReadTest): def setUp(self): @@ -322,6 +326,7 @@ fobj.seek(offset) # Test if the tarfile starts with the second member. + self.tar.close() self.tar = tarfile.open(tarname(self.comp), "r:", fileobj=fobj) t = self.tar.next() self.assertEqual(t.name, name) @@ -330,6 +335,8 @@ self.tar.getmembers() self.assertEqual(self.tar.extractfile(t).read(), data, "seek back did not work") + self.tar.close() + fobj.close() class WriteTest(BaseTest): mode = 'w' @@ -460,9 +467,11 @@ s = f.read() f.close() elif self.comp == "bz2": - f = bz2.BZ2Decompressor() - s = file(self.dstname).read() - s = f.decompress(s) + b = bz2.BZ2Decompressor() + f = file(self.dstname) + s = f.read() + f.close() + s = b.decompress(s) self.assertEqual(len(f.unused_data), 0, "trailing data") else: f = file(self.dstname) @@ -718,22 +727,27 @@ def test_no_name_argument(self): fobj = open(testtar, "rb") - tar = tarfile.open(fileobj=fobj, mode="r") - self.assertEqual(tar.name, os.path.abspath(fobj.name)) + self.tar = tarfile.open(fileobj=fobj, mode="r") + self.assertEqual(self.tar.name, os.path.abspath(fobj.name)) + fobj.close() def test_no_name_attribute(self): - data = open(testtar, "rb").read() + fp = open(testtar, "rb") + data = fp.read() + fp.close() fobj = StringIO.StringIO(data) self.assertRaises(AttributeError, getattr, fobj, "name") - tar = tarfile.open(fileobj=fobj, mode="r") - self.assertEqual(tar.name, None) + self.tar = tarfile.open(fileobj=fobj, mode="r") + self.assertEqual(self.tar.name, None) def test_empty_name_attribute(self): - data = open(testtar, "rb").read() + fp = open(testtar, "rb") + data = fp.read() + fp.close() fobj = StringIO.StringIO(data) fobj.name = "" - tar = tarfile.open(fileobj=fobj, mode="r") - self.assertEqual(tar.name, None) + self.tar = tarfile.open(fileobj=fobj, mode="r") + self.assertEqual(self.tar.name, None) if bz2: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 07:00:31
|
Revision: 6382 http://jython.svn.sourceforge.net/jython/?rev=6382&view=rev Author: pjenvey Date: 2009-05-26 07:00:22 +0000 (Tue, 26 May 2009) Log Message: ----------- upgrade Windows environ.os.update from CPython 2.5's os.py Modified Paths: -------------- trunk/jython/Lib/os.py Modified: trunk/jython/Lib/os.py =================================================================== --- trunk/jython/Lib/os.py 2009-05-26 06:50:56 UTC (rev 6381) +++ trunk/jython/Lib/os.py 2009-05-26 07:00:22 UTC (rev 6382) @@ -904,9 +904,22 @@ return key.upper() in self.data def get(self, key, failobj=None): return self.data.get(key.upper(), failobj) - def update(self, dict): - for k, v in dict.items(): - self[k] = v + def update(self, dict=None, **kwargs): + if dict: + try: + keys = dict.keys() + except AttributeError: + # List of (key, value) + for k, v in dict: + self[k] = v + else: + # got keys + # cannot use items(), since mappings + # may not have them. + for k in keys: + self[k] = dict[k] + if kwargs: + self.update(kwargs) def copy(self): return dict(self) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 06:51:06
|
Revision: 6381 http://jython.svn.sourceforge.net/jython/?rev=6381&view=rev Author: pjenvey Date: 2009-05-26 06:50:56 +0000 (Tue, 26 May 2009) Log Message: ----------- add os.fsync/datasync Modified Paths: -------------- trunk/jython/Lib/os.py Modified: trunk/jython/Lib/os.py =================================================================== --- trunk/jython/Lib/os.py 2009-05-26 06:49:37 UTC (rev 6380) +++ trunk/jython/Lib/os.py 2009-05-26 06:50:56 UTC (rev 6381) @@ -30,9 +30,9 @@ 'O_RDWR', 'O_SYNC', 'O_TRUNC', 'O_WRONLY', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'W_OK', 'X_OK', '_exit', 'access', 'altsep', 'chdir', 'chmod', 'close', 'curdir', 'defpath', - 'environ', 'error', 'fdopen', 'getcwd', 'getcwdu', 'getenv', - 'getpid', 'isatty', 'linesep', 'listdir', 'lseek', 'lstat', - 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', + 'environ', 'error', 'fdopen', 'fsync', 'getcwd', 'getcwdu', + 'getenv', 'getpid', 'isatty', 'linesep', 'listdir', 'lseek', + 'lstat', 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', 'pathsep', 'popen', 'popen2', 'popen3', 'popen4', 'putenv', 'read', 'remove', 'removedirs', 'rename', 'renames', 'rmdir', 'sep', 'stat', 'stat_result', 'strerror', 'system', 'unlink', @@ -1048,10 +1048,41 @@ raise OSError(status[0], strerror(status[0])) return res_pid, status[0] + def fdatasync(fd): + """fdatasync(fildes) + + force write of file with filedescriptor to disk. + does not force update of metadata. + """ + _fsync(fd, False) + __all__.extend(['link', 'symlink', 'readlink', 'getegid', 'geteuid', 'getgid', 'getlogin', 'getpgrp', 'getppid', 'getuid', - 'setpgrp', 'setsid', 'kill', 'wait', 'waitpid']) + 'setpgrp', 'setsid', 'kill', 'wait', 'waitpid', + 'fdatasync']) +def fsync(fd): + """fsync(fildes) + + force write of file with filedescriptor to disk. + """ + _fsync(fd, True) + +def _fsync(fd, metadata): + """Internal fsync impl""" + rawio = FileDescriptors.get(fd) + rawio.checkClosed() + + from java.nio.channels import FileChannel + channel = rawio.getChannel() + if not isinstance(channel, FileChannel): + raise OSError(errno.EINVAL, strerror(errno.EINVAL)) + + try: + channel.force(metadata) + except java.io.IOException, ioe: + raise OSError(ioe) + def getpid(): """getpid() -> pid This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 06:49:59
|
Revision: 6380 http://jython.svn.sourceforge.net/jython/?rev=6380&view=rev Author: pjenvey Date: 2009-05-26 06:49:37 +0000 (Tue, 26 May 2009) Log Message: ----------- add windows skips, close files in test_traceback Modified Paths: -------------- trunk/jython/Lib/test/regrtest.py trunk/jython/Lib/test/test_dircache.py trunk/jython/Lib/test/test_signal.py trunk/jython/Lib/test/test_traceback.py Modified: trunk/jython/Lib/test/regrtest.py =================================================================== --- trunk/jython/Lib/test/regrtest.py 2009-05-26 06:40:28 UTC (rev 6379) +++ trunk/jython/Lib/test/regrtest.py 2009-05-26 06:49:37 UTC (rev 6380) @@ -1532,9 +1532,7 @@ if test_support.is_jython: if os._name != 'posix': - self.expected.add('test_mhlib') - import platform - os_name = platform.java_ver()[3][0] + self.expected.update(['test_mhlib', 'test_signal']) self.valid = True Modified: trunk/jython/Lib/test/test_dircache.py =================================================================== --- trunk/jython/Lib/test/test_dircache.py 2009-05-26 06:40:28 UTC (rev 6379) +++ trunk/jython/Lib/test/test_dircache.py 2009-05-26 06:49:37 UTC (rev 6380) @@ -4,7 +4,7 @@ """ import unittest -from test.test_support import run_unittest, TESTFN +from test.test_support import is_jython, run_unittest, TESTFN import dircache, os, time, sys, tempfile @@ -44,7 +44,8 @@ # That is, this test can't possibly work under Windows -- dircache # is only good for capturing a one-shot snapshot there. - if sys.platform[:3] not in ('win', 'os2'): + if (sys.platform[:3] not in ('win', 'os2') or + (is_jython and os._name != 'nt')): # Sadly, dircache has the same granularity as stat.mtime, and so # can't notice any changes that occurred within 1 sec of the last # time it examined a directory. Modified: trunk/jython/Lib/test/test_signal.py =================================================================== --- trunk/jython/Lib/test/test_signal.py 2009-05-26 06:40:28 UTC (rev 6379) +++ trunk/jython/Lib/test/test_signal.py 2009-05-26 06:49:37 UTC (rev 6380) @@ -20,7 +20,8 @@ import traceback import sys, os, time, errno -if sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos': +if (sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos' or + (test_support.is_jython and os._name == 'nt')): raise test_support.TestSkipped("Can't test signal on %s" % \ sys.platform) Modified: trunk/jython/Lib/test/test_traceback.py =================================================================== --- trunk/jython/Lib/test/test_traceback.py 2009-05-26 06:40:28 UTC (rev 6379) +++ trunk/jython/Lib/test/test_traceback.py 2009-05-26 06:49:37 UTC (rev 6380) @@ -1,5 +1,6 @@ """Test cases for traceback module""" +from __future__ import with_statement import unittest from test.test_support import run_unittest, is_jython @@ -62,7 +63,8 @@ try: sys.path.insert(0, testdir) testfile = os.path.join(testdir, 'test_bug737473.py') - print >> open(testfile, 'w'), """ + with open(testfile, 'w') as fp: + print >> fp, """ def test(): raise ValueError""" @@ -84,7 +86,8 @@ # three seconds are needed for this test to pass reliably :-( time.sleep(4) - print >> open(testfile, 'w'), """ + with open(testfile, 'w') as fp: + print >> fp, """ def test(): raise NotImplementedError""" reload(test_bug737473) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 06:40:45
|
Revision: 6379 http://jython.svn.sourceforge.net/jython/?rev=6379&view=rev Author: pjenvey Date: 2009-05-26 06:40:28 +0000 (Tue, 26 May 2009) Log Message: ----------- from: http://svn.python.org/projects/python/branches/release25-maint/Lib/test/test_dircache.py@41342 Added Paths: ----------- trunk/jython/Lib/test/test_dircache.py Added: trunk/jython/Lib/test/test_dircache.py =================================================================== --- trunk/jython/Lib/test/test_dircache.py (rev 0) +++ trunk/jython/Lib/test/test_dircache.py 2009-05-26 06:40:28 UTC (rev 6379) @@ -0,0 +1,73 @@ +""" + Test cases for the dircache module + Nick Mathewson +""" + +import unittest +from test.test_support import run_unittest, TESTFN +import dircache, os, time, sys, tempfile + + +class DircacheTests(unittest.TestCase): + def setUp(self): + self.tempdir = tempfile.mkdtemp() + + def tearDown(self): + for fname in os.listdir(self.tempdir): + self.delTemp(fname) + os.rmdir(self.tempdir) + + def writeTemp(self, fname): + f = open(os.path.join(self.tempdir, fname), 'w') + f.close() + + def mkdirTemp(self, fname): + os.mkdir(os.path.join(self.tempdir, fname)) + + def delTemp(self, fname): + fname = os.path.join(self.tempdir, fname) + if os.path.isdir(fname): + os.rmdir(fname) + else: + os.unlink(fname) + + def test_listdir(self): + ## SUCCESSFUL CASES + entries = dircache.listdir(self.tempdir) + self.assertEquals(entries, []) + + # Check that cache is actually caching, not just passing through. + self.assert_(dircache.listdir(self.tempdir) is entries) + + # Directories aren't "files" on Windows, and directory mtime has + # nothing to do with when files under a directory get created. + # That is, this test can't possibly work under Windows -- dircache + # is only good for capturing a one-shot snapshot there. + + if sys.platform[:3] not in ('win', 'os2'): + # Sadly, dircache has the same granularity as stat.mtime, and so + # can't notice any changes that occurred within 1 sec of the last + # time it examined a directory. + time.sleep(1) + self.writeTemp("test1") + entries = dircache.listdir(self.tempdir) + self.assertEquals(entries, ['test1']) + self.assert_(dircache.listdir(self.tempdir) is entries) + + ## UNSUCCESSFUL CASES + self.assertRaises(OSError, dircache.listdir, self.tempdir+"_nonexistent") + + def test_annotate(self): + self.writeTemp("test2") + self.mkdirTemp("A") + lst = ['A', 'test2', 'test_nonexistent'] + dircache.annotate(self.tempdir, lst) + self.assertEquals(lst, ['A/', 'test2', 'test_nonexistent']) + + +def test_main(): + run_unittest(DircacheTests) + + +if __name__ == "__main__": + test_main() Property changes on: trunk/jython/Lib/test/test_dircache.py ___________________________________________________________________ Added: svn:keywords + Id This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 06:38:55
|
Revision: 6378 http://jython.svn.sourceforge.net/jython/?rev=6378&view=rev Author: pjenvey Date: 2009-05-26 06:38:46 +0000 (Tue, 26 May 2009) Log Message: ----------- Thread ClassLoader can be null in the Finalizer thread (e.g. importing in __del__) Modified Paths: -------------- trunk/jython/src/org/python/core/Py.java Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2009-05-26 06:28:07 UTC (rev 6377) +++ trunk/jython/src/org/python/core/Py.java 2009-05-26 06:38:46 UTC (rev 6378) @@ -749,7 +749,7 @@ private static boolean secEnv = false; - public static Class findClass(String name) { + public static Class<?> findClass(String name) { try { ClassLoader classLoader = Py.getSystemState().getClassLoader(); if (classLoader != null) { @@ -771,8 +771,11 @@ } } - return Thread.currentThread().getContextClassLoader().loadClass(name); - + classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader != null) { + return classLoader.loadClass(name); + } + return null; } catch (ClassNotFoundException e) { // e.printStackTrace(); return null; @@ -785,7 +788,7 @@ } } - public static Class findClassEx(String name, String reason) { + public static Class<?> findClassEx(String name, String reason) { try { ClassLoader classLoader = Py.getSystemState().getClassLoader(); if (classLoader != null) { @@ -813,7 +816,11 @@ writeDebug("import", "trying " + name + " as " + reason + " in Class.forName"); - return Thread.currentThread().getContextClassLoader().loadClass(name); + classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader != null) { + return classLoader.loadClass(name); + } + return null; } catch (ClassNotFoundException e) { return null; } catch (IllegalArgumentException e) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 06:28:28
|
Revision: 6377 http://jython.svn.sourceforge.net/jython/?rev=6377&view=rev Author: pjenvey Date: 2009-05-26 06:28:07 +0000 (Tue, 26 May 2009) Log Message: ----------- disable test_mailbox on Windows for now because it fails so miserably and ruins other tests Modified Paths: -------------- trunk/jython/Lib/test/regrtest.py Modified: trunk/jython/Lib/test/regrtest.py =================================================================== --- trunk/jython/Lib/test/regrtest.py 2009-05-26 00:03:26 UTC (rev 6376) +++ trunk/jython/Lib/test/regrtest.py 2009-05-26 06:28:07 UTC (rev 6377) @@ -1489,6 +1489,10 @@ _platform = sys.platform if _platform[:4] == 'java': _platform = 'java' + if os._name == 'nt': + # XXX: Omitted for now because it fails so miserably and ruins + # other tests + _failures['java'] += '\ntest_mailbox' class _ExpectedSkips: def __init__(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-26 00:03:42
|
Revision: 6376 http://jython.svn.sourceforge.net/jython/?rev=6376&view=rev Author: pjenvey Date: 2009-05-26 00:03:26 +0000 (Tue, 26 May 2009) Log Message: ----------- fix quoted/escaped non-sequence str cmdlines on Windows by first parsing them into an escaped argv. painful but necessary as Java takes a List<String> cmdline. cases like these are ruined otherwise as Java rejoins it with a list2cmdline-like routine for passing to Windows' CreateProcess Modified Paths: -------------- trunk/jython/Lib/subprocess.py trunk/jython/Lib/test/test_subprocess_jy.py Modified: trunk/jython/Lib/subprocess.py =================================================================== --- trunk/jython/Lib/subprocess.py 2009-05-25 06:07:22 UTC (rev 6375) +++ trunk/jython/Lib/subprocess.py 2009-05-26 00:03:26 UTC (rev 6376) @@ -544,21 +544,80 @@ if jython: - # Escape the command line arguments with list2cmdline on Windows - _escape_args_oses = ['nt'] + # Parse command line arguments for Windows + _win_oses = ['nt'] + _cmdline2list = None _escape_args = None _shell_command = None + def cmdline2list(cmdline): + """Build an argv list from a Microsoft shell style cmdline str + + The reverse of list2cmdline that follows the same MS C runtime + rules. + + Java's ProcessBuilder takes a List<String> cmdline that's joined + with a list2cmdline-like routine for Windows CreateProcess + (which takes a String cmdline). This process ruins String + cmdlines from the user with escapes or quotes. To avoid this we + first parse these cmdlines into an argv. + + Runtime.exec(String) is too naive and useless for this case. + """ + whitespace = ' \t' + # count of preceding '\' + bs_count = 0 + in_quotes = False + arg = [] + argv = [] + + for ch in cmdline: + if ch in whitespace and not in_quotes: + if arg: + # finalize arg and reset + argv.append(''.join(arg)) + arg = [] + bs_count = 0 + elif ch == '\\': + arg.append(ch) + bs_count += 1 + elif ch == '"': + if not bs_count % 2: + # Even number of '\' followed by a '"'. Place one + # '\' for every pair and treat '"' as a delimiter + if bs_count: + del arg[-(bs_count / 2):] + in_quotes = not in_quotes + else: + # Odd number of '\' followed by a '"'. Place one '\' + # for every pair and treat '"' as an escape sequence + # by the remaining '\' + del arg[-(bs_count / 2 + 1):] + arg.append(ch) + bs_count = 0 + else: + # regular char + arg.append(ch) + bs_count = 0 + + # A single trailing '"' delimiter yields an empty arg + if arg or in_quotes: + argv.append(''.join(arg)) + + return argv + def _setup_platform(): """Setup the shell command and the command line argument escape function depending on the underlying platform """ - global _escape_args, _shell_command + global _cmdline2list, _escape_args, _shell_command - if os._name in _escape_args_oses: + if os._name in _win_oses: + _cmdline2list = cmdline2list _escape_args = lambda args: [list2cmdline([arg]) for arg in args] else: + _cmdline2list = lambda args: [args] _escape_args = lambda args: args os_info = os._os_map.get(os._name) @@ -1167,7 +1226,7 @@ """Execute program (Java version)""" if isinstance(args, types.StringTypes): - args = [args] + args = _cmdline2list(args) else: args = list(args) # NOTE: CPython posix (execv) will str() any unicode @@ -1175,7 +1234,7 @@ # posix. Windows passes unicode through, however if any(not isinstance(arg, (str, unicode)) for arg in args): raise TypeError('args must contain only strings') - args = _escape_args(args) + args = _escape_args(args) if shell: args = _shell_command + args Modified: trunk/jython/Lib/test/test_subprocess_jy.py =================================================================== --- trunk/jython/Lib/test/test_subprocess_jy.py 2009-05-25 06:07:22 UTC (rev 6375) +++ trunk/jython/Lib/test/test_subprocess_jy.py 2009-05-26 00:03:26 UTC (rev 6376) @@ -3,7 +3,7 @@ import os import sys from test import test_support -from subprocess import Popen, PIPE +from subprocess import PIPE, Popen, cmdline2list class EnvironmentInheritanceTest(unittest.TestCase): @@ -38,9 +38,41 @@ self.assertEquals(options, p1.stdout.read()) +class Cmdline2ListTestCase(unittest.TestCase): + + cmdlines = { + # From "Parsing C Command-Line Arguments" + # http://msdn.microsoft.com/en-us/library/a1y7w461(VS.80).aspx + '"a b c" d e': ['a b c', 'd', 'e'], + r'"ab\"c" "\\" d': ['ab"c', '\\', 'd'], + r'a\\\b d"e f"g h': [r'a\\\b', 'de fg', 'h'], + r'a\\\"b c d': [r'a\"b', 'c', 'd'], + r'a\\\\"b c" d e': [r'a\\b c', 'd', 'e'], + + r'C:\\foo\bar\baz jy thon': [r'C:\\foo\bar\baz', 'jy', 'thon'], + r'C:\\Program Files\Foo\Bar qu \\ ux': + [r'C:\\Program', 'Files\Foo\Bar', 'qu', '\\\\', 'ux'], + r'"C:\\Program Files\Foo\Bar" qu \\ ux': + [r'C:\\Program Files\Foo\Bar', 'qu', '\\\\', 'ux'], + r'dir "C:\\Program Files\Foo\\" bar': + ['dir', 'C:\\\\Program Files\\Foo\\', 'bar'], + + r'echo "\"I hate Windows!\""': ['echo', '"I hate Windows!"'], + r'print "jython" "': ['print', 'jython', ''], + r'print \"jython\" \"': ['print', '"jython"', '"'], + r'print \"jython\" \\"': ['print', '"jython"', '\\'] + } + + def test_cmdline2list(self): + for cmdline, argv in self.cmdlines.iteritems(): + self.assertEqual(cmdline2list(cmdline), argv) + + def test_main(): - test_support.run_unittest(EnvironmentInheritanceTest, - JythonOptsTest) + test_support.run_unittest( + EnvironmentInheritanceTest, + JythonOptsTest, + Cmdline2ListTestCase) if __name__ == '__main__': This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2009-05-25 06:07:31
|
Revision: 6375 http://jython.svn.sourceforge.net/jython/?rev=6375&view=rev Author: otmarhumbel Date: 2009-05-25 06:07:22 +0000 (Mon, 25 May 2009) Log Message: ----------- fix expected java command under windows Modified Paths: -------------- trunk/installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java Modified: trunk/installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java =================================================================== --- trunk/installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java 2009-05-24 03:30:08 UTC (rev 6374) +++ trunk/installer/test/java/org/python/util/install/driver/StandaloneVerifierTest.java 2009-05-25 06:07:22 UTC (rev 6375) @@ -51,7 +51,9 @@ .concat("bin") .concat(File.separator) .concat("java"); - if (Installation.isWindows()) {} + if (Installation.isWindows()) { + expectedCommand = expectedCommand.concat(".exe"); + } String expectedArgument = prefix.concat("autotest.py"); _verifier.setTargetDir(targetDir); String[] command = _verifier.getSimpleCommand(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-24 03:30:31
|
Revision: 6374 http://jython.svn.sourceforge.net/jython/?rev=6374&view=rev Author: pjenvey Date: 2009-05-24 03:30:08 +0000 (Sun, 24 May 2009) Log Message: ----------- swallow Windows IOExceptions here instead of the localized message bit, since it's during init. if the file has real issues you'll hopefully notice later Modified Paths: -------------- trunk/jython/src/org/python/core/io/FileIO.java Modified: trunk/jython/src/org/python/core/io/FileIO.java =================================================================== --- trunk/jython/src/org/python/core/io/FileIO.java 2009-05-24 03:19:33 UTC (rev 6373) +++ trunk/jython/src/org/python/core/io/FileIO.java 2009-05-24 03:30:08 UTC (rev 6374) @@ -164,13 +164,15 @@ fileChannel.truncate(0); } catch (IOException ioe) { // On Solaris and Linux, ftruncate(3C) returns EINVAL if not a regular - // file whereas, e.g., open(os.devnull, "w") works. Likewise Windows - // returns ERROR_INVALID_FUNCTION. Because we have to simulate the "w" - // mode in Java, we suppress the exception. - String message = ioe.getMessage(); - if (((Platform.IS_SOLARIS || Platform.IS_LINUX) - && Errno.EINVAL.description().equals(message)) - || (Platform.IS_WINDOWS && isIncorrectFunction(message))) { + // file whereas, e.g., open(os.devnull, "w") works. Because we have to + // simulate the "w" mode in Java, we suppress the exception. + // Likewise Windows returns ERROR_INVALID_FUNCTION in that case and + // ERROR_INVALID_HANDLE on ttys. Identifying those by the IOException + // message is tedious as their messages are localized, so we suppress them + // all =[ + if (Platform.IS_WINDOWS || + ((Platform.IS_SOLARIS || Platform.IS_LINUX) + && Errno.EINVAL.description().equals(ioe.getMessage()))) { return; } throw Py.IOError(ioe); @@ -178,16 +180,6 @@ } } - private boolean isIncorrectFunction(String msg) { - String ae = "\u00E4"; - if ("Incorrect function".equals(msg)) { // en - return true; - } else if ("Unzul".concat(ae).concat("ssige Funktion").equals(msg)) { // de_CH - return true; - } - return false; - } - /** {@inheritDoc} */ public boolean isatty() { checkClosed(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-24 03:19:38
|
Revision: 6373 http://jython.svn.sourceforge.net/jython/?rev=6373&view=rev Author: pjenvey Date: 2009-05-24 03:19:33 +0000 (Sun, 24 May 2009) Log Message: ----------- small cleanup Modified Paths: -------------- trunk/jython/Lib/test/test_chdir.py Modified: trunk/jython/Lib/test/test_chdir.py =================================================================== --- trunk/jython/Lib/test/test_chdir.py 2009-05-24 02:53:41 UTC (rev 6372) +++ trunk/jython/Lib/test/test_chdir.py 2009-05-24 03:19:33 UTC (rev 6373) @@ -17,13 +17,8 @@ COMPILED_SUFFIX = [suffix for suffix, mode, type in imp.get_suffixes() if type == imp.PY_COMPILED][0] -EXECUTABLE = sys.executable or \ - (sys.platform.startswith('java') and 'jython' or None) +WINDOWS = (os._name if test_support.is_jython else os.name) == 'nt' -WINDOWS = os.name in ('nt', 'ce') or sys.platform.startswith('java') and \ - os._name in ('nt', 'ce') - - CODE1 = """result = 'result is %r' % (100.0 * (3.0 / 5.0))""" CODE1_RESULT = 'result is %r' % (100.0 * (3.0 / 5.0)) @@ -383,7 +378,7 @@ # Write out the external app's cwd to a file we'll specify in setUp COMMAND = '''\ "%s" -c "import os; fp = open(r'%%s', 'w'); fp.write(os.getcwd())"''' % \ - EXECUTABLE + sys.executable def test_popen(self): os.popen(self._command()).read() @@ -684,13 +679,13 @@ ListdirTestCase, DirsTestCase, FilesTestCase] - if sys.platform.startswith('java'): + if WINDOWS: + tests.append(WindowsChdirTestCase) + if test_support.is_jython: tests.extend((ImportJavaClassTestCase, ImportJarTestCase)) if test_support.is_resource_enabled('subprocess'): tests.append(SubprocessTestCase) - if WINDOWS: - tests.append(WindowsChdirTestCase) test_support.run_unittest(*tests) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-24 02:53:58
|
Revision: 6372 http://jython.svn.sourceforge.net/jython/?rev=6372&view=rev Author: pjenvey Date: 2009-05-24 02:53:41 +0000 (Sun, 24 May 2009) Log Message: ----------- use $py.class instead of just .class for the imp.PY_COMPILED suffix Modified Paths: -------------- trunk/jython/Lib/test/test_chdir.py trunk/jython/src/org/python/modules/imp.java Modified: trunk/jython/Lib/test/test_chdir.py =================================================================== --- trunk/jython/Lib/test/test_chdir.py 2009-05-23 20:33:14 UTC (rev 6371) +++ trunk/jython/Lib/test/test_chdir.py 2009-05-24 02:53:41 UTC (rev 6372) @@ -14,9 +14,8 @@ import zipimport from test import test_support -COMPILED_SUFFIX = sys.platform.startswith('java') and '$py.class' or \ - [suffix for suffix, mode, type in imp.get_suffixes() - if type == imp.PY_COMPILED][0] +COMPILED_SUFFIX = [suffix for suffix, mode, type in imp.get_suffixes() + if type == imp.PY_COMPILED][0] EXECUTABLE = sys.executable or \ (sys.platform.startswith('java') and 'jython' or None) Modified: trunk/jython/src/org/python/modules/imp.java =================================================================== --- trunk/jython/src/org/python/modules/imp.java 2009-05-23 20:33:14 UTC (rev 6371) +++ trunk/jython/src/org/python/modules/imp.java 2009-05-24 02:53:41 UTC (rev 6372) @@ -253,7 +253,7 @@ return new PyList(new PyObject[] {new PyTuple(new PyString(".py"), new PyString("r"), Py.newInteger(PY_SOURCE)), - new PyTuple(new PyString(".class"), + new PyTuple(new PyString("$py.class"), new PyString("rb"), Py.newInteger(PY_COMPILED)),}); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-23 20:33:33
|
Revision: 6371 http://jython.svn.sourceforge.net/jython/?rev=6371&view=rev Author: pjenvey Date: 2009-05-23 20:33:14 +0000 (Sat, 23 May 2009) Log Message: ----------- was catching potential IllegalArgumentExceptions in the wrong place Modified Paths: -------------- trunk/jython/Lib/subprocess.py Modified: trunk/jython/Lib/subprocess.py =================================================================== --- trunk/jython/Lib/subprocess.py 2009-05-23 20:01:52 UTC (rev 6370) +++ trunk/jython/Lib/subprocess.py 2009-05-23 20:33:14 UTC (rev 6371) @@ -1170,12 +1170,11 @@ args = [args] else: args = list(args) - for arg in args: - # XXX: CPython posix (execv) will str() any unicode - # args first, maybe we should do the same on - # posix. Windows passes unicode through however - if not isinstance(arg, (str, unicode)): - raise TypeError('args must contain only strings') + # NOTE: CPython posix (execv) will str() any unicode + # args first, maybe we should do the same on + # posix. Windows passes unicode through, however + if any(not isinstance(arg, (str, unicode)) for arg in args): + raise TypeError('args must contain only strings') args = _escape_args(args) if shell: @@ -1184,11 +1183,7 @@ if executable is not None: args[0] = executable - try: - builder = java.lang.ProcessBuilder(args) - except java.lang.IllegalArgumentException, iae: - raise OSError(iae.getMessage() or iae) - + builder = java.lang.ProcessBuilder(args) # os.environ may be inherited for compatibility with CPython self._setup_env(dict(os.environ if env is None else env), builder.environment()) @@ -1210,8 +1205,9 @@ try: self._process = builder.start() - except java.io.IOException, ioe: - raise OSError(ioe.getMessage() or ioe) + except (java.io.IOException, + java.lang.IllegalArgumentException), e: + raise OSError(e.getMessage() or e) self._child_created = True This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2009-05-23 20:02:07
|
Revision: 6370 http://jython.svn.sourceforge.net/jython/?rev=6370&view=rev Author: pjenvey Date: 2009-05-23 20:01:52 +0000 (Sat, 23 May 2009) Log Message: ----------- "force" the exit code by running exit through COMSPEC /c fixes #1352 Modified Paths: -------------- trunk/jython/src/shell/jython.bat Modified: trunk/jython/src/shell/jython.bat =================================================================== --- trunk/jython/src/shell/jython.bat 2009-05-23 06:22:38 UTC (rev 6369) +++ trunk/jython/src/shell/jython.bat 2009-05-23 20:01:52 UTC (rev 6370) @@ -202,4 +202,4 @@ set _TRIMMED_JYTHON_OPTS= :finish -exit /b %E% +%COMSPEC% /c exit /b %E% This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |