Merged revisions 59376-59406 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r59377 | georg.brandl | 2007-12-06 01:24:23 +0100 (Thu, 06 Dec 2007) | 2 lines

  Add another GHOP student to ACKS.
........
  r59378 | raymond.hettinger | 2007-12-06 01:56:53 +0100 (Thu, 06 Dec 2007) | 5 lines

  Fix Issue 1045.
  Factor-out common calling code by simplifying the length_hint API.
  Speed-up the function by caching the PyObject_String for the attribute lookup.
........
  r59380 | georg.brandl | 2007-12-06 02:52:24 +0100 (Thu, 06 Dec 2007) | 2 lines

  Diverse markup fixes.
........
  r59383 | georg.brandl | 2007-12-06 10:45:39 +0100 (Thu, 06 Dec 2007) | 2 lines

  Better re.split examples.
........
  r59386 | christian.heimes | 2007-12-06 14:15:13 +0100 (Thu, 06 Dec 2007) | 2 lines

  Fixed get_config_h_filename for Windows. Without the patch it can't find the pyconfig.h file inside a build tree.
  Added several small unit tests for sysconfig.
........
  r59387 | christian.heimes | 2007-12-06 14:30:11 +0100 (Thu, 06 Dec 2007) | 1 line

  Silence more warnings, _CRT_NONSTDC_NO_DEPRECATE is already defined in pyconfig.h but several projects don't include it.
........
  r59389 | christian.heimes | 2007-12-06 14:55:01 +0100 (Thu, 06 Dec 2007) | 1 line

  Disabled one test that is failing on Unix
........
  r59399 | christian.heimes | 2007-12-06 22:13:06 +0100 (Thu, 06 Dec 2007) | 8 lines

  Several Windows related cleanups:
  * Removed a #define from pyconfig.h. The macro was already defined a few lines higher.
  * Fixed path to tix in the build_tkinter.py script
  * Changed make_buildinfo.c to use versions of unlink and strcat which are considered safe by Windows (as suggested by MvL).
  * Removed two defines from pyproject.vsprops that are no longer required. Both are defined in pyconfig.h and make_buildinfo.c doesn't use the unsafe versions any more (as suggested by MvL).
  * Added some more information about PGO and the property files to PCbuild9/readme.txt.

  Are you fine with the changes, Martin?
........
  r59400 | raymond.hettinger | 2007-12-07 02:53:01 +0100 (Fri, 07 Dec 2007) | 4 lines

  Don't have the docs berate themselves.  Keep a professional tone.
  If a todo is needed, put it in the tracker.
........
  r59402 | georg.brandl | 2007-12-07 10:07:10 +0100 (Fri, 07 Dec 2007) | 3 lines

  Increase unit test coverage of SimpleXMLRPCServer.
  Written for GHOP by Turkay Eren.
........
  r59406 | georg.brandl | 2007-12-07 16:16:57 +0100 (Fri, 07 Dec 2007) | 2 lines

  Update to windows doc from Robert.
........
diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
index 2674716..75a69e8 100644
--- a/Lib/test/test_xmlrpc.py
+++ b/Lib/test/test_xmlrpc.py
@@ -7,6 +7,9 @@
 import SimpleXMLRPCServer
 import threading
 import mimetools
+import httplib
+import socket
+import os
 from test import test_support
 
 alist = [{'astring': 'foo@bar.baz.spam',
@@ -254,9 +257,16 @@
 def http_server(evt, numrequests):
     class TestInstanceClass:
         def div(self, x, y):
-            '''This is the div function'''
             return x // y
 
+        def _methodHelp(self, name):
+            if name == 'div':
+                return 'This is the div function'
+
+    def my_function():
+        '''This is my function'''
+        return True
+
     try:
         serv = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 0),
                         logRequests=False, bind_and_activate=False)
@@ -268,6 +278,7 @@
         serv.register_multicall_functions()
         serv.register_function(pow)
         serv.register_function(lambda x,y: x+y, 'add')
+        serv.register_function(my_function)
         serv.register_instance(TestInstanceClass())
 
         # handle up to 'numrequests' requests
@@ -284,7 +295,6 @@
 
 
 
-
 class SimpleServerTestCase(unittest.TestCase):
     def setUp(self):
         # enable traceback reporting
@@ -318,12 +328,25 @@
             # protocol error; provide additional information in test output
             self.fail("%s\n%s" % (e, e.headers))
 
+    def test_404(self):
+        # send POST with httplib, it should return 404 header and
+        # 'Not Found' message.
+        import pdb; pdb.set_trace()
+        conn = httplib.HTTPConnection('localhost', PORT)
+        conn.request(b'POST', b'/this-is-not-valid')
+        response = conn.getresponse()
+        conn.close()
+
+        self.assertEqual(response.status, 404)
+        self.assertEqual(response.reason, 'Not Found')
+
     def test_introspection1(self):
         try:
             p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
             meth = p.system.listMethods()
-            expected_methods = set(['pow', 'div', 'add', 'system.listMethods',
-                'system.methodHelp', 'system.methodSignature', 'system.multicall'])
+            expected_methods = set(['pow', 'div', 'my_function', 'add',
+                                    'system.listMethods', 'system.methodHelp',
+                                    'system.methodSignature', 'system.multicall'])
             self.assertEqual(set(meth), expected_methods)
         except xmlrpclib.ProtocolError as e:
             # protocol error; provide additional information in test output
