Exemplo n.º 1
0
        def work():
            for code in (
                    responsecode.CREATED,
                    responsecode.PRECONDITION_FAILED,
                    responsecode.NO_CONTENT,
                    responsecode.PRECONDITION_FAILED,
                    responsecode.NO_CONTENT,
                    responsecode.CREATED,
            ):

                def checkResult(response, code=code):
                    response = IResponse(response)

                    if response.code != code:
                        self.fail(
                            "Incorrect response code for PUT (%s != %s)" %
                            (response.code, code))

                def onError(f):
                    f.trap(HTTPError)
                    return checkResult(f.value.response)

                request = SimpleRequest(self.site, "PUT", dst_uri)
                request.stream = FileStream(file(__file__, "rb"))

                if code == responsecode.CREATED:
                    if os.path.isfile(dst_path):
                        os.remove(dst_path)
                    request.headers.setHeader("if-none-match", ("*", ))
                elif code == responsecode.PRECONDITION_FAILED:
                    request.headers.setHeader("if-none-match", ("*", ))

                yield (request, (checkResult, onError))
Exemplo n.º 2
0
    def test_MKCOL_invalid_body(self):
        """
        MKCOL request with invalid request body
        (Any body at all is invalid in our implementation; there is no
        such thing as a valid body.)
        """
        path, uri = self.mkdtemp("collection")

        rmdir(path)

        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.UNSUPPORTED_MEDIA_TYPE:
                self.fail("MKCOL response %s != %s" %
                          (response.code, responsecode.UNSUPPORTED_MEDIA_TYPE))

            if os.path.isdir(path):
                self.fail("MKCOL incorrectly created directory %s" % (path, ))

        request = SimpleRequest(self.site, "MKCOL", uri)
        request.stream = MemoryStream(
            "This is not a valid MKCOL request body.")

        return self.send(request, check_result)
Exemplo n.º 3
0
        def work():
            for which in (davxml.AllProperties(), davxml.PropertyName()):
                query = davxml.PropertyFind(which)

                request = SimpleRequest(self.site, "PROPFIND", "/")
                request.headers.setHeader("depth", "0")
                request.stream = MemoryStream(query.toxml())

                yield (request, check_result(which))
Exemplo n.º 4
0
        def _secondRequest(ign):
            request = SimpleRequest(site, "GET", '/sub/dummy')

            d2 = request.locateResource('/sub/dummy')

            d2.addCallback(lambda resource: self.getPage(request, resource))
            d2.addCallback(_secondResponse)

            return d2
Exemplo n.º 5
0
        def _secondRequest(ign):
            request = SimpleRequest(site, "GET", '/sub/dummy')

            d2 = request.locateResource('/sub/dummy')

            d2.addCallback(lambda resource: self.getPage(request, resource))
            d2.addCallback(_secondResponse)

            return d2
Exemplo n.º 6
0
    def test_scriptsExecute(self):
        """
        Verify that CGI scripts within a CGIDirectory can actually be executed
        """

        cgiBinDir = os.path.abspath(self.mktemp())
        os.mkdir(cgiBinDir)

        root = twcgi.CGIDirectory(cgiBinDir)

        self.createScript(os.path.join(cgiBinDir, 'dummy'))

        cgiSubDir = os.path.join(cgiBinDir, 'sub')
        os.mkdir(cgiSubDir)

        self.createScript(os.path.join(cgiSubDir, 'dummy'))

        site = server.Site(root)

        request = SimpleRequest(site, "GET", "/dummy")

        d = request.locateResource('/dummy')

        def _firstResponse(res):
            self.failUnlessEqual(res, "cgi output%s" % os.linesep)

        def _firstRequest(resource):
            d1 = self.getPage(request, resource)
            d1.addCallback(_firstResponse)

            return d1

        d.addCallback(_firstRequest)

        def _secondResponse(res):
            self.failUnlessEqual(res, "cgi output%s" % os.linesep)

        def _secondRequest(ign):
            request = SimpleRequest(site, "GET", '/sub/dummy')

            d2 = request.locateResource('/sub/dummy')

            d2.addCallback(lambda resource: self.getPage(request, resource))
            d2.addCallback(_secondResponse)

            return d2

        d.addCallback(_secondRequest)

        return d
