]> granicus.if.org Git - python/commitdiff
Merged revisions 59441-59449 via svnmerge from
authorChristian Heimes <christian@cheimes.de>
Mon, 10 Dec 2007 16:18:49 +0000 (16:18 +0000)
committerChristian Heimes <christian@cheimes.de>
Mon, 10 Dec 2007 16:18:49 +0000 (16:18 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r59442 | georg.brandl | 2007-12-09 22:15:07 +0100 (Sun, 09 Dec 2007) | 5 lines

  Two fixes in DocXMLRPCServer:
  * remove parameter default that didn't make sense
  * properly escape values in output
  Thanks to Jeff Wheeler from GHOP!
........
  r59444 | georg.brandl | 2007-12-09 23:38:26 +0100 (Sun, 09 Dec 2007) | 2 lines

  Add Jeff Wheeler.
........
  r59445 | georg.brandl | 2007-12-09 23:39:12 +0100 (Sun, 09 Dec 2007) | 2 lines

  Add DocXMLRPCServer test from GHOP task #136, written by Jeff Wheeler.
........
  r59447 | christian.heimes | 2007-12-10 16:12:41 +0100 (Mon, 10 Dec 2007) | 1 line

  Added wide char api variants of getch and putch to msvcrt module. The wide char methods are required to fix #1578 in py3k. I figured out that they might be useful in 2.6, too.
........
  r59448 | christian.heimes | 2007-12-10 16:39:09 +0100 (Mon, 10 Dec 2007) | 1 line

  Stupid save all didn't safe it all ...
........

Doc/library/msvcrt.rst
Lib/DocXMLRPCServer.py
Lib/test/test_docxmlrpc.py [new file with mode: 0644]
Misc/ACKS
PC/msvcrtmodule.c

index d43bb4c60f1056aed85b5b2dbb01ab2e78d2fabf..9fa49daf27f79873767199a7d8cf32ca34feb6e6 100644 (file)
@@ -16,6 +16,10 @@ this in the implementation of the :func:`getpass` function.
 Further documentation on these functions can be found in the Platform API
 documentation.
 
+The module implements both the normal and wide char variants of the console I/O
+api. The normal API deals only with ASCII characters and is of limited use
+for internationalized applications. The wide char API should be used where 
+ever possible
 
 .. _msvcrt-files:
 
@@ -94,6 +98,13 @@ Console I/O
    return the keycode.  The :kbd:`Control-C` keypress cannot be read with this
    function.
 
+   
+.. function:: getwch()
+
+   Wide char variant of `func:getch`, returns unicode.
+   
+   ..versionadded:: 2.6
+   
 
 .. function:: getche()
 
@@ -101,16 +112,37 @@ Console I/O
    printable character.
 
 
+.. function:: getwche()
+
+   Wide char variant of `func:getche`, returns unicode.
+   
+   ..versionadded:: 2.6
+
+
 .. function:: putch(char)
 
    Print the character *char* to the console without buffering.
 
+   
+.. function:: putwch(unicode_char)
+
+   Wide char variant of `func:putch`, accepts unicode.
+   
+   ..versionadded:: 2.6
+   
 
 .. function:: ungetch(char)
 
    Cause the character *char* to be "pushed back" into the console buffer; it will
    be the next character read by :func:`getch` or :func:`getche`.
 
+   
+.. function:: ungetwch(unicode_char)
+
+   Wide char variant of `func:ungetch`, accepts unicode.
+   
+   ..versionadded:: 2.6
+
 
 .. _msvcrt-other:
 
index 08e1f10f9faa2b29f941d03c81d068800f98dd31..c95210ace12624dffedfa943525ed0abd646cbbe 100644 (file)
@@ -64,14 +64,15 @@ class ServerHTMLDoc(pydoc.HTMLDoc):
         results.append(escape(text[here:]))
         return ''.join(results)
 
-    def docroutine(self, object, name=None, mod=None,
+    def docroutine(self, object, name, mod=None,
                    funcs={}, classes={}, methods={}, cl=None):
         """Produce HTML documentation for a function or method object."""
 
         anchor = (cl and cl.__name__ or '') + '-' + name
         note = ''
 
-        title = '<a name="%s"><strong>%s</strong></a>' % (anchor, name)
+        title = '<a name="%s"><strong>%s</strong></a>' % (
+            self.escape(anchor), self.escape(name))
 
         if inspect.ismethod(object):
             args, varargs, varkw, defaults = inspect.getargspec(object)
@@ -113,6 +114,7 @@ class ServerHTMLDoc(pydoc.HTMLDoc):
             fdict[key] = '#-' + key
             fdict[value] = fdict[key]
 
+        server_name = self.escape(server_name)
         head = '<big><big><strong>%s</strong></big></big>' % server_name
         result = self.heading(head, '#ffffff', '#7799ee')
 
@@ -280,29 +282,3 @@ class DocCGIXMLRPCRequestHandler(   CGIXMLRPCRequestHandler,
     def __init__(self):
         CGIXMLRPCRequestHandler.__init__(self)
         XMLRPCDocGenerator.__init__(self)
-
-if __name__ == '__main__':
-    def deg_to_rad(deg):
-        """deg_to_rad(90) => 1.5707963267948966
-
-        Converts an angle in degrees to an angle in radians"""
-        import math
-        return deg * math.pi / 180
-
-    server = DocXMLRPCServer(("localhost", 8000))
-
-    server.set_server_title("Math Server")
-    server.set_server_name("Math XML-RPC Server")
-    server.set_server_documentation("""This server supports various mathematical functions.
-
-You can use it from Python as follows:
-
->>> from xmlrpclib import ServerProxy
->>> s = ServerProxy("http://localhost:8000")
->>> s.deg_to_rad(90.0)
-1.5707963267948966""")
-
-    server.register_function(deg_to_rad)
-    server.register_introspection_functions()
-
-    server.serve_forever()
diff --git a/Lib/test/test_docxmlrpc.py b/Lib/test/test_docxmlrpc.py
new file mode 100644 (file)
index 0000000..55c2143
--- /dev/null
@@ -0,0 +1,152 @@
+from DocXMLRPCServer import DocXMLRPCServer
+import httplib
+from test import test_support
+import threading
+import time
+import unittest
+import xmlrpclib
+
+PORT = None
+
+def server(evt, numrequests):
+    try:
+        serv = DocXMLRPCServer(("localhost", 0), logRequests=False)
+
+        global PORT
+        PORT = serv.socket.getsockname()[1]
+
+        # Add some documentation
+        serv.set_server_title("DocXMLRPCServer Test Documentation")
+        serv.set_server_name("DocXMLRPCServer Test Docs")
+        serv.set_server_documentation(
+"""This is an XML-RPC server's documentation, but the server can be used by
+POSTing to /RPC2. Try self.add, too.""")
+
+        # Create and register classes and functions
+        class TestClass(object):
+            def test_method(self, arg):
+                """Test method's docs. This method truly does very little."""
+                self.arg = arg
+
+        serv.register_introspection_functions()
+        serv.register_instance(TestClass())
+
+        def add(x, y):
+            """Add two instances together. This follows PEP008, but has nothing
+            to do with RFC1952. Case should matter: pEp008 and rFC1952.  Things
+            that start with http and ftp should be auto-linked, too:
+            http://google.com.
+            """
+            return x + y
+
+        serv.register_function(add)
+        serv.register_function(lambda x, y: x-y)
+
+        while numrequests > 0:
+            serv.handle_request()
+            numrequests -= 1
+    except socket.timeout:
+        pass
+    finally:
+        serv.server_close()
+        PORT = None
+        evt.set()
+
+class DocXMLRPCHTTPGETServer(unittest.TestCase):
+    def setUp(self):
+        # Enable server feedback
+        DocXMLRPCServer._send_traceback_header = True
+
+        self.evt = threading.Event()
+        threading.Thread(target=server, args=(self.evt, 1)).start()
+
+        # wait for port to be assigned
+        n = 1000
+        while n > 0 and PORT is None:
+            time.sleep(0.001)
+            n -= 1
+
+        self.client = httplib.HTTPConnection("localhost:%d" % PORT)
+
+    def tearDown(self):
+        self.client.close()
+
+        self.evt.wait()
+
+        # Disable server feedback
+        DocXMLRPCServer._send_traceback_header = False
+
+    def test_valid_get_response(self):
+        self.client.request("GET", "/")
+        response = self.client.getresponse()
+
+        self.assertEqual(response.status, 200)
+        self.assertEqual(response.getheader("Content-type"), "text/html")
+
+        # Server throws an exception if we don't start to read the data
+        response.read()
+
+    def test_invalid_get_response(self):
+        self.client.request("GET", "/spam")
+        response = self.client.getresponse()
+
+        self.assertEqual(response.status, 404)
+        self.assertEqual(response.getheader("Content-type"), "text/plain")
+
+        response.read()
+
+    def test_lambda(self):
+        """Test that lambda functionality stays the same.  The output produced
+        currently is, I suspect invalid because of the unencoded brackets in the
+        HTML, "<lambda>".
+
+        The subtraction lambda method is tested.
+        """
+        self.client.request("GET", "/")
+        response = self.client.getresponse()
+
+        self.assert_(
+"""<dl><dt><a name="-&lt;lambda&gt;"><strong>&lt;lambda&gt;</strong></a>(x, y)</dt></dl>"""
+            in response.read())
+
+    def test_autolinking(self):
+        """Test that the server correctly automatically wraps references to PEPS
+        and RFCs with links, and that it linkifies text starting with http or
+        ftp protocol prefixes.
+
+        The documentation for the "add" method contains the test material.
+        """
+        self.client.request("GET", "/")
+        response = self.client.getresponse()
+
+        self.assert_( # This is ugly ... how can it be made better?
+"""<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd><tt>Add&nbsp;two&nbsp;instances&nbsp;together.&nbsp;This&nbsp;follows&nbsp;<a href="http://www.python.org/peps/pep-0008.html">PEP008</a>,&nbsp;but&nbsp;has&nbsp;nothing<br>\nto&nbsp;do&nbsp;with&nbsp;<a href="http://www.rfc-editor.org/rfc/rfc1952.txt">RFC1952</a>.&nbsp;Case&nbsp;should&nbsp;matter:&nbsp;pEp008&nbsp;and&nbsp;rFC1952.&nbsp;&nbsp;Things<br>\nthat&nbsp;start&nbsp;with&nbsp;http&nbsp;and&nbsp;ftp&nbsp;should&nbsp;be&nbsp;auto-linked,&nbsp;too:<br>\n<a href="http://google.com">http://google.com</a>.</tt></dd></dl>"""
+          in response.read())
+
+    def test_system_methods(self):
+        """Test the precense of three consecutive system.* methods.
+
+        This also tests their use of parameter type recognition and the systems
+        related to that process.
+        """
+        self.client.request("GET", "/")
+        response = self.client.getresponse()
+
+        self.assert_(
+"""<dl><dt><a name="-system.listMethods"><strong>system.listMethods</strong></a>()</dt><dd><tt><a href="#-system.listMethods">system.listMethods</a>()&nbsp;=&gt;&nbsp;[\'add\',&nbsp;\'subtract\',&nbsp;\'multiple\']<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;list&nbsp;of&nbsp;the&nbsp;methods&nbsp;supported&nbsp;by&nbsp;the&nbsp;server.</tt></dd></dl>\n <dl><dt><a name="-system.methodHelp"><strong>system.methodHelp</strong></a>(method_name)</dt><dd><tt><a href="#-system.methodHelp">system.methodHelp</a>(\'add\')&nbsp;=&gt;&nbsp;"Adds&nbsp;two&nbsp;integers&nbsp;together"<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;string&nbsp;containing&nbsp;documentation&nbsp;for&nbsp;the&nbsp;specified&nbsp;method.</tt></dd></dl>\n <dl><dt><a name="-system.methodSignature"><strong>system.methodSignature</strong></a>(method_name)</dt><dd><tt><a href="#-system.methodSignature">system.methodSignature</a>(\'add\')&nbsp;=&gt;&nbsp;[double,&nbsp;int,&nbsp;int]<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;list&nbsp;describing&nbsp;the&nbsp;signature&nbsp;of&nbsp;the&nbsp;method.&nbsp;In&nbsp;the<br>\nabove&nbsp;example,&nbsp;the&nbsp;add&nbsp;method&nbsp;takes&nbsp;two&nbsp;integers&nbsp;as&nbsp;arguments<br>\nand&nbsp;returns&nbsp;a&nbsp;double&nbsp;result.<br>\n&nbsp;<br>\nThis&nbsp;server&nbsp;does&nbsp;NOT&nbsp;support&nbsp;system.methodSignature.</tt></dd></dl>"""
+            in response.read())
+
+    def test_autolink_dotted_methods(self):
+        """Test that selfdot values are made strong automatically in the
+        documentation."""
+        self.client.request("GET", "/")
+        response = self.client.getresponse()
+
+        self.assert_("""Try&nbsp;self.<strong>add</strong>,&nbsp;too.""" in
+            response.read())
+
+def test_main():
+    test_support.run_unittest(DocXMLRPCHTTPGETServer)
+
+if __name__ == '__main__':
+    test_main()
index 602a4983a616912c714f2bae8fa9a70067badb18..26bbb0b0b6830ea987a86ecf16ee0a5817380611 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -699,6 +699,7 @@ Zack Weinberg
 Edward Welbourne
 Cliff Wells
 Rickard Westman
+Jeff Wheeler
 Mats Wichmann
 Truida Wiedijk
 Felix Wiemann
index ae6b911d7da2d6c4d1d144e4e82416a7524488ec..a137ed0bb9059e30d815465f4f7dcc826562b47e 100755 (executable)
@@ -145,6 +145,22 @@ msvcrt_getch(PyObject *self, PyObject *args)
        return PyString_FromStringAndSize(s, 1);
 }
 
+static PyObject *
+msvcrt_getwch(PyObject *self, PyObject *args)
+{
+       Py_UNICODE ch;
+       Py_UNICODE u[1];
+
+       if (!PyArg_ParseTuple(args, ":getwch"))
+               return NULL;
+
+       Py_BEGIN_ALLOW_THREADS
+       ch = _getwch();
+       Py_END_ALLOW_THREADS
+       u[0] = ch;
+       return PyUnicode_FromUnicode(u, 1);
+}
+
 static PyObject *
 msvcrt_getche(PyObject *self, PyObject *args)
 {
@@ -161,6 +177,22 @@ msvcrt_getche(PyObject *self, PyObject *args)
        return PyString_FromStringAndSize(s, 1);
 }
 
+static PyObject *
+msvcrt_getwche(PyObject *self, PyObject *args)
+{
+       Py_UNICODE ch;
+       Py_UNICODE s[1];
+
+       if (!PyArg_ParseTuple(args, ":getwche"))
+               return NULL;
+
+       Py_BEGIN_ALLOW_THREADS
+       ch = _getwche();
+       Py_END_ALLOW_THREADS
+       s[0] = ch;
+       return PyUnicode_FromUnicode(s, 1);
+}
+
 static PyObject *
 msvcrt_putch(PyObject *self, PyObject *args)
 {
@@ -174,6 +206,26 @@ msvcrt_putch(PyObject *self, PyObject *args)
        return Py_None;
 }
 
+
+static PyObject *
+msvcrt_putwch(PyObject *self, PyObject *args)
+{
+       Py_UNICODE *ch;
+       int size;
+
+       if (!PyArg_ParseTuple(args, "u#:putwch", &ch, &size))
+               return NULL;
+
+       if (size == 0) {
+               PyErr_SetString(PyExc_ValueError,
+                       "Expected unicode string of length 1");
+               return NULL;
+       }
+       _putwch(*ch);
+       Py_RETURN_NONE;
+
+}
+
 static PyObject *
 msvcrt_ungetch(PyObject *self, PyObject *args)
 {
@@ -188,6 +240,19 @@ msvcrt_ungetch(PyObject *self, PyObject *args)
        return Py_None;
 }
 
+static PyObject *
+msvcrt_ungetwch(PyObject *self, PyObject *args)
+{
+       Py_UNICODE ch;
+
+       if (!PyArg_ParseTuple(args, "u:ungetwch", &ch))
+               return NULL;
+
+       if (_ungetch(ch) == EOF)
+               return PyErr_SetFromErrno(PyExc_IOError);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
 
 static void
 insertint(PyObject *d, char *name, int value)
@@ -276,6 +341,10 @@ static struct PyMethodDef msvcrt_functions[] = {
        {"CrtSetReportMode",    msvcrt_setreportmode, METH_VARARGS},
        {"set_error_mode",      msvcrt_seterrormode, METH_VARARGS},
 #endif
+       {"getwch",              msvcrt_getwch, METH_VARARGS},
+       {"getwche",             msvcrt_getwche, METH_VARARGS},
+       {"putwch",              msvcrt_putwch, METH_VARARGS},
+       {"ungetwch",            msvcrt_ungetwch, METH_VARARGS},
        {NULL,                  NULL}
 };