Chris McDonough wrote: ... >> On the other hand, I do understand some motivation for this for >> creating eclectic URL layouts. But I wonder if there's a better way? >> In particular, make sure that writing routing code isn't hard, so that >> custom code for different site layouts is easy. There are at least >> two modest methods in WebOb for this -- req.path_info_peek() and >> req.path_info_pop(), which both get the next segment of the URL. >> Along with req.urlvars (and req.urlargs) there's a way to save the >> captured data without having to instantly inspect the model (unless >> you want to inspect the model). And domain names can be just as valid >> a thing to parse, and don't really fit any traversal pattern. > > That blew my stack, sorry.
Well, maybe an example where graph traversal seems easier is something like a filesystem (or ZODB filesystemish system) with verbs at the end. E.g., /path/to/file.txt/view, /path/to/file.txt/edit, etc. You could do something like: def route_fs(req): path, verb = req.path_info.rsplit('/', 1)[-1] if not verb: verb = 'index' obj = File(path) return getattr(obj, verb)(req) Though I think even better would be something like: def route_fs(req): fs = Filesystem() while 1: segment = req.path_info_peek() if segment is None: return fs.view() elif segment == '': # trailing / return fs.index() else: try: fs = fs[segment] except KeyError: return fs(req) else: req.path_info_pop() And maybe that's more complicated than simple traversal, I don't know. One thing I was thinking about as a general idea was to look for .wsgi_application on objects, and use that. Then traversable objects might look like: class Filesystem(object): def __init__(self, path): self.path = path wsgi_application = TraverseGetitem('index') @wsgiapp def index(req): ... return resp def __getitem__(self, segment): return self.__class__(os.path.join(self.path, segment)) class TraverseGetitem(object): def __init__(self, index_meth=None): self.index_meth = index_meth def __get__(self, obj, type=None): if obj is None: return self def app(environ, start_response): req = Request(environ) next = req.path_info_peek() if next: try: next = obj[next] except KeyError: next = None else: req.path_info_pop() else: next = None if next is None: next = self.index_meth if isinstance(next, basestring): next = getattr(obj, next) if hasattr(next, '__get__'): next = next.__get__(obj) if hasattr(next, 'wsgi_application'): next = next.wsgi_application return next(environ, start_response) return app >> So I'd be interested in use cases people have where Routes alone isn't >> enough. I'm sure these exist (I could come up with a few), but I'm >> also pretty sure there's other solutions than object publishing. >> >>> - Its equivalent of the publisher doesn't attempt to traverse into >>> *code* stored in the object graph. All code is on the filesystem. >>> The only thing in the object graph is "model" data. >> >> How do you deal with distinguishing between model instantiation data, >> and traversal of the models themselves? E.g., /archive/2008/06/ -- >> /archive probably points to an Archive class or an instance >> (singleton?) of ArchiveManager or something. /2008 and /06 probably >> translate to datetime(2008, 6) or something along those lines, which >> provide the arguments to instantiate an Archive object, and then you >> call some default method like index or __call__. > > It's simpler than that. We are always traversing model instances. We > just call __geitem__ the whole way through the model graph until we > either exhaust the path or find an item that doesnt have a __getitem__ > or whose __getitem__ raises a KeyError. The "next" name becomes the > view name. Any leftover path elements become a "subpath". It really is > just block and tackle graph traversal of data, there's nothing tricky > going on. The views are code, yes? How are view names mapped to code? Presumably you can have a URL ".../view" where the actual function called depends on the type of object you traversed to. The examples don't make this clear. -- Ian Bicking : [EMAIL PROTECTED] : http://blog.ianbicking.org _______________________________________________ Repoze-dev mailing list Repoze-dev@lists.repoze.org http://lists.repoze.org/listinfo/repoze-dev