1.1 --- a/WebStack/Generic.py Wed Nov 16 18:26:16 2005 +0000
1.2 +++ b/WebStack/Generic.py Wed Nov 16 18:26:51 2005 +0000
1.3 @@ -330,6 +330,22 @@
1.4
1.5 raise NotImplementedError, "get_path_info"
1.6
1.7 + def get_path_without_info(self, encoding=None):
1.8 +
1.9 + """
1.10 + Returns the entire path from the request minus the query string and the
1.11 + "path info" as a Unicode object containing genuine characters (as
1.12 + opposed to "URL encoded" character values).
1.13 +
1.14 + If the optional 'encoding' is set, use that in preference to the default
1.15 + encoding to convert the path into a form not containing "URL encoded"
1.16 + character values.
1.17 + """
1.18 +
1.19 + entire_path = self.get_path_without_query(encoding)
1.20 + path_info = self.get_path_info(encoding)
1.21 + return entire_path[:-len(path_info)]
1.22 +
1.23 def get_query_string(self):
1.24
1.25 """
1.26 @@ -611,6 +627,79 @@
1.27 else:
1.28 return real_path_info[:i]
1.29
1.30 + # Utility methods.
1.31 +
1.32 + def update_path(self, path, relative_path):
1.33 +
1.34 + """
1.35 + Transform the given 'path' using the specified 'relative_path'. For
1.36 + example:
1.37 +
1.38 + trans.update_path("/parent/node", "other") -> "/parent/other"
1.39 + trans.update_path("/parent/node/", "other") -> "/parent/node/other"
1.40 + trans.update_path("/parent/node", "../other") -> "/other"
1.41 + trans.update_path("/parent/node/", "../other") -> "/parent/other"
1.42 + trans.update_path("/parent/node", "../../other") -> "/other"
1.43 + trans.update_path("/parent/node/", "../../other") -> "/other"
1.44 +
1.45 + Where 'relative_path' begins with "/", the 'path' is reset to "/" and
1.46 + the components of the 'relative_path' are then applied to that new path:
1.47 +
1.48 + trans.update_path("/parent/node", "/other") -> "/other"
1.49 +
1.50 + Where 'relative_path' ends with "/", the final "/" is added to the
1.51 + result:
1.52 +
1.53 + trans.update_path("/parent/node", "other/") -> "/parent/other/"
1.54 +
1.55 + Where 'relative_path' is empty, the result is 'path' minus the last
1.56 + component, unless it was an empty component:
1.57 +
1.58 + trans.update_path("/parent/node", "") -> "/parent/"
1.59 + trans.update_path("/parent/node/", "") -> "/parent/node/"
1.60 + """
1.61 +
1.62 + rparts = relative_path.split("/")
1.63 +
1.64 + if relative_path.startswith("/"):
1.65 + parts = [""]
1.66 + del rparts[0]
1.67 + elif relative_path == "":
1.68 + parts = path.split("/")
1.69 + parts[-1] = ""
1.70 + del rparts[0]
1.71 + else:
1.72 + parts = path.split("/")
1.73 + del parts[-1]
1.74 +
1.75 + for rpart in rparts:
1.76 + if rpart == ".":
1.77 + continue
1.78 + elif rpart == "..":
1.79 + if len(parts) > 1:
1.80 + parts = parts[:-1]
1.81 + else:
1.82 + parts.append(rpart)
1.83 +
1.84 + return "/".join(parts)
1.85 +
1.86 + def redirect(self, path, code=302):
1.87 +
1.88 + """
1.89 + Send a redirect response to the client, providing the given 'path' as
1.90 + the suggested location of a resource. The optional 'code' (set to 302 by
1.91 + default) may be used to change the exact meaning of the response
1.92 + according to the HTTP specifications.
1.93 +
1.94 + Note that 'path' should be a plain string suitable for header output.
1.95 + Use the 'encode_path' method to convert Unicode objects into such
1.96 + strings.
1.97 + """
1.98 +
1.99 + self.set_response_code(code)
1.100 + self.set_header_value("Location", path)
1.101 + raise EndOfResponse
1.102 +
1.103 class Resource:
1.104
1.105 "A generic resource interface."