python (3.11.7)

(root)/
lib/
python3.11/
test/
test_docxmlrpc.py
       1  from xmlrpc.server import DocXMLRPCServer
       2  import http.client
       3  import re
       4  import sys
       5  import threading
       6  import unittest
       7  from test import support
       8  
       9  support.requires_working_socket(module=True)
      10  
      11  def make_request_and_skipIf(condition, reason):
      12      # If we skip the test, we have to make a request because
      13      # the server created in setUp blocks expecting one to come in.
      14      if not condition:
      15          return lambda func: func
      16      def decorator(func):
      17          def make_request_and_skip(self):
      18              self.client.request("GET", "/")
      19              self.client.getresponse()
      20              raise unittest.SkipTest(reason)
      21          return make_request_and_skip
      22      return decorator
      23  
      24  
      25  def make_server():
      26      serv = DocXMLRPCServer(("localhost", 0), logRequests=False)
      27  
      28      try:
      29          # Add some documentation
      30          serv.set_server_title("DocXMLRPCServer Test Documentation")
      31          serv.set_server_name("DocXMLRPCServer Test Docs")
      32          serv.set_server_documentation(
      33              "This is an XML-RPC server's documentation, but the server "
      34              "can be used by POSTing to /RPC2. Try self.add, too.")
      35  
      36          # Create and register classes and functions
      37          class ESC[4;38;5;81mTestClass(ESC[4;38;5;149mobject):
      38              def test_method(self, arg):
      39                  """Test method's docs. This method truly does very little."""
      40                  self.arg = arg
      41  
      42          serv.register_introspection_functions()
      43          serv.register_instance(TestClass())
      44  
      45          def add(x, y):
      46              """Add two instances together. This follows PEP008, but has nothing
      47              to do with RFC1952. Case should matter: pEp008 and rFC1952.  Things
      48              that start with http and ftp should be auto-linked, too:
      49              http://google.com.
      50              """
      51              return x + y
      52  
      53          def annotation(x: int):
      54              """ Use function annotations. """
      55              return x
      56  
      57          class ESC[4;38;5;81mClassWithAnnotation:
      58              def method_annotation(self, x: bytes):
      59                  return x.decode()
      60  
      61          serv.register_function(add)
      62          serv.register_function(lambda x, y: x-y)
      63          serv.register_function(annotation)
      64          serv.register_instance(ClassWithAnnotation())
      65          return serv
      66      except:
      67          serv.server_close()
      68          raise
      69  
      70  class ESC[4;38;5;81mDocXMLRPCHTTPGETServer(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      71      def setUp(self):
      72          # Enable server feedback
      73          DocXMLRPCServer._send_traceback_header = True
      74  
      75          self.serv = make_server()
      76          self.thread = threading.Thread(target=self.serv.serve_forever)
      77          self.thread.start()
      78  
      79          PORT = self.serv.server_address[1]
      80          self.client = http.client.HTTPConnection("localhost:%d" % PORT)
      81  
      82      def tearDown(self):
      83          self.client.close()
      84  
      85          # Disable server feedback
      86          DocXMLRPCServer._send_traceback_header = False
      87          self.serv.shutdown()
      88          self.thread.join()
      89          self.serv.server_close()
      90  
      91      def test_valid_get_response(self):
      92          self.client.request("GET", "/")
      93          response = self.client.getresponse()
      94  
      95          self.assertEqual(response.status, 200)
      96          self.assertEqual(response.getheader("Content-type"), "text/html; charset=UTF-8")
      97  
      98          # Server raises an exception if we don't start to read the data
      99          response.read()
     100  
     101      def test_get_css(self):
     102          self.client.request("GET", "/pydoc.css")
     103          response = self.client.getresponse()
     104  
     105          self.assertEqual(response.status, 200)
     106          self.assertEqual(response.getheader("Content-type"), "text/css; charset=UTF-8")
     107  
     108          # Server raises an exception if we don't start to read the data
     109          response.read()
     110  
     111      def test_invalid_get_response(self):
     112          self.client.request("GET", "/spam")
     113          response = self.client.getresponse()
     114  
     115          self.assertEqual(response.status, 404)
     116          self.assertEqual(response.getheader("Content-type"), "text/plain")
     117  
     118          response.read()
     119  
     120      def test_lambda(self):
     121          """Test that lambda functionality stays the same.  The output produced
     122          currently is, I suspect invalid because of the unencoded brackets in the
     123          HTML, "<lambda>".
     124  
     125          The subtraction lambda method is tested.
     126          """
     127          self.client.request("GET", "/")
     128          response = self.client.getresponse()
     129  
     130          self.assertIn((b'<dl><dt><a name="-&lt;lambda&gt;"><strong>'
     131                         b'&lt;lambda&gt;</strong></a>(x, y)</dt></dl>'),
     132                        response.read())
     133  
     134      @make_request_and_skipIf(sys.flags.optimize >= 2,
     135                       "Docstrings are omitted with -O2 and above")
     136      def test_autolinking(self):
     137          """Test that the server correctly automatically wraps references to
     138          PEPS and RFCs with links, and that it linkifies text starting with
     139          http or ftp protocol prefixes.
     140  
     141          The documentation for the "add" method contains the test material.
     142          """
     143          self.client.request("GET", "/")
     144          response = self.client.getresponse().read()
     145  
     146          self.assertIn(
     147              (b'<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd>'
     148               b'<tt>Add&nbsp;two&nbsp;instances&nbsp;together.&nbsp;This&nbsp;'
     149               b'follows&nbsp;<a href="https://peps.python.org/pep-0008/">'
     150               b'PEP008</a>,&nbsp;but&nbsp;has&nbsp;nothing<br>\nto&nbsp;do&nbsp;'
     151               b'with&nbsp;<a href="https://www.rfc-editor.org/rfc/rfc1952.txt">'
     152               b'RFC1952</a>.&nbsp;Case&nbsp;should&nbsp;matter:&nbsp;pEp008&nbsp;'
     153               b'and&nbsp;rFC1952.&nbsp;&nbsp;Things<br>\nthat&nbsp;start&nbsp;'
     154               b'with&nbsp;http&nbsp;and&nbsp;ftp&nbsp;should&nbsp;be&nbsp;'
     155               b'auto-linked,&nbsp;too:<br>\n<a href="http://google.com">'
     156               b'http://google.com</a>.</tt></dd></dl>'), response)
     157  
     158      @make_request_and_skipIf(sys.flags.optimize >= 2,
     159                       "Docstrings are omitted with -O2 and above")
     160      def test_system_methods(self):
     161          """Test the presence of three consecutive system.* methods.
     162  
     163          This also tests their use of parameter type recognition and the
     164          systems related to that process.
     165          """
     166          self.client.request("GET", "/")
     167          response = self.client.getresponse().read()
     168  
     169          self.assertIn(
     170              (b'<dl><dt><a name="-system.methodHelp"><strong>system.methodHelp'
     171               b'</strong></a>(method_name)</dt><dd><tt><a href="#-system.method'
     172               b'Help">system.methodHelp</a>(\'add\')&nbsp;=&gt;&nbsp;"Adds&nbsp;'
     173               b'two&nbsp;integers&nbsp;together"<br>\n&nbsp;<br>\nReturns&nbsp;a'
     174               b'&nbsp;string&nbsp;containing&nbsp;documentation&nbsp;for&nbsp;'
     175               b'the&nbsp;specified&nbsp;method.</tt></dd></dl>\n<dl><dt><a name'
     176               b'="-system.methodSignature"><strong>system.methodSignature</strong>'
     177               b'</a>(method_name)</dt><dd><tt><a href="#-system.methodSignature">'
     178               b'system.methodSignature</a>(\'add\')&nbsp;=&gt;&nbsp;[double,&nbsp;'
     179               b'int,&nbsp;int]<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;list&nbsp;'
     180               b'describing&nbsp;the&nbsp;signature&nbsp;of&nbsp;the&nbsp;method.'
     181               b'&nbsp;In&nbsp;the<br>\nabove&nbsp;example,&nbsp;the&nbsp;add&nbsp;'
     182               b'method&nbsp;takes&nbsp;two&nbsp;integers&nbsp;as&nbsp;arguments'
     183               b'<br>\nand&nbsp;returns&nbsp;a&nbsp;double&nbsp;result.<br>\n&nbsp;'
     184               b'<br>\nThis&nbsp;server&nbsp;does&nbsp;NOT&nbsp;support&nbsp;system'
     185               b'.methodSignature.</tt></dd></dl>'), response)
     186  
     187      def test_autolink_dotted_methods(self):
     188          """Test that selfdot values are made strong automatically in the
     189          documentation."""
     190          self.client.request("GET", "/")
     191          response = self.client.getresponse()
     192  
     193          self.assertIn(b"""Try&nbsp;self.<strong>add</strong>,&nbsp;too.""",
     194                        response.read())
     195  
     196      def test_annotations(self):
     197          """ Test that annotations works as expected """
     198          self.client.request("GET", "/")
     199          response = self.client.getresponse()
     200          docstring = (b'' if sys.flags.optimize >= 2 else
     201                       b'<dd><tt>Use&nbsp;function&nbsp;annotations.</tt></dd>')
     202          self.assertIn(
     203              (b'<dl><dt><a name="-annotation"><strong>annotation</strong></a>'
     204               b'(x: int)</dt>' + docstring + b'</dl>\n'
     205               b'<dl><dt><a name="-method_annotation"><strong>'
     206               b'method_annotation</strong></a>(x: bytes)</dt></dl>'),
     207              response.read())
     208  
     209      def test_server_title_escape(self):
     210          # bpo-38243: Ensure that the server title and documentation
     211          # are escaped for HTML.
     212          self.serv.set_server_title('test_title<script>')
     213          self.serv.set_server_documentation('test_documentation<script>')
     214          self.assertEqual('test_title<script>', self.serv.server_title)
     215          self.assertEqual('test_documentation<script>',
     216                  self.serv.server_documentation)
     217  
     218          generated = self.serv.generate_html_documentation()
     219          title = re.search(r'<title>(.+?)</title>', generated).group()
     220          documentation = re.search(r'<p><tt>(.+?)</tt></p>', generated).group()
     221          self.assertEqual('<title>Python: test_title&lt;script&gt;</title>', title)
     222          self.assertEqual('<p><tt>test_documentation&lt;script&gt;</tt></p>', documentation)
     223  
     224  
     225  if __name__ == '__main__':
     226      unittest.main()