1
2 """This module contains everything needed to setup an Oort-based web
3 application. It also imports relevant parts from ``oort.display``.
4 """
5
6 import urllib
7 import logging
8 from pkg_resources import EntryPoint
9 from rdflib import URIRef
10 from paste.wsgiwrappers import WSGIRequest, WSGIResponse
11 from paste.httpexceptions import HTTPTemporaryRedirect
12 from oort.display import DisplayBase, Display, SubTypeAwareDisplay
13 from oort.display import AspectBase, Aspect, TpltAspect, JsonAspect, RdfAspect
14 from oort.rdfview import RdfQuery
15 from oort.util.code import SlotStruct, contract, autosuper
16 __metaclass__ = autosuper
17
18
19
20
21
22
23
39
40
42 """Base class - not for direct usage."""
43 __metaclass__ = resource_viewer_meta
44
45 @classmethod
46 - def app_factory(cls, global_conf=None,
47 graph_factory=None, **cfg):
48 """Factory method compatible with the app_factory feature of Paste Deploy."""
49 mk_graph = EntryPoint.parse("x=%s" % graph_factory).load(False)
50 graph = mk_graph()
51 return cls(graph, cfg)
52
53 VARIANT_SEP = '-'
54 RESOURCE_QUERY_KEY = 'resource'
55
56
57 langOrder = ()
58
65
66 - def __call__(self, environ, start_response):
67 req = WSGIRequest(environ)
68
69 self._viewPathTemplate = req.script_name + '/%s/%s/'
70 args = req.path_info.split('/')
71 try:
72 args.pop(0)
73 lang = args.pop(0)
74 displayArg = args.pop(0)
75 except IndexError:
76 lang, displayArg = None, None
77 if not displayArg:
78 return self._default_redirect(lang, environ, start_response)
79
80 uri = req.GET.get(self.RESOURCE_QUERY_KEY) or self.resource_from(args)
81
82 get_result, contentType = self.prepared_display(
83 URIRef(uri), lang, displayArg, req)
84
85 headerMap = {}
86 if contentType:
87 headerMap['Content-Type'] = contentType
88
89 start_response('200 OK', headerMap.items())
90 return get_result(self.graph)
91
96
97 @contract.template_method
99 raise NotImplementedError
100
101 @contract.template_method
103 raise NotImplementedError
104
105 - def app_url_for(self, lang, displayArg, resource=None, fallback=True):
118
120 args = displayArg.split(self.VARIANT_SEP, 1)
121 name, variantArg = args[0], len(args) > 1 and args[1]
122 display = self.displays[name]
123 current = Current(resource, lang)
124 appUtil = AppUtil(current, displayArg, self, req)
125
126 self._logger.debug("Prepared display with: %s %s %s"
127 % (current, appUtil, display ))
128
129
130 def get_result(graph):
131 return display.get_result_generator(graph, appUtil, variantArg)
132
133 return get_result, display.contentType
134
135
136 LOG_LEVEL_NAMES = 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
137
146
147
149 """Representation of the current *resource* request."""
150 __slots__ = 'resource', 'lang'
151
153 """"An instance of this class is provided to the templates under the name
154 'app'. It provides a controlled interface to the application and the
155 current state (request)."""
156
157 __slots__ = 'current', '_displayArg', '_viewer', '_req'
158
162
163 - def link(self, resource=None, lang=None, display=None, fallback=True, displayArg=None):
164 """Returns an URL within the current app. The following arguments
165 can be given (all defaults to current unless provided):
166
167 resource
168 A target URI or an instance of an RdfQuery.
169
170 lang
171 The language to use.
172
173 display
174 The display name to use.
175
176 fallback
177 Revert to a GET for the resource if no app url can be made.
178 Defaults to True.
179 """
180 if resource:
181 if isinstance(resource, RdfQuery):
182 resource = resource._subject
183 else: resource = self.current.resource
184 lang = lang or self.current.lang
185 displayArg = display or displayArg or self._displayArg
186 return self._viewer.app_url_for(lang, displayArg, resource, fallback)
187
189 return self.link(fallback=False)
190
191 @property
193 """Returns the base URL of this web app."""
194 return self._req.script_name
195
196
198 """Use for simple apps where all URIs in the graph share the same base URI
199 (set ``resourceBase`` to that)."""
200 resourceBase =None
201 trailSep='/'
202
206
208 return self._uriBase % self.trailSep.join(pathArgs)
209
216
217
219 """Use for full-fledged apps where many different base URIs will be
220 "mounted" at different named bases (done with the dictionary
221 ``resourceBases``)."""""
222 resourceBases = {}
223 defaultResource = ''
224
225
226
237
247