Skip to content
This repository has been archived by the owner on Feb 10, 2023. It is now read-only.

Commit

Permalink
Integrate xmlrpc code from Zope.
Browse files Browse the repository at this point in the history
  • Loading branch information
hannosch committed Sep 3, 2016
1 parent 1d68460 commit 7176f5a
Show file tree
Hide file tree
Showing 10 changed files with 427 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/ZServer/ClockServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

""" Zope clock server. Generate a faux HTTP request on a regular basis
by coopting the asyncore API. """
from __future__ import absolute_import

import posixpath
import os
Expand Down
15 changes: 8 additions & 7 deletions src/ZServer/FCGIServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,24 @@
"""

#----------------------------------------------------------------------
from __future__ import absolute_import

import asynchat, asyncore
from medusa import logger
from medusa.counter import counter
from medusa.http_server import compute_timezone_for_log
from ZServer.medusa import logger
from ZServer.medusa.counter import counter
from ZServer.medusa.http_server import compute_timezone_for_log

from ZServer import requestCloseOnExec

from PubCore import handle
from PubCore.ZEvent import Wakeup
from ZServer.PubCore import handle
from ZServer.PubCore.ZEvent import Wakeup
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.HTTPRequest import HTTPRequest
from Producers import ShutdownProducer, LoggingProducer, file_part_producer, file_close_producer
from ZServer.Producers import ShutdownProducer, LoggingProducer, file_part_producer, file_close_producer

from ZServer.Zope2.Startup import config

import DebugLogger
from ZServer import DebugLogger

from cStringIO import StringIO
from tempfile import TemporaryFile
Expand Down
1 change: 1 addition & 0 deletions src/ZServer/FTPRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
The FTP Request does the dirty work of turning an FTP request into something
that ZPublisher can understand.
"""
from __future__ import absolute_import

from ZPublisher.HTTPRequest import HTTPRequest

Expand Down
10 changes: 5 additions & 5 deletions src/ZServer/FTPServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@
"""

from PubCore import handle
from medusa.ftp_server import ftp_channel, ftp_server, recv_channel
from ZServer.PubCore import handle
from ZServer.medusa.ftp_server import ftp_channel, ftp_server, recv_channel
import asyncore, asynchat
from medusa import filesys
from ZServer.medusa import filesys

from FTPResponse import make_response
from FTPRequest import FTPRequest
from ZServer.FTPResponse import make_response
from ZServer.FTPRequest import FTPRequest

from ZServer import requestCloseOnExec

Expand Down
9 changes: 5 additions & 4 deletions src/ZServer/HTTPResponse.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
The HTTPResponse class takes care of server headers, response munging
and logging duties.
"""
from __future__ import absolute_import

import asyncore
from cStringIO import StringIO
import re
Expand All @@ -26,9 +27,9 @@

from zope.event import notify

from ZPublisher.HTTPResponse import HTTPResponse # XXX WTF?
from ZPublisher.Iterators import IStreamIterator # XXX WTF?
from ZPublisher.pubevents import PubBeforeStreaming # XXX WTF?
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.Iterators import IStreamIterator
from ZPublisher.pubevents import PubBeforeStreaming

from ZServer.medusa.http_date import build_http_date
from ZServer.PubCore.ZEvent import Wakeup
Expand Down
2 changes: 1 addition & 1 deletion src/ZServer/PubCore/ZServerPublisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class ZServerPublisher:
def __init__(self, accept):
from sys import exc_info
from ZPublisher import publish_module
from ZPublisher.Publish import publish_module
from ZPublisher.WSGIPublisher import publish_module as publish_wsgi
while 1:
try:
Expand Down
Empty file.
Empty file.
200 changes: 200 additions & 0 deletions src/ZServer/ZPublisher/tests/test_xmlrpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import unittest
import xmlrpclib

from DateTime import DateTime


class FauxResponse:

def __init__(self):
self._headers = {}
self._body = None

def setBody(self, body):
self._body = body

def setHeader(self, name, value):
self._headers[name] = value

def setStatus(self, status):
self._status = status


class FauxInstance:
def __init__(self, **kw):
self.__dict__.update(kw)


class XMLRPCResponseTests(unittest.TestCase):

def _getTargetClass(self):
from ZServer.ZPublisher.xmlrpc import Response
return Response

