zope.publisher

https://travis-ci.org/zopefoundation/zope.publisher.png?branch=master Documentation Status

This package allows you to publish Python objects on the web. It has support for plain HTTP/WebDAV clients, web browsers as well as XML-RPC and FTP clients. Input and output streams are represented by request and response objects which allow for easy client interaction from Python. The behaviour of the publisher is geared towards WSGI compatibility.

Documentation is hosted at https://zopepublisher.readthedocs.io/

Base API Reference

Interfaces

Interfaces for the publisher.

exception zope.publisher.interfaces.Retry(orig_exc=None)[source]

Bases: zope.publisher.interfaces.PublishingException

Raise this to retry a request.

orig_exc must be a 3-tuple as returned from sys.exc_info() or None

interface zope.publisher.interfaces.IExceptionSideEffects[source]

An exception caught by the publisher is adapted to this so that it can have persistent side-effects.

__call__(obj, request, exc_info)

Effect persistent side-effects.

Arguments are:
obj context-wrapped object that was published request the request exc_info the exception info being handled
interface zope.publisher.interfaces.IResponse[source]

Interface used by the publsher

setResult(result)

Sets the response result value.

handleException(exc_info)

Handles an exception.

This method is intended only as a convenience for the publication object. The publication object can choose to handle exceptions by calling this method. The publication object can also choose not to call this method at all.

Implementations set the reponse body.

internalError()

Called when the exception handler bombs.

Should report back to the client that an internal error occurred.

reset()

Reset the output result.

Reset the response by nullifying already set variables.

retry()

Returns a retry response

Returns a response suitable for repeating the publication attempt.

interface zope.publisher.interfaces.IPublication[source]

Object publication framework.

The responsibility of publication objects is to provide application hooks for the publishing process. This allows application-specific tasks, such as connecting to databases, managing transactions, and setting security contexts to be invoked during the publishing process.

beforeTraversal(request)

Pre-traversal hook.

This is called once before any traversal has been done.

getApplication(request)

Returns the object where traversal should commence.

callTraversalHooks(request, ob)

Invokes any traversal hooks associated with the object.

This is called before traversing each object. The ob argument is the object that is about to be traversed.

traverseName(request, ob, name)

Traverses to the next object.

Name must be an ASCII string or Unicode object.

afterTraversal(request, ob)

Post-traversal hook.

This is called after all traversal.

callObject(request, ob)

Call the object, returning the result.

For GET/POST this means calling it, but for other methods (including those of WebDAV and FTP) this might mean invoking a method of an adapter.

afterCall(request, ob)

Post-callObject hook (if it was successful).

handleException(object, request, exc_info, retry_allowed=1)

Handle an exception

Either: - sets the body of the response, request.response, or - raises a Retry exception, or - throws another exception, which is a Bad Thing.

endRequest(request, ob)

Do any end-of-request cleanup

interface zope.publisher.interfaces.IPublicationRequest[source]

Extends: zope.security.interfaces.IParticipation

Interface provided by requests to IPublication objects

response

The request’s response object

Return an IPublisherResponse for the request.

close()

Release resources held by the request.

hold(held)

Hold a reference to an object until the request is closed.

The object should be an IHeld. If it is an IHeld, its release method will be called when it is released.

getTraversalStack()

Return the request traversal stack

This is a sequence of steps to traverse in reverse order. They will be traversed from last to first.

setTraversalStack(stack)

Change the traversal stack.

See getTraversalStack.

getPositionalArguments()

Return the positional arguments given to the request.

setPrincipal(principal)

Set the principal attribute.

It should be IPrincipal wrapped in its AuthenticationService’s context.

interface zope.publisher.interfaces.IHeld[source]

Object to be held and explicitly released by a request

release()

Release the held object

This is called by a request that holds the IHeld when the request is closed

interface zope.publisher.interfaces.IPublisherRequest[source]

Extends: zope.publisher.interfaces.IPublicationRequest

Request interface use by the publisher

The responsibility of requests is to encapsulate protocol specific details, especially wrt request inputs.

Request objects also serve as “context” objects, providing construction of and access to responses and storage of publication objects.

supportsRetry()

Check whether the request supports retry

Return a boolean value indicating whether the request can be retried.

retry()

Return a retry request

Return a request suitable for repeating the publication attempt.

publication

The request’s publication object

The publication object, an IRequestPublication provides application-specific functionality hooks.

setPublication(publication)

Set the request’s publication object

traverse(obj)

Traverse from the given object to the published object

The published object is returned.

The following hook methods on the publication will be called:

  • callTraversalHooks is called before each step and after the last step.
  • traverseName to actually do a single traversal
processInputs()

Do any input processing that needs to be done before traversing

This is done after construction to allow the publisher to handle errors that arise.

interface zope.publisher.interfaces.IDebugFlags[source]

Features that support debugging.

sourceAnnotations

Enable ZPT source annotations

showTAL

Leave TAL markup in rendered page templates

interface zope.publisher.interfaces.IApplicationRequest[source]

Extends: zope.interface.common.mapping.IEnumerableMapping

Features that support application logic

principal

Principal object associated with the request This is a read-only attribute.

bodyStream

The stream that provides the data of the request.

The data returned by the stream will not include any possible header information, which should have been stripped by the server (or previous layer) before.

Also, the body stream might already be read and not return any data. This is commonly done when retrieving the data for the body attribute.

If you access this stream directly to retrieve data, it will not be possible by other parts of the framework to access the data of the request via the body attribute.

debug

Debug flags (see IDebugFlags).

__getitem__(key)

Return request data

The only request data are environment variables.

environment

Request environment data

This is a read-only mapping from variable name to value.

annotations

Stores arbitrary application data under package-unique keys.

By “package-unique keys”, we mean keys that are are unique by virtue of including the dotted name of a package as a prefex. A package name is used to limit the authority for picking names for a package to the people using that package.

For example, when implementing annotations for hypothetical request-persistent adapters in a hypothetical zope.persistentadapter package, the key would be (or at least begin with) the following:

"zope.persistentadapter"
interface zope.publisher.interfaces.IRequest[source]

Extends: zope.publisher.interfaces.IPublisherRequest, zope.publisher.interfaces.IPublicationRequest, zope.publisher.interfaces.IApplicationRequest

The basic request contract

interface zope.publisher.interfaces.IRequestEvent[source]

An event which is about or for a request.

request

The request this event is about.

interface zope.publisher.interfaces.IEndRequestEvent[source]

Extends: zope.publisher.interfaces.IRequestEvent

An event which gets sent when the publication is ended.

interface zope.publisher.interfaces.IStartRequestEvent[source]

Extends: zope.publisher.interfaces.IRequestEvent

An event which gets sent before publication of a request.

class zope.publisher.interfaces.RequestEvent(request)[source]

Bases: object

Events for requests.

Parameters:request – The request the event is for.
class zope.publisher.interfaces.EndRequestEvent(ob, request)[source]

Bases: zope.publisher.interfaces.RequestEvent

An event which gets sent when the publication is ended

class zope.publisher.interfaces.StartRequestEvent(request)[source]

Bases: zope.publisher.interfaces.RequestEvent

An event send when before publication of a request.

interface zope.publisher.interfaces.ISkinType[source]

Extends: zope.interface.interfaces.IInterface

Base interface for skin types.

interface zope.publisher.interfaces.ISkinnable[source]

A skinnable (request) can provide a skin.

The implementation in BrowserRequest will apply a default skin/layer called IDefaultBrowserLayer if not default skin get registered.

interface zope.publisher.interfaces.IDefaultSkin[source]

Any component providing this interface must be a skin.

This is a marker interface, so that we can register the default skin as an adapter from the presentation type to IDefaultSkin.

interface zope.publisher.interfaces.ISkinChangedEvent[source]

Extends: zope.publisher.interfaces.IRequestEvent

Event that gets triggered when the skin of a request is changed.

interface zope.publisher.interfaces.IDefaultViewName[source]

A string that contains the default view name

A default view name is used to select a view when a user hasn’t specified one.

interface zope.publisher.interfaces.IReRaiseException[source]

An exception that should be reraised, when handled in publisher.

Under some circumstances (for instance if acting in a WSGI pipeline with debugger middleware) certain exceptions occuring while publishing should be handled by the Zope machinery and never reach the ‘outside world’.

Adapters providing this interface for a certain exception type which also return False when being called, indicate by this that the exception should not be reraised during publishing.

This makes it possible, for instance, to authenticate with basic-auth when a debugger middleware is used and IUnauthorized is raised.

