1.1 --- a/XSLForms/Resources.py Tue Oct 25 17:52:28 2005 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,312 +0,0 @@
1.4 -#!/usr/bin/env python
1.5 -
1.6 -"""
1.7 -Resources for use with WebStack.
1.8 -
1.9 -Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk>
1.10 -
1.11 -This library is free software; you can redistribute it and/or
1.12 -modify it under the terms of the GNU Lesser General Public
1.13 -License as published by the Free Software Foundation; either
1.14 -version 2.1 of the License, or (at your option) any later version.
1.15 -
1.16 -This library is distributed in the hope that it will be useful,
1.17 -but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.19 -Lesser General Public License for more details.
1.20 -
1.21 -You should have received a copy of the GNU Lesser General Public
1.22 -License along with this library; if not, write to the Free Software
1.23 -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.24 -"""
1.25 -
1.26 -import WebStack.Generic
1.27 -import XSLForms.Fields
1.28 -import XSLForms.Prepare
1.29 -import XSLForms.Output
1.30 -from XSLTools import XSLOutput
1.31 -import os
1.32 -
1.33 -class XSLFormsResource:
1.34 -
1.35 - """
1.36 - A generic XSLForms resource for use with WebStack.
1.37 -
1.38 - When overriding this class, define the following attributes appropriately:
1.39 -
1.40 - * template_resources - a dictionary mapping output identifiers to
1.41 - (template_filename, output_filename) tuples,
1.42 - indicating the template and stylesheet filenames
1.43 - to be employed
1.44 -
1.45 - * in_page_resources - a dictionary mapping fragment identifiers to
1.46 - (output_filename, node_identifier) tuples,
1.47 - indicating the stylesheet filename to be
1.48 - employed, along with the node identifier used in
1.49 - the original template and output documents to
1.50 - mark a region of those documents as the fragment
1.51 - to be updated upon "in-page" requests
1.52 -
1.53 - * init_resources - a dictionary mapping initialiser/input
1.54 - identifiers to (template_filename,
1.55 - input_filename) tuples, indicating the template
1.56 - and initialiser/input stylesheet filenames to be
1.57 - employed
1.58 -
1.59 - * transform_resources - a dictionary mapping transform identifiers to
1.60 - lists of stylesheet filenames for use with the
1.61 - transformation methods
1.62 -
1.63 - * document_resources - a dictionary mapping document identifiers to
1.64 - single filenames for use as source documents or
1.65 - as references with the transformation methods
1.66 -
1.67 - * resource_dir - the absolute path of the directory in which
1.68 - stylesheet resources are to reside
1.69 -
1.70 - All filenames shall be simple leafnames for files residing in the resource's
1.71 - special resource directory 'resource_dir'.
1.72 -
1.73 - The following attributes may also be specified:
1.74 -
1.75 - * path_encoding - the assumed encoding of characters in request
1.76 - paths
1.77 -
1.78 - * encoding - the assumed encoding of characters in request
1.79 - bodies
1.80 - """
1.81 -
1.82 - path_encoding = "utf-8"
1.83 - encoding = "utf-8"
1.84 - template_resources = {}
1.85 - in_page_resources = {}
1.86 - transform_resources = {}
1.87 - document_resources = {}
1.88 - resource_dir = None
1.89 -
1.90 - def clean_parameters(self, parameters):
1.91 -
1.92 - """
1.93 - Workaround stray zero value characters from Konqueror in XMLHttpRequest
1.94 - communications.
1.95 - """
1.96 -
1.97 - for name, values in parameters.items():
1.98 - new_values = []
1.99 - for value in values:
1.100 - if value.endswith("\x00"):
1.101 - new_values.append(value[:-1])
1.102 - else:
1.103 - new_values.append(value)
1.104 - parameters[name] = new_values
1.105 -
1.106 - def prepare_output(self, output_identifier):
1.107 -
1.108 - """
1.109 - Prepare the output stylesheets using the given 'output_identifier' to
1.110 - indicate which templates and stylesheets are to be employed in the
1.111 - production of output from the resource.
1.112 -
1.113 - The 'output_identifier' is used as a key to the 'template_resources'
1.114 - dictionary attribute.
1.115 -
1.116 - Return the full path to the output stylesheet for use with 'send_output'
1.117 - or 'get_result'.
1.118 - """
1.119 -
1.120 - template_filename, output_filename = self.template_resources[output_identifier]
1.121 - output_path = os.path.abspath(os.path.join(self.resource_dir, output_filename))
1.122 - template_path = os.path.abspath(os.path.join(self.resource_dir, template_filename))
1.123 - XSLForms.Prepare.ensure_stylesheet(template_path, output_path)
1.124 - return output_path
1.125 -
1.126 - def prepare_fragment(self, output_identifier, fragment_identifier):
1.127 -
1.128 - """
1.129 - Prepare the output stylesheets for the given 'output_identifier' and
1.130 - 'fragment_identifier', indicating which templates and stylesheets are to
1.131 - be employed in the production of output from the resource.
1.132 -
1.133 - The 'output_identifier' is used as a key to the 'template_resources'
1.134 - dictionary attribute; the 'fragment_identifier' is used as a key to the
1.135 - 'in_page_resources' dictionary attribute.
1.136 -
1.137 - Return the full path to the output stylesheet for use with 'send_output'
1.138 - or 'get_result'.
1.139 - """
1.140 -
1.141 - output_path = self.prepare_output(output_identifier)
1.142 - fragment_filename, node_identifier = self.in_page_resources[fragment_identifier]
1.143 - fragment_path = os.path.abspath(os.path.join(self.resource_dir, fragment_filename))
1.144 - XSLForms.Prepare.ensure_stylesheet_fragment(output_path, fragment_path, node_identifier)
1.145 - return fragment_path
1.146 -
1.147 - def prepare_parameters(self, parameters):
1.148 -
1.149 - """
1.150 - Prepare the stylesheet parameters from the given request 'parameters'.
1.151 - This is most useful when preparing fragments for in-page update output.
1.152 - """
1.153 -
1.154 - element_path = parameters.get("element-path", [""])[0]
1.155 - if element_path:
1.156 - return {"element-path" : element_path}
1.157 - else:
1.158 - return {}
1.159 -
1.160 - def send_output(self, trans, stylesheet_filenames, document, stylesheet_parameters=None,
1.161 - stylesheet_expressions=None, references=None):
1.162 -
1.163 - """
1.164 - Send the output from the resource to the user employing the transaction
1.165 - 'trans', stylesheets having the given 'stylesheet_filenames', the
1.166 - 'document' upon which the output will be based, the optional parameters
1.167 - as defined in the 'stylesheet_parameters' dictionary, the optional
1.168 - expressions are defined in the 'stylesheet_expressions' dictionary, and
1.169 - the optional 'references' to external documents.
1.170 - """
1.171 -
1.172 - # Sanity check for the filenames list.
1.173 -
1.174 - if isinstance(stylesheet_filenames, str) or isinstance(stylesheet_filenames, unicode):
1.175 - raise ValueError, stylesheet_filenames
1.176 -
1.177 - proc = XSLOutput.Processor(stylesheet_filenames, parameters=stylesheet_parameters,
1.178 - expressions=stylesheet_expressions, references=references)
1.179 - proc.send_output(trans.get_response_stream(), trans.get_response_stream_encoding(),
1.180 - document)
1.181 -
1.182 - def get_result(self, stylesheet_filenames, document, stylesheet_parameters=None,
1.183 - stylesheet_expressions=None, references=None):
1.184 -
1.185 - """
1.186 - Get the result of applying a transformation using stylesheets with the
1.187 - given 'stylesheet_filenames', the 'document' upon which the result will
1.188 - be based, the optional parameters as defined in the
1.189 - 'stylesheet_parameters' dictionary, the optional parameters as defined
1.190 - in the 'stylesheet_parameters' dictionaryand the optional 'references'
1.191 - to external documents.
1.192 - """
1.193 -
1.194 - # Sanity check for the filenames list.
1.195 -
1.196 - if isinstance(stylesheet_filenames, str) or isinstance(stylesheet_filenames, unicode):
1.197 - raise ValueError, stylesheet_filenames
1.198 -
1.199 - proc = XSLOutput.Processor(stylesheet_filenames, parameters=stylesheet_parameters,
1.200 - expressions=stylesheet_expressions, references=references)
1.201 - return proc.get_result(document)
1.202 -
1.203 - def prepare_initialiser(self, input_identifier):
1.204 -
1.205 - """
1.206 - Prepare an initialiser/input transformation using the given
1.207 - 'input_identifier'.
1.208 -
1.209 - Return the full path to the input stylesheet for use with 'send_output'
1.210 - or 'get_result'.
1.211 - """
1.212 -
1.213 - template_filename, input_filename = self.init_resources[input_identifier]
1.214 - input_path = os.path.abspath(os.path.join(self.resource_dir, input_filename))
1.215 - template_path = os.path.abspath(os.path.join(self.resource_dir, template_filename))
1.216 - XSLForms.Prepare.ensure_input_stylesheet(template_path, input_path)
1.217 - return input_path
1.218 -
1.219 - def prepare_transform(self, transform_identifier):
1.220 -
1.221 - """
1.222 - Prepare a transformation using the given 'transform_identifier'.
1.223 -
1.224 - Return a list of full paths to the output stylesheets for use with
1.225 - 'send_output' or 'get_result'.
1.226 - """
1.227 -
1.228 - filenames = self.transform_resources[transform_identifier]
1.229 - paths = []
1.230 - for filename in filenames:
1.231 - paths.append(os.path.abspath(os.path.join(self.resource_dir, filename)))
1.232 - return paths
1.233 -
1.234 - def prepare_document(self, document_identifier):
1.235 -
1.236 - """
1.237 - Prepare a document using the given 'document_identifier'.
1.238 -
1.239 - Return the full path of the document for use either as the source
1.240 - document or as a reference with 'send_output' or 'get_result'.
1.241 - """
1.242 -
1.243 - filename = self.document_resources[document_identifier]
1.244 - return os.path.abspath(os.path.join(self.resource_dir, filename))
1.245 -
1.246 - def get_in_page_resource(self, trans):
1.247 -
1.248 - """
1.249 - Return the in-page resource being referred to in the given transaction
1.250 - 'trans'.
1.251 - """
1.252 -
1.253 - return trans.get_path_info(self.path_encoding).split("/")[-1]
1.254 -
1.255 - def respond(self, trans):
1.256 -
1.257 - """
1.258 - Respond to the request described by the given transaction 'trans'.
1.259 - """
1.260 -
1.261 - # Only obtain field information according to the stated method.
1.262 -
1.263 - method = trans.get_request_method()
1.264 - in_page_resource = self.get_in_page_resource(trans)
1.265 -
1.266 - # Handle typical request methods, processing request information.
1.267 -
1.268 - if method == "GET":
1.269 -
1.270 - # Get the fields from the request path (URL).
1.271 - # NOTE: The encoding is actually redundant since WebStack produces
1.272 - # NOTE: Unicode values.
1.273 -
1.274 - form = XSLForms.Fields.Form(encoding=self.path_encoding, values_are_lists=1)
1.275 - parameters = trans.get_fields_from_path()
1.276 - form.set_parameters(parameters)
1.277 -
1.278 - elif method == "POST":
1.279 -
1.280 - # Get the fields from the request body.
1.281 - # NOTE: The encoding is actually redundant since WebStack produces
1.282 - # NOTE: Unicode values.
1.283 -
1.284 - form = XSLForms.Fields.Form(encoding=self.encoding, values_are_lists=1)
1.285 - parameters = trans.get_fields_from_body(self.encoding)
1.286 -
1.287 - # NOTE: Konqueror workaround.
1.288 - self.clean_parameters(parameters)
1.289 -
1.290 - form.set_parameters(parameters)
1.291 -
1.292 - else:
1.293 -
1.294 - # Initialise empty containers.
1.295 -
1.296 - parameters = {}
1.297 - documents = {}
1.298 -
1.299 - # Call an overridden method with the processed request information.
1.300 -
1.301 - self.respond_to_form(trans, form)
1.302 -
1.303 - def respond_to_form(self, trans, form):
1.304 -
1.305 - """
1.306 - Respond to the request described by the given transaction 'trans', using
1.307 - the given 'form' object to conveniently retrieve field (request
1.308 - parameter) information and structured form information (as DOM-style XML
1.309 - documents).
1.310 - """
1.311 -
1.312 - trans.set_response_code(500)
1.313 - raise WebStack.Generic.EndOfResponse
1.314 -
1.315 -# vim: tabstop=4 expandtab shiftwidth=4