Exemplo n.º 7
0
    def test_scriptsExecute(self):
        """
        Verify that CGI scripts within a CGIDirectory can actually be executed
        """

        cgiBinDir = os.path.abspath(self.mktemp())
        os.mkdir(cgiBinDir)

        root = twcgi.CGIDirectory(cgiBinDir)

        self.createScript(os.path.join(cgiBinDir, 'dummy'))

        cgiSubDir = os.path.join(cgiBinDir, 'sub')
        os.mkdir(cgiSubDir)

        self.createScript(os.path.join(cgiSubDir, 'dummy'))

        site = server.Site(root)

        request = SimpleRequest(site, "GET", "/dummy")

        d = request.locateResource('/dummy')

        def _firstResponse(res):
            self.failUnlessEqual(res, "cgi output%s" % os.linesep)

        def _firstRequest(resource):
            d1 = self.getPage(request, resource)
            d1.addCallback(_firstResponse)

            return d1

        d.addCallback(_firstRequest)

        def _secondResponse(res):
            self.failUnlessEqual(res, "cgi output%s" % os.linesep)

        def _secondRequest(ign):
            request = SimpleRequest(site, "GET", '/sub/dummy')

            d2 = request.locateResource('/sub/dummy')

            d2.addCallback(lambda resource: self.getPage(request, resource))
            d2.addCallback(_secondResponse)

            return d2

        d.addCallback(_secondRequest)

        return d
Exemplo n.º 8
0
    def test_REPORT_no_body(self):
        """
        REPORT request with no body
        """
        def do_test(response):
            response = IResponse(response)

            if response.code != responsecode.BAD_REQUEST:
                self.fail("Unexpected response code for REPORT with no body: %s"
                          % (response.code,))

        request = SimpleRequest(self.site, "REPORT", "/")
        request.stream = MemoryStream("")

        return self.send(request, do_test)
Exemplo n.º 9
0
    def testOperatesOnStreamDirectly(self):
        def gotResponse(resp):
            self.assertEquals(resp.code, 200)
            self.assertEquals(resp.headers.getHeader('Content-Type'),
                              http_headers.MimeType.fromString('text/plain'))

            stream = resp.stream
            resp.stream = None

            return defer.maybeDeferred(stream.read).addCallback(
                self.assertEquals, '42')

        req = SimpleRequest(None, 'GET', '/')

        d = self.doTestSCGI(req)
        d.addCallback(gotResponse)

        self.iterate(self.cxn)

        headers = parseSCGIHeaders(self.cxn.server.data)

        self.assertEquals(headers[0], ('CONTENT_LENGTH', '0'))

        self.failUnlessIn(('SCGI', '1'), headers)

        self.writeLines(self.cxn, [
            'Status: 200 OK', 'Content-Type: text/plain', 'Content-Length: 2',
            '', '42'
        ])

        return d
Exemplo n.º 10
0
 def test_locateChild(self):
     resource = LeafResource()
     child, segments = (resource.locateChild(
         SimpleRequest(Site(resource), "GET", "/"),
         ("", "foo"),
     ))
     self.assertEquals(child, resource)
     self.assertEquals(segments, StopTraversal)
Exemplo n.º 11
0
    def test_PUT_no_parent(self):
        """
        PUT with no parent
        """
        dst_uri = "/put/no/parent"

        def checkResult(response):
            response = IResponse(response)

            if response.code != responsecode.CONFLICT:
                self.fail(
                    "Incorrect response code for PUT with no parent (%s != %s)"
                    % (response.code, responsecode.CONFLICT))

        request = SimpleRequest(self.site, "PUT", dst_uri)
        request.stream = FileStream(file(__file__, "rb"))

        return self.send(request, checkResult)
Exemplo n.º 12
0
        def work():
            dst_uri = "/dst"

            for name in os.listdir(self.docroot):
                if name == "dst":
                    continue

                path = os.path.join(self.docroot, name)

                # Can't really PUT something you can't read
                if not os.path.isfile(path): continue

                def do_test(response):
                    checkResult(response, path)

                request = SimpleRequest(self.site, "PUT", dst_uri)
                request.stream = FileStream(file(path, "rb"))

                yield (request, do_test)