__call__()

Return True if an exception should be re-raised

Implementation

Base implementations of the Publisher objects

Specifically, ‘BaseRequest’, ‘BaseResponse’, and ‘DefaultPublication’ are specified here.

class zope.publisher.base.BaseResponse[source]

Bases: object

Base Response Class

setResult(result)[source]

See IPublisherResponse

handleException(exc_info)[source]

See IPublisherResponse

internalError()[source]

See IPublisherResponse

reset()[source]

See IPublisherResponse

retry()[source]

See IPublisherResponse

class zope.publisher.base.DebugFlags[source]

Bases: object

Debugging flags.

class zope.publisher.base.BaseRequest(body_instream, environ, response=None, positional=None)[source]

Bases: object

Represents a publishing request.

This object provides access to request data. Request data may vary depending on the protocol used.

Request objects are created by the object publisher and will be passed to published objects through the argument name, REQUEST.

The request object is a mapping object that represents a collection of variable to value mappings.

publication

See IPublisherRequest

processInputs()[source]

See IPublisherRequest

retry()[source]

See IPublisherRequest

setPublication(pub)[source]

See IPublisherRequest

supportsRetry()[source]

See IPublisherRequest

traverse(obj)[source]

See IPublisherRequest

close()[source]

See IPublicationRequest

getPositionalArguments()[source]

See IPublicationRequest

getTraversalStack()[source]

See IPublicationRequest

hold(object)[source]

See IPublicationRequest

setTraversalStack(stack)[source]

See IPublicationRequest

bodyStream

See zope.publisher.interfaces.IApplicationRequest

items()[source]

See Interface.Common.Mapping.IEnumerableMapping

keys()[source]

See Interface.Common.Mapping.IEnumerableMapping

values()[source]

See Interface.Common.Mapping.IEnumerableMapping

get(key, default=None)[source]

See Interface.Common.Mapping.IReadMapping

has_key(key)

See Interface.Common.Mapping.IReadMapping

class zope.publisher.base.DefaultPublication(app)[source]

Bases: object

A stub publication.

This works just like Zope2’s ZPublisher. It rejects any name starting with an underscore and any objects (specifically: method) that doesn’t have a docstring.

HTTP API Reference

Interfaces

HTTP-related publisher interfaces.

interface zope.publisher.interfaces.http.IVirtualHostRequest[source]

The support for virtual hosts in Zope is very important.

In order to make virtual hosts working, we need to support several methods in our Request object. This interface defines the required methods.

setVirtualHostRoot(names)

Marks the currently traversed object as the root of a virtual host.

Any path elements traversed up to that

Set the names which compose the application path. These are the path elements that appear in the beginning of the generated URLs.

Should be called during traversal.

getVirtualHostRoot()

Returns the object which is the virtual host root for this request

Return None if setVirtualHostRoot hasn’t been called.

setApplicationServer(host, proto='http', port=None)

Override the host, protocol and port parts of generated URLs.

This affects automatically inserted <base> tags and URL getters in the request, but not things like @@absolute_url views.

shiftNameToApplication()

Add the name being traversed to the application name

This is only allowed in the case where the name is the first name.

A Value error is raised if the shift can’t be performed.

interface zope.publisher.interfaces.http.IHTTPApplicationRequest[source]

Extends: zope.publisher.interfaces.IApplicationRequest, zope.publisher.interfaces.http.IVirtualHostRequest

HTTP request data.

This object provides access to request data. This includes, the input headers, server data, and cookies.

Request objects are created by the object publisher and will be passed to published objects through the argument name, REQUEST.

The request object is a mapping object that represents a collection of variable to value mappings. In addition, variables are divided into four categories:

The request object may be used as a mapping object, in which case values will be looked up in the order: environment variables, other variables, cookies, and special.

__getitem__(key)

Return HTTP request data

Request data sre retrieved from one of:

Cookies are searched before environmental data.

getCookies()

Return the cookie data

Data are returned as a mapping object, mapping cookie name to value.

cookies

Request cookie data

This is a read-only mapping from variable name to value.

getHeader(name, default=None, literal=False)

Get a header value

Return the named HTTP header, or an optional default argument or None if the header is not found. Note that both original and CGI-ified header names are recognized, e.g. ‘Content-Type’, ‘CONTENT_TYPE’ and ‘HTTP_CONTENT_TYPE’ should all return the Content-Type header, if available.

If the literal argument is passed, the header is searched ‘as is’, eg: only if the case matches.

headers

Request header data

This is a read-only mapping from variable name to value. It does not support iteration.

URL

Request URL data

When converted to a string, this gives the effective published URL.

This object can also be used as a mapping object. The key must be an integer or a string that can be converted to an integer. A non-negative integer returns a URL n steps from the URL of the top-level application objects. A negative integer gives a URL that is -n steps back from the effective URL.

For example, ‘request.URL[-2]’ is equivalent to the Zope 2 ‘request[“URL2”]’. The notion is that this would be used in path expressions, like ‘request/URL/-2’.

getURL(level=0, path_only=False)

Return the published URL with level names removed from the end.

If path_only is true, then only a path will be returned.

getApplicationURL(depth=0, path_only=False)

Return the application URL plus depth steps

If path_only is true, then only a path will be returned.

interface zope.publisher.interfaces.http.IHTTPPublisher[source]

Extends: zope.publisher.interfaces.IPublishTraverse

HTTP Publisher

interface zope.publisher.interfaces.http.IHTTPView[source]

Extends: zope.browser.interfaces.IView

HTTP View

interface zope.publisher.interfaces.http.IHTTPApplicationResponse[source]

HTTP Response

redirect(location, status=302, trusted=False)

Causes a redirection without raising an error.

By default redirects are untrusted which restricts target URLs to the same host that the request was sent to.

If the trusted flag is set, redirects are allowed for any target URL.

interface zope.publisher.interfaces.http.IHeaderOutput[source]

Interface for setting HTTP response headers.

This allows the HTTP server and the application to both set response headers.

zope.publisher.http.HTTPResponse is optionally passed an object which implements this interface in order to intermingle its headers with the HTTP server’s response headers, and for the purpose of better logging.

setResponseStatus(status, reason)

Sets the status code and the accompanying message.

setResponseHeaders(mapping)

Sets headers. The headers must be Correctly-Cased.

appendResponseHeaders(lst)

Sets headers that can potentially repeat.

Takes a list of strings.

wroteResponseHeader()

Returns a flag indicating whether the response

header has already been sent.

setAuthUserName(name)

Sets the name of the authenticated user so the name can be logged.

interface zope.publisher.interfaces.http.IResult[source]

An iterable that provides the body data of the response.

For simplicity, an adapter to this interface may in fact return any iterable, without needing to strictly have the iterable provide IResult.

IMPORTANT: The result object may be held indefinitely by a server and may be accessed by arbitrary threads. For that reason the result should not hold on to any application resources (i.e., should not have a connection to the database) and should be prepared to be invoked from any thread.

This iterable should generally be appropriate for WSGI iteration.

Each element of the iteration should generally be much larger than a character or line; concrete advice on chunk size is hard to come by, but a single chunk of even 100 or 200 K is probably fine.

If the IResult is a string, then, the default iteration of per-character is wildly too small. Because this is such a common case, if a string is used as an IResult then this is special-cased to simply convert to a tuple of one value, the string.

Adaptation to this interface provides the opportunity for efficient file delivery, pipelining hooks, and more.

__iter__()

iterate over the values that should be returned as the result.

See IHTTPResponse.setResult.

interface zope.publisher.interfaces.http.IHTTPResponse[source]

Extends: zope.publisher.interfaces.IResponse

An object representation of an HTTP response.

The Response type encapsulates all possible responses to HTTP requests. Responses are normally created by the object publisher. A published object may recieve the response object as an argument named ‘RESPONSE’. A published object may also create its own response object. Normally, published objects use response objects to:

  • Provide specific control over output headers,
  • Set cookies, or
  • Provide stream-oriented output.

If stream oriented output is used, then the response object passed into the object must be used.

authUser

The authenticated user message.

getStatus()

Returns the current HTTP status code as an integer.

setStatus(status, reason=None)

Sets the HTTP status code of the response

The status parameter must be either an integer (preferred), a value that can be converted to an integer using the int() function, or one of the standard status messages listed in the status_codes dict of the zope.publisher.http module (including “OK”, “NotFound”, and so on). If the parameter is some other value, the status will be set to 500.

