# HG changeset patch # User paulb # Date 1132165611 0 # Node ID eb9d8fab5631f5095e201e3e38ce818f4eb89c90 # Parent ab5e075411f7181f3b77457d521d6f6631f991fd [project @ 2005-11-16 18:26:51 by paulb] Added get_path_without_info, update_path and redirect methods. diff -r ab5e075411f7 -r eb9d8fab5631 WebStack/Generic.py --- a/WebStack/Generic.py Wed Nov 16 18:26:16 2005 +0000 +++ b/WebStack/Generic.py Wed Nov 16 18:26:51 2005 +0000 @@ -330,6 +330,22 @@ raise NotImplementedError, "get_path_info" + def get_path_without_info(self, encoding=None): + + """ + Returns the entire path from the request minus the query string and the + "path info" as a Unicode object containing genuine characters (as + opposed to "URL encoded" character values). + + If the optional 'encoding' is set, use that in preference to the default + encoding to convert the path into a form not containing "URL encoded" + character values. + """ + + entire_path = self.get_path_without_query(encoding) + path_info = self.get_path_info(encoding) + return entire_path[:-len(path_info)] + def get_query_string(self): """ @@ -611,6 +627,79 @@ else: return real_path_info[:i] + # Utility methods. + + def update_path(self, path, relative_path): + + """ + Transform the given 'path' using the specified 'relative_path'. For + example: + + trans.update_path("/parent/node", "other") -> "/parent/other" + trans.update_path("/parent/node/", "other") -> "/parent/node/other" + trans.update_path("/parent/node", "../other") -> "/other" + trans.update_path("/parent/node/", "../other") -> "/parent/other" + trans.update_path("/parent/node", "../../other") -> "/other" + trans.update_path("/parent/node/", "../../other") -> "/other" + + Where 'relative_path' begins with "/", the 'path' is reset to "/" and + the components of the 'relative_path' are then applied to that new path: + + trans.update_path("/parent/node", "/other") -> "/other" + + Where 'relative_path' ends with "/", the final "/" is added to the + result: + + trans.update_path("/parent/node", "other/") -> "/parent/other/" + + Where 'relative_path' is empty, the result is 'path' minus the last + component, unless it was an empty component: + + trans.update_path("/parent/node", "") -> "/parent/" + trans.update_path("/parent/node/", "") -> "/parent/node/" + """ + + rparts = relative_path.split("/") + + if relative_path.startswith("/"): + parts = [""] + del rparts[0] + elif relative_path == "": + parts = path.split("/") + parts[-1] = "" + del rparts[0] + else: + parts = path.split("/") + del parts[-1] + + for rpart in rparts: + if rpart == ".": + continue + elif rpart == "..": + if len(parts) > 1: + parts = parts[:-1] + else: + parts.append(rpart) + + return "/".join(parts) + + def redirect(self, path, code=302): + + """ + Send a redirect response to the client, providing the given 'path' as + the suggested location of a resource. The optional 'code' (set to 302 by + default) may be used to change the exact meaning of the response + according to the HTTP specifications. + + Note that 'path' should be a plain string suitable for header output. + Use the 'encode_path' method to convert Unicode objects into such + strings. + """ + + self.set_response_code(code) + self.set_header_value("Location", path) + raise EndOfResponse + class Resource: "A generic resource interface."