Exemplo n.º 13
0
    def test_REPORT_unknown(self):
        """
        Unknown/bogus report type
        """
        def do_test(response):
            response = IResponse(response)

            if response.code != responsecode.FORBIDDEN:
                self.fail("Unexpected response code for unknown REPORT: %s"
                          % (response.code,))
        class GoofyReport (davxml.WebDAVUnknownElement):
            namespace = "GOOFY:"
            name      = "goofy-report"
            def __init__(self): super(GoofyReport, self).__init__()

        request = SimpleRequest(self.site, "REPORT", "/")
        request.stream = MemoryStream(GoofyReport().toxml())

        return self.send(request, do_test)
Exemplo n.º 14
0
    def test_renderHTTP(self):
        """
        Test that if the renderHTTP method is ever called we authenticate
        the request and delegate rendering to the wrapper.
        """
        self.protectedResource.responseText = "I hope you can see me."
        self.protectedResource.addSlash = True

        root = wrapper.HTTPAuthResource(self.protectedResource,
                                        [self.credFactory],
                                        self.portal,
                                        interfaces=(IHTTPUser, ))

        request = SimpleRequest(None, "GET", "/")
        request.prepath = ['']

        def _gotSecondResponse(response):
            self.assertEquals(response.code, 200)
            self.assertEquals(str(response.stream.read()),
                              "I hope you can see me.")

        def _gotResponse(exception):
            response = exception.response

            self.assertEquals(response.code, 401)
            self.failUnless(response.headers.hasHeader('WWW-Authenticate'))
            self.assertEquals(response.headers.getHeader('WWW-Authenticate'),
                              [('basic', {
                                  'realm': "test realm"
                              })])

            credentials = base64.encodestring('username:password')

            request.headers.setHeader('authorization', ['basic', credentials])

            d = root.renderHTTP(request)
            d.addCallback(_gotSecondResponse)

        d = self.assertFailure(root.renderHTTP(request), http.HTTPError)

        d.addCallback(_gotResponse)

        return d
Exemplo n.º 15
0
    def test_renderHTTP(self):
        """
        Test that if the renderHTTP method is ever called we authenticate
        the request and delegate rendering to the wrapper.
        """
        self.protectedResource.responseText = "I hope you can see me."
        self.protectedResource.addSlash = True

        root = wrapper.HTTPAuthResource(self.protectedResource,
                                        [self.credFactory],
                                        self.portal,
                                        interfaces = (IHTTPUser,))

        request = SimpleRequest(None, "GET", "/")
        request.prepath = ['']

        def _gotSecondResponse(response):
            self.assertEquals(response.code, 200)
            self.assertEquals(str(response.stream.read()),
                              "I hope you can see me.")

        def _gotResponse(exception):
            response = exception.response

            self.assertEquals(response.code, 401)
            self.failUnless(response.headers.hasHeader('WWW-Authenticate'))
            self.assertEquals(response.headers.getHeader('WWW-Authenticate'),
                              [('basic', {'realm': "test realm"})])

            credentials = base64.encodestring('username:password')

            request.headers.setHeader('authorization',
                                      ['basic', credentials])

            d = root.renderHTTP(request)
            d.addCallback(_gotSecondResponse)

        d = self.assertFailure(root.renderHTTP(request),
                               http.HTTPError)

        d.addCallback(_gotResponse)

        return d
Exemplo n.º 16
0
    def _test_level(self, level):
        def doTest(response):
            response = IResponse(response)

            dav = response.headers.getHeader("dav")
            if not dav: self.fail("no DAV header: %s" % (response.headers, ))
            self.assertIn(level, dav, "no DAV level %s header" % (level, ))

            return response

        return self.send(SimpleRequest(self.site, "OPTIONS", "/"), doTest)
Exemplo n.º 17
0
    def test_checkPreconditions_none(self):
        """
        RenderMixin.checkPreconditions()
        checkPreconditions() returns None
        """
        resource = TestResource()
        request = SimpleRequest(Site(resource), "SWEETHOOKUPS", "/")

        # Check that checkPreconditions without a raise doesn't barf
        self.assertEquals(resource.renderHTTP(request),
                          responsecode.NO_CONTENT)
Exemplo n.º 18
0
    def testReadEmptyInput(self):
        """
        Test that the CGI can successfully read from an empty input stream
        """

        request = SimpleRequest(None, 'GET', '/cgi')

        resource = self.setUpResource(READINPUT_CGI)

        d = self.getPage(request, resource)
        d.addCallback(self._testReadEmptyInput_1)
        return d