The reason parameter is a short message to be sent with the status code to the client. If reason is not provided, a standard reason will be supplied, falling back to “Unknown” for unregistered status codes.

getStatusString()

Return the status followed by the reason.

setHeader(name, value, literal=False)

Sets an HTTP return header “name” with value “value”

The previous value is cleared. If the literal flag is true, the case of the header name is preserved, otherwise word-capitalization will be performed on the header name on output.

addHeader(name, value)

Add an HTTP Header

Sets a new HTTP return header with the given value, while retaining any previously set headers with the same name.

getHeader(name, default=None)

Gets a header value

Returns the value associated with a HTTP return header, or ‘default’ if no such header has been set in the response yet.

getHeaders()

Returns a list of header name, value tuples.

appendToCookie(name, value)

Append text to a cookie value

If a value for the cookie has previously been set, the new value is appended to the old one separated by a colon.

expireCookie(name, **kw)

Causes an HTTP cookie to be removed from the browser

The response will include an HTTP header that will remove the cookie corresponding to “name” on the client, if one exists. This is accomplished by sending a new cookie with an expiration date that has already passed. Note that some clients require a path to be specified - this path must exactly match the path given when creating the cookie. The path can be specified as a keyword argument. If the value of a keyword argument is None, it will be ignored.

setCookie(name, value, **kw)

Sets an HTTP cookie on the browser

The response will include an HTTP header that sets a cookie on cookie-enabled browsers with a key “name” and value “value”. This overwrites any previously set value for the cookie in the Response object. If the value of a keyword argument is None, it will be ignored.

getCookie(name, default=None)

Gets HTTP cookie data as a dict

Returns the dict of values associated with an HTTP cookie set in the response, or ‘default’ if no such cookie has been set in the response yet.

setResult(result)

Sets response result value based on input.

Input is usually a unicode string, a string, None, or an object that can be adapted to IResult with the request. The end result is an iterable such as WSGI prefers, determined by following the process described below.

Try to adapt the given input, with the request, to IResult (found above in this file). If this fails, and the original value was a string, use the string as the result; or if was None, use an empty string as the result; and if it was anything else, raise a TypeError.

If the result of the above (the adaptation or the default handling of string and None) is unicode, encode it (to the preferred encoding found by adapting the request to zope.i18n.interfaces.IUserPreferredCharsets, usually implemented by looking at the HTTP Accept-Charset header in the request, and defaulting to utf-8) and set the proper encoding information on the Content-Type header, if present. Otherwise (the end result was not unicode) application is responsible for setting Content-Type header encoding value as necessary.

If the result of the above is a string, set the Content-Length header, and make the string be the single member of an iterable such as a tuple (to send large chunks over the wire; see discussion in the IResult interface). Otherwise (the end result was not a string) application is responsible for setting Content-Length header as necessary.

Set the result of all of the above as the response’s result. If the status has not been set, set it to 200 (OK).

consumeBody()

Returns the response body as a string.

Note that this function can be only requested once, since it is constructed from the result.

consumeBodyIter()

Returns the response body as an iterable.

Note that this function can be only requested once, since it is constructed from the result.

interface zope.publisher.interfaces.http.IHTTPVirtualHostChangedEvent[source]

The host, port and/or the application path have changed.

The request referred to in this event implements at least the IHTTPAppliationRequest interface.

request

The application request whose virtual host info has been altered

interface zope.publisher.interfaces.http.IHTTPException[source]

Marker interface for http exceptions views

interface zope.publisher.interfaces.http.IMethodNotAllowed[source]

Extends: zope.interface.common.interfaces.IException

An exception that signals the 405 Method Not Allowed HTTP error

object

The object on which the error occurred

request

The request in which the error occurred

exception zope.publisher.interfaces.http.MethodNotAllowed(object, request)[source]

Bases: exceptions.Exception

An exception that signals the 405 Method Not Allowed HTTP error

Implementation

HTTP Publisher

class zope.publisher.http.HTTPInputStream(stream, environment)[source]

Bases: object

Special stream that supports caching the read data.

This is important, so that we can retry requests.

class zope.publisher.http.HTTPRequest(body_instream, environ, response=None)[source]

Bases: zope.publisher.base.BaseRequest

Model HTTP request data.

This object provides access to request data. This includes, the input headers, form data, server data, and cookies.

Request objects are created by the object publisher and will be passed to published objects through the argument name, REQUEST.

The request object is a mapping object that represents a collection of variable to value mappings. In addition, variables are divided into four categories:

  • Environment variables

    These variables include input headers, server data, and other request-related data. The variable names are as <a href=”http://hoohoo.ncsa.uiuc.edu/cgi/env.html“>specified</a> in the <a href=”http://hoohoo.ncsa.uiuc.edu/cgi/interface.html“>CGI specification</a>

  • Form data

    These are data extracted from either a URL-encoded query string or body, if present.

  • Cookies

    These are the cookie data, if present.

  • Other

    Data that may be set by an application object.

The form attribute of a request is actually a Field Storage object. When file uploads are used, this provides a richer and more complex interface than is provided by accessing form data as items of the request. See the FieldStorage class documentation for more details.

The request object may be used as a mapping object, in which case values will be looked up in the order: environment variables, other variables, form data, and then cookies.

supportsRetry()[source]

See IPublisherRequest

retry()[source]

See IPublisherRequest

traverse(obj)[source]

See IPublisherRequest

getHeader(name, default=None, literal=False)[source]

See IHTTPRequest

getCookies()[source]

See IHTTPApplicationRequest

setPathSuffix(steps)[source]

See IHTTPRequest

unauthorized(challenge)[source]

See IHTTPCredentials

setPrincipal(principal)[source]

See IPublicationRequest

getApplicationURL(depth=0, path_only=False)[source]

See IHTTPApplicationRequest

shiftNameToApplication()[source]

Add the name being traversed to the application name

This is only allowed in the case where the name is the first name.

A Value error is raise if the shift can’t be performed.

get(key, default=None)[source]

See Interface.Common.Mapping.IReadMapping

keys()[source]

See Interface.Common.Mapping.IEnumerableMapping

zope.publisher.http.getCharsetUsingRequest(request)[source]

See IHTTPResponse

class zope.publisher.http.DirectResult(body)[source]

Bases: object

A generic result object.

The result’s body can be any iterable. It is the responsibility of the application to specify all headers related to the content, such as the content type and length.

Creating HTTP Results

This document describes the state of creating HTTP results for Zope 3.4. This is different than it was in the past.

Traditionally in Zope, HTTP results are created by simply returning strings. Strings are inspected to deduce their content type, which is usually HTML. Applications can override this by setting a response headers (calling request.response.setHeader).

In Zope 2, applications could also call response.write. This allows both:

  • Effecient handling of large output
  • HTTP chucked output for streaming

Before release 3.1, Zope 3 has a response write method that did neither of these things. Developers coming from Zope 2 might use the write method, expecting it to have the same bahavior as it does in Zope 2. At least until we can satisfy those expectations, we have disabled the response write method for now. Maybe we’ll reinstate it in the future.

There is currently no support for streaming (at least while holding on to a database connection and transaction), but there is now support for returning large amounts of data.

Returning large amounts of data without storing the data in memory

To return a large result, you should write the result to a temporary file (tempfile.TemporaryFile) and return the temporary file. Alternatively, if the data you want to return is already in a (non-temporary) file, just open and return that file. The publisher (actually an adapter used by the publisher) will handle a returned file very efficiently.

The publisher will compute the response content length from the file automatically. It is up to applications to set the content type. It will also take care of positioning the file to it’s beginning, so applications don’t need to do this beforehand.

This is actually accomplished via zope.app.wsgi.fileresult.FileResult, and happens if and only if that, or something like it, is registered as an adapter. The FileResult, however, does what needs to happen thanks to a special hook associated with the IResult interface, used by the http module in this package.

zope.publisher.interfaces.http.IResult

The interface for IResult describes the interface thoroughly. The IHTTPResponse.setHeader method that uses it also documents how it is used. Reading the IResult interface and the IHTTPResponse.setHeader description (in the same interface file) is highly recommended.

In addition to supporting sending large amoounts of data, IResult supports postprocessing of output. setResult tries to adapt everything to IResult. Postprocessing might include XSLT transforms, adding an O-wrap around the content, adding JavaScript and CSS header lines on the basis of elements added to a page, or pipelining somehow to do all of it sequentially. May the best approach win! This merely makes the different options possible.

To close, we’ll build a quick example so you can see it working.

