3

I have a typical WSGI application like so:

app = webapp2.WSGIApplication([
    ('/site/path/one',     'package.module.ClassOne'),
    ('/site/path/two',     'package.module.ClassTwo'),
    ('/site/path/three',   'package.module.ClassThree'),
])

I would like to be able to retrieve the list of routes later in my application, say for example, in ClassOne:

class ClassOne(webapp2.RequestHandler):
    def get(self):
        print ''' list of routes (e.g. '/site/path/one', '/site/path/two', etc.) '''
Trevor
  • 13,085
  • 13
  • 76
  • 99

2 Answers2

4

It looks like WSGIApplication has a router property

Router has

def __repr__(self):
        routes = self.match_routes + [v for k, v in \
            self.build_routes.iteritems() if v not in self.match_routes]

        return '<Router(%r)>' % routes

Your wsgiApplication instance is a property of your webapp2.RequestHandler

so I think request.app.router

So hopefully there is a more straighforward way but if not the above should worK?

Webapp2 had really great searchable source code available at http://webapp2.readthedocs.io/en/latest/

Ahmed
  • 2,825
  • 1
  • 25
  • 39
dm03514
  • 54,664
  • 18
  • 108
  • 145
2

I just wrote this function to extract useful information about all the URI routes in a webapp2 app router, even including nested routes created using webapp2_extras.routes.PathPrefixRoute:

def get_route_list(router):
  """
  Get a nested list of all the routes in the app's router
  """
  def get_routes(r):
    """get list of routes from either a router object or a PathPrefixRoute object,
    because they were too stupid to give them the same interface.
    """
    if hasattr(r, 'match_routes'):
      return r.match_routes
    else:
      return list(r.get_routes())

  def get_doc(handler, method):
    """get the doc from the method if there is one,
    otherwise get the doc from the handler class."""
    if method:
      return getattr(handler,method).__doc__
    else:
      return handler.__doc__

  routes=[]
  for i in get_routes(router):
    if hasattr(i, 'handler'):
      # I think this means it's a route, not a path prefix
      cur_template = i.template
      cur_handler  = i.handler
      cur_method   = i.handler_method
      cur_doc      = get_doc(cur_handler,cur_method)
      r={'template':cur_template, 'handler':cur_handler, 'method':cur_method, 'doc':cur_doc}
    else:
      r=get_route_list(i)
    routes.append(r)
  return routes

This returns a nested list of lists, but if you just want a flat list (as I actually do) you can flatten it with the function here: Flattening a shallow list in python Note: you probably need to edit that flattening a shallow list function to also avoid iterating dictionaries. Namely, add here: "...and not isinstance(el, basestring) and not isinstance(el, dict)"

This should be obvious from looking at the code, but the way I wrote this, for each route it gives you the doc string from the custom method if there is one; otherwise, it gives you the doc string for the handler class. The idea is that this should be useful for the OP's purpose, which is also what I wanted to do.

Community
  • 1
  • 1
David M. Perlman
  • 4,851
  • 2
  • 16
  • 12