Exemplo n.º 19
0
    def _simple_PROPPATCH(self, patch, prop, expected_code, what):
        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.MULTI_STATUS:
                self.fail("Incorrect response code for PROPPATCH (%s != %s)" %
                          (response.code, responsecode.MULTI_STATUS))

            return davXMLFromStream(response.stream).addCallback(check_xml)

        def check_xml(doc):
            response = doc.root_element.childOfType(davxml.Response)
            propstat = response.childOfType(davxml.PropertyStatus)

            self.failUnless(
                response.childOfType(davxml.HRef) == "/",
                "Incorrect response URI: %s != /" %
                (response.childOfType(davxml.HRef), ))

            self.failIf(
                propstat.childOfType(
                    davxml.PropertyContainer).childOfType(prop) is None,
                "Not a %s in PROPPATCH property status: %s" %
                (prop.sname(), propstat.toxml()))

            if not have_dead_properties:
                raise SkipTest(
                    "No dead property store available for DAVFile.  "
                    "Install xattr (http://undefined.org/python/#xattr) to enable use of dead properties."
                )

            self.failUnless(
                propstat.childOfType(davxml.Status).code == expected_code,
                "Incorrect status code for PROPPATCH %s: %s != %s" %
                (what, propstat.childOfType(
                    davxml.Status).code, expected_code))

        request = SimpleRequest(self.site, "PROPPATCH", "/")
        request.stream = MemoryStream(patch.toxml())
        return self.send(request, check_result)
Exemplo n.º 20
0
    def test_readInput(self):
        """
        Test that we can successfully read an input stream with data
        """
        request = SimpleRequest(None,
                                "POST",
                                "/cgi",
                                content="Here is your stdin")

        resource = self.setUpResource(READINPUT_CGI)
        d = self.getPage(request, resource)
        d.addCallback(self._testReadInput_1)
        return d
Exemplo n.º 21
0
    def test_CGI(self):
        """
        Test that the given DUMMY_CGI is executed and the expected output
        returned
        """

        request = SimpleRequest(None, 'GET', '/cgi')

        resource = self.setUpResource(DUMMY_CGI)

        d = self.getPage(request, resource)
        d.addCallback(self._testCGI_1)
        return d
Exemplo n.º 22
0
    def test_checkPreconditions_raises(self):
        """
        RenderMixin.checkPreconditions()
        Exception raised in checkPreconditions()
        """
        resource = TestResource()
        request = SimpleRequest(Site(resource), "BLEARGH", "/")

        # Check that checkPreconditions raises as expected
        self.assertRaises(PreconditionError, resource.checkPreconditions,
                          request)

        # Check that renderHTTP calls checkPreconditions
        self.assertRaises(PreconditionError, resource.renderHTTP, request)
Exemplo n.º 23
0
    def test_checkPreconditions_deferred(self):
        """
        RenderMixin.checkPreconditions()
        checkPreconditions() returns a deferred
        """
        resource = TestResource()
        request = SimpleRequest(Site(resource), "HOOKUPS", "/")

        # Check that checkPreconditions without a raise doesn't barf
        def checkResponse(response):
            self.assertEquals(response, responsecode.NO_CONTENT)

        d = resource.renderHTTP(request)
        d.addCallback(checkResponse)
Exemplo n.º 24
0
    def test_failsWithDifferentMethod(self):
        """
        Test that the response fails if made for a different request method
        than it is being issued for.
        """

        challenge = self.credentialFactory.getChallenge(clientAddress)

        clientResponse = authRequest1 % (
            challenge['nonce'], self.getDigestResponse(
                challenge, "00000001"), challenge['opaque'])

        creds = self.credentialFactory.decode(clientResponse,
                                              SimpleRequest(None, 'POST', '/'))
        self.failIf(creds.checkPassword('password'))
Exemplo n.º 25
0
    def test_readAllInput(self):
        """
        Test that we can all input can be read regardless of CONTENT_LENGTH
        """

        request = SimpleRequest(None,
                                "POST",
                                "/cgi",
                                content="Here is your stdin")

        resource = self.setUpResource(READALLINPUT_CGI)

        d = self.getPage(request, resource)

        d.addCallback(self._testReadAllInput_1)
        return d