(To make the code work in both python-2.x and python-3.x, define unicode name for python-3.x:

>>> import sys
>>> if sys.version_info[0] > 2:
...     unicode = str
>>> import zope.interface
>>> import zope.component
>>> from zope.publisher.browser import TestRequest
>>> from zope.publisher.interfaces.http import IResult, IHTTPRequest
>>> try:
...     from html import escape
... except ImportError:
...     from cgi import escape
>>> @zope.interface.implementer(IResult)
... @zope.component.adapter(unicode, IHTTPRequest)
... def do_something_silly_to_unicode_results(val, request):
...     request.response.setHeader('X-Silly', 'Yes')
...     return (unicode('<html>\n<head>\n<title>raw</title>\n</head>\n<body>\n') +
...             escape(val) + '\n</body>\n</html>')
...
>>> zope.component.provideAdapter(do_something_silly_to_unicode_results)

That’s returning a unicode string, which is special cased to (1) make an iterable that is chunked, (2) encode, and (3) set content-length.

>>> request = TestRequest()
>>> request.response.setHeader('content-type', 'text/html')
>>> request.response.setResult(unicode('<h1>Foo!</h1>'))
>>> request.response.getHeader('x-silly')
'Yes'
>>> request.response.getHeader('content-type')
'text/html;charset=utf-8'
>>> res = tuple(request.response.consumeBodyIter())
>>> res
(b'<html>\n<head>\n<title>raw</title>\n</head>\n<body>\n&lt;h1&gt;Foo!&lt;/h1&gt;\n</body>\n</html>',)
>>> len(res[0]) == int(request.response.getHeader('content-length'))
True

You can also do everything yourself by returning any non-basestring iterable (for instance, a list or tuple).

>>> @zope.interface.implementer(IResult)
... @zope.component.adapter(int, IHTTPRequest)
... def do_something_silly_to_int_results(val, request):
...     return ['This', ' is an int: %i' % (val,),]
...
>>> zope.component.provideAdapter(do_something_silly_to_int_results)
>>> request = TestRequest()
>>> request.response.setHeader('content-type', 'text/plain')
>>> request.response.setResult(42)
>>> request.response.getHeader('content-type')
'text/plain'
>>> res = tuple(request.response.consumeBodyIter())
>>> res
('This', ' is an int: 42')
>>> request.response.getHeader('content-length') is None
True

Again, READ THE INTERFACES. One important bit is that you can’t hold on to a database connection in one of these iterables.

You can bypass the adaptation by calling setResult with an object that provides IResult. The DirectResult class in the http module is the simplest way to do this, but any other IResult should work.

>>> from zope.publisher.http import DirectResult
>>> @zope.interface.implementer(IResult)
... @zope.component.adapter(DirectResult, IHTTPRequest)
... def dont_touch_this(val, request):
...     raise ValueError('boo!  hiss!') # we don't get here.
...
>>> request = TestRequest()
>>> request.response.setResult(DirectResult(('hi',)))
>>> tuple(request.response.consumeBodyIter())
('hi',)

Browser API Reference

Interfaces

Browser Interfaces

interface zope.publisher.interfaces.browser.IBrowserApplicationRequest[source]

Extends: zope.publisher.interfaces.http.IHTTPApplicationRequest

Browser-specific requests

__getitem__(key)

Return Browser request data

Request data are retrieved from one of:

Form data are searched before cookies, which are searched before environmental data.

form

Form data

This is a read-only mapping from name to form value for the name.

interface zope.publisher.interfaces.browser.IBrowserPublication[source]

Extends: zope.publisher.interfaces.IPublication

Object publication framework.

getDefaultTraversal(request, ob)

Get the default published object for the request

Allows a default view to be added to traversal. Returns (ob, steps_reversed).

interface zope.publisher.interfaces.browser.IBrowserRequest[source]

Extends: zope.publisher.interfaces.http.IHTTPRequest, zope.publisher.interfaces.ISkinnable

Browser-specific Request functionality.

Note that the browser is special in many ways, since it exposes the Request object to the end-developer.

interface zope.publisher.interfaces.browser.IBrowserPage[source]

Extends: zope.browser.interfaces.IBrowserView, zope.publisher.interfaces.browser.IBrowserPublisher

Browser page

__call__(*args, **kw)

Compute a response body

interface zope.publisher.interfaces.browser.IBrowserSkinType[source]

Extends: zope.publisher.interfaces.ISkinType

A skin is a set of layers.

interface zope.publisher.interfaces.browser.IDefaultBrowserLayer[source]

Extends: zope.publisher.interfaces.browser.IBrowserRequest

The default layer.

Implementation

Browser-specific Publisher classes

Here we define the specific ‘BrowserRequest’ and ‘BrowserResponse’ class. The big improvement of the ‘BrowserRequest’ to ‘HTTPRequest’ is that is can handle HTML form data and convert them into a Python-native format. Even file data is packaged into a nice, Python-friendly ‘FileUpload’ object.

search(string[, pos[, endpos]]) –> match object or None. Scan through string looking for a match, and return a corresponding match object instance. Return None if no position in the string matches.

search(string[, pos[, endpos]]) –> match object or None. Scan through string looking for a match, and return a corresponding match object instance. Return None if no position in the string matches.

zope.publisher.browser.isRelative()

match(string[, pos[, endpos]]) –> match object or None. Matches zero or more characters at the beginning of the string

zope.publisher.browser.get_converter()

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

zope.publisher.browser.registerTypeConverter(field_type, converter, replace=False)[source]

Add a custom type converter to the registry.

o If ‘replace’ is not true, raise a KeyError if a converter is
already registered for ‘field_type’.
class zope.publisher.browser.FileUpload(aFieldStorage)[source]

Bases: object

File upload objects

File upload objects are used to represent file-uploaded data.

File upload objects can be used just like files.

In addition, they have a ‘headers’ attribute that is a dictionary containing the file-upload headers, and a ‘filename’ attribute containing the name of the uploaded file.

class zope.publisher.browser.RedirectingBrowserRequest(body_instream, environ, response=None)[source]

Bases: zope.publisher.browser.BrowserRequest

Browser requests that redirect when the actual and effective URLs differ

class zope.publisher.browser.TestRequest(body_instream=None, environ=None, form=None, skin=None, **kw)[source]

Bases: zope.publisher.browser.BrowserRequest

Browser request with a constructor convenient for testing

class zope.publisher.browser.BrowserResponse[source]

Bases: zope.publisher.http.HTTPResponse

Browser response

zope.publisher.browser.isHTML(str)[source]

Try to determine whether str is HTML or not.

exception zope.publisher.browser.NotCompatibleAdapterError[source]

Bases: exceptions.Exception

Adapter not compatible with zope.i18n.interfaces.IModifiableBrowserLanguages has been used.

class zope.publisher.browser.BrowserView(context, request)[source]

Bases: zope.location.location.Location

Browser View.

>>> view = BrowserView("context", "request")
>>> view.context
'context'
>>> view.request
'request'
>>> view.__parent__
'context'
>>> view.__parent__ = "parent"
>>> view.__parent__
'parent'
class zope.publisher.browser.BrowserPage(context, request)[source]

Bases: zope.publisher.browser.BrowserView

Browser page

To create a page, which is an object that is published as a page, you need to provide an object that:

  • has a __call__ method and that
  • provides IBrowserPublisher, and
  • if ZPT is going to be used, then your object should also provide request and context attributes.

The BrowserPage base class provides a standard constructor and a simple implementation of IBrowserPublisher:

>>> class MyPage(BrowserPage):
...     pass
>>> request = TestRequest()
>>> context = object()
>>> page = MyPage(context, request)
>>> from zope.publisher.interfaces.browser import IBrowserPublisher
>>> IBrowserPublisher.providedBy(page)
True
>>> page.browserDefault(request) == (page, ())
True
>>> page.publishTraverse(request, 'bob') 
Traceback (most recent call last):
...
NotFound: Object: <zope.publisher.browser.MyPage object at ...>, name: 'bob'
>>> page.request is request
True
>>> page.context is context
True

But it doesn’t supply a __call__ method:

>>> page()
Traceback (most recent call last):
  ...
NotImplementedError: Subclasses should override __call__ to provide a response body

It is the subclass’ responsibility to do that.

FTP API Reference

Interfaces

Virtual File System interfaces for the publisher.

interface zope.publisher.interfaces.ftp.IFTPRequest[source]

Extends: zope.publisher.interfaces.IRequest

FTP Request

interface zope.publisher.interfaces.ftp.IFTPView[source]

Extends: zope.browser.interfaces.IView

FTP View

interface zope.publisher.interfaces.ftp.IFTPPublisher[source]

Extends: zope.publisher.interfaces.IPublishTraverse

FTP Publisher

Implementation

FTP Publisher

Logging API Reference

Interfaces

An interface for LoggingInfo.

interface zope.publisher.interfaces.logginginfo.ILoggingInfo[source]

Provides information about the object to be included in the logs.

In the class we need an __init__ method that accepts an object.

getLogMessage()

Returns a log string made from the object it was adapted from.

Implementation

Adapter:

Adapts zope.security.interfaces.IPrincipal to zope.publisher.interfaces.logginginfo.ILoggingInfo.

class zope.publisher.principallogging.PrincipalLogging(principal)[source]

Bases: object

Adapts zope.security.interfaces.IPrincipal to zope.publisher.interfaces.logginginfo.ILoggingInfo.

Default View Name API

Default view name API

zope.publisher.defaultview.queryDefaultViewName(object, request, default=None, context=None)[source]

query the default view for a given object and request.

>>> from zope.publisher.defaultview import queryDefaultViewName

lets create an object with a default view.

>>> import zope.interface
>>> class IMyObject(zope.interface.Interface):
...   pass
>>> @zope.interface.implementer(IMyObject)
... class MyObject(object):
...   pass
>>> queryDefaultViewName(MyObject(), object()) is None
True

Now we can will set a default view.

>>> import zope.component
>>> import zope.publisher.interfaces
>>> zope.component.provideAdapter('name',
...     adapts=(IMyObject, zope.interface.Interface),
...     provides=zope.publisher.interfaces.IDefaultViewName)
>>> queryDefaultViewName(MyObject(), object())
'name'

This also works if the name is empty

>>> zope.component.provideAdapter('',
...     adapts=(IMyObject, zope.interface.Interface),
...     provides=zope.publisher.interfaces.IDefaultViewName)
>>> queryDefaultViewName(MyObject(), object())
''

Skinnable

Requests can provide skins. But what exactly is a skin? At the code level, a skin is just an interface which a request provides. Why do we need skins? We can use skins for registering different adapters.

That’s a little bit much use of the word skin. Let’s explain it in more detail. A skin is an interface which provides an interface. This interface is called ISkinType. The zope.publisher right now provides only one specific skin type interface used in the IBrowserRequest implementation. This interface is called BrowserSkinType.

Since the zope server provides request factories for building a request, each such request type could provide it’s own skin type interface. This ensures that we can register a skin type for each request.

Now let’s look at a higher level. A skin is a concept which we can use for providing different kinds of views, templates or other adapters adapting a request. These skins are the key component for providing different kind of application layers. A skin makes it possible for an application to act very differently with each skin. Of course, that’s only the case at the interaction level where the request is involved. But that’s the case most of the time since we have a web application server.

Another part of the skinnable concept is that an application can define zero or more default skins. This is done with the IDefaultSkin interface. Default skins can be defined for request interfaces or implementations. Such a default skin can get overriden in a custom setup. Overriding a skin can be done by using the defaultSkin directive offered from zope.app.publication.zcml.

Why does a request need a default skin? If a request needs to provide some pluggable concepts that require that a default adapter is registered for a request, this adapter could be registered for the default skin. If a project likes to use another pattern and needs to register another request adapter, the project could register its own skin and register the custom adapter for this new project based skin. This is very handy and allows developers to skip a complete default-skin-based setup for a given request.

In general, this means a request interface and the request class that implements the request interface only provides the basic API but no adapters if the request needs to delegate things to an adapter. For such a request a default skin can get defined. This default skin can provide all adapters which the request implementation needs to have. This gives us the option to replace the default skin within a custom skin and provide custom adapters.

Our exmple will define a full request and all its components from scratch. it doesn’t depend on IBrowserRequest. We’ll use a JSON-RPC as sample like the z3c.jsonrpc package provides.

Layers and Skins

We also use the term “layer” if we talk about skins. A layer or skin layer is an interface registered as a ISkinType without a name. Zope provides a traversal pattern which allows traversal to a skin within a skin namespace called skin. This allows traversal to a method called applySkin which will apply a registered named skin. This means if we register an ISkinType with a name argument, we will register a skin. if we register a ISkinType without a name just we register a layer. This means, layers are not traversable ISkinType interfaces.

Let’s start define a request:

>>> from zope.publisher.interfaces import IRequest
>>> class IJSONRequest(IRequest):
...     """JSON request."""

And we define a skin type:

>>> from zope.publisher.interfaces import ISkinType
>>> class IJSONSkinType(ISkinType):
...     """JSON skin type."""

A request would implement the IJSONRequest interface but not the request type interface:

>>> import zope.interface
>>> from zope.publisher.base import BaseRequest
>>> @zope.interface.implementer(IJSONRequest)
... class JSONRequest(BaseRequest):
...     """JSON request implementation."""

Now our request provides IJSONRequest because it implement that interface:

>>> from io import BytesIO
>>> request = JSONRequest(BytesIO(b''), {})
>>> IJSONRequest.providedBy(request)
True

setDefaultSkin

The default skin is a marker interface that can be registered as an adapter that provides IDefaultSkin for the request type. A default skin interface like any other skin must also provide ISkinType. This is important since applySkin will lookup for skins based on this type.

Note: Any interfaces that are directly provided by the request coming into this method are replaced by the applied layer/skin interface. This is very important since the retry pattern can use a clean request without any directly provided interface after a retry gets started.

If a default skin is not available, the fallback default skin is applied if available for the given request type. The default fallback skin is implemented as an named adapter factory providing IDefaultSkin and using default as name.

Important to know is that some skin adapters get registered as interfaces and the fallback skins as adapters. See the defaultSkin directive in zope.app.publication.zcml for more information. It registers plain interfaces as adapters which are not adaptable. We have special code to handle this case, which we will demonstrate below.

Each request can only have one (unnamed) default skin and will fallback to the named (default) fallback skin if available.

Only the IBrowserRequest provides such a default fallback adapter. This adapter will apply the IDefaultBrowserLayer if no explicit default skin is registered for IBrowserRequest.

Our test setup requires a custom default layer which we will apply to our request. Let’s define a custm layer:

>>> class IJSONDefaultLayer(zope.interface.Interface):
...     """JSON default layyer."""

To illustrate, we’ll first use setDefaultSkin without a registered IDefaultSkin adapter:

>>> IJSONDefaultLayer.providedBy(request)
False

If we try to set a default skin and no one exist we will not fail but nothing happens

>>> from zope.publisher.skinnable import setDefaultSkin
>>> setDefaultSkin(request)

Make sure our IJSONDefaultLayer provides the ISkinType interface. This is normaly done in a configure.zcml using the interface directive:

>>> ISkinType.providedBy(IJSONDefaultLayer)
False
>>> zope.interface.alsoProvides(IJSONDefaultLayer, ISkinType)
>>> ISkinType.providedBy(IJSONDefaultLayer)
True

Now let’s examine what can happen with our legacy case: an interface is registered as an adapter.

>>> from zope.publisher.interfaces import IDefaultSkin
>>> sm = zope.component.getSiteManager()
>>> sm.registerAdapter(
...     IJSONDefaultLayer, (IJSONRequest,), IDefaultSkin, name='default')
>>> request = JSONRequest(BytesIO(b''), {})
>>> IJSONDefaultLayer.providedBy(request)
False
>>> setDefaultSkin(request)
>>> IJSONDefaultLayer.providedBy(request)
True

What if the request already provides the interface?

>>> IJSONDefaultLayer.providedBy(request)
True
>>> setDefaultSkin(request)
>>> IJSONDefaultLayer.providedBy(request)
True

Now let’s define a default skin adapter which the setDefaultSkin can use. This adapter return our IJSONDefaultLayer. We also register this adapter within default as name:

>>> def getDefaultJSONLayer(request):
...     return IJSONDefaultLayer
>>> zope.component.provideAdapter(getDefaultJSONLayer,
...     (IJSONRequest,), IDefaultSkin, name='default')
>>> setDefaultSkin(request)
>>> IJSONDefaultLayer.providedBy(request)
True

When we register a default skin, without that the skin provides an ISkinType, the setDefaultSkin will raise a TypeError:

>>> from zope.interface import Interface
>>> class IMySkin(Interface):
...     pass
>>> zope.component.provideAdapter(IMySkin, (IJSONRequest,), IDefaultSkin)
>>> setDefaultSkin(request)
Traceback (most recent call last):
...
TypeError: Skin interface <InterfaceClass __builtin__.IMySkin> doesn't provide ISkinType

The default skin must provide ISkinType:

>>> zope.interface.alsoProvides(IMySkin, ISkinType)
>>> ISkinType.providedBy(IMySkin)
True

setDefaultSkin uses the custom layer interface instead of IJSONDefaultLayer:

>>> request = JSONRequest(BytesIO(b''), {})
>>> IMySkin.providedBy(request)
False
>>> IJSONDefaultLayer.providedBy(request)
False
>>> setDefaultSkin(request)
>>> IMySkin.providedBy(request)
True
>>> IJSONDefaultLayer.providedBy(request)
False

Any interfaces that are directly provided by the request coming into this method are replaced by the applied layer/skin interface. This is important for our retry pattern which will ensure that we start with a clean request:

>>> request = JSONRequest(BytesIO(b''), {})
>>> class IFoo(Interface):
...     pass
>>> zope.interface.directlyProvides(request, IFoo)
>>> IFoo.providedBy(request)
True
>>> setDefaultSkin(request)
>>> IFoo.providedBy(request)
False

applySkin

The applySkin method is able to apply any given skin. Let’s define some custom skins:

>>> import pprint
>>> from zope.interface import Interface
>>> class ISkinA(Interface):
...     pass
>>> zope.interface.directlyProvides(ISkinA, ISkinType)
>>> class ISkinB(Interface):
...     pass
>>> zope.interface.directlyProvides(ISkinB, ISkinType)

Let’s start with a fresh request:

>>> request = JSONRequest(BytesIO(b''), {})

Now we can apply the SkinA:

>>> from zope.publisher.skinnable import applySkin
>>> applySkin(request, ISkinA)
>>> pprint.pprint(list(zope.interface.providedBy(request).interfaces()))
[<InterfaceClass __builtin__.ISkinA>,
 <InterfaceClass __builtin__.IJSONRequest>,
 <InterfaceClass zope.publisher.interfaces.IRequest>]

And if we apply ISkinB, ISkinA get removed at the same time ISkinB get applied:

>>> applySkin(request, ISkinB)
>>> pprint.pprint(list(zope.interface.providedBy(request).interfaces()))
[<InterfaceClass __builtin__.ISkinB>,
 <InterfaceClass __builtin__.IJSONRequest>,
 <InterfaceClass zope.publisher.interfaces.IRequest>]

setDefaultSkin and applySkin

If we set a default skin and later apply a custom skin, the default skin get removed at the time the applySkin get called within a new ISkinType:

>>> request = JSONRequest(BytesIO(b''), {})

Note, that our IMySkin is the default skin for IJSONRequest. We can aprove that by lookup an IDefaultSkin interface for our request:

>>> adapters = zope.component.getSiteManager().adapters
>>> default = adapters.lookup((zope.interface.providedBy(request),),
...     IDefaultSkin, '')
>>> default
<InterfaceClass __builtin__.IMySkin>
>>> setDefaultSkin(request)
>>> IMySkin.providedBy(request)
True
>>> ISkinA.providedBy(request)
False

Now apply our skin ISkinA. This should remove the IMySkin at the same time the ISkinA get applied:

>>> applySkin(request, ISkinA)
>>> IMySkin.providedBy(request)
False
>>> ISkinA.providedBy(request)
True

SkinChangedEvent

We will use python-3 style print function, so we import it from the future:

>>> from __future__ import print_function

Changing the skin on a request triggers the ISkinChangedEvent event:

>>> import zope.component
>>> from zope.publisher.interfaces import ISkinChangedEvent
>>> def receiveSkinEvent(event):
...     print("Notified SkinEvent for: %s" % event.request.__class__.__name__)
>>> zope.component.provideHandler(receiveSkinEvent, (ISkinChangedEvent,))
>>> applySkin(request, ISkinA)
Notified SkinEvent for: JSONRequest

Implementation

Browser-specific skin implementations.

class zope.publisher.skinnable.SkinChangedEvent(request)[source]

Bases: object

Skin changed event.

zope.publisher.skinnable.getDefaultSkin(request)[source]

Returns the IDefaultSkin layer for IBrowserRequest.

zope.publisher.skinnable.setDefaultSkin(request)[source]

Sets the default skin for a given request.

zope.publisher.skinnable.applySkin(request, skin)[source]

Change the presentation skin for this request.

XMLRPC publisher

Pre-marshal / Proxy removal

>>> sample = {'foo': (1, ['x', 'y', 1.2])}

if we put the sample in a security proxy:

>>> from zope.security.checker import ProxyFactory
>>> proxied_sample = ProxyFactory(sample)

We can still get to the data, but the non-rock data is proxied:

>>> from zope.security.proxy import Proxy
>>> proxied_sample['foo']
(1, ['x', 'y', 1.2])
>>> type(proxied_sample['foo']) is Proxy
True
>>> type(proxied_sample['foo'][1]) is Proxy
True

But we can strip the proxies using premarshal:

>>> from zope.publisher.xmlrpc import premarshal
>>> stripped = premarshal(proxied_sample)
>>> stripped
{'foo': [1, ['x', 'y', 1.2]]}
>>> type(stripped['foo']) is Proxy
False
>>> type(stripped['foo'][1]) is Proxy
False

So xmlrpclib will be happy. :)

