Question

I want to learn Trac and Bloodhound source code. I have a background in web programming and some frameworks especially Django. But Trac and Bloodhound are quite different from the traditional web applications build with frameworks.

How does the URL dispatcher work for these projects? How does source code browser work?

Was it helpful?

Solution

In Django you have the URL dispatcher, which matches requests to certain patterns and then passes a HttpRequest as the first argument to the associated view function(see the django docs).

In Trac you have a number of interfaces which match requests in a similar way. The simplest example is the IRequestHandler which has two methods, match_request() and process_request(). You can think of the the match_request() as the URL pattern matching in Django, and the process_request() as the subsequent view which is invoked if the associated match_request() returns True.

For an example of this from the Trac sourcecode, see how trac matches requests to view tickets inside trac/ticket/web_ui.py

# IRequestHandler methods

def match_request(self, req):
    if req.path_info == "/newticket":
        return True
    match = re.match(r'/ticket/([0-9]+)$', req.path_info)
    if match:
        req.args['id'] = match.group(1)
        return True

def process_request(self, req):
    if 'id' in req.args:
        if req.path_info == '/newticket':
            raise TracError(_("id can't be set for a new ticket request."))
        return self._process_ticket_request(req)

    return self._process_newticket_request(req)

So if you wanted to write a plugin which matches web requests, you would have to implement an extension point for the IRequestHandler interface. The convention is to put web related stuff in a web_ui.py file, which would have to define a new Component. I recommend you read this Trac dev page for another example.

In the diagram RjOllos linked to, you can actually see that there are a number of interface at work for each request. For example you can change the handler inside a pre_process_request() or add data after a initial match_request() with a post_process_request(). These are methods from the IRequestFilter inteface.

For the full list of interfaces which can be invoked when handing web requests, see trac.web.api.

One final subtlety to note, is that in Django you have a request object, but in Trac you have a req object. They contain similar method and attributes, describing the meta-data around each request.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top