1 #!/usr/bin/env python 2 3 """ 4 Generic Web framework interfaces. 5 The WebStack architecture consists of the following layers: 6 7 * Framework - The underlying Web framework implementation. 8 * Adapter - Code operating under the particular framework which creates 9 WebStack abstractions and issues them to the application. 10 * Resources - Units of functionality operating within the hosted Web 11 application. 12 13 Resources can act as both content producers within an application and as request 14 dispatchers to other resources; in the latter role, they may be referred to as 15 directors. 16 """ 17 18 class ContentType: 19 20 "A container for content type information." 21 22 def __init__(self, content_type, charset=None): 23 self.content_type = content_type 24 self.charset = charset 25 26 class Transaction: 27 28 """ 29 A generic transaction interface containing framework-specific methods to be 30 overridden. 31 """ 32 33 # Utility methods. 34 35 def parse_content_type(self, content_type_field): 36 37 """ 38 Determine the content type and charset from the supplied 39 'content_type_field' string. 40 """ 41 42 if content_type_field is None: 43 return ContentType(None, "iso-8859-1") 44 45 t = content_type_field.split("; charset=") 46 if len(t) == 1: 47 return ContentType(t[0], "iso-8859-1") 48 else: 49 return ContentType(t[0], t[1]) 50 51 def format_content_type(self, content_type): 52 53 """ 54 Format the given 'content_type' object, producing a string suitable for 55 the response header field. 56 """ 57 58 if content_type.charset: 59 field = "%s; charset=%s" % (content_type.content_type, content_type.charset) 60 else: 61 field = content_type.content_type 62 63 # Make sure that only ASCII is used in the header. 64 65 return field.encode("US-ASCII") 66 67 def parse_content_preferences(self, accept_preference): 68 69 """ 70 Returns the preferences as requested by the user agent. The preferences are 71 returned as a list of codes in the same order as they appeared in the 72 appropriate environment variable. In other words, the explicit weighting 73 criteria are ignored. 74 75 As the 'accept_preference' parameter, values for language and charset 76 preferences are appropriate. 77 """ 78 79 accept_defs = accept_preference.split(",") 80 accept_prefs = [] 81 for accept_def in accept_defs: 82 t = accept_def.split(";") 83 if len(t) >= 1: 84 accept_prefs.append(t[0].strip()) 85 return accept_prefs 86 87 # Request-related methods. 88 89 def get_request_stream(self): 90 91 """ 92 A framework-specific method which returns the request stream for 93 the transaction. 94 """ 95 96 raise NotImplementedError, "get_request_stream" 97 98 def get_request_method(self): 99 100 """ 101 A framework-specific method which gets the request method. 102 """ 103 104 raise NotImplementedError, "get_request_method" 105 106 def get_headers(self): 107 108 """ 109 A framework-specific method which returns the request headers. 110 NOTE: Experimental, since framework support varies somewhat. 111 """ 112 113 raise NotImplementedError, "get_headers" 114 115 def get_content_type(self): 116 117 """ 118 A framework-specific method which gets the content type specified on the 119 request, along with the charset employed. 120 """ 121 122 raise NotImplementedError, "get_content_type" 123 124 def get_content_charsets(self): 125 126 """ 127 Returns the character set preferences. 128 """ 129 130 raise NotImplementedError, "get_content_charsets" 131 132 def get_content_languages(self): 133 134 """ 135 A framework-specific method which extracts language information from 136 the transaction. 137 """ 138 139 raise NotImplementedError, "get_content_languages" 140 141 def get_path(self): 142 143 """ 144 A framework-specific method which gets the entire path from the request. 145 """ 146 147 raise NotImplementedError, "get_path" 148 149 def get_path_info(self): 150 151 """ 152 A framework-specific method which gets the "path info" (the part of the 153 URL after the resource name handling the current request) from the 154 request. 155 """ 156 157 raise NotImplementedError, "get_path_info" 158 159 def get_fields(self): 160 161 """ 162 A framework-specific method which extracts the form fields from the 163 transaction. 164 """ 165 166 raise NotImplementedError, "get_fields" 167 168 def get_agent_information(self): 169 170 """ 171 A framework-specific method which extracts agent information from 172 the transaction. 173 """ 174 175 raise NotImplementedError, "get_agent_information" 176 177 # Response-related methods. 178 179 def get_response_stream(self): 180 181 """ 182 A framework-specific method which returns the response stream for 183 the transaction. 184 """ 185 186 raise NotImplementedError, "get_response_stream" 187 188 def set_content_type(self, content_type): 189 190 """ 191 A framework-specific method which sets the 'content_type' for the 192 response. 193 """ 194 195 raise NotImplementedError, "set_content_type" 196 197 class Resource: 198 199 "A generic resource interface." 200 201 def respond(self, trans): 202 203 """ 204 An application-specific method which performs activities on the basis of 205 the transaction object 'trans'. 206 """ 207 208 raise NotImplementedError, "respond" 209 210 # vim: tabstop=4 expandtab shiftwidth=4