Import xmlrpclib depending on current python interpreter version

>>> import sys
>>> if sys.version_info[0] == 2:
...     import xmlrpclib
... else:
...     import xmlrpc.client as xmlrpclib

We can also use premarshal to strip proxies off of Fault objects. We have to make a security declaration first though:

>>> fault = xmlrpclib.Fault(1, 'waaa')
>>> proxied_fault = ProxyFactory(fault)
>>> stripped_fault = premarshal(proxied_fault)
>>> type(stripped_fault) is Proxy
False

Standard python datetime objects are also handled:

>>> import datetime
>>> sample = datetime.datetime(2006,6,17,21,41,00)
>>> stripped_date = premarshal(sample)
>>> isinstance(stripped_date, datetime.datetime)
False
>>> isinstance(stripped_date, xmlrpclib.DateTime)
True

We can also use premarshal to strip proxies off of Binary objects. We have to make a security declaration first though:

>>> binary = xmlrpclib.Binary(b'foobar')
>>> proxied_binary = ProxyFactory(binary)
>>> stripped_binary = premarshal(proxied_binary)
>>> type(stripped_binary) is Proxy
False

Interfaces

Interfaces for the XMLRPC publisher.

interface zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher[source]

Extends: zope.publisher.interfaces.IPublishTraverse