def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)

def test_setBody(self):
body = FauxInstance(_secret='abc', public='def')
faux = FauxResponse()
response = self._makeOne(faux)

response.setBody(body)

body_str = faux._body
self.assertEqual(type(body_str), type(''))

as_set, method = xmlrpclib.loads(body_str)
as_set = as_set[0]

self.assertEqual(method, None)
self.assertFalse('_secret' in as_set.keys())
self.assertTrue('public' in as_set.keys())
self.assertEqual(as_set['public'], 'def')

def test_nil(self):
body = FauxInstance(public=None)
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
self.assert_(data[0]['public'] is None)

def test_instance(self):
# Instances are turned into dicts with their private
# attributes removed.
body = FauxInstance(_secret='abc', public='def')
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]
self.assertEqual(data, {'public': 'def'})

def test_instanceattribute(self):
# While the removal of private ('_') attributes works fine for the
# top-level instance, how about attributes that are themselves
# instances?
body = FauxInstance(public=FauxInstance(_secret='abc', public='def'))
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]['public']
self.assertEqual(data, {'public': 'def'})

def test_instanceattribute_recursive(self):
# Instance "flattening" should work recursively, ad infinitum
body = FauxInstance(public=FauxInstance(public=FauxInstance(
_secret='abc', public='def')))
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]['public']['public']
self.assertEqual(data, {'public': 'def'})

def test_instance_in_list(self):
# Instances are turned into dicts with their private
# attributes removed, even when embedded in another
# data structure.
body = [FauxInstance(_secret='abc', public='def')]
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0][0]
self.assertEqual(data, {'public': 'def'})

def test_instance_in_dict(self):
# Instances are turned into dicts with their private
# attributes removed, even when embedded in another
# data structure.
body = {'faux': FauxInstance(_secret='abc', public='def')}
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]['faux']
self.assertEqual(data, {'public': 'def'})

def test_zopedatetimeinstance(self):
# DateTime instance at top-level
body = DateTime('2006-05-24 07:00:00 GMT+0')
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]
self.assertTrue(isinstance(data, xmlrpclib.DateTime))
self.assertEqual(data.value, u'2006-05-24T07:00:00+00:00')

def test_zopedatetimeattribute(self):
# DateTime instance as attribute
body = FauxInstance(public=DateTime('2006-05-24 07:00:00 GMT+0'))
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]['public']
self.assertTrue(isinstance(data, xmlrpclib.DateTime))
self.assertEqual(data.value, u'2006-05-24T07:00:00+00:00')

def test_zopedatetimeattribute_recursive(self):
# DateTime encoding should work recursively
body = FauxInstance(public=FauxInstance(
public=DateTime('2006-05-24 07:00:00 GMT+0')))
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]['public']['public']
self.assertTrue(isinstance(data, xmlrpclib.DateTime))
self.assertEqual(data.value, u'2006-05-24T07:00:00+00:00')

def test_zopedatetimeinstance_in_list(self):
# DateTime instance embedded in a list
body = [DateTime('2006-05-24 07:00:00 GMT+0')]
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0][0]
self.assertTrue(isinstance(data, xmlrpclib.DateTime))
self.assertEqual(data.value, u'2006-05-24T07:00:00+00:00')

def test_zopedatetimeinstance_in_dict(self):
# DateTime instance embedded in a dict
body = {'date': DateTime('2006-05-24 07:00:00 GMT+0')}
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]['date']
self.assertTrue(isinstance(data, xmlrpclib.DateTime))
self.assertEqual(data.value, u'2006-05-24T07:00:00+00:00')

def test_functionattribute(self):
# Cannot marshal functions or methods, obviously

def foo():
pass

body = FauxInstance(public=foo)
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
func = xmlrpclib.loads(faux._body)
self.assertEqual(func, (({'public': {}},), None))

def test_emptystringattribute(self):
# Test an edge case: attribute name '' is possible,
# at least in theory.
body = FauxInstance(_secret='abc')
setattr(body, '', True)
faux = FauxResponse()
response = self._makeOne(faux)
response.setBody(body)
data, method = xmlrpclib.loads(faux._body)
data = data[0]
self.assertEqual(data, {'': True})
Loading

0 comments on commit 7176f5a

Please sign in to comment.