Exemplo n.º 26
0
        def work():
            for filename in os.listdir(self.docroot):
                path = os.path.join(self.docroot, filename)
                uri = urllib.quote("/" + filename)

                if os.path.isdir(path): uri = uri + "/"

                def do_test(response, path=path):
                    return check_result(response, path)

                request = SimpleRequest(self.site, "DELETE", uri)

                depth = random.choice(("infinity", None))
                if depth is not None:
                    request.headers.setHeader("depth", depth)

                yield (request, do_test)
Exemplo n.º 27
0
    def test_MKCOL(self):
        """
        MKCOL request
        """
        path, uri = self.mkdtemp("collection")

        rmdir(path)

        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.CREATED:
                self.fail("MKCOL response %s != %s" %
                          (response.code, responsecode.CREATED))

            if not os.path.isdir(path):
                self.fail("MKCOL did not create directory %s" % (path, ))

        request = SimpleRequest(self.site, "MKCOL", uri)

        return self.send(request, check_result)
Exemplo n.º 28
0
def work(self, test, overwrite=None, dst=None, depths=("0", "infinity", None)):
    if dst is None:
        dst = os.path.join(self.docroot, "dst")
        os.mkdir(dst)

    for basename in os.listdir(self.docroot):
        if basename == "dst": continue

        path = os.path.join(self.docroot, basename)
        uri = "/" + basename
        isfile = os.path.isfile(path)
        sum = sumFile(path)
        basename = os.path.basename(path)
        dst_path = os.path.join(dst, basename)
        dst_uri = urllib.quote("/dst/" + basename)

        if not isfile:
            uri     += "/"
            dst_uri += "/"

        if overwrite is not None:
            # Create a file at dst_path to create a conflict
            file(dst_path, "w").close()

        for depth in depths:
            def do_test(response, path=path, isfile=isfile, sum=sum, uri=uri, depth=depth, dst_path=dst_path):
                test(response, path, isfile, sum, uri, depth, dst_path)

            request = SimpleRequest(self.site, self.__class__.__name__, uri)
            request.headers.setHeader("destination", dst_uri)
            if depth is not None:
                request.headers.setHeader("depth", depth)
            if overwrite is not None:
                request.headers.setHeader("overwrite", overwrite)

            yield (request, do_test)
Exemplo n.º 29
0
    def test_PROPFIND_basic(self):
        """
        PROPFIND request
        """
        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.MULTI_STATUS:
                self.fail("Incorrect response code for PROPFIND (%s != %s)" %
                          (response.code, responsecode.MULTI_STATUS))

            content_type = response.headers.getHeader("content-type")
            if content_type not in (http_headers.MimeType("text", "xml"),
                                    http_headers.MimeType(
                                        "application", "xml")):
                self.fail(
                    "Incorrect content-type for PROPFIND response (%r not in %r)"
                    % (content_type,
                       (http_headers.MimeType("text", "xml"),
                        http_headers.MimeType("application", "xml"))))

            return davXMLFromStream(response.stream).addCallback(check_xml)

        def check_xml(doc):
            multistatus = doc.root_element

            if not isinstance(multistatus, davxml.MultiStatus):
                self.fail(
                    "PROPFIND response XML root element is not multistatus: %r"
                    % (multistatus, ))

            for response in multistatus.childrenOfType(
                    davxml.PropertyStatusResponse):
                if response.childOfType(davxml.HRef) == "/":
                    for propstat in response.childrenOfType(
                            davxml.PropertyStatus):
                        status = propstat.childOfType(davxml.Status)
                        properties = propstat.childOfType(
                            davxml.PropertyContainer).children

                        if status.code != responsecode.OK:
                            self.fail(
                                "PROPFIND failed (status %s) to locate live properties: %s"
                                % (status.code, properties))

                        properties_to_find = [
                            p.qname() for p in live_properties
                        ]

                        for property in properties:
                            qname = property.qname()
                            if qname in properties_to_find:
                                properties_to_find.remove(qname)
                            else:
                                self.fail(
                                    "PROPFIND found property we didn't ask for: %r"
                                    % (property, ))

                        if properties_to_find:
                            self.fail(
                                "PROPFIND failed to find properties: %r" %
                                (properties_to_find, ))

                    break

            else:
                self.fail("No response for URI /")

        query = davxml.PropertyFind(davxml.PropertyContainer(*live_properties))

        request = SimpleRequest(self.site, "PROPFIND", "/")

        depth = random.choice(("0", "1", "infinity", None))
        if depth is not None:
            request.headers.setHeader("depth", depth)

        request.stream = MemoryStream(query.toxml())

        return self.send(request, check_result)