XML-RPC Publisher

interface zope.publisher.interfaces.xmlrpc.IXMLRPCPublication[source]

Extends: zope.publisher.interfaces.IPublication

Object publication framework.

getDefaultTraversal(request, ob)

Get the default published object for the request

Allows a default view to be added to traversal. Returns (ob, steps_reversed).

interface zope.publisher.interfaces.xmlrpc.IXMLRPCRequest[source]

Extends: zope.publisher.interfaces.http.IHTTPRequest

XML-RPC Request

interface zope.publisher.interfaces.xmlrpc.IXMLRPCView[source]

Extends: zope.browser.interfaces.IView

XMLRPC View

interface zope.publisher.interfaces.xmlrpc.IXMLRPCPremarshaller[source]

Pre-Marshaller to remove proxies for xmlrpclib

__call__(self)

Return the given object without proxies.

Implementation

XML-RPC Publisher

This module contains the XMLRPCRequest and XMLRPCResponse

class zope.publisher.xmlrpc.XMLRPCResponse[source]

Bases: zope.publisher.http.HTTPResponse

XMLRPC response.

This object is responsible for converting all output to valid XML-RPC.

setResult(result)[source]

Sets the result of the response

Sets the return body equal to the (string) argument “body”. Also updates the “content-length” return header.

If the body is a 2-element tuple, then it will be treated as (title,body)

If is_error is true then the HTML will be formatted as a Zope error message instead of a generic HTML page.

handleException(exc_info)[source]

Handle Errors during publsihing and wrap it in XML-RPC XML

>>> import sys
>>> resp = XMLRPCResponse()
>>> try:
...     raise AttributeError('xyz')
... except:
...     exc_info = sys.exc_info()
...     resp.handleException(exc_info)
>>> resp.getStatusString()
'200 OK'
>>> resp.getHeader('content-type')
'text/xml;charset=utf-8'
>>> body = ''.join(resp.consumeBody())
>>> 'Unexpected Zope exception: AttributeError: xyz' in body
True
class zope.publisher.xmlrpc.XMLRPCView(context, request)[source]