@@ -331,6 +354,7 @@
 
     def test_introspection2(self):
         try:
+            # test _methodHelp()
             p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
             divhelp = p.system.methodHelp('div')
             self.assertEqual(divhelp, 'This is the div function')
@@ -339,6 +363,18 @@
             self.fail("%s\n%s" % (e, e.headers))
 
     def test_introspection3(self):
+        try:
+            # test native doc
+            p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
+            myfunction = p.system.methodHelp('my_function')
+            self.assertEqual(myfunction, 'This is my function')
+        except xmlrpclib.ProtocolError as e:
+            # ignore failures due to non-blocking socket 'unavailable' errors
+            if not is_unavailable_exception(e):
+                # protocol error; provide additional information in test output
+                self.fail("%s\n%s" % (e, e.headers))
+
+    def test_introspection4(self):
         # the SimpleXMLRPCServer doesn't support signatures, but
         # at least check that we can try making the call
         try:
@@ -364,6 +400,34 @@
             # protocol error; provide additional information in test output
             self.fail("%s\n%s" % (e, e.headers))
 
+    def test_non_existing_multicall(self):
+        try:
+            p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
+            multicall = xmlrpclib.MultiCall(p)
+            multicall.this_is_not_exists()
+            result = multicall()
+
+            # result.results contains;
+            # [{'faultCode': 1, 'faultString': '<type \'exceptions.Exception\'>:'
+            #   'method "this_is_not_exists" is not supported'>}]
+
+            self.assertEqual(result.results[0]['faultCode'], 1)
+            self.assertEqual(result.results[0]['faultString'],
+                '<type \'exceptions.Exception\'>:method "this_is_not_exists" '
+                'is not supported')
+        except xmlrpclib.ProtocolError as e:
+            # ignore failures due to non-blocking socket 'unavailable' errors
+            if not is_unavailable_exception(e):
+                # protocol error; provide additional information in test output
+                self.fail("%s\n%s" % (e, e.headers))
+
+    def test_dotted_attribute(self):
+        # this will raise AttirebuteError because code don't want us to use
+        # private methods
+        self.assertRaises(AttributeError,
+                          SimpleXMLRPCServer.resolve_dotted_attribute, str, '__add')
+
+        self.assert_(SimpleXMLRPCServer.resolve_dotted_attribute(str, 'title'))
 
 # This is a contrived way to make a failure occur on the server side
 # in order to test the _send_traceback_header flag on the server
@@ -447,6 +511,70 @@
         else:
             self.fail('ProtocolError not raised')
 
+class CGIHandlerTestCase(unittest.TestCase):
+    def setUp(self):
+        self.cgi = SimpleXMLRPCServer.CGIXMLRPCRequestHandler()
+
+    def tearDown(self):
+        self.cgi = None
+
+    def test_cgi_get(self):
+        os.environ['REQUEST_METHOD'] = 'GET'
+        # if the method is GET and no request_text is given, it runs handle_get
+        # get sysout output
+        tmp = sys.stdout
+        sys.stdout = open(test_support.TESTFN, "w")
+        self.cgi.handle_request()
+        sys.stdout.close()
+        sys.stdout = tmp
+
+        # parse Status header
+        handle = open(test_support.TESTFN, "r").read()
+        status = handle.split()[1]
+        message = ' '.join(handle.split()[2:4])
+
+        self.assertEqual(status, '400')
+        self.assertEqual(message, 'Bad Request')
+
+        os.remove(test_support.TESTFN)
+        os.environ['REQUEST_METHOD'] = ''
+
+    def test_cgi_xmlrpc_response(self):
+        data = """<?xml version='1.0'?>
+<methodCall>
+    <methodName>test_method</methodName>
+    <params>
+        <param>
+            <value><string>foo</string></value>
+        </param>
+        <param>
+            <value><string>bar</string></value>
+        </param>
+     </params>
+</methodCall>
+"""
+        open("xmldata.txt", "w").write(data)
+        tmp1 = sys.stdin
+        tmp2 = sys.stdout
+
+        sys.stdin = open("xmldata.txt", "r")
+        sys.stdout = open(test_support.TESTFN, "w")
+
+        self.cgi.handle_request()
+
+        sys.stdin.close()
+        sys.stdout.close()
+        sys.stdin = tmp1
+        sys.stdout = tmp2
+
+        # will respond exception, if so, our goal is achieved ;)
+        handle = open(test_support.TESTFN, "r").read()
+
+        # start with 44th char so as not to get http header, we just need only xml
+        self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, handle[44:])
+
+        os.remove("xmldata.txt")
+        os.remove(test_support.TESTFN)
 
 def test_main():
     xmlrpc_tests = [XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
@@ -459,6 +587,7 @@
     if sys.platform != 'win32':
         xmlrpc_tests.append(SimpleServerTestCase)
         xmlrpc_tests.append(FailingServerTestCase)
+        xmlrpc_tests.append(CGIHandlerTestCase)
 
     test_support.run_unittest(*xmlrpc_tests)