Exemplo n.º 30
0
def generateResponse(method):
    resource = TestResource()
    method = getattr(resource, "http_" + method)
    return method(SimpleRequest(Site(resource), method, "/"))
Exemplo n.º 31
0
        def _gotSecondResponse(response):
            self.assertEquals(response.code, 200)
            self.assertEquals(str(response.stream.read()),
                              "I hope you can see me.")

        def _gotResponse(exception):
            response = exception.response

            self.assertEquals(response.code, 401)
            self.failUnless(response.headers.hasHeader('WWW-Authenticate'))
            self.assertEquals(response.headers.getHeader('WWW-Authenticate'),
                              [('basic', {
                                  'realm': "test realm"
                              })])

            credentials = base64.encodestring('username:password')

            request.headers.setHeader('authorization', ['basic', credentials])

            d = root.renderHTTP(request)
            d.addCallback(_gotSecondResponse)

        d = self.assertFailure(root.renderHTTP(request), http.HTTPError)

        d.addCallback(_gotResponse)

        return d


_trivial_GET = SimpleRequest(None, 'GET', '/')
Exemplo n.º 32
0
    def test_PROPPATCH_basic(self):
        """
        PROPPATCH
        """

        # FIXME:
        # Do PROPFIND to make sure it's still there
        # Test nonexistant resource
        # Test None namespace in property

        def check_patch_response(response):
            response = IResponse(response)

            if response.code != responsecode.MULTI_STATUS:
                self.fail("Incorrect response code for PROPFIND (%s != %s)" %
                          (response.code, responsecode.MULTI_STATUS))

            content_type = response.headers.getHeader("content-type")
            if content_type not in (http_headers.MimeType("text", "xml"),
                                    http_headers.MimeType(
                                        "application", "xml")):
                self.fail(
                    "Incorrect content-type for PROPPATCH response (%r not in %r)"
                    % (content_type,
                       (http_headers.MimeType("text", "xml"),
                        http_headers.MimeType("application", "xml"))))

            return davXMLFromStream(
                response.stream).addCallback(check_patch_xml)

        def check_patch_xml(doc):
            multistatus = doc.root_element

            if not isinstance(multistatus, davxml.MultiStatus):
                self.fail(
                    "PROPFIND response XML root element is not multistatus: %r"
                    % (multistatus, ))

            # Requested a property change one resource, so there should be exactly one response
            response = multistatus.childOfType(davxml.Response)

            # Should have a response description (its contents are arbitrary)
            response.childOfType(davxml.ResponseDescription)

            # Requested property change was on /
            self.failUnless(
                response.childOfType(davxml.HRef) == "/",
                "Incorrect response URI: %s != /" %
                (response.childOfType(davxml.HRef), ))

            # Requested one property change, so there should be exactly one property status
            propstat = response.childOfType(davxml.PropertyStatus)

            # And the contained property should be a SpiffyProperty
            self.failIf(
                propstat.childOfType(
                    davxml.PropertyContainer).childOfType(SpiffyProperty) is
                None, "Not a SpiffyProperty in PROPPATCH property status: %s" %
                (propstat.toxml()))

            if not have_dead_properties:
                raise SkipTest(
                    "No dead property store available for DAVFile.  "
                    "Install xattr (http://undefined.org/python/#xattr) to enable use of dead properties."
                )

            # And the status should be 200
            self.failUnless(
                propstat.childOfType(davxml.Status).code == responsecode.OK,
                "Incorrect status code for PROPPATCH of property %s: %s != %s"
                % (propstat.childOfType(davxml.PropertyContainer).toxml(),
                   propstat.childOfType(davxml.Status).code, responsecode.OK))

        patch = davxml.PropertyUpdate(
            davxml.Set(
                davxml.PropertyContainer(
                    SpiffyProperty.fromString("This is a spiffy resource."))))

        request = SimpleRequest(self.site, "PROPPATCH", "/")
        request.stream = MemoryStream(patch.toxml())
        return self.send(request, check_patch_response)