Bases: object

A base XML-RPC view that can be used as mix-in for XML-RPC views.

class zope.publisher.xmlrpc.PreMarshallerBase(data)[source]

Bases: object

Abstract base class for pre-marshallers.

class zope.publisher.xmlrpc.DictPreMarshaller(data)[source]

Bases: zope.publisher.xmlrpc.PreMarshallerBase

Pre-marshaller for dicts

class zope.publisher.xmlrpc.ListPreMarshaller(data)[source]

Bases: zope.publisher.xmlrpc.PreMarshallerBase

Pre-marshaller for list

class zope.publisher.xmlrpc.BinaryPreMarshaller(data)[source]

Bases: zope.publisher.xmlrpc.PreMarshallerBase

Pre-marshaller for xmlrpc.Binary

class zope.publisher.xmlrpc.FaultPreMarshaller(data)[source]

Bases: zope.publisher.xmlrpc.PreMarshallerBase

Pre-marshaller for xmlrpc.Fault

class zope.publisher.xmlrpc.DateTimePreMarshaller(data)[source]

Bases: zope.publisher.xmlrpc.PreMarshallerBase

Pre-marshaller for xmlrpc.DateTime

class zope.publisher.xmlrpc.PythonDateTimePreMarshaller(data)[source]

Bases: zope.publisher.xmlrpc.PreMarshallerBase

Pre-marshaller for datetime.datetime

zope.publisher.xmlrpc.premarshal(data)[source]

Premarshal data before handing it to xmlrpclib for marhalling

The initial purpose of this function is to remove security proxies without resorting to removeSecurityProxy. This way, we can avoid inadvertently providing access to data that should be protected.

Package configuration

The zope.publisher package provides a ZCML file that configures some adapters and security:

>>> from zope.configuration.xmlconfig import XMLConfig
>>> import zope.publisher
>>> XMLConfig('configure.zcml', zope.publisher)()
>>> len(list(zope.component.getGlobalSiteManager().registeredUtilities()))
22
>>> len(list(zope.component.getGlobalSiteManager().registeredAdapters()))
11

ZCML Directives

This package also defines some ZCML directives for defining the default skin (browser:defaultSkin) and default view (browser:defaultView).

Default view and default skin ZCML configuration feature.

interface zope.publisher.zcml.IDefaultSkinDirective[source]

Sets the default browser skin

name

Default skin name

Default skin name

interface zope.publisher.zcml.IDefaultViewDirective[source]

The name of the view that should be the default.

This name refers to view that should be the view used by default (if no view name is supplied explicitly).

name

The name of the view that should be the default.

This name refers to view that should be the view used by default (if no view name is supplied explicitly).

for_

The interface this view is the default for.

Specifies the interface for which the view is registered.

All objects implementing this interface can make use of this view. If this attribute is not specified, the view is available for all objects.

layer

The layer the default view is declared for

The default layer for which the default view is applicable. By default it is applied to all layers.

zope.publisher.zcml.setDefaultSkin(name, info='')[source]

Set the default skin.

>>> from zope.interface import directlyProvides
>>> from zope.app.testing import ztapi
>>> class Skin1: pass
>>> directlyProvides(Skin1, IBrowserSkinType)
>>> ztapi.provideUtility(IBrowserSkinType, Skin1, 'Skin1')
>>> setDefaultSkin('Skin1')
>>> adapters = component.getSiteManager().adapters
Lookup the default skin for a request that has the
>>> adapters.lookup((IBrowserRequest,), IDefaultSkin, '') is Skin1
True

Changes

4.3.3 (unreleased)

  • Nothing changed yet.

4.3.2 (2017-05-23)

  • Fix instances of BaseRequest (including BrowserRequest) being unexpectedly False on Python 3 by defining __bool__. Such instances were always True on Python 2. See issue 18.

4.3.1 (2017-04-24)

  • Add support for Python 3.6.

  • Accept both new and old locations for __code__ in zope.publisher.publisher.unwrapMethod. This restores compatibility with Products.PythonScripts, where parameters were not extracted. [maurits, thet, MatthewWilkes]

  • Fix file uploads on python 3.4 and up. cgi.FieldStorage explicitly closes files when it is garbage collected. For details, see:

    We now keep a reference to the FieldStorage till we are finished processing the request.

  • Fix POST with large values on Python 3. Related to cgi.FieldStorage doing the decoding in Python 3. See pull 16.

4.3.0 (2016-07-04)

  • Add support for Python 3.5.
  • Drop support for Python 2.6 and 3.2.

