|
[Jython-checkins] SF.net SVN: jython: [2973] branches/2.3
From: <cgroves@us...> - 2006-11-18 19:47
|
Revision: 2973
http://svn.sourceforge.net/jython/?rev=2973&view=rev
Author: cgroves
Date: 2006-11-18 11:47:26 -0800 (Sat, 18 Nov 2006)
Log Message:
-----------
Merged 2830 to HEAD from trunk
Modified Paths:
--------------
branches/2.3/Lib/javaos.py
branches/2.3/Lib/test/regrtest.py
branches/2.3/Lib/test/test_descr.py
branches/2.3/Tools/jythonc/ImportName.py
branches/2.3/build.xml
branches/2.3/registry
branches/2.3/src/org/python/compiler/CodeCompiler.java
branches/2.3/src/org/python/compiler/Module.java
branches/2.3/src/org/python/compiler/ProxyMaker.java
branches/2.3/src/org/python/compiler/ScopeInfo.java
branches/2.3/src/org/python/compiler/ScopesCompiler.java
branches/2.3/src/org/python/core/CachedJarsPackageManager.java
branches/2.3/src/org/python/core/Py.java
branches/2.3/src/org/python/core/PyBaseString.java
branches/2.3/src/org/python/core/PyBooleanDerived.java
branches/2.3/src/org/python/core/PyClassMethodDerived.java
branches/2.3/src/org/python/core/PyComplexDerived.java
branches/2.3/src/org/python/core/PyDictionary.java
branches/2.3/src/org/python/core/PyDictionaryDerived.java
branches/2.3/src/org/python/core/PyFileDerived.java
branches/2.3/src/org/python/core/PyFloatDerived.java
branches/2.3/src/org/python/core/PyFrame.java
branches/2.3/src/org/python/core/PyIntegerDerived.java
branches/2.3/src/org/python/core/PyJavaClass.java
branches/2.3/src/org/python/core/PyListDerived.java
branches/2.3/src/org/python/core/PyLongDerived.java
branches/2.3/src/org/python/core/PyMethod.java
branches/2.3/src/org/python/core/PyObject.java
branches/2.3/src/org/python/core/PyObjectDerived.java
branches/2.3/src/org/python/core/PyPropertyDerived.java
branches/2.3/src/org/python/core/PyString.java
branches/2.3/src/org/python/core/PyStringDerived.java
branches/2.3/src/org/python/core/PySuperDerived.java
branches/2.3/src/org/python/core/PySystemState.java
branches/2.3/src/org/python/core/PyTableCode.java
branches/2.3/src/org/python/core/PyTuple.java
branches/2.3/src/org/python/core/PyTupleDerived.java
branches/2.3/src/org/python/core/PyTypeDerived.java
branches/2.3/src/org/python/core/PyUnicode.java
branches/2.3/src/org/python/core/PyUnicodeDerived.java
branches/2.3/src/org/python/core/ZipFileImporter.java
branches/2.3/src/org/python/core/__builtin__.java
branches/2.3/src/org/python/core/imp.java
branches/2.3/src/org/python/modules/cPickle.java
branches/2.3/src/org/python/modules/imp.java
branches/2.3/src/org/python/modules/time/PyTimeTuple.java
branches/2.3/src/org/python/modules/time/PyTimeTupleSetup.java
branches/2.3/src/org/python/util/PyServlet.java
branches/2.3/src/org/python/util/jython.java
branches/2.3/src/templates/float.derived
branches/2.3/src/templates/list.expose
branches/2.3/src/templates/long.derived
branches/2.3/src/templates/object.derived
branches/2.3/src/templates/str.expose
branches/2.3/src/templates/timetuple.expose
branches/2.3/src/templates/tuple.expose
branches/2.3/src/templates/unicode.expose
Added Paths:
-----------
branches/2.3/Lib/test/test_cpickle.py
branches/2.3/Lib/test/test_minidom.py
branches/2.3/Lib/test/test_sax.py
branches/2.3/Lib/test/test_scope.py
branches/2.3/Lib/xml/
branches/2.3/Lib/xml/FtCore.py
branches/2.3/Lib/xml/Uri.py
branches/2.3/Lib/xml/__init__.py
branches/2.3/Lib/xml/dom/
branches/2.3/Lib/xml/dom/MessageSource.py
branches/2.3/Lib/xml/dom/NodeFilter.py
branches/2.3/Lib/xml/dom/__init__.py
branches/2.3/Lib/xml/dom/domreg.py
branches/2.3/Lib/xml/dom/minicompat.py
branches/2.3/Lib/xml/dom/minidom.py
branches/2.3/Lib/xml/dom/pulldom.py
branches/2.3/Lib/xml/dom/xmlbuilder.py
branches/2.3/Lib/xml/sax/
branches/2.3/Lib/xml/sax/__init__.py
branches/2.3/Lib/xml/sax/_exceptions.py
branches/2.3/Lib/xml/sax/drivers2/
branches/2.3/Lib/xml/sax/drivers2/__init__.py
branches/2.3/Lib/xml/sax/drivers2/drv_javasax.py
branches/2.3/Lib/xml/sax/handler.py
branches/2.3/Lib/xml/sax/saxlib.py
branches/2.3/Lib/xml/sax/saxutils.py
branches/2.3/Lib/xml/sax/xmlreader.py
branches/2.3/src/org/python/core/FilelikeInputStream.java
branches/2.3/src/org/python/core/JavaImportHelper.java
branches/2.3/src/templates/basestring.expose
Removed Paths:
-------------
branches/2.3/Lib/xml/FtCore.py
branches/2.3/Lib/xml/Uri.py
branches/2.3/Lib/xml/__init__.py
branches/2.3/Lib/xml/dom/
branches/2.3/Lib/xml/dom/MessageSource.py
branches/2.3/Lib/xml/dom/NodeFilter.py
branches/2.3/Lib/xml/dom/__init__.py
branches/2.3/Lib/xml/dom/domreg.py
branches/2.3/Lib/xml/dom/minicompat.py
branches/2.3/Lib/xml/dom/minidom.py
branches/2.3/Lib/xml/dom/pulldom.py
branches/2.3/Lib/xml/dom/xmlbuilder.py
branches/2.3/Lib/xml/sax/
branches/2.3/Lib/xml/sax/__init__.py
branches/2.3/Lib/xml/sax/_exceptions.py
branches/2.3/Lib/xml/sax/drivers2/
branches/2.3/Lib/xml/sax/drivers2/__init__.py
branches/2.3/Lib/xml/sax/drivers2/drv_javasax.py
branches/2.3/Lib/xml/sax/handler.py
branches/2.3/Lib/xml/sax/saxlib.py
branches/2.3/Lib/xml/sax/saxutils.py
branches/2.3/Lib/xml/sax/xmlreader.py
Modified: branches/2.3/Lib/javaos.py
===================================================================
--- branches/2.3/Lib/javaos.py 2006-11-16 07:49:15 UTC (rev 2972)
+++ branches/2.3/Lib/javaos.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -49,22 +49,31 @@
def __init__(self, results):
if len(results) != 10:
- raise TypeError("stat_result() takes an at least 10-sequence")
+ raise TypeError("stat_result() takes an a 10-sequence")
for (name, index) in stat_result._stat_members:
self.__dict__[name] = results[index]
+
def __getitem__(self, i):
if i < 0 or i > 9:
raise IndexError(i)
return getattr(self, stat_result._stat_members[i][0])
+
def __setitem__(self, x, value):
raise TypeError("object doesn't support item assignment")
+
def __setattr__(self, name, value):
if name in [x[0] for x in stat_result._stat_members]:
raise TypeError(name)
raise AttributeError("readonly attribute")
+
def __len__(self):
return 10
+ def __cmp__(self, other):
+ if not isinstance(other, stat_result):
+ return 1
+ return cmp(self.__dict__, other.__dict__)
+
error = OSError
name = 'java' # discriminate based on JDK version?
Modified: branches/2.3/Lib/test/regrtest.py
===================================================================
--- branches/2.3/Lib/test/regrtest.py 2006-11-16 07:49:15 UTC (rev 2972)
+++ branches/2.3/Lib/test/regrtest.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -372,7 +372,7 @@
sys.path = saved_sys_path
- test = test_spec
+# test = test_spec
if ok > 0:
good.append(test)
@@ -407,27 +407,14 @@
if verbose:
print "CAUTION: stdout isn't compared in verbose mode: a test"
print "that passes in verbose mode may fail without it."
+ if skipped and not quiet:
+ print count(len(skipped), "test"), "skipped:"
+ printlist(skipped)
+ printsurprises(_Expected(_skips), skipped, 'skip')
if bad:
print count(len(bad), "test"), "failed:"
printlist(bad)
- if skipped and not quiet:
- print count(len(skipped), "test"), "skipped:"
- printlist(skipped)
-
- e = _ExpectedSkips()
- plat = sys.platform
- if e.isvalid():
- surprise = _Set(skipped) - e.getexpected()
- if surprise:
- print count(len(surprise), "skip"), \
- "unexpected on", plat + ":"
- printlist(surprise)
- else:
- print "Those skips are all expected on", plat + "."
- else:
- print "Ask someone to teach regrtest.py about which tests are"
- print "expected to get skipped on", plat + "."
-
+ printsurprises(_Expected(_failures), bad, 'fail')
## if single:
## alltests = findtests(testdir, stdtests, nottests)
## for i in range(len(alltests)):
@@ -644,6 +631,18 @@
if len(line) > indent:
print line
+def printsurprises(e, actual, name):
+ plat = sys.platform
+ if e.isvalid():
+ surprise = _Set(actual) - e.getexpected()
+ if surprise:
+ print count(len(surprise), name), \
+ "unexpected on", plat + ":"
+ printlist(surprise)
+ else:
+ print "Ask someone to teach regrtest.py about which tests are"
+ print "expected to %s on %s." % (name, plat)
+
class _Set:
def __init__(self, seq=[]):
data = self.data = {}
@@ -672,7 +671,7 @@
data.sort()
return data
-_expectations = {
+_skips = {
'win32':
"""
test_al
@@ -983,18 +982,104 @@
test_winreg
test_winsound
""",
+ 'java':
+ """
+ test_al
+ test_asynchat
+ test_audioop
+ test_bsddb
+ test_capi
+ test_cd
+ test_cl
+ test_cmath
+ test_commands
+ test_crypt
+ test_curses
+ test_dbm
+ test_dl
+ test_email
+ test_email_codecs
+ test_fcntl
+ test_fork1
+ test_gc
+ test_gdbm
+ test_gettext
+ test_gl
+ test_grp
+ test_hotshot
+ test_imageop
+ test_imgfile
+ test_linuxaudiodev
+ test_locale
+ test_longexp
+ test_mmap
+ test_nis
+ test_openpty
+ test_parser
+ test_poll
+ test_pty
+ test_pwd
+ test_pyexpat
+ test_regex
+ test_rgbimg
+ test_rotor
+ test_select
+ test_signal
+ test_socket_ssl
+ test_socketserver
+ test_strop
+ test_sunaudiodev
+ test_sundry
+ test_symtable
+ test_timing
+ test_ucn
+ test_unicode_file
+ test_unicodedata
+ test_wave
+ test_winreg
+ test_winsound
+ """
}
-class _ExpectedSkips:
- def __init__(self):
+_failures = {
+ 'java':
+ '''
+ test_atexit
+ test_class
+ test_cpickle
+ test_descr
+ test_descrtut
+ test_doctest2
+ test_frozen
+ test_long_future
+ test_marshal
+ test_new
+ test_pickle
+ test_pkgimport
+ test_profilehooks
+ test_pyclbr
+ test_sre
+ test_threaded_import
+ test_trace
+ test_uu
+ test_weakref
+ test_zlib
+ ''',
+}
+
+class _Expected:
+ def __init__(self, expect_dict):
self.valid = 0
- if _expectations.has_key(sys.platform):
- s = _expectations[sys.platform]
+ platform = sys.platform
+ if platform[:4] == 'java':
+ platform = 'java'
+ if expect_dict.has_key(platform):
+ s = expect_dict[platform]
self.expected = _Set(s.split())
self.valid = 1
def isvalid(self):
- "Return true iff _ExpectedSkips knows about the current platform."
+ "Return true iff _Expected knows about the current platform."
return self.valid
def getexpected(self):
Copied: branches/2.3/Lib/test/test_cpickle.py (from rev 2972, trunk/jython/Lib/test/test_cpickle.py)
===================================================================
--- branches/2.3/Lib/test/test_cpickle.py (rev 0)
+++ branches/2.3/Lib/test/test_cpickle.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -0,0 +1,81 @@
+import cPickle
+import test_support
+import unittest
+from cStringIO import StringIO
+from pickletester import AbstractPickleTests, AbstractPickleModuleTests
+
+class cPickleTests(AbstractPickleTests, AbstractPickleModuleTests):
+
+ def setUp(self):
+ self.dumps = cPickle.dumps
+ self.loads = cPickle.loads
+
+ error = cPickle.BadPickleGet
+ module = cPickle
+
+class cPicklePicklerTests(AbstractPickleTests):
+
+ def dumps(self, arg, bin=0):
+ f = StringIO()
+ p = cPickle.Pickler(f, bin)
+ p.dump(arg)
+ f.seek(0)
+ return f.read()
+
+ def loads(self, buf):
+ f = StringIO(buf)
+ p = cPickle.Unpickler(f)
+ return p.load()
+
+ error = cPickle.BadPickleGet
+
+class cPickleListPicklerTests(AbstractPickleTests):
+
+ def dumps(self, arg, bin=0):
+ p = cPickle.Pickler(bin)
+ p.dump(arg)
+ return p.getvalue()
+
+ def loads(self, *args):
+ f = StringIO(args[0])
+ p = cPickle.Unpickler(f)
+ return p.load()
+
+ error = cPickle.BadPickleGet
+
+class cPickleFastPicklerTests(AbstractPickleTests):
+
+ def dumps(self, arg, bin=0):
+ f = StringIO()
+ p = cPickle.Pickler(f, bin)
+ p.fast = 1
+ p.dump(arg)
+ f.seek(0)
+ return f.read()
+
+ def loads(self, *args):
+ f = StringIO(args[0])
+ p = cPickle.Unpickler(f)
+ return p.load()
+
+ error = cPickle.BadPickleGet
+
+ def test_nonrecursive_deep(self):
+ a = []
+ for i in range(100):
+ a = [a]
+ b = self.loads(self.dumps(a))
+ self.assertEqual(a, b)
+
+def test_main():
+ loader = unittest.TestLoader()
+ suite = unittest.TestSuite()
+ suite.addTest(loader.loadTestsFromTestCase(cPickleTests))
+ suite.addTest(loader.loadTestsFromTestCase(cPicklePicklerTests))
+ #Jython doesn't support list based picklers
+ #suite.addTest(loader.loadTestsFromTestCase(cPickleListPicklerTests))
+ suite.addTest(loader.loadTestsFromTestCase(cPickleFastPicklerTests))
+ test_support.run_suite(suite)
+
+if __name__ == "__main__":
+ test_main()
Modified: branches/2.3/Lib/test/test_descr.py
===================================================================
--- branches/2.3/Lib/test/test_descr.py 2006-11-16 07:49:15 UTC (rev 2972)
+++ branches/2.3/Lib/test/test_descr.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -3927,7 +3927,7 @@
testrmul,
testipow,
test_mutable_bases,
- test_mutable_bases_with_failing_mro,
+ #test_mutable_bases_with_failing_mro,
test_mutable_bases_catch_mro_conflict,
mutable_names,
subclass_right_op,
Copied: branches/2.3/Lib/test/test_minidom.py (from rev 2972, trunk/jython/Lib/test/test_minidom.py)
===================================================================
--- branches/2.3/Lib/test/test_minidom.py (rev 0)
+++ branches/2.3/Lib/test/test_minidom.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -0,0 +1,648 @@
+# test for xml.dom.minidom
+
+from xml.dom.minidom import parse, Node, Document, parseString
+from xml.dom import HierarchyRequestErr
+
+import os
+import sys
+import traceback
+from test_support import verbose
+
+if __name__ == "__main__":
+ base = sys.argv[0]
+else:
+ base = __file__
+tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
+del base
+
+def confirm(test, testname = "Test"):
+ if not test:
+ print "Failed " + testname
+ raise Exception
+
+Node._debug = 1
+
+def testParseFromFile():
+ from StringIO import StringIO
+ dom = parse(StringIO(open(tstfile).read()))
+ dom.unlink()
+ confirm(isinstance(dom,Document))
+
+def testGetElementsByTagName():
+ dom = parse(tstfile)
+ confirm(dom.getElementsByTagName("LI") == \
+ dom.documentElement.getElementsByTagName("LI"))
+ dom.unlink()
+
+def testInsertBefore():
+ dom = parseString("<doc><foo/></doc>")
+ root = dom.documentElement
+ elem = root.childNodes[0]
+ nelem = dom.createElement("element")
+ root.insertBefore(nelem, elem)
+ confirm(len(root.childNodes) == 2
+ and root.childNodes.length == 2
+ and root.childNodes[0] is nelem
+ and root.childNodes.item(0) is nelem
+ and root.childNodes[1] is elem
+ and root.childNodes.item(1) is elem
+ and root.firstChild is nelem
+ and root.lastChild is elem
+ and root.toxml() == "<doc><element/><foo/></doc>"
+ , "testInsertBefore -- node properly placed in tree")
+ nelem = dom.createElement("element")
+ root.insertBefore(nelem, None)
+ confirm(len(root.childNodes) == 3
+ and root.childNodes.length == 3
+ and root.childNodes[1] is elem
+ and root.childNodes.item(1) is elem
+ and root.childNodes[2] is nelem
+ and root.childNodes.item(2) is nelem
+ and root.lastChild is nelem
+ and nelem.previousSibling is elem
+ and root.toxml() == "<doc><element/><foo/><element/></doc>"
+ , "testInsertBefore -- node properly placed in tree")
+ nelem2 = dom.createElement("bar")
+ root.insertBefore(nelem2, nelem)
+ confirm(len(root.childNodes) == 4
+ and root.childNodes.length == 4
+ and root.childNodes[2] is nelem2
+ and root.childNodes.item(2) is nelem2
+ and root.childNodes[3] is nelem
+ and root.childNodes.item(3) is nelem
+ and nelem2.nextSibling is nelem
+ and nelem.previousSibling is nelem2
+ and root.toxml() == "<doc><element/><foo/><bar/><element/></doc>"
+ , "testInsertBefore -- node properly placed in tree")
+ dom.unlink()
+
+def _create_fragment_test_nodes():
+ dom = parseString("<doc/>")
+ orig = dom.createTextNode("original")
+ c1 = dom.createTextNode("foo")
+ c2 = dom.createTextNode("bar")
+ c3 = dom.createTextNode("bat")
+ dom.documentElement.appendChild(orig)
+ frag = dom.createDocumentFragment()
+ frag.appendChild(c1)
+ frag.appendChild(c2)
+ frag.appendChild(c3)
+ return dom, orig, c1, c2, c3, frag
+
+def testInsertBeforeFragment():
+ dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
+ dom.documentElement.insertBefore(frag, None)
+ confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
+ "insertBefore(<fragment>, None)")
+ frag.unlink()
+ dom.unlink()
+ #
+ dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
+ dom.documentElement.insertBefore(frag, orig)
+ confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig),
+ "insertBefore(<fragment>, orig)")
+ frag.unlink()
+ dom.unlink()
+
+def testAppendChild():
+ dom = parse(tstfile)
+ dom.documentElement.appendChild(dom.createComment(u"Hello"))
+ confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
+ confirm(dom.documentElement.childNodes[-1].data == "Hello")
+ dom.unlink()
+
+def testAppendChildFragment():
+ dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
+ dom.documentElement.appendChild(frag)
+ confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
+ "appendChild(<fragment>)")
+ frag.unlink()
+ dom.unlink()
+
+def testReplaceChildFragment():
+ dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
+ dom.documentElement.replaceChild(frag, orig)
+ orig.unlink()
+ confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
+ "replaceChild(<fragment>)")
+ frag.unlink()
+ dom.unlink()
+
+def testLegalChildren():
+ dom = Document()
+ elem = dom.createElement('element')
+ text = dom.createTextNode('text')
+
+ try: dom.appendChild(text)
+ except HierarchyRequestErr: pass
+ else:
+ print "dom.appendChild didn't raise HierarchyRequestErr"
+
+ dom.appendChild(elem)
+ try: dom.insertBefore(text, elem)
+ except HierarchyRequestErr: pass
+ else:
+ print "dom.appendChild didn't raise HierarchyRequestErr"
+
+ try: dom.replaceChild(text, elem)
+ except HierarchyRequestErr: pass
+ else:
+ print "dom.appendChild didn't raise HierarchyRequestErr"
+
+ nodemap = elem.attributes
+ try: nodemap.setNamedItem(text)
+ except HierarchyRequestErr: pass
+ else:
+ print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
+
+ try: nodemap.setNamedItemNS(text)
+ except HierarchyRequestErr: pass
+ else:
+ print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
+
+ elem.appendChild(text)
+ dom.unlink()
+
+def testNamedNodeMapSetItem():
+ dom = Document()
+ elem = dom.createElement('element')
+ attrs = elem.attributes
+ attrs["foo"] = "bar"
+ a = attrs.item(0)
+ confirm(a.ownerDocument is dom,
+ "NamedNodeMap.__setitem__() sets ownerDocument")
+ confirm(a.ownerElement is elem,
+ "NamedNodeMap.__setitem__() sets ownerElement")
+ confirm(a.value == "bar",
+ "NamedNodeMap.__setitem__() sets value")
+ confirm(a.nodeValue == "bar",
+ "NamedNodeMap.__setitem__() sets nodeValue")
+ elem.unlink()
+ dom.unlink()
+
+def testNonZero():
+ dom = parse(tstfile)
+ confirm(dom)# should not be zero
+ dom.appendChild(dom.createComment("foo"))
+ confirm(not dom.childNodes[-1].childNodes)
+ dom.unlink()
+
+def testUnlink():
+ dom = parse(tstfile)
+ dom.unlink()
+
+def testElement():
+ dom = Document()
+ dom.appendChild(dom.createElement("abc"))
+ confirm(dom.documentElement)
+ dom.unlink()
+
+def testAAA():
+ dom = parseString("<abc/>")
+ el = dom.documentElement
+ el.setAttribute("spam", "jam2")
+ confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
+ a = el.getAttributeNode("spam")
+ confirm(a.ownerDocument is dom,
+ "setAttribute() sets ownerDocument")
+ confirm(a.ownerElement is dom.documentElement,
+ "setAttribute() sets ownerElement")
+ dom.unlink()
+
+def testAAB():
+ dom = parseString("<abc/>")
+ el = dom.documentElement
+ el.setAttribute("spam", "jam")
+ el.setAttribute("spam", "jam2")
+ confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
+ dom.unlink()
+
+def testAddAttr():
+ dom = Document()
+ child = dom.appendChild(dom.createElement("abc"))
+
+ child.setAttribute("def", "ghi")
+ confirm(child.getAttribute("def") == "ghi")
+ confirm(child.attributes["def"].value == "ghi")
+
+ child.setAttribute("jkl", "mno")
+ confirm(child.getAttribute("jkl") == "mno")
+ confirm(child.attributes["jkl"].value == "mno")
+
+ confirm(len(child.attributes) == 2)
+
+ child.setAttribute("def", "newval")
+ confirm(child.getAttribute("def") == "newval")
+ confirm(child.attributes["def"].value == "newval")
+
+ confirm(len(child.attributes) == 2)
+ dom.unlink()
+
+def testDeleteAttr():
+ dom = Document()
+ child = dom.appendChild(dom.createElement("abc"))
+
+ confirm(len(child.attributes) == 0)
+ child.setAttribute("def", "ghi")
+ confirm(len(child.attributes) == 1)
+ del child.attributes["def"]
+ confirm(len(child.attributes) == 0)
+ dom.unlink()
+
+def testRemoveAttr():
+ dom = Document()
+ child = dom.appendChild(dom.createElement("abc"))
+
+ child.setAttribute("def", "ghi")
+ confirm(len(child.attributes) == 1)
+ child.removeAttribute("def")
+ confirm(len(child.attributes) == 0)
+
+ dom.unlink()
+
+def testRemoveAttrNS():
+ dom = Document()
+ child = dom.appendChild(
+ dom.createElementNS("http://www.python.org", "python:abc"))
+ child.setAttributeNS("http://www.w3.org", "xmlns:python",
+ "http://www.python.org")
+ child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
+ confirm(len(child.attributes) == 2)
+ child.removeAttributeNS("http://www.python.org", "abcattr")
+ confirm(len(child.attributes) == 1)
+
+ dom.unlink()
+
+def testRemoveAttributeNode():
+ dom = Document()
+ child = dom.appendChild(dom.createElement("foo"))
+ child.setAttribute("spam", "jam")
+ confirm(len(child.attributes) == 1)
+ node = child.getAttributeNode("spam")
+ child.removeAttributeNode(node)
+ confirm(len(child.attributes) == 0)
+
+ dom.unlink()
+
+def testChangeAttr():
+ dom = parseString("<abc/>")
+ el = dom.documentElement
+ el.setAttribute("spam", "jam")
+ confirm(len(el.attributes) == 1)
+ el.setAttribute("spam", "bam")
+ confirm(len(el.attributes) == 1)
+ el.attributes["spam"] = "ham"
+ confirm(len(el.attributes) == 1)
+ el.setAttribute("spam2", "bam")
+ confirm(len(el.attributes) == 2)
+ el.attributes[ "spam2"] = "bam2"
+ confirm(len(el.attributes) == 2)
+ dom.unlink()
+
+def testGetAttrList():
+ pass
+
+def testGetAttrValues(): pass
+
+def testGetAttrLength(): pass
+
+def testGetAttribute(): pass
+
+def testGetAttributeNS(): pass
+
+def testGetAttributeNode(): pass
+
+def testGetElementsByTagNameNS():
+ d="""<foo xmlns:minidom="http://pyxml.sf.net/minidom">
+ <minidom:myelem/>
+ </foo>"""
+ dom = parseString(d)
+ elem = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom","myelem")
+ confirm(len(elem) == 1)
+ dom.unlink()
+
+def testGetEmptyNodeListFromElementsByTagNameNS(): pass
+
+def testElementReprAndStr():
+ dom = Document()
+ el = dom.appendChild(dom.createElement("abc"))
+ string1 = repr(el)
+ string2 = str(el)
+ confirm(string1 == string2)
+ dom.unlink()
+
+# commented out until Fredrick's fix is checked in
+def _testElementReprAndStrUnicode():
+ dom = Document()
+ el = dom.appendChild(dom.createElement(u"abc"))
+ string1 = repr(el)
+ string2 = str(el)
+ confirm(string1 == string2)
+ dom.unlink()
+
+# commented out until Fredrick's fix is checked in
+def _testElementReprAndStrUnicodeNS():
+ dom = Document()
+ el = dom.appendChild(
+ dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
+ string1 = repr(el)
+ string2 = str(el)
+ confirm(string1 == string2)
+ confirm(string1.find("slash:abc") != -1)
+ dom.unlink()
+
+def testAttributeRepr():
+ dom = Document()
+ el = dom.appendChild(dom.createElement(u"abc"))
+ node = el.setAttribute("abc", "def")
+ confirm(str(node) == repr(node))
+ dom.unlink()
+
+def testTextNodeRepr(): pass
+
+def testWriteXML():
+ str = '<?xml version="1.0" ?>\n<a b="c"/>'
+ dom = parseString(str)
+ domstr = dom.toxml()
+ dom.unlink()
+ confirm(str == domstr)
+
+def testProcessingInstruction(): pass
+
+def testProcessingInstructionRepr(): pass
+
+def testTextRepr(): pass
+
+def testWriteText(): pass
+
+def testDocumentElement(): pass
+
+def testTooManyDocumentElements():
+ doc = parseString("<doc/>")
+ elem = doc.createElement("extra")
+ try:
+ doc.appendChild(elem)
+ except HierarchyRequestErr:
+ pass
+ else:
+ print "Failed to catch expected exception when" \
+ " adding extra document element."
+ elem.unlink()
+ doc.unlink()
+
+def testCreateElementNS(): pass
+
+def testCreateAttributeNS(): pass
+
+def testParse(): pass
+
+def testParseString(): pass
+
+def testComment(): pass
+
+def testAttrListItem(): pass
+
+def testAttrListItems(): pass
+
+def testAttrListItemNS(): pass
+
+def testAttrListKeys(): pass
+
+def testAttrListKeysNS(): pass
+
+def testAttrListValues(): pass
+
+def testAttrListLength(): pass
+
+def testAttrList__getitem__(): pass
+
+def testAttrList__setitem__(): pass
+
+def testSetAttrValueandNodeValue(): pass
+
+def testParseElement(): pass
+
+def testParseAttributes(): pass
+
+def testParseElementNamespaces(): pass
+
+def testParseAttributeNamespaces(): pass
+
+def testParseProcessingInstructions(): pass
+
+def testChildNodes(): pass
+
+def testFirstChild(): pass
+
+def testHasChildNodes(): pass
+
+def testCloneElementShallow():
+ dom, clone = _setupCloneElement(0)
+ confirm(len(clone.childNodes) == 0
+ and clone.childNodes.length == 0
+ and clone.parentNode is None
+ and clone.toxml() == '<doc attr="value"/>'
+ , "testCloneElementShallow")
+ dom.unlink()
+
+def testCloneElementDeep():
+ dom, clone = _setupCloneElement(1)
+ confirm(len(clone.childNodes) == 1
+ and clone.childNodes.length == 1
+ and clone.parentNode is None
+ and clone.toxml() == '<doc attr="value"><foo/></doc>'
+ , "testCloneElementDeep")
+ dom.unlink()
+
+def _setupCloneElement(deep):
+ dom = parseString("<doc attr='value'><foo/></doc>")
+ root = dom.documentElement
+ clone = root.cloneNode(deep)
+ _testCloneElementCopiesAttributes(
+ root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
+ # mutilate the original so shared data is detected
+ root.tagName = root.nodeName = "MODIFIED"
+ root.setAttribute("attr", "NEW VALUE")
+ root.setAttribute("added", "VALUE")
+ return dom, clone
+
+def _testCloneElementCopiesAttributes(e1, e2, test):
+ attrs1 = e1.attributes
+ attrs2 = e2.attributes
+ keys1 = attrs1.keys()
+ keys2 = attrs2.keys()
+ keys1.sort()
+ keys2.sort()
+ confirm(keys1 == keys2, "clone of element has same attribute keys")
+ for i in range(len(keys1)):
+ a1 = attrs1.item(i)
+ a2 = attrs2.item(i)
+ confirm(a1 is not a2
+ and a1.value == a2.value
+ and a1.nodeValue == a2.nodeValue
+ and a1.namespaceURI == a2.namespaceURI
+ and a1.localName == a2.localName
+ , "clone of attribute node has proper attribute values")
+ confirm(a2.ownerElement is e2,
+ "clone of attribute node correctly owned")
+
+
+def testCloneDocumentShallow(): pass
+
+def testCloneDocumentDeep(): pass
+
+def testCloneAttributeShallow(): pass
+
+def testCloneAttributeDeep(): pass
+
+def testClonePIShallow(): pass
+
+def testClonePIDeep(): pass
+
+def testNormalize():
+ doc = parseString("<doc/>")
+ root = doc.documentElement
+ root.appendChild(doc.createTextNode("first"))
+ root.appendChild(doc.createTextNode("second"))
+ confirm(len(root.childNodes) == 2
+ and root.childNodes.length == 2, "testNormalize -- preparation")
+ doc.normalize()
+ confirm(len(root.childNodes) == 1
+ and root.childNodes.length == 1
+ and root.firstChild is root.lastChild
+ and root.firstChild.data == "firstsecond"
+ , "testNormalize -- result")
+ doc.unlink()
+
+ doc = parseString("<doc/>")
+ root = doc.documentElement
+ root.appendChild(doc.createTextNode(""))
+ doc.normalize()
+ confirm(len(root.childNodes) == 0
+ and root.childNodes.length == 0,
+ "testNormalize -- single empty node removed")
+ doc.unlink()
+
+def testSiblings():
+ doc = parseString("<doc><?pi?>text?<elm/></doc>")
+ root = doc.documentElement
+ (pi, text, elm) = root.childNodes
+
+ confirm(pi.nextSibling is text and
+ pi.previousSibling is None and
+ text.nextSibling is elm and
+ text.previousSibling is pi and
+ elm.nextSibling is None and
+ elm.previousSibling is text, "testSiblings")
+
+ doc.unlink()
+
+def testParents():
+ doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
+ root = doc.documentElement
+ elm1 = root.childNodes[0]
+ (elm2a, elm2b) = elm1.childNodes
+ elm3 = elm2b.childNodes[0]
+
+ confirm(root.parentNode is doc and
+ elm1.parentNode is root and
+ elm2a.parentNode is elm1 and
+ elm2b.parentNode is elm1 and
+ elm3.parentNode is elm2b, "testParents")
+
+ doc.unlink()
+
+def testNodeListItem():
+ doc = parseString("<doc><e/><e/></doc>")
+ children = doc.childNodes
+ docelem = children[0]
+ confirm(children[0] is children.item(0)
+ and children.item(1) is None
+ and docelem.childNodes.item(0) is docelem.childNodes[0]
+ and docelem.childNodes.item(1) is docelem.childNodes[1]
+ and docelem.childNodes.item(0).childNodes.item(0) is None,
+ "test NodeList.item()")
+ doc.unlink()
+
+def testSAX2DOM():
+ from xml.dom import pulldom
+
+ sax2dom = pulldom.SAX2DOM()
+ sax2dom.startDocument()
+ sax2dom.startElement("doc", {})
+ sax2dom.characters("text")
+ sax2dom.startElement("subelm", {})
+ sax2dom.characters("text")
+ sax2dom.endElement("subelm")
+ sax2dom.characters("text")
+ sax2dom.endElement("doc")
+ sax2dom.endDocument()
+
+ doc = sax2dom.document
+ root = doc.documentElement
+ (text1, elm1, text2) = root.childNodes
+ text3 = elm1.childNodes[0]
+
+ confirm(text1.previousSibling is None and
+ text1.nextSibling is elm1 and
+ elm1.previousSibling is text1 and
+ elm1.nextSibling is text2 and
+ text2.previousSibling is elm1 and
+ text2.nextSibling is None and
+ text3.previousSibling is None and
+ text3.nextSibling is None, "testSAX2DOM - siblings")
+
+ confirm(root.parentNode is doc and
+ text1.parentNode is root and
+ elm1.parentNode is root and
+ text2.parentNode is root and
+ text3.parentNode is elm1, "testSAX2DOM - parents")
+
+ doc.unlink()
+
+# --- MAIN PROGRAM
+
+names = globals().keys()
+names.sort()
+
+failed = []
+
+try:
+ Node.allnodes
+except AttributeError:
+ # We don't actually have the minidom from the standard library,
+ # but are picking up the PyXML version from site-packages.
+ def check_allnodes():
+ pass
+else:
+ def check_allnodes():
+ confirm(len(Node.allnodes) == 0,
+ "assertion: len(Node.allnodes) == 0")
+ if len(Node.allnodes):
+ print "Garbage left over:"
+ if verbose:
+ print Node.allnodes.items()[0:10]
+ else:
+ # Don't print specific nodes if repeatable results
+ # are needed
+ print len(Node.allnodes)
+ Node.allnodes = {}
+
+for name in names:
+ if name.startswith("test"):
+ func = globals()[name]
+ try:
+ func()
+ check_allnodes()
+ except:
+ failed.append(name)
+ print "Test Failed: ", name
+ sys.stdout.flush()
+ traceback.print_exception(*sys.exc_info())
+ print `sys.exc_info()[1]`
+ Node.allnodes = {}
+
+if failed:
+ print "\n\n\n**** Check for failures in these tests:"
+ for name in failed:
+ print " " + name
Copied: branches/2.3/Lib/test/test_sax.py (from rev 2972, trunk/jython/Lib/test/test_sax.py)
===================================================================
--- branches/2.3/Lib/test/test_sax.py (rev 0)
+++ branches/2.3/Lib/test/test_sax.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -0,0 +1,713 @@
+# -*- coding: iso-8859-1 -*-
+# regression test for SAX 2.0
+# $Id: test_sax.py,v 1.13 2004/03/20 07:46:04 fdrake Exp $
+
+from xml.sax import handler, make_parser, ContentHandler, \
+ SAXException, SAXReaderNotAvailable, SAXParseException
+try:
+ make_parser()
+except SAXReaderNotAvailable:
+ # don't try to test this module if we cannot create a parser
+ raise ImportError("no XML parsers available")
+from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
+ XMLFilterBase, Location
+from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
+from cStringIO import StringIO
+from test.test_support import verbose, TestFailed, findfile
+
+# ===== Utilities
+
+tests = 0
+failures = []
+
+def confirm(outcome, name):
+ global tests
+
+ tests = tests + 1
+ if outcome:
+ if verbose:
+ print "Passed", name
+ else:
+ print "Failed", name
+ failures.append(name)
+
+def test_make_parser2():
+ try:
+ # Creating parsers several times in a row should succeed.
+ # Testing this because there have been failures of this kind
+ # before.
+ from xml.sax import make_parser
+ p = make_parser()
+ from xml.sax import make_parser
+ p = make_parser()
+ from xml.sax import make_parser
+ p = make_parser()
+ from xml.sax import make_parser
+ p = make_parser()
+ from xml.sax import make_parser
+ p = make_parser()
+ from xml.sax import make_parser
+ p = make_parser()
+ except:
+ return 0
+ else:
+ return p
+
+
+# ===========================================================================
+#
+# saxutils tests
+#
+# ===========================================================================
+
+# ===== escape
+
+def test_escape_basic():
+ return escape("Donald Duck & Co") == "Donald Duck & Co"
+
+def test_escape_all():
+ return escape("<Donald Duck & Co>") == "<Donald Duck & Co>"
+
+def test_escape_extra():
+ return escape("Hei p\xE5 deg", {"\xE5" : "å"}) == "Hei på deg"
+
+# ===== unescape
+
+def test_unescape_basic():
+ return unescape("Donald Duck & Co") == "Donald Duck & Co"
+
+def test_unescape_all():
+ return unescape("<Donald Duck & Co>") == "<Donald Duck & Co>"
+
+def test_unescape_extra():
+ return unescape("Hei p\xE5 deg", {"\xE5" : "å"}) == "Hei på deg"
+
+def test_unescape_amp_extra():
+ return unescape("&foo;", {"&foo;": "splat"}) == "&foo;"
+
+# ===== quoteattr
+
+def test_quoteattr_basic():
+ return quoteattr("Donald Duck & Co") == '"Donald Duck & Co"'
+
+def test_single_quoteattr():
+ return (quoteattr('Includes "double" quotes')
+ == '\'Includes "double" quotes\'')
+
+def test_double_quoteattr():
+ return (quoteattr("Includes 'single' quotes")
+ == "\"Includes 'single' quotes\"")
+
+def test_single_double_quoteattr():
+ return (quoteattr("Includes 'single' and \"double\" quotes")
+ == "\"Includes 'single' and "double" quotes\"")
+
+# ===== make_parser
+
+def test_make_parser():
+ try:
+ # Creating a parser should succeed - it should fall back
+ # to the expatreader
+ p = make_parser(['xml.parsers.no_such_parser'])
+ except:
+ return 0
+ else:
+ return p
+
+
+# ===== XMLGenerator
+
+start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
+
+def test_xmlgen_basic():
+ result = StringIO()
+ gen = XMLGenerator(result)
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + "<doc></doc>"
+
+def test_xmlgen_content():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.characters("huhei")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + "<doc>huhei</doc>"
+
+def test_xmlgen_escaped_content():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.characters(unicode("\xa0\\u3042", "unicode-escape"))
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + "<doc>\xa0あ</doc>"
+
+def test_xmlgen_escaped_attr():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {"x": unicode("\\u3042", "unicode-escape")})
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + '<doc x="あ"></doc>'
+
+def test_xmlgen_pi():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.processingInstruction("test", "data")
+ gen.startElement("doc", {})
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + "<?test data?><doc></doc>"
+
+def test_xmlgen_content_escape():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.characters("<huhei&")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + "<doc><huhei&</doc>"
+
+def test_xmlgen_attr_escape():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {"a": '"'})
+ gen.startElement("e", {"a": "'"})
+ gen.endElement("e")
+ gen.startElement("e", {"a": "'\""})
+ gen.endElement("e")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start \
+ + "<doc a='\"'><e a=\"'\"></e><e a=\"'"\"></e></doc>"
+
+def test_xmlgen_attr_escape_manydouble():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {"a": '"\'"'})
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + "<doc a='\"'\"'></doc>"
+
+def test_xmlgen_attr_escape_manysingle():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {"a": "'\"'"})
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + '<doc a="\'"\'"></doc>'
+
+def test_xmlgen_ignorable():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startElement("doc", {})
+ gen.ignorableWhitespace(" ")
+ gen.endElement("doc")
+ gen.endDocument()
+
+ return result.getvalue() == start + "<doc> </doc>"
+
+ns_uri = "http://www.python.org/xml-ns/saxtest/"
+
+def test_xmlgen_ns():
+ result = StringIO()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startPrefixMapping("ns1", ns_uri)
+ gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
+ # add an unqualified name
+ gen.startElementNS((None, "udoc"), None, {})
+ gen.endElementNS((None, "udoc"), None)
+ gen.endElementNS((ns_uri, "doc"), "ns1:doc")
+ gen.endPrefixMapping("ns1")
+ gen.endDocument()
+
+ return result.getvalue() == start + \
+ ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
+ ns_uri)
+
+# ===== XMLFilterBase
+
+def test_filter_basic():
+ result = StringIO()
+ gen = XMLGenerator(result)
+ filter = XMLFilterBase()
+ filter.setContentHandler(gen)
+
+ filter.startDocument()
+ filter.startElement("doc", {})
+ filter.characters("content")
+ filter.ignorableWhitespace(" ")
+ filter.endElement("doc")
+ filter.endDocument()
+
+ return result.getvalue() == start + "<doc>content </doc>"
+
+# ===========================================================================
+#
+# expatreader tests
+#
+# ===========================================================================
+
+# ===== XMLReader support
+
+def test_expat_file():
+ parser = make_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+
+ parser.setContentHandler(xmlgen)
+ parser.parse(open(findfile("test.xml")))
+
+ return result.getvalue() == xml_test_out
+
+# ===== DTDHandler support
+
+class TestDTDHandler:
+
+ def __init__(self):
+ self._notations = []
+ self._entities = []
+
+ def notationDecl(self, name, publicId, systemId):
+ self._notations.append((name, publicId, systemId))
+
+ def unparsedEntityDecl(self, name, publicId, systemId, ndata):
+ self._entities.append((name, publicId, systemId, ndata))
+
+def test_expat_dtdhandler():
+ parser = make_parser()
+ handler = TestDTDHandler()
+ parser.setDTDHandler(handler)
+
+ parser.parse(StringIO('''<!DOCTYPE doc [
+ <!ENTITY img SYSTEM "expat.gif" NDATA GIF>
+ <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">
+]>
+<doc></doc>'''))
+ if len(handler._entities) != 1 or len(handler._entities[0]) != 4:
+ return 0
+ name, pubId, sysId, ndata = handler._entities[0]
+ if name != 'img' or not pubId is None or not sysId.endswith('expat.gif') or ndata != 'GIF':
+ return 0
+ return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)]
+
+# ===== EntityResolver support
+
+class TestEntityResolver:
+
+ def resolveEntity(self, publicId, systemId):
+ inpsrc = InputSource()
+ inpsrc.setByteStream(StringIO("<entity/>"))
+ return inpsrc
+
+def test_expat_entityresolver():
+ parser = make_parser()
+ parser.setEntityResolver(TestEntityResolver())
+ result = StringIO()
+ parser.setContentHandler(XMLGenerator(result))
+
+ parser.parse(StringIO('''<!DOCTYPE doc [
+ <!ENTITY test SYSTEM "whatever">
+]>
+<doc>&test;</doc>'''))
+ return result.getvalue() == start + "<doc><entity></entity></doc>"
+
+# ===== Attributes support
+
+class AttrGatherer(ContentHandler):
+
+ def startElement(self, name, attrs):
+ self._attrs = attrs
+
+ def startElementNS(self, name, qname, attrs):
+ self._attrs = attrs
+
+def test_expat_attrs_empty():
+ parser = make_parser()
+ gather = AttrGatherer()
+ parser.setContentHandler(gather)
+
+ parser.parse(StringIO("<doc/>"))
+
+ return verify_empty_attrs(gather._attrs)
+
+def test_expat_attrs_wattr():
+ parser = make_parser()
+ gather = AttrGatherer()
+ parser.setContentHandler(gather)
+
+ parser.parse(StringIO("<doc attr='val'/>"))
+
+ return verify_attrs_wattr(gather._attrs)
+
+def test_expat_nsattrs_empty():
+ parser = make_parser()
+ parser.setFeature(handler.feature_namespaces, 1)
+ gather = AttrGatherer()
+ parser.setContentHandler(gather)
+
+ parser.parse(StringIO("<doc/>"))
+
+ return verify_empty_nsattrs(gather._attrs)
+
+def test_expat_nsattrs_wattr():
+ parser = make_parser()
+ parser.setFeature(handler.feature_namespaces, 1)
+ gather = AttrGatherer()
+ parser.setContentHandler(gather)
+
+ parser.parse(StringIO("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri))
+
+ attrs = gather._attrs
+
+ return attrs.getLength() == 1 and \
+ attrs.getNames() == [(ns_uri, "attr")] and \
+ attrs.getQNames() == ["ns:attr"] and \
+ len(attrs) == 1 and \
+ attrs.has_key((ns_uri, "attr")) and \
+ attrs.keys() == [(ns_uri, "attr")] and \
+ attrs.get((ns_uri, "attr")) == "val" and \
+ attrs.get((ns_uri, "attr"), 25) == "val" and \
+ attrs.items() == [((ns_uri, "attr"), "val")] and \
+ attrs.values() == ["val"] and \
+ attrs.getValue((ns_uri, "attr")) == "val" and \
+ attrs[(ns_uri, "attr")] == "val"
+
+# ===== InputSource support
+
+xml_test_out = open(findfile("test.xml.out")).read()
+
+def test_expat_inpsource_filename():
+ parser = make_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+
+ parser.setContentHandler(xmlgen)
+ parser.parse(findfile("test.xml"))
+
+ return result.getvalue() == xml_test_out
+
+def test_expat_inpsource_sysid():
+ parser = make_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+
+ parser.setContentHandler(xmlgen)
+ parser.parse(InputSource(findfile("test.xml")))
+
+ return result.getvalue() == xml_test_out
+
+def test_expat_inpsource_stream():
+ parser = make_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+
+ parser.setContentHandler(xmlgen)
+ inpsrc = InputSource()
+ inpsrc.setByteStream(open(findfile("test.xml")))
+ parser.parse(inpsrc)
+
+ return result.getvalue() == xml_test_out
+
+# ===== Locator support
+
+class LocatorTest(XMLGenerator):
+ def __init__(self, out=None, encoding="iso-8859-1"):
+ XMLGenerator.__init__(self, out, encoding)
+ self.location = None
+
+ def endDocument(self):
+ XMLGenerator.endDocument(self)
+ self.location = Location(self._locator)
+
+def test_expat_locator_noinfo():
+ result = StringIO()
+ xmlgen = LocatorTest(result)
+ parser = make_parser()
+ parser.setContentHandler(xmlgen)
+
+ parser.parse(StringIO("<doc></doc>"))
+
+ return xmlgen.location.getSystemId() is None and \
+ xmlgen.location.getPublicId() is None and \
+ xmlgen.location.getLineNumber() == 1
+
+def test_expat_locator_withinfo():
+ result = StringIO()
+ xmlgen = LocatorTest(result)
+ parser = make_parser()
+ parser.setContentHandler(xmlgen)
+ parser.parse(findfile("test.xml"))
+
+ return xmlgen.location.getSystemId().endswith(findfile("test.xml")) and \
+ xmlgen.location.getPublicId() is None
+
+
+# ===========================================================================
+#
+# error reporting
+#
+# ===========================================================================
+
+def test_expat_incomplete():
+ parser = make_parser()
+ parser.setContentHandler(ContentHandler()) # do nothing
+ try:
+ parser.parse(StringIO("<foo>"))
+ except SAXParseException:
+ return 1 # ok, error found
+ else:
+ return 0
+
+def test_sax_location_str():
+ # pass various values from a locator to the SAXParseException to
+ # make sure that the __str__() doesn't fall apart when None is
+ # passed instead of an integer line and column number
+ #
+ # use "normal" values for the locator:
+ str(Location(DummyLocator(1, 1)))
+ # use None for the line number:
+ str(Location(DummyLocator(None, 1)))
+ # use None for the column number:
+ str(Location(DummyLocator(1, None)))
+ # use None for both:
+ str(Location(DummyLocator(None, None)))
+ return 1
+
+def test_sax_parse_exception_str():
+ # pass various values from a locator to the SAXParseException to
+ # make sure that the __str__() doesn't fall apart when None is
+ # passed instead of an integer line and column number
+ #
+ # use "normal" values for the locator:
+ str(SAXParseException("message", None,
+ DummyLocator(1, 1)))
+ # use None for the line number:
+ str(SAXParseException("message", None,
+ DummyLocator(None, 1)))
+ # use None for the column number:
+ str(SAXParseException("message", None,
+ DummyLocator(1, None)))
+ # use None for both:
+ str(SAXParseException("message", None,
+ DummyLocator(None, None)))
+ return 1
+
+class DummyLocator:
+ def __init__(self, lineno, colno):
+ self._lineno = lineno
+ self._colno = colno
+
+ def getPublicId(self):
+ return "pubid"
+
+ def getSystemId(self):
+ return "sysid"
+
+ def getLineNumber(self):
+ return self._lineno
+
+ def getColumnNumber(self):
+ return self._colno
+
+# ===========================================================================
+#
+# xmlreader tests
+#
+# ===========================================================================
+
+# ===== AttributesImpl
+
+def verify_empty_attrs(attrs):
+ try:
+ attrs.getValue("attr")
+ gvk = 0
+ except KeyError:
+ gvk = 1
+
+ try:
+ attrs.getValueByQName("attr")
+ gvqk = 0
+ except KeyError:
+ gvqk = 1
+
+ try:
+ attrs.getNameByQName("attr")
+ gnqk = 0
+ except KeyError:
+ gnqk = 1
+
+ try:
+ attrs.getQNameByName("attr")
+ gqnk = 0
+ except KeyError:
+ gqnk = 1
+
+ try:
+ attrs["attr"]
+ gik = 0
+ except KeyError:
+ gik = 1
+
+ return attrs.getLength() == 0 and \
+ attrs.getNames() == [] and \
+ attrs.getQNames() == [] and \
+ len(attrs) == 0 and \
+ not attrs.has_key("attr") and \
+ attrs.keys() == [] and \
+ attrs.get("attrs") is None and \
+ attrs.get("attrs", 25) == 25 and \
+ attrs.items() == [] and \
+ attrs.values() == [] and \
+ gvk and gvqk and gnqk and gik and gqnk
+
+def verify_attrs_wattr(attrs):
+ return attrs.getLength() == 1 and \
+ attrs.getNames() == ["attr"] and \
+ attrs.getQNames() == ["attr"] and \
+ len(attrs) == 1 and \
+ attrs.has_key("attr") and \
+ attrs.keys() == ["attr"] and \
+ attrs.get("attr") == "val" and \
+ attrs.get("attr", 25) == "val" and \
+ attrs.items() == [("attr", "val")] and \
+ attrs.values() == ["val"] and \
+ attrs.getValue("attr") == "val" and \
+ attrs.getValueByQName("attr") == "val" and \
+ attrs.getNameByQName("attr") == "attr" and \
+ attrs["attr"] == "val" and \
+ attrs.getQNameByName("attr") == "attr"
+
+def test_attrs_empty():
+ return verify_empty_attrs(AttributesImpl({}))
+
+def test_attrs_wattr():
+ return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
+
+# ===== AttributesImpl
+
+def verify_empty_nsattrs(attrs):
+ try:
+ attrs.getValue((ns_uri, "attr"))
+ gvk = 0
+ except KeyError:
+ gvk = 1
+
+ try:
+ attrs.getValueByQName("ns:attr")
+ gvqk = 0
+ except KeyError:
+ gvqk = 1
+
+ try:
+ attrs.getNameByQName("ns:attr")
+ gnqk = 0
+ except KeyError:
+ gnqk = 1
+
+ try:
+ attrs.getQNameByName((ns_uri, "attr"))
+ gqnk = 0
+ except KeyError:
+ gqnk = 1
+
+ try:
+ attrs[(ns_uri, "attr")]
+ gik = 0
+ except KeyError:
+ gik = 1
+
+ return attrs.getLength() == 0 and \
+ attrs.getNames() == [] and \
+ attrs.getQNames() == [] and \
+ len(attrs) == 0 and \
+ not attrs.has_key((ns_uri, "attr")) and \
+ attrs.keys() == [] and \
+ attrs.get((ns_uri, "attr")) is None and \
+ attrs.get((ns_uri, "attr"), 25) == 25 and \
+ attrs.items() == [] and \
+ attrs.values() == [] and \
+ gvk and gvqk and gnqk and gik and gqnk
+
+def test_nsattrs_empty():
+ return verify_empty_nsattrs(AttributesNSImpl({}, {}))
+
+def test_nsattrs_wattr():
+ attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
+ {(ns_uri, "attr") : "ns:attr"})
+
+ return attrs.getLength() == 1 and \
+ attrs.getNames() == [(ns_uri, "attr")] and \
+ attrs.getQNames() == ["ns:attr"] and \
+ len(attrs) == 1 and \
+ attrs.has_key((ns_uri, "attr")) and \
+ attrs.keys() == [(ns_uri, "attr")] and \
+ attrs.get((ns_uri, "attr")) == "val" and \
+ attrs.get((ns_uri, "attr"), 25) == "val" and \
+ attrs.items() == [((ns_uri, "attr"), "val")] and \
+ attrs.values() == ["val"] and \
+ attrs.getValue((ns_uri, "attr")) == "val" and \
+ attrs.getValueByQName("ns:attr") == "val" and \
+ attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \
+ attrs[(ns_uri, "attr")] == "val" and \
+ attrs.getQNameByName((ns_uri, "attr")) == "ns:attr"
+
+
+# ===== Main program
+
+def make_test_output():
+ parser = make_parser()
+ result = StringIO()
+ xmlgen = XMLGenerator(result)
+
+ parser.setContentHandler(xmlgen)
+ parser.parse(findfile("test.xml"))
+
+ outf = open(findfile("test.xml.out"), "w")
+ outf.write(result.getvalue())
+ outf.close()
+
+items = locals().items()
+items.sort()
+for (name, value) in items:
+ if name[:5] == "test_":
+ confirm(value(), name)
+
+if verbose:
+ print "%d tests, %d failures" % (tests, len(failures))
+if failures:
+ raise TestFailed("%d of %d tests failed: %s"
+ % (len(failures), tests, ", ".join(failures)))
Copied: branches/2.3/Lib/test/test_scope.py (from rev 2972, trunk/jython/Lib/test/test_scope.py)
===================================================================
--- branches/2.3/Lib/test/test_scope.py (rev 0)
+++ branches/2.3/Lib/test/test_scope.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -0,0 +1,530 @@
+from test_support import verify, TestFailed, check_syntax
+
+import warnings
+warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<string>")
+
+print "1. simple nesting"
+
+def make_adder(x):
+ def adder(y):
+ return x + y
+ return adder
+
+inc = make_adder(1)
+plus10 = make_adder(10)
+
+verify(inc(1) == 2)
+verify(plus10(-2) == 8)
+
+print "2. extra nesting"
+
+def make_adder2(x):
+ def extra(): # check freevars passing through non-use scopes
+ def adder(y):
+ return x + y
+ return adder
+ return extra()
+
+inc = make_adder2(1)
+plus10 = make_adder2(10)
+
+verify(inc(1) == 2)
+verify(plus10(-2) == 8)
+
+print "3. simple nesting + rebinding"
+
+def make_adder3(x):
+ def adder(y):
+ return x + y
+ x = x + 1 # check tracking of assignment to x in defining scope
+ return adder
+
+inc = make_adder3(0)
+plus10 = make_adder3(9)
+
+verify(inc(1) == 2)
+verify(plus10(-2) == 8)
+
+print "4. nesting with global but no free"
+
+def make_adder4(): # XXX add exta level of indirection
+ def nest():
+ def nest():
+ def adder(y):
+ return global_x + y # check that plain old globals work
+ return adder
+ return nest()
+ return nest()
+
+global_x = 1
+adder = make_adder4()
+verify(adder(1) == 2)
+
+global_x = 10
+verify(adder(-2) == 8)
+
+print "5. nesting through class"
+
+def make_adder5(x):
+ class Adder:
+ def __call__(self, y):
+ return x + y
+ return Adder()
+
+inc = make_adder5(1)
+plus10 = make_adder5(10)
+
+verify(inc(1) == 2)
+verify(plus10(-2) == 8)
+
+print "6. nesting plus free ref to global"
+
+def make_adder6(x):
+ global global_nest_x
+ def adder(y):
+ return global_nest_x + y
+ global_nest_x = x
+ return adder
+
+inc = make_adder6(1)
+plus10 = make_adder6(10)
+
+verify(inc(1) == 11) # there's only one global
+verify(plus10(-2) == 8)
+
+print "7. nearest enclosing scope"
+
+def f(x):
+ def g(y):
+ x = 42 # check that this masks binding in f()
+ def h(z):
+ return x + z
+ return h
+ return g(2)
+
+test_func = f(10)
+verify(test_func(5) == 47)
+
+print "8. mixed freevars and cellvars"
+
+def identity(x):
+ return x
+
+def f(x, y, z):
+ def g(a, b, c):
+ a = a + x # 3
+ def h():
+ # z * (4 + 9)
+ # 3 * 13
+ return identity(z * (b + y))
+ y = c + z # 9
+ return h
+ return g
+
+g = f(1, 2, 3)
+h = g(2, 4, 6)
+verify(h() == 39)
+
+print "9. free variable in method"
+
+def test():
+ method_and_var = "var"
+ class Test:
+ def method_and_var(self):
+ return "method"
+ def test(self):
+ return method_and_var
+ def actual_global(self):
+ return str("global")
+ def str(self):
+ return str(self)
+ return Test()
+
+t = test()
+verify(t.test() == "var")
+verify(t.method_and_var() == "method")
+verify(t.actual_global() == "global")
+
+method_and_var = "var"
+class Test:
+ # this class is not nested, so the rules are different
+ def method_and_var(self):
+ return "method"
+ def test(self):
+ return method_and_var
+ def actual_global(self):
+ return str("global")
+ def str(self):
+ return str(self)
+
+t = Test()
+verify(t.test() == "var")
+verify(t.method_and_var() == "method")
+verify(t.actual_global() == "global")
+
+print "10. recursion"
+
+def f(x):
+ def fact(n):
+ if n == 0:
+ return 1
+ else:
+ return n * fact(n - 1)
+ if x >= 0:
+ return fact(x)
+ else:
+ raise ValueError, "x must be >= 0"
+
+verify(f(6) == 720)
+
+
+print "11. unoptimized namespaces"
+
+check_syntax("""\
+def unoptimized_clash1(strip):
+ def f(s):
+ from string import *
+ return strip(s) # ambiguity: free or local
+ return f
+""")
+
+check_syntax("""\
+def unoptimized_clash2():
+ from string import *
+ def f(s):
+ return strip(s) # ambiguity: global or local
+ return f
+""")
+
+check_syntax("""\
+def unoptimized_clash2():
+ from string import *
+ def g():
+ def f(s):
+ return strip(s) # ambiguity: global or local
+ return f
+""")
+
+# XXX could allow this for exec with const argument, but what's the point
+check_syntax("""\
+def error(y):
+ exec "a = 1"
+ def f(x):
+ return x + y
+ return f
+""")
+
+check_syntax("""\
+def f(x):
+ def g():
+ return x
+ del x # can't del name
+""")
+
+check_syntax("""\
+def f():
+ def g():
+ from string import *
+ return strip # global or local?
+""")
+
+# and verify a few cases that should work
+
+exec """
+def noproblem1():
+ from string import *
+ f = lambda x:x
+
+def noproblem2():
+ from string import *
+ def f(x):
+ return x + 1
+
+def noproblem3():
+ from string import *
+ def f(x):
+ global y
+ y = x
+"""
+
+print "12. lambdas"
+
+f1 = lambda x: lambda y: x + y
+inc = f1(1)
+plus10 = f1(10)
+verify(inc(1) == 2)
+verify(plus10(5) == 15)
+
+f2 = lambda x: (lambda : lambda y: x + y)()
+inc = f2(1)
+plus10 = f2(10)
+verify(inc(1) == 2)
+verify(plus10(5) == 15)
+
+f3 = lambda x: lambda y: global_x + y
+global_x = 1
+inc = f3(None)
+verify(inc(2) == 3)
+
+f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
+g = f8(1, 2, 3)
+h = g(2, 4, 6)
+verify(h() == 18)
+
+print "13. UnboundLocal"
+
+def errorInOuter():
+ print y
+ def inner():
+ return y
+ y = 1
+
+def errorInInner():
+ def inner():
+ return y
+ inner()
+ y = 1
+
+try:
+ errorInOuter()
+except UnboundLocalError:
+ pass
+else:
+ raise TestFailed
+
+try:
+ errorInInner()
+except NameError:
+ pass
+else:
+ raise TestFailed
+
+print "14. complex definitions"
+
+def makeReturner(*lst):
+ def returner():
+ return lst
+ return returner
+
+verify(makeReturner(1,2,3)() == (1,2,3))
+
+def makeReturner2(**kwargs):
+ def returner():
+ return kwargs
+ return returner
+
+verify(makeReturner2(a=11)()['a'] == 11)
+
+def makeAddPair((a, b)):
+ def addPair((c, d)):
+ return (a + c, b + d)
+ return addPair
+
+verify(makeAddPair((1, 2))((100, 200)) == (101,202))
+
+print "15. scope of global statements"
+# Examples posted by Samuele Pedroni to python-dev on 3/1/2001
+
+# I
+x = 7
+def f():
+ x = 1
+ def g():
+ global x
+ def i():
+ def h():
+ return x
+ return h()
+ return i()
+ return g()
+verify(f() == 7)
+verify(x == 7)
+
+# II
+x = 7
+def f():
+ x = 1
+ def g():
+ x = 2
+ def i():
+ def h():
+ return x
+ return h()
+ return i()
+ return g()
+verify(f() == 2)
+verify(x == 7)
+
+# III
+x = 7
+def f():
+ x = 1
+ def g():
+ global x
+ x = 2
+ def i():
+ def h():
+ return x
+ return h()
+ return i()
+ return g()
+verify(f() == 2)
+verify(x == 2)
+
+# IV
+x = 7
+def f():
+ x = 3
+ def g():
+ global x
+ x = 2
+ def i():
+ def h():
+ return x
+ return h()
+ return i()
+ return g()
+verify(f() == 2)
+verify(x == 2)
+
+print "16. check leaks"
+
+class Foo:
+ count = 0
+
+ def __init__(self):
+ Foo.count += 1
+
+ def __del__(self):
+ Foo.count -= 1
+
+def f1():
+ x = Foo()
+ def f2():
+ return x
+ f2()
+
+for i in range(100):
+ f1()
+
+import os
+if os.name == 'java':
+ from java.lang import System, Thread
+ System.gc()
+ Thread.sleep(100)
+ System.gc()
+verify(Foo.count == 0)
+
+print "17. class and global"
+
+def test(x):
+ class Foo:
+ global x
+ def __call__(self, y):
+ return x + y
+ return Foo()
+
+x = 0
+verify(test(6)(2) == 8)
+x = -1
+verify(test(3)(2) == 5)
+
+print "18. verify that locals() works"
+
+def f(x):
+ def g(y):
+ def h(z):
+ return y + z
+ w = x + y
+ y += 3
+ return locals()
+ return g
+
+d = f(2)(4)
+verify(d.has_key('h'))
+del d['h']
+verify(d == {'x': 2, 'y': 7, 'w': 6})
+
+print "19. var is bound and free in class"
+
+def f(x):
+ class C:
+ def m(self):
+ return x
+ a = x
+ return C
+
+inst = f(3)()
+verify(inst.a == inst.m())
+
+print "20. interaction with trace function"
+
+import sys
+def tracer(a,b,c):
+ return tracer
+
+def adaptgetter(name, klass, getter):
+ kind, des = getter
+ if kind == 1: # AV happens when stepping from this line to next
+ if des == "":
+ des = "_%s__%s" % (klass.__name__, name)
+ return lambda obj: getattr(obj, des)
+
+class TestClass:
+ pass
+
+sys.settrace(tracer)
+adaptgetter("foo", TestClass, (1, ""))
+sys.settrace(None)
+
+try: sys.settrace()
+except TypeError: pass
+else: raise TestFailed, 'sys.settrace() did not raise TypeError'
+
+print "20. eval and exec with free variables"
+
+def f(x):
+ return lambda: x + 1
+
+g = f(3)
+try:
+ eval(g.func_code)
+except TypeError:
+ pass
+else:
+ print "eval() should have failed, because code contained free vars"
+
+try:
+ exec g.func_code
+except TypeError:
+ pass
+else:
+ print "exec should have failed, because code contained free vars"
+
+print "21. list comprehension with local variables"
+
+try:
+ print bad
+except NameError:
+ pass
+else:
+ print "bad should not be defined"
+
+def x():
+ [bad for s in 'a b' for bad in s.split()]
+
+x()
+try:
+ print bad
+except NameError:
+ pass
+
+print "22. eval with free variables"
+
+def f(x):
+ def g():
+ x
+ eval("x + 1")
+ return g
+
+f(4)()
Copied: branches/2.3/Lib/xml (from rev 2972, trunk/jython/Lib/xml)
Property changes on: branches/2.3/Lib/xml
___________________________________________________________________
Name: svn:ignore
+ *$py.class
Deleted: branches/2.3/Lib/xml/FtCore.py
===================================================================
--- trunk/jython/Lib/xml/FtCore.py 2006-11-16 07:49:15 UTC (rev 2972)
+++ branches/2.3/Lib/xml/FtCore.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -1,58 +0,0 @@
-"""
-Contains various definitions common to modules acquired from 4Suite
-"""
-
-__all__ = ["FtException", "get_translator"]
-
-
-class FtException(Exception):
- def __init__(self, errorCode, messages, args):
- # By defining __str__, args will be available. Otherwise
- # the __init__ of Exception sets it to the passed in arguments.
- self.params = args
- self.errorCode = errorCode
- self.message = messages[errorCode] % args
- Exception.__init__(self, self.message, args)
-
- def __str__(self):
- return self.message
-
-
-# What follows is used to provide support for I18N in the rest of the
-# 4Suite-derived packages in PyXML.
-#
-# Each sub-package of the top-level "xml" package that contains 4Suite
-# code is really a separate text domain, but they're all called
-# '4Suite'. For each domain, a translation object is provided using
-# message catalogs stored inside the package. The code below defines
-# a get_translator() function that returns an appropriate gettext
-# function to be used as _() in the sub-package named by the
-# parameter. This handles all the compatibility issues related to
-# Python versions (whether the gettext module can be found) and
-# whether the message catalogs can actually be found.
-
-def _(msg):
- return msg
-
-try:
- import gettext
-
-except (ImportError, IOError):
- def get_translator(pkg):
- return _
-
-else:
- import os
-
- _cache = {}
- _top = os.path.dirname(os.path.abspath(__file__))
-
- def get_translator(pkg):
- if not _cache.has_key(pkg):
- locale_dir = os.path.join(_top, pkg.replace(".", os.sep))
- try:
- f = gettext.translation('4Suite', locale_dir).gettext
- except IOError:
- f = _
- _cache[pkg] = f
- return _cache[pkg]
Copied: branches/2.3/Lib/xml/FtCore.py (from rev 2972, trunk/jython/Lib/xml/FtCore.py)
===================================================================
--- branches/2.3/Lib/xml/FtCore.py (rev 0)
+++ branches/2.3/Lib/xml/FtCore.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -0,0 +1,58 @@
+"""
+Contains various definitions common to modules acquired from 4Suite
+"""
+
+__all__ = ["FtException", "get_translator"]
+
+
+class FtException(Exception):
+ def __init__(self, errorCode, messages, args):
+ # By defining __str__, args will be available. Otherwise
+ # the __init__ of Exception sets it to the passed in arguments.
+ self.params = args
+ self.errorCode = errorCode
+ self.message = messages[errorCode] % args
+ Exception.__init__(self, self.message, args)
+
+ def __str__(self):
+ return self.message
+
+
+# What follows is used to provide support for I18N in the rest of the
+# 4Suite-derived packages in PyXML.
+#
+# Each sub-package of the top-level "xml" package that contains 4Suite
+# code is really a separate text domain, but they're all called
+# '4Suite'. For each domain, a translation object is provided using
+# message catalogs stored inside the package. The code below defines
+# a get_translator() function that returns an appropriate gettext
+# function to be used as _() in the sub-package named by the
+# parameter. This handles all the compatibility issues related to
+# Python versions (whether the gettext module can be found) and
+# whether the message catalogs can actually be found.
+
+def _(msg):
+ return msg
+
+try:
+ import gettext
+
+except (ImportError, IOError):
+ def get_translator(pkg):
+ return _
+
+else:
+ import os
+
+ _cache = {}
+ _top = os.path.dirname(os.path.abspath(__file__))
+
+ def get_translator(pkg):
+ if not _cache.has_key(pkg):
+ locale_dir = os.path.join(_top, pkg.replace(".", os.sep))
+ try:
+ f = gettext.translation('4Suite', locale_dir).gettext
+ except IOError:
+ f = _
+ _cache[pkg] = f
+ return _cache[pkg]
Deleted: branches/2.3/Lib/xml/Uri.py
===================================================================
--- trunk/jython/Lib/xml/Uri.py 2006-11-16 07:49:15 UTC (rev 2972)
+++ branches/2.3/Lib/xml/Uri.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -1,380 +0,0 @@
-# pylint: disable-msg=C0103
-#
-# backported code from 4Suite with slight modifications, started from r1.89 of
-# Ft/Lib/Uri.py, by syt@... on 2005-02-09
-#
-# part if not all of this code should probably move to urlparse (or be used
-# to fix some existant functions in this module)
-#
-#
-# Copyright 2004 Fourthought, Inc. (USA).
-# Detailed license and copyright information: http://4suite.org/COPYRIGHT
-# Project home, documentation, distributions: http://4suite.org/
-import os.path
-import sys
-import re
-import urlparse, urllib, urllib2
-
-def UnsplitUriRef(uriRefSeq):
- """should replace urlparse.urlunsplit
-
- Given a sequence as would be produced by SplitUriRef(), assembles and
- returns a URI reference as a string.
- """
- if not isinstance(uriRefSeq, (tuple, list)):
- raise TypeError("sequence expected, got %s" % type(uriRefSeq))
- (scheme, authority, path, query, fragment) = uriRefSeq
- uri = ''
- if scheme is not None:
- uri += scheme + ':'
- if authority is not None:
- uri += '//' + authority
- uri += path
- if query is not None:
- uri += '?' + query
- if fragment is not None:
- uri += '#' + fragment
- return uri
-
-SPLIT_URI_REF_PATTERN = re.compile(r"^(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?(?P<path>[^?#]*)(?:\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?$")
-
-def SplitUriRef(uriref):
- """should replace urlparse.urlsplit
-
- Given a valid URI reference as a string, returns a tuple representing the
- generic URI components, as per RFC 2396 appendix B. The tuple's structure
- is (scheme, authority, path, query, fragment).
-
- All values will be strings (possibly empty) or None if undefined.
-
- Note that per rfc3986, there is no distinction between a path and
- an "opaque part", as there was in RFC 2396.
- """
- # the pattern will match every possible string, so it's safe to
- # assume there's a groupdict method to call.
- g = SPLIT_URI_REF_PATTERN.match(uriref).groupdict()
- scheme = g['scheme']
- authority = g['authority']
- path = g['path']
- query = g['query']
- fragment = g['fragment']
- return (scheme, authority, path, query, fragment)
-
-
-def Absolutize(uriRef, baseUri):
- """
- Resolves a URI reference to absolute form, effecting the result of RFC
- 3986 section 5. The URI reference is considered to be relative to the
- given base URI.
-
- It is the caller's responsibility to ensure that the base URI matches
- the absolute-URI syntax rule of RFC 3986, and that its path component
- does not contain '.' or '..' segments if the scheme is hierarchical.
- Unexpected results may occur otherwise.
-
- This function only conducts a minimal sanity check in order to determine
- if relative resolution is possible: it raises a UriException if the base
- URI does not have a scheme component. While it is true that the base URI
- is irrelevant if the URI reference has a scheme, an exception is raised
- in order to signal that the given string does not even come close to
- meeting the criteria to be usable as a base URI.
-
- It is the caller's responsibility to make a determination of whether the
- URI reference constitutes a "same-document reference", as defined in RFC
- 2396 or RFC 3986. As per the spec, dereferencing a same-document
- reference "should not" involve retrieval of a new representation of the
- referenced resource. Note that the two specs have different definitions
- of same-document reference: RFC 2396 says it is *only* the cases where the
- reference is the empty string, or "#" followed by a fragment; RFC 3986
- requires making a comparison of the base URI to the absolute form of the
- reference (as is returned by the spec), minus its fragment component,
- if any.
-
- This function is similar to urlparse.urljoin() and urllib.basejoin().
- Those functions, however, are (as of Python 2.3) outdated, buggy, and/or
- designed to produce results acceptable for use with other core Python
- libraries, rather than being earnest implementations of the relevant
- specs. Their problems are most noticeable in their handling of
- same-document references and 'file:' URIs, both being situations that
- come up far too often to consider the functions reliable enough for
- general use.
- """
- # Reasons to avoid using urllib.basejoin() and urlparse.urljoin():
- # - Both are partial implementations of long-obsolete specs.
- # - Both accept relative URLs as the base, which no spec allows.
- # - urllib.basejoin() mishandles the '' and '..' references.
- # - If the base URL uses a non-hierarchical or relative path,
- # or if the URL scheme is unrecognized, the result is not
- # always as expected (partly due to issues in RFC 1808).
- # - If the authority component of a 'file' URI is empty,
- # the authority component is removed altogether. If it was
- # not present, an empty authority component is in the result.
- # - '.' and '..' segments are not always collapsed as well as they
- # should be (partly due to issues in RFC 1808).
- # - Effective Python 2.4, urllib.basejoin() *is* urlparse.urljoin(),
- # but urlparse.urljoin() is still based on RFC 1808.
-
- # This procedure is based on the pseudocode in RFC 3986 sec. 5.2.
- #
- # ensure base URI is absolute
- if not baseUri:
- raise ValueError('baseUri is required and must be a non empty string')
- if not IsAbsolute(baseUri):
- raise ValueError('%r is not an absolute URI' % baseUri)
- # shortcut for the simplest same-document reference cases
- if uriRef == '' or uriRef[0] == '#':
- return baseUri.split('#')[0] + uriRef
- # ensure a clean slate
- tScheme = tAuth = tPath = tQuery = None
- # parse the reference into its components
- (rScheme, rAuth, rPath, rQuery, rFrag) = SplitUriRef(uriRef)
- # if the reference is absolute, eliminate '.' and '..' path segments
- # and skip to the end
- if rScheme is not None:
- tScheme = rScheme
- tAuth = rAuth
- tPath = RemoveDotSegments(rPath)
- tQuery = rQuery
- else:
- # the base URI's scheme, and possibly more, will be inherited
- (bScheme, bAuth, bPath, bQuery, bFrag) = SplitUriRef(baseUri)
- # if the reference is a net-path, just eliminate '.' and '..' path
- # segments; no other changes needed.
- if rAuth is not None:
- tAuth = rAuth
- tPath = RemoveDotSegments(rPath)
- tQuery = rQuery
- # if it's not a net-path, we need to inherit pieces of the base URI
- else:
- # use base URI's path if the reference's path is empty
- if not rPath:
- tPath = bPath
- # use the reference's query, if any, or else the base URI's,
- tQuery = rQuery is not None and rQuery or bQuery
- # the reference's path is not empty
- else:
- # just use the reference's path if it's absolute
- if rPath[0] == '/':
- tPath = RemoveDotSegments(rPath)
- # merge the reference's relative path with the base URI's path
- else:
- if bAuth is not None and not bPath:
- tPath = '/' + rPath
- else:
- tPath = bPath[:bPath.rfind('/')+1] + rPath
- tPath = RemoveDotSegments(tPath)
- # use the reference's query
- tQuery = rQuery
- # since the reference isn't a net-path,
- # use the authority from the base URI
- tAuth = bAuth
- # inherit the scheme from the base URI
- tScheme = bScheme
- # always use the reference's fragment (but no need to define another var)
- #tFrag = rFrag
-
- # now compose the target URI (RFC 3986 sec. 5.3)
- return UnsplitUriRef((tScheme, tAuth, tPath, tQuery, rFrag))
-
-
-REG_NAME_HOST_PATTERN = re.compile(r"^(?:(?:[0-9A-Za-z\-_\.!~*'();&=+$,]|(?:%[0-9A-Fa-f]{2}))*)$")
-
-def MakeUrllibSafe(uriRef):
- """
- Makes the given RFC 3986-conformant URI reference safe for passing
- to legacy urllib functions. The result may not be a valid URI.
-
- As of Python 2.3.3, urllib.urlopen() does not fully support
- internationalized domain names, it does not strip fragment components,
- and on Windows, it expects file URIs to use '|' instead of ':' in the
- path component corresponding to the drivespec. It also relies on
- urllib.unquote(), which mishandles unicode arguments. This function
- produces a URI reference that will work around these issues, although
- the IDN workaround is limited to Python 2.3 only. May raise a
- UnicodeEncodeError if the URI reference is Unicode and erroneously
- contains non-ASCII characters.
- """
- # IDN support requires decoding any percent-encoded octets in the
- # host part (if it's a reg-name) of the authority component, and when
- # doing DNS lookups, applying IDNA encoding to that string first.
- # As of Python 2.3, there is an IDNA codec, and the socket and httplib
- # modules accept Unicode strings and apply IDNA encoding automatically
- # where necessary. However, urllib.urlopen() has not yet been updated
- # to do the same; it raises an exception if you give it a Unicode
- # string, and does no conversion on non-Unicode strings, meaning you
- # have to give it an IDNA string yourself. We will only support it on
- # Python 2.3 and up.
- #
- # see if host is a reg-name, as opposed to IPv4 or IPv6 addr.
- if isinstance(uriRef, unicode):
- try:
- uriRef = uriRef.encode('us-ascii') # parts of urllib are not unicode safe
- except UnicodeError:
- raise ValueError("uri %r must consist of ASCII characters." % uriRef)
- (scheme, auth, path, query, frag) = urlparse.urlsplit(uriRef)
- if auth and auth.find('@') > -1:
- userinfo, hostport = auth.split('@')
- else:
- userinfo = None
- hostport = auth
- if hostport and hostport.find(':') > -1:
- host, port = hostport.split(':')
- else:
- host = hostport
- port = None
- if host and REG_NAME_HOST_PATTERN.match(host):
- # percent-encoded hostnames will always fail DNS lookups
- host = urllib.unquote(host) #PercentDecode(host)
- # IDNA-encode if possible.
- # We shouldn't do this for schemes that don't need DNS lookup,
- # but are there any (that you'd be calling urlopen for)?
- if sys.version_info[0:2] >= (2, 3):
- if isinstance(host, str):
- host = host.decode('utf-8')
- host = host.encode('idna')
- # reassemble the authority with the new hostname
- # (percent-decoded, and possibly IDNA-encoded)
- auth = ''
- if userinfo:
- auth += userinfo + '@'
- auth += host
- if port:
- auth += ':' + port
-
- # On Windows, ensure that '|', not ':', is used in a drivespec.
- if os.name == 'nt' and scheme == 'file':
- path = path.replace(':', '|', 1)
-
- # Note that we drop fragment, if any. See RFC 3986 sec. 3.5.
- uri = urlparse.urlunsplit((scheme, auth, path, query, None))
-
- return uri
-
-
-
-def BaseJoin(base, uriRef):
- """
- Merges a base URI reference with another URI reference, returning a
- new URI reference.
-
- It behaves exactly the same as Absolutize(), except the arguments
- are reversed, and it accepts any URI reference (even a relative URI)
- as the base URI. If the base has no scheme component, it is
- evaluated as if it did, and then the scheme component of the result
- is removed from the result, unless the uriRef had a scheme. Thus, if
- neither argument has a scheme component, the result won't have one.
-
- This function is named BaseJoin because it is very much like
- urllib.basejoin(), but it follows the current rfc3986 algorithms
- for path merging, dot segment elimination, and inheritance of query
- and fragment components.
-
- WARNING: This function exists for 2 reasons: (1) because of a need
- within the 4Suite repository to perform URI reference absolutization
- using base URIs that are stored (inappropriately) as absolute paths
- in the subjects of statements in the RDF model, and (2) because of
- a similar need to interpret relative repo paths in a 4Suite product
- setup.xml file as being relative to a path that can be set outside
- the document. When these needs go away, this function probably will,
- too, so it is not advisable to use it.
- """
- if IsAbsolute(base):
- return Absolutize(uriRef, base)
- else:
- dummyscheme = 'basejoin'
- res = Absolutize(uriRef, '%s:%s' % (dummyscheme, base))
- if IsAbsolute(uriRef):
- # scheme will be inherited from uriRef
- return res
- else:
- # no scheme in, no scheme out
- return res[len(dummyscheme)+1:]
-
-
-def RemoveDotSegments(path):
- """
- Supports Absolutize() by implementing the remove_dot_segments function
- described in RFC 3986 sec. 5.2. It collapses most of the '.' and '..'
- segments out of a path without eliminating empty segments. It is intended
- to be used during the path merging process and may not give expected
- results when used independently. Use NormalizePathSegments() or
- NormalizePathSegmentsInUri() if more general normalization is desired.
-
- semi-private because it is not for general use. I've implemented it
- using two segment stacks, as alluded to in the spec, rather than the
- explicit string-walking algorithm that would be too inefficient. (mbrown)
- """
- # return empty string if entire path is just "." or ".."
- if path == '.' or path == '..':
- return path[0:0] # preserves string type
- # remove all "./" or "../" segments at the beginning
- while path:
- if path[:2] == './':
- path = path[2:]
- elif path[:3] == '../':
- path = path[3:]
- else:
- break
- # We need to keep track of whether there was a leading slash,
- # because we're going to drop it in order to prevent our list of
- # segments from having an ambiguous empty first item when we call
- # split().
- leading_slash = 0
- if path[:1] == '/':
- path = path[1:]
- leading_slash = 1
- # replace a trailing "/." with just "/"
- if path[-2:] == '/.':
- path = path[:-1]
- # convert the segments into a list and process each segment in
- # order from left to right.
- segments = path.split('/')
- keepers = []
- segments.reverse()
- while segments:
- seg = segments.pop()
- # '..' means drop the previous kept segment, if any.
- # If none, and if the path is relative, then keep the '..'.
- # If the '..' was the last segment, ensure
- # that the result ends with '/'.
- if seg == '..':
- if keepers:
- keepers.pop()
- elif not leading_slash:
- keepers.append(seg)
- if not segments:
- keepers.append('')
- # ignore '.' segments and keep all others, even empty ones
- elif seg != '.':
- keepers.append(seg)
- # reassemble the kept segments
- return leading_slash * '/' + '/'.join(keepers)
-
-
-SCHEME_PATTERN = re.compile(r'([a-zA-Z][a-zA-Z0-9+\-.]*):')
-def GetScheme(uriRef):
- """
- Obtains, with optimum efficiency, just the scheme from a URI reference.
- Returns a string, or if no scheme could be found, returns None.
- """
- # Using a regex seems to be the best option. Called 50,000 times on
- # different URIs, on a 1.0-GHz PIII with FreeBSD 4.7 and Python
- # 2.2.1, this method completed in 0.95s, and 0.05s if there was no
- # scheme to find. By comparison,
- # urllib.splittype()[0] took 1.5s always;
- # Ft.Lib.Uri.SplitUriRef()[0] took 2.5s always;
- # urlparse.urlparse()[0] took 3.5s always.
- m = SCHEME_PATTERN.match(uriRef)
- if m is None:
- return None
- else:
- return m.group(1)
-
-
-def IsAbsolute(identifier):
- """
- Given a string believed to be a URI or URI reference, tests that it is
- absolute (as per RFC 2396), not relative -- i.e., that it has a scheme.
- """
- # We do it this way to avoid compiling another massive regex.
- return GetScheme(identifier) is not None
Copied: branches/2.3/Lib/xml/Uri.py (from rev 2972, trunk/jython/Lib/xml/Uri.py)
===================================================================
--- branches/2.3/Lib/xml/Uri.py (rev 0)
+++ branches/2.3/Lib/xml/Uri.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -0,0 +1,380 @@
+# pylint: disable-msg=C0103
+#
+# backported code from 4Suite with slight modifications, started from r1.89 of
+# Ft/Lib/Uri.py, by syt@... on 2005-02-09
+#
+# part if not all of this code should probably move to urlparse (or be used
+# to fix some existant functions in this module)
+#
+#
+# Copyright 2004 Fourthought, Inc. (USA).
+# Detailed license and copyright information: http://4suite.org/COPYRIGHT
+# Project home, documentation, distributions: http://4suite.org/
+import os.path
+import sys
+import re
+import urlparse, urllib, urllib2
+
+def UnsplitUriRef(uriRefSeq):
+ """should replace urlparse.urlunsplit
+
+ Given a sequence as would be produced by SplitUriRef(), assembles and
+ returns a URI reference as a string.
+ """
+ if not isinstance(uriRefSeq, (tuple, list)):
+ raise TypeError("sequence expected, got %s" % type(uriRefSeq))
+ (scheme, authority, path, query, fragment) = uriRefSeq
+ uri = ''
+ if scheme is not None:
+ uri += scheme + ':'
+ if authority is not None:
+ uri += '//' + authority
+ uri += path
+ if query is not None:
+ uri += '?' + query
+ if fragment is not None:
+ uri += '#' + fragment
+ return uri
+
+SPLIT_URI_REF_PATTERN = re.compile(r"^(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?(?P<path>[^?#]*)(?:\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?$")
+
+def SplitUriRef(uriref):
+ """should replace urlparse.urlsplit
+
+ Given a valid URI reference as a string, returns a tuple representing the
+ generic URI components, as per RFC 2396 appendix B. The tuple's structure
+ is (scheme, authority, path, query, fragment).
+
+ All values will be strings (possibly empty) or None if undefined.
+
+ Note that per rfc3986, there is no distinction between a path and
+ an "opaque part", as there was in RFC 2396.
+ """
+ # the pattern will match every possible string, so it's safe to
+ # assume there's a groupdict method to call.
+ g = SPLIT_URI_REF_PATTERN.match(uriref).groupdict()
+ scheme = g['scheme']
+ authority = g['authority']
+ path = g['path']
+ query = g['query']
+ fragment = g['fragment']
+ return (scheme, authority, path, query, fragment)
+
+
+def Absolutize(uriRef, baseUri):
+ """
+ Resolves a URI reference to absolute form, effecting the result of RFC
+ 3986 section 5. The URI reference is considered to be relative to the
+ given base URI.
+
+ It is the caller's responsibility to ensure that the base URI matches
+ the absolute-URI syntax rule of RFC 3986, and that its path component
+ does not contain '.' or '..' segments if the scheme is hierarchical.
+ Unexpected results may occur otherwise.
+
+ This function only conducts a minimal sanity check in order to determine
+ if relative resolution is possible: it raises a UriException if the base
+ URI does not have a scheme component. While it is true that the base URI
+ is irrelevant if the URI reference has a scheme, an exception is raised
+ in order to signal that the given string does not even come close to
+ meeting the criteria to be usable as a base URI.
+
+ It is the caller's responsibility to make a determination of whether the
+ URI reference constitutes a "same-document reference", as defined in RFC
+ 2396 or RFC 3986. As per the spec, dereferencing a same-document
+ reference "should not" involve retrieval of a new representation of the
+ referenced resource. Note that the two specs have different definitions
+ of same-document reference: RFC 2396 says it is *only* the cases where the
+ reference is the empty string, or "#" followed by a fragment; RFC 3986
+ requires making a comparison of the base URI to the absolute form of the
+ reference (as is returned by the spec), minus its fragment component,
+ if any.
+
+ This function is similar to urlparse.urljoin() and urllib.basejoin().
+ Those functions, however, are (as of Python 2.3) outdated, buggy, and/or
+ designed to produce results acceptable for use with other core Python
+ libraries, rather than being earnest implementations of the relevant
+ specs. Their problems are most noticeable in their handling of
+ same-document references and 'file:' URIs, both being situations that
+ come up far too often to consider the functions reliable enough for
+ general use.
+ """
+ # Reasons to avoid using urllib.basejoin() and urlparse.urljoin():
+ # - Both are partial implementations of long-obsolete specs.
+ # - Both accept relative URLs as the base, which no spec allows.
+ # - urllib.basejoin() mishandles the '' and '..' references.
+ # - If the base URL uses a non-hierarchical or relative path,
+ # or if the URL scheme is unrecognized, the result is not
+ # always as expected (partly due to issues in RFC 1808).
+ # - If the authority component of a 'file' URI is empty,
+ # the authority component is removed altogether. If it was
+ # not present, an empty authority component is in the result.
+ # - '.' and '..' segments are not always collapsed as well as they
+ # should be (partly due to issues in RFC 1808).
+ # - Effective Python 2.4, urllib.basejoin() *is* urlparse.urljoin(),
+ # but urlparse.urljoin() is still based on RFC 1808.
+
+ # This procedure is based on the pseudocode in RFC 3986 sec. 5.2.
+ #
+ # ensure base URI is absolute
+ if not baseUri:
+ raise ValueError('baseUri is required and must be a non empty string')
+ if not IsAbsolute(baseUri):
+ raise ValueError('%r is not an absolute URI' % baseUri)
+ # shortcut for the simplest same-document reference cases
+ if uriRef == '' or uriRef[0] == '#':
+ return baseUri.split('#')[0] + uriRef
+ # ensure a clean slate
+ tScheme = tAuth = tPath = tQuery = None
+ # parse the reference into its components
+ (rScheme, rAuth, rPath, rQuery, rFrag) = SplitUriRef(uriRef)
+ # if the reference is absolute, eliminate '.' and '..' path segments
+ # and skip to the end
+ if rScheme is not None:
+ tScheme = rScheme
+ tAuth = rAuth
+ tPath = RemoveDotSegments(rPath)
+ tQuery = rQuery
+ else:
+ # the base URI's scheme, and possibly more, will be inherited
+ (bScheme, bAuth, bPath, bQuery, bFrag) = SplitUriRef(baseUri)
+ # if the reference is a net-path, just eliminate '.' and '..' path
+ # segments; no other changes needed.
+ if rAuth is not None:
+ tAuth = rAuth
+ tPath = RemoveDotSegments(rPath)
+ tQuery = rQuery
+ # if it's not a net-path, we need to inherit pieces of the base URI
+ else:
+ # use base URI's path if the reference's path is empty
+ if not rPath:
+ tPath = bPath
+ # use the reference's query, if any, or else the base URI's,
+ tQuery = rQuery is not None and rQuery or bQuery
+ # the reference's path is not empty
+ else:
+ # just use the reference's path if it's absolute
+ if rPath[0] == '/':
+ tPath = RemoveDotSegments(rPath)
+ # merge the reference's relative path with the base URI's path
+ else:
+ if bAuth is not None and not bPath:
+ tPath = '/' + rPath
+ else:
+ tPath = bPath[:bPath.rfind('/')+1] + rPath
+ tPath = RemoveDotSegments(tPath)
+ # use the reference's query
+ tQuery = rQuery
+ # since the reference isn't a net-path,
+ # use the authority from the base URI
+ tAuth = bAuth
+ # inherit the scheme from the base URI
+ tScheme = bScheme
+ # always use the reference's fragment (but no need to define another var)
+ #tFrag = rFrag
+
+ # now compose the target URI (RFC 3986 sec. 5.3)
+ return UnsplitUriRef((tScheme, tAuth, tPath, tQuery, rFrag))
+
+
+REG_NAME_HOST_PATTERN = re.compile(r"^(?:(?:[0-9A-Za-z\-_\.!~*'();&=+$,]|(?:%[0-9A-Fa-f]{2}))*)$")
+
+def MakeUrllibSafe(uriRef):
+ """
+ Makes the given RFC 3986-conformant URI reference safe for passing
+ to legacy urllib functions. The result may not be a valid URI.
+
+ As of Python 2.3.3, urllib.urlopen() does not fully support
+ internationalized domain names, it does not strip fragment components,
+ and on Windows, it expects file URIs to use '|' instead of ':' in the
+ path component corresponding to the drivespec. It also relies on
+ urllib.unquote(), which mishandles unicode arguments. This function
+ produces a URI reference that will work around these issues, although
+ the IDN workaround is limited to Python 2.3 only. May raise a
+ UnicodeEncodeError if the URI reference is Unicode and erroneously
+ contains non-ASCII characters.
+ """
+ # IDN support requires decoding any percent-encoded octets in the
+ # host part (if it's a reg-name) of the authority component, and when
+ # doing DNS lookups, applying IDNA encoding to that string first.
+ # As of Python 2.3, there is an IDNA codec, and the socket and httplib
+ # modules accept Unicode strings and apply IDNA encoding automatically
+ # where necessary. However, urllib.urlopen() has not yet been updated
+ # to do the same; it raises an exception if you give it a Unicode
+ # string, and does no conversion on non-Unicode strings, meaning you
+ # have to give it an IDNA string yourself. We will only support it on
+ # Python 2.3 and up.
+ #
+ # see if host is a reg-name, as opposed to IPv4 or IPv6 addr.
+ if isinstance(uriRef, unicode):
+ try:
+ uriRef = uriRef.encode('us-ascii') # parts of urllib are not unicode safe
+ except UnicodeError:
+ raise ValueError("uri %r must consist of ASCII characters." % uriRef)
+ (scheme, auth, path, query, frag) = urlparse.urlsplit(uriRef)
+ if auth and auth.find('@') > -1:
+ userinfo, hostport = auth.split('@')
+ else:
+ userinfo = None
+ hostport = auth
+ if hostport and hostport.find(':') > -1:
+ host, port = hostport.split(':')
+ else:
+ host = hostport
+ port = None
+ if host and REG_NAME_HOST_PATTERN.match(host):
+ # percent-encoded hostnames will always fail DNS lookups
+ host = urllib.unquote(host) #PercentDecode(host)
+ # IDNA-encode if possible.
+ # We shouldn't do this for schemes that don't need DNS lookup,
+ # but are there any (that you'd be calling urlopen for)?
+ if sys.version_info[0:2] >= (2, 3):
+ if isinstance(host, str):
+ host = host.decode('utf-8')
+ host = host.encode('idna')
+ # reassemble the authority with the new hostname
+ # (percent-decoded, and possibly IDNA-encoded)
+ auth = ''
+ if userinfo:
+ auth += userinfo + '@'
+ auth += host
+ if port:
+ auth += ':' + port
+
+ # On Windows, ensure that '|', not ':', is used in a drivespec.
+ if os.name == 'nt' and scheme == 'file':
+ path = path.replace(':', '|', 1)
+
+ # Note that we drop fragment, if any. See RFC 3986 sec. 3.5.
+ uri = urlparse.urlunsplit((scheme, auth, path, query, None))
+
+ return uri
+
+
+
+def BaseJoin(base, uriRef):
+ """
+ Merges a base URI reference with another URI reference, returning a
+ new URI reference.
+
+ It behaves exactly the same as Absolutize(), except the arguments
+ are reversed, and it accepts any URI reference (even a relative URI)
+ as the base URI. If the base has no scheme component, it is
+ evaluated as if it did, and then the scheme component of the result
+ is removed from the result, unless the uriRef had a scheme. Thus, if
+ neither argument has a scheme component, the result won't have one.
+
+ This function is named BaseJoin because it is very much like
+ urllib.basejoin(), but it follows the current rfc3986 algorithms
+ for path merging, dot segment elimination, and inheritance of query
+ and fragment components.
+
+ WARNING: This function exists for 2 reasons: (1) because of a need
+ within the 4Suite repository to perform URI reference absolutization
+ using base URIs that are stored (inappropriately) as absolute paths
+ in the subjects of statements in the RDF model, and (2) because of
+ a similar need to interpret relative repo paths in a 4Suite product
+ setup.xml file as being relative to a path that can be set outside
+ the document. When these needs go away, this function probably will,
+ too, so it is not advisable to use it.
+ """
+ if IsAbsolute(base):
+ return Absolutize(uriRef, base)
+ else:
+ dummyscheme = 'basejoin'
+ res = Absolutize(uriRef, '%s:%s' % (dummyscheme, base))
+ if IsAbsolute(uriRef):
+ # scheme will be inherited from uriRef
+ return res
+ else:
+ # no scheme in, no scheme out
+ return res[len(dummyscheme)+1:]
+
+
+def RemoveDotSegments(path):
+ """
+ Supports Absolutize() by implementing the remove_dot_segments function
+ described in RFC 3986 sec. 5.2. It collapses most of the '.' and '..'
+ segments out of a path without eliminating empty segments. It is intended
+ to be used during the path merging process and may not give expected
+ results when used independently. Use NormalizePathSegments() or
+ NormalizePathSegmentsInUri() if more general normalization is desired.
+
+ semi-private because it is not for general use. I've implemented it
+ using two segment stacks, as alluded to in the spec, rather than the
+ explicit string-walking algorithm that would be too inefficient. (mbrown)
+ """
+ # return empty string if entire path is just "." or ".."
+ if path == '.' or path == '..':
+ return path[0:0] # preserves string type
+ # remove all "./" or "../" segments at the beginning
+ while path:
+ if path[:2] == './':
+ path = path[2:]
+ elif path[:3] == '../':
+ path = path[3:]
+ else:
+ break
+ # We need to keep track of whether there was a leading slash,
+ # because we're going to drop it in order to prevent our list of
+ # segments from having an ambiguous empty first item when we call
+ # split().
+ leading_slash = 0
+ if path[:1] == '/':
+ path = path[1:]
+ leading_slash = 1
+ # replace a trailing "/." with just "/"
+ if path[-2:] == '/.':
+ path = path[:-1]
+ # convert the segments into a list and process each segment in
+ # order from left to right.
+ segments = path.split('/')
+ keepers = []
+ segments.reverse()
+ while segments:
+ seg = segments.pop()
+ # '..' means drop the previous kept segment, if any.
+ # If none, and if the path is relative, then keep the '..'.
+ # If the '..' was the last segment, ensure
+ # that the result ends with '/'.
+ if seg == '..':
+ if keepers:
+ keepers.pop()
+ elif not leading_slash:
+ keepers.append(seg)
+ if not segments:
+ keepers.append('')
+ # ignore '.' segments and keep all others, even empty ones
+ elif seg != '.':
+ keepers.append(seg)
+ # reassemble the kept segments
+ return leading_slash * '/' + '/'.join(keepers)
+
+
+SCHEME_PATTERN = re.compile(r'([a-zA-Z][a-zA-Z0-9+\-.]*):')
+def GetScheme(uriRef):
+ """
+ Obtains, with optimum efficiency, just the scheme from a URI reference.
+ Returns a string, or if no scheme could be found, returns None.
+ """
+ # Using a regex seems to be the best option. Called 50,000 times on
+ # different URIs, on a 1.0-GHz PIII with FreeBSD 4.7 and Python
+ # 2.2.1, this method completed in 0.95s, and 0.05s if there was no
+ # scheme to find. By comparison,
+ # urllib.splittype()[0] took 1.5s always;
+ # Ft.Lib.Uri.SplitUriRef()[0] took 2.5s always;
+ # urlparse.urlparse()[0] took 3.5s always.
+ m = SCHEME_PATTERN.match(uriRef)
+ if m is None:
+ return None
+ else:
+ return m.group(1)
+
+
+def IsAbsolute(identifier):
+ """
+ Given a string believed to be a URI or URI reference, tests that it is
+ absolute (as per RFC 2396), not relative -- i.e., that it has a scheme.
+ """
+ # We do it this way to avoid compiling another massive regex.
+ return GetScheme(identifier) is not None
Deleted: branches/2.3/Lib/xml/__init__.py
===================================================================
--- trunk/jython/Lib/xml/__init__.py 2006-11-16 07:49:15 UTC (rev 2972)
+++ branches/2.3/Lib/xml/__init__.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -1,41 +0,0 @@
-"""Core XML support for Jython.
-
-This package contains two sub-packages:
-
-dom -- The W3C Document Object Model. This supports DOM Level 1 +
- Namespaces.
-
-sax -- The Simple API for XML, developed by XML-Dev, led by David
- Megginson and ported to Python by Lars Marius Garshol. This
- supports the SAX 2 API.
-
-"""
-
-__all__ = ['dom', 'sax']
-
-# When being checked-out without options, this has the form
-# "<dollar>Revision: x.y </dollar>"
-# When exported using -kv, it is "x.y".
-__version__ = "$Revision$".split()[-2:][0]
-
-
-_MINIMUM_XMLPLUS_VERSION = (0, 8, 5)
-
-
-try:
- import _xmlplus
-except ImportError:
- pass
-else:
- try:
- v = _xmlplus.version_info
- except AttributeError:
- # _xmlplus is too old; ignore it
- pass
- else:
- if v >= _MINIMUM_XMLPLUS_VERSION:
- import sys
- _xmlplus.__path__.extend(__path__)
- sys.modules[__name__] = _xmlplus
- else:
- del v
Copied: branches/2.3/Lib/xml/__init__.py (from rev 2972, trunk/jython/Lib/xml/__init__.py)
===================================================================
--- branches/2.3/Lib/xml/__init__.py (rev 0)
+++ branches/2.3/Lib/xml/__init__.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -0,0 +1,41 @@
+"""Core XML support for Jython.
+
+This package contains two sub-packages:
+
+dom -- The W3C Document Object Model. This supports DOM Level 1 +
+ Namespaces.
+
+sax -- The Simple API for XML, developed by XML-Dev, led by David
+ Megginson and ported to Python by Lars Marius Garshol. This
+ supports the SAX 2 API.
+
+"""
+
+__all__ = ['dom', 'sax']
+
+# When being checked-out without options, this has the form
+# "<dollar>Revision: x.y </dollar>"
+# When exported using -kv, it is "x.y".
+__version__ = "$Revision$".split()[-2:][0]
+
+
+_MINIMUM_XMLPLUS_VERSION = (0, 8, 5)
+
+
+try:
+ import _xmlplus
+except ImportError:
+ pass
+else:
+ try:
+ v = _xmlplus.version_info
+ except AttributeError:
+ # _xmlplus is too old; ignore it
+ pass
+ else:
+ if v >= _MINIMUM_XMLPLUS_VERSION:
+ import sys
+ _xmlplus.__path__.extend(__path__)
+ sys.modules[__name__] = _xmlplus
+ else:
+ del v
Copied: branches/2.3/Lib/xml/dom (from rev 2972, trunk/jython/Lib/xml/dom)
Property changes on: branches/2.3/Lib/xml/dom
___________________________________________________________________
Name: svn:ignore
+ *$py.class
Deleted: branches/2.3/Lib/xml/dom/MessageSource.py
===================================================================
--- trunk/jython/Lib/xml/dom/MessageSource.py 2006-11-16 07:49:15 UTC (rev 2972)
+++ branches/2.3/Lib/xml/dom/MessageSource.py 2006-11-18 19:47:26 UTC (rev 2973)
@@ -1,54 +0,0 @@
-# DOMException
-from xml.dom import INDEX_SIZE_ERR, DOMSTRING_SIZE_ERR , HIERARCHY_REQUEST_ERR
-from xml.dom import WRONG_DOCUMENT_ERR, INVALID_CHARACTER_ERR, NO_DATA_ALLOWED_ERR
-from xml.dom import NO_MODIFICATION_ALLOWED_ERR, NOT_FOUND_ERR, NOT_SUPPORTED_ERR
-from xml.dom import INUSE_ATTRIBUTE_ERR, INVALID_STATE_ERR, SYNTAX_ERR
-from xml.dom import INVALID_MODIFICATION_ERR, NAMESPACE_ERR, INVALID_ACCESS_ERR
-from xml.dom import VALIDATION_ERR
-
-# EventException
-from xml.dom import UNSPECIFIED_EVENT_TYPE_ERR
-
-#Range Exceptions
-from xml.dom import BAD_BOUNDARYPOINTS_ERR
-from xml.dom import INVALID_NODE_TYPE_ERR
-
-# Fourthought Exceptions
-from xml.dom import XML_PARSE_ERR
-
-from xml.FtCore import get_translator
-
-_ = get_translator("dom")
-
-
-DOMExceptionStrings = {
- INDEX_SIZE_ERR: _("Index error accessing NodeList or NamedNodeMap"),
- DOMSTRING_SIZE_ERR: _("DOMString exceeds maximum size"),
- HIERARCHY_REQUEST_ERR: _("Node manipulation results in invalid parent/child relationship."),
- WRONG_DOCUMENT_ERR: _("Node is from a different document"),
- INVALID_CHARACTER_ERR: _("Invalid or illegal character"),
- NO_DATA_ALLOWED_ERR: _("Node does not support data"),
- NO_MODIFICATION_ALLOWED_ERR: _("Attempt to modify a read-only object"),
- NOT_FOUND_ERR: _("Node does not exist in this context"),
- NOT_SUPPORTED_ERR: _("Object or operation not supported"),
- INUSE_ATTRIBUTE_ERR: _("Attribute already in use by an element"),
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
| Thread | Author | Date | |
|---|---|---|---|
| [Jython-checkins] SF.net SVN: jython: [2839] branches/2.3 | <m_small@us...> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|