-
Notifications
You must be signed in to change notification settings - Fork 0
/
publish.py
81 lines (62 loc) · 2.25 KB
/
publish.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# -*- coding: utf-8 -*-
import crom
import dawnlight
from urllib.parse import unquote
from cromlech.browser import IRequest, IResponse
from cromlech.browser import IPublisher, IView, IResponseFactory
from zope.location import ILocation, LocationProxy, locate
from .lookup import ModelLookup, ViewLookup
from .utils import safeguard
shortcuts = {
'@@': dawnlight.VIEW,
}
base_model_lookup = ModelLookup()
base_view_lookup = ViewLookup()
class PublicationError(Exception):
pass
@crom.implements(IPublisher)
class DawnlightPublisher(object):
"""A publisher using model and view lookup components.
"""
def __init__(self,
model_lookup=base_model_lookup,
view_lookup=base_view_lookup):
self.model_lookup = model_lookup
self.view_lookup = view_lookup
def base_path(self, request):
path = unquote(request.path)
script_name = request.script_name
if path.startswith(script_name):
return path[len(script_name):]
return path
@safeguard
def publish(self, request, root, handle_errors):
path = self.base_path(request)
stack = dawnlight.parse_path(path, shortcuts)
model, crumbs = self.model_lookup(request, root, stack)
if IResponse.providedBy(model):
# The found object can be returned safely.
return model
if IResponseFactory.providedBy(model):
return model()
# The model needs an renderer
component = self.view_lookup(request, model, crumbs)
if component is None:
raise PublicationError('%r can not be rendered.' % model)
# This renderer needs to be resolved into an IResponse
if not IResponse.providedBy(component):
factory = IResponseFactory(component)
return factory()
return component
@crom.adapter
@crom.sources(IRequest, Exception)
@crom.target(IResponseFactory)
def exception_view(request, exception):
view = IView(exception, request)
if view is not None:
# Make sure it's properly located.
if not ILocation.providedBy(view):
view = LocationProxy(view)
locate(view, parent=exception, name='exception')
return IResponseFactory(view)
return None