4.2.2 (2015-11-16)

  • Emit HTTP response headers in a deterministic order (GH #8).

4.2.1 (2015-06-05)

  • Add support for Python 3.2.

4.2.0 (2015-06-02)

  • Add support for PyPy and PyPy3.

4.1.0 (2014-12-27)

  • Add support for Python 3.4.

4.0.0 (2014-12-22)

  • Enable testing on Travis.
  • Add __traceback_info__ to response.redirect() to ease debugging untrusted redirects.
  • Add trusted support for Redirect exception

4.0.0a4 (2013-03-12)

  • Support UTF-8-encoding application/json responses returned as Unicode.
  • Add YAML for travis-ci.

4.0.0a3 (2013-02-28)

  • Return bytes from PrincipalLogging.getLogMessage instead of unicode.

4.0.0a2 (2013-02-22)

  • Use BytesIO in zope.publisher.xmlrpc.TestRequest.

4.0.0a1 (2013-02-21)

  • Replace deprecated zope.component.adapts usage with equivalent zope.component.adapter decorator.

  • Replace deprecated zope.interface.implements usage with equivalent zope.interface.implementer decorator.

  • Drop support for Python 2.4, 2.5 and pypy.

  • Add support for Python 3.3.

  • Wrap with interaction() in try/finally.

  • Don’t guess the content type with 304 responses which MUST NOT / SHOULD NOT include it according to: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5

    Unfortunately, the content type will still be guessed if the result is set before the status.

3.13.0 (2011-11-17)

  • Fix error when no charset matches form data and HTTP_ACCEPT_CHARSET contains a *.
  • Add test convenience helper create_interaction and with interaction().

3.12.6 (2010-12-17)

  • Upload a non-CRLF version to pypi.

3.12.5 (2010-12-14)

  • Rename the tests extra to test.
  • Add a test for our own configure.zcml.
  • Use UTF-8 as the charset if the browser does not set a header, per W3C spec.

3.12.4 (2010-07-15)

  • LP #131460: Make principal logging unicode safe.
  • Remove use of string exceptions in tests, http://bugs.debian.org/585343
  • Add IStartRequestEvent and StartRequestEvent for use in zope.app.publication (matching up with IEndRequestEvent and EndRequestEvent). Includes refactoring to produce one definition of ‘event with a request’ - IRequestEvent.

3.12.3 (2010-04-30)

  • LP #209440: Don’t obscure original exception when handling retries in publish.publish() with handleErrors == False. This change makes debugging such exception in unit tests easier. Thanks to James Henstridge for the patch.
  • LP #98395: allow unicode output of XML content whose mimetype does not begin with text/, per RFC 3023 as well as for content types ending in +xml such as Mozilla XUL’s application/vnd+xml. Thanks to Justin Ryan for the patch.

3.12.2 (2010-04-16)

  • Remove use of zope.testing.doctestunit in favor of stdlib’s doctest.
  • Fix bug where xml-rpc requests would hang when served using paster.httpserver.

3.12.1 (2010-02-21)

  • Ensure that BaseRequest.traverse does not call traversal hooks on elements previously traversed but wrapped in a security proxy.

3.12.0 (2009-12-31)

  • Revert change done in 3.6.2, removing the zope.authentication dependency again. Move the BasicAuthAdapter and FTPAuth adapters to the new zope.login package.

3.11.0 (2009-12-15)

  • Move EndRequestEvent and IEndRequestEvent here from zope.app.publication.

3.10.1 (2009-11-28)

  • Declare minimum dependency on zope.contenttype 3.5 (omitted in 3.10).

3.10.0 (2009-10-22)

  • Move the implementation of zope.publisher.contenttype to zope.contenttype.parse, leaving BBB imports and moving tests along. zope.contenttype is a new but light-weight dependency of this package.
  • Support Python 2.6 by keeping QUERY_STRING out of request.form if the method is a POST. The original QUERY_STRING is still available if further processing is needed.
  • Better support the zcml defaultSkin directive’s behavior (registering an interface as a default skin) in the setDefaultSkin function.

3.9.3 (2009-10-08)

  • Fix the check for untrusted redirects introduced in 3.9.0 so it works with virtual hosting.

3.9.2 (2009-10-07)

  • Make redirect validation works without HTTP_HOST variable.
  • Add DoNotReRaiseException adapter that can be registered for exceptions to flag that they should not be re-raised by publisher when handle_errors parameter of the publish method is False.

3.9.1 (2009-09-01)

  • Convert a location, passed to a redirect method of HTTPRequest to string before checking for trusted host redirection, because a location object may be some non-string convertable to string, like URLGetter.

3.9.0 (2009-08-27)

  • Move some parts of zope.app.publisher into this package during zope.app.publisher refactoring:

    • IModifiableUserPreferredLanguages adapter for requests
    • browser:defaultView and browser:defaultSkin ZCML directives
    • IHTTPView, IXMLRPCView and like interfaces
    • security ZCML declarations for some of zope.publisher classes
  • Introduce IReRaiseException interface. If during publishing an exception occurs and for this exception an adapter is available that returns False on being called, the exception won’t be reraised by the publisher. This happens only if handle_errors parameter of the publish() method is set to False. Fixes problems when acting in a WSGI pipeline with a debugger middleware enabled.

    See https://bugs.launchpad.net/grok/+bug/332061 for details.

  • Fix #98471: Restrict redirects to current host. This causes a ValueError to be raised in the case of redirecting to a different host. If this is intentional, the parameter trusted can be given.

  • Move dependency on zope.testing from install_requires to tests_require.

  • Remove time.sleep in the supportsRetry http request.

  • Add a fix for Internet Explorer versions which upload files with full filesystem paths as filenames.

3.8.0 (2009-05-23)

  • Move IHTTPException, IMethodNotAllowed, and MethodNotAllowed here from zope.app.http, fixing dependency cycles involving zope.app.http.
  • Move the DefaultViewName API here from zope.app.publisher.browser, making it accessible to other packages that need it.

3.7.0 (2009-05-13)

  • Move IView and IBrowserView interfaces into zope.browser.interfaces, leaving BBB imports.

3.6.4 (2009-04-26)

  • Add some BBB code to setDefaultSkin to allow IBrowserRequest’s to continue to work without configuring any special adapter for IDefaultSkin.
  • Move getDefaultSkin to the skinnable module next to the setDefaultSkin method, leaving a BBB import in place. Mark IDefaultBrowserLayer as a IBrowserSkinType in code instead of relying on the ZCML to be loaded.

3.6.3 (2009-03-18)

  • Mark HTTPRequest as IAttributeAnnotatable if zope.annotation is available, this was previously done by zope.app.i18n.
  • Register IHTTPRequest -> IUserPreferredCharsets adapter in ZCML configuration. This was also previously done by zope.app.i18n.

3.6.2 (2009-03-14)

  • Add an adapter from zope.security.interfaces.IPrincipal to zope.publisher.interfaces.logginginfo.ILoggingInfo. It was moved from zope.app.security as a part of refactoring process.

  • Add adapters from HTTP and FTP request to zope.authentication.ILoginPassword interface. They are moved from zope.app.security as a part of refactoring process. This change adds a dependency on the zope.authentication package, but it’s okay, since it’s a tiny contract definition-only package.

    See http://mail.zope.org/pipermail/zope-dev/2009-March/035325.html for reasoning.

3.6.1 (2009-03-09)

  • Fix: remove IBrowserRequest dependency in http implementation based on condition for setDefaultSkin. Use ISkinnable instead of IBrowserRequest.

3.6.0 (2009-03-08)

  • Clean-up: Move skin related code from zope.publisher.interfaces.browser and zope.publisher.browser to zope.publihser.interfaces and zope.publisher.skinnable and provide BBB imports. See skinnable.txt for more information.

  • Fix: ensure that we only apply skin interface in setDefaultSkin which also provide IBrowserSkinType. This will ensure that we find a skin if the applySkin method will lookup for a skin based on this type interface.

  • Fix: Make it possible to use adapters and not only interfaces as skins from the adapter registry. Right now the defaultSkin directive registers simple interfaces as skin adapters which will run into a TypeError if someone tries to adapter such a skin adapter. Probably we should change the defaultSkin directive and register real adapters instead of using the interfaces as fake adapters where we expect adapter factories.

  • Feature: allow use of applySkinof with different skin types using the optional skinType argument, which is by default set to IBrowserSkinType.

  • Feature: implement the default skin pattern within adapters. This allows us to register default skins for other requests then only IBrowserRequest using IDefaultSkin adapters.

    Note, ISkinnable and ISkinType and the skin implementation should be moved out of the browser request modules. Packages like z3c.jsonrpc do not depend on IBrowserRequest but they are skinnable.

  • Feature: add ISkinnable interface which allows us to implement the apply skin pattern not only for IBrowserRequest.

  • Fix: Don’t cause warnings on Python 2.6

  • Fix: Make IBrowserPage inherit IBrowserView.

  • Move IView and IDefaultViewName here from zope.component.interfaces. Stop inheriting from deprecated (for years) interfaces defined in zope.component.

  • Remove deprecated code.

  • Clean-up: Move zope.testing from extras to dependencies, per Zope Framework policy. Remove zope.app.testing as a dependency: tests run fine without it.

3.5.6 (2009-02-14)

  • Fix an untested code path that incorrectly attempted to construct a NotFound, adding a test.

3.5.5 (2009-02-04)

  • LP #322486: setStatus() now allows any int()-able status value.

3.5.4 (2008-09-22)

  • LP #98440: interfaces lost on retried request
  • LP #273296: dealing more nicely with malformed HTTP_ACCEPT_LANGUAGE headers within getPreferredLanguages().
  • LP #253362: dealing more nicely with malformed HTTP_ACCEPT_CHARSET headers within getPreferredCharsets().
  • LP #98284: Pass the size argument to readline, as the version of twisted used in zope.app.twisted supports it.
  • Fix the LP #98284 fix: do not pass size argument of None that causes cStringIO objects to barf with a TypeError.

3.5.3 (2008-06-20)

  • It turns out that some Web servers (Paste for example) do not send the EOF character after the data has been transmitted and the read() of the cached stream simply hangs if no expected content length has been specified.

3.5.2 (2008-04-06)

  • A previous fix to handle posting of non-form data broke handling of form data with extra information in the content type, as in:

    application/x-www-form-urlencoded; charset=UTF-8
    

3.5.1 (2008-03-23)

  • When posting non-form (and non-multipart) data, the request body was consumed and discarded. This makes it impossible to deal with other post types, like xml-rpc or json without resorting to overly complex “request factory” contortions.

  • https://bugs.launchpad.net/zope2/+bug/143873

    zope.publisher.http.HTTPCharsets was confused by the Zope 2 publisher, which gives misleading information about which headers it has.

3.5.0 (2008-03-02)

  • Added a PasteDeploy app_factory implementation. This should make it easier to integrate Zope 3 applications with PasteDeploy. It also makes it easier to control the publication used, giving far greater control over application policies (e.g. whether or not to use the ZODB).

3.4.2 (2007-12-07)

  • Made segmentation of URLs not strip (trailing) whitespace from path segments to allow URLs ending in %20 to be handled correctly. (#172742)

3.4.1 (2007-09-29)

No changes since 3.4.1b2.

3.4.1b2 (2007-08-02)

  • Add support for Python 2.5.
  • Fix a problem with request.get() when the object that’s to be retrieved is the request itself.

3.4.1b1 (2007-07-13)

No changes.

3.4.0b2 (2007-07-05)

  • LP #122054: HTTPInputStream understands both the CONTENT_LENGTH and HTTP_CONTENT_LENGTH environment variables. It is also now tolerant of empty strings and will treat those as if the variable were absent.

3.4.0b1 (2007-07-05)

  • Fix caching issue. The input stream never got cached in a temp file because of a wrong content-length header lookup. Added CONTENT_LENGTH header check in addition to the previous used HTTP_CONTENT_LENGTH. The HTTP_ prefix is sometimes added by some CGI proxies, but CONTENT_LENGTH is the right header info for the size.
  • LP #98413: HTTPResponse.handleException should set the content type

3.4.0a1 (2007-04-22)

Initial release as a separate project, corresponds to zope.publisher from Zope 3.4.0a1

Development

zope.publisher is hosted at GitHub:

Project URLs

Indices and tables