href.py :  » Project-Management » Trac » Trac-0.11.7 » trac » web » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Project Management » Trac 
Trac » Trac 0.11.7 » trac » web » href.py
# -*- coding: utf-8 -*-
#
# Copyright (C) 2003-2009 Edgewall Software
# Copyright (C) 2003-2004 Jonas Borgstrm <jonas@edgewall.com>
# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.org/wiki/TracLicense.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/log/.
#
# Author: Jonas Borgstrm <jonas@edgewall.com>
#         Christopher Lenz <cmlenz@gmx.de>

from urllib import quote,urlencode
from trac.util.text import unicode_quote,unicode_urlencode


class Href(object):
    """Implements a callable that constructs URLs with the given base. The
    function can be called with any number of positional and keyword
    arguments which than are used to assemble the URL.

    Positional arguments are appended as individual segments to
    the path of the URL:

    >>> href = Href('/trac')
    >>> href('ticket', 540)
    '/trac/ticket/540'
    >>> href('ticket', 540, 'attachment', 'bugfix.patch')
    '/trac/ticket/540/attachment/bugfix.patch'
    >>> href('ticket', '540/attachment/bugfix.patch')
    '/trac/ticket/540/attachment/bugfix.patch'

    If a positional parameter evaluates to None, it will be skipped:

    >>> href('ticket', 540, 'attachment', None)
    '/trac/ticket/540/attachment'

    The first path segment can also be specified by calling an attribute
    of the instance, as follows:

    >>> href.ticket(540)
    '/trac/ticket/540'
    >>> href.changeset(42, format='diff')
    '/trac/changeset/42?format=diff'

    Simply calling the Href object with no arguments will return the base URL:

    >>> href()
    '/trac'

    Keyword arguments are added to the query string, unless the value is None:

    >>> href = Href('/trac')
    >>> href('timeline', format='rss')
    '/trac/timeline?format=rss'
    >>> href('timeline', format=None)
    '/trac/timeline'
    >>> href('search', q='foo bar')
    '/trac/search?q=foo+bar'

    Multiple values for one parameter are specified using a sequence (a list or
    tuple) for the parameter:

    >>> href('timeline', show=['ticket', 'wiki', 'changeset'])
    '/trac/timeline?show=ticket&show=wiki&show=changeset'

    Alternatively, query string parameters can be added by passing a dict or
    list as last positional argument:

    >>> href('timeline', {'from': '02/24/05', 'daysback': 30})
    '/trac/timeline?daysback=30&from=02%2F24%2F05'

    The usual way of quoting arguments that would otherwise be interpreted
    as Python keywords is supported too:

    >>> href('timeline', from_='02/24/05', daysback=30)
    '/trac/timeline?from=02%2F24%2F05&daysback=30'

    If the order of query string parameters should be preserved, you may also
    pass a sequence of (name, value) tuples as last positional argument:

    >>> href('query', (('group', 'component'), ('groupdesc', 1)))
    '/trac/query?group=component&groupdesc=1'

    >>> params = []
    >>> params.append(('group', 'component'))
    >>> params.append(('groupdesc', 1))
    >>> href('query', params)
    '/trac/query?group=component&groupdesc=1'

    By specifying an absolute base, the function returned will also generate
    absolute URLs:

    >>> href = Href('http://trac.edgewall.org')
    >>> href('ticket', 540)
    'http://trac.edgewall.org/ticket/540'

    >>> href = Href('https://trac.edgewall.org')
    >>> href('ticket', 540)
    'https://trac.edgewall.org/ticket/540'

    In common usage, it may improve readability to use the function-calling
    ability for the first component of the URL as mentioned earlier:

    >>> href = Href('/trac')
    >>> href.ticket(540)
    '/trac/ticket/540'
    >>> href.browser('/trunk/README.txt', format='txt')
    '/trac/browser/trunk/README.txt?format=txt'
    """

    def __init__(self, base):
        self.base = base.rstrip('/')
        self._derived = {}

    def __call__(self, *args, **kw):
        href = self.base
        params = []

        def add_param(name, value):
            if type(value) in (list, tuple):
                for i in [i for i in value if i is not None]:
                    params.append((name, i))
            elif value is not None:
                params.append((name, value))

        if args:
            lastp = args[-1]
            if lastp and type(lastp) is dict:
                for k, v in lastp.items():
                    add_param(k, v)
                args = args[:-1]
            elif lastp and type(lastp) in (list, tuple):
                for k, v in lastp:
                    add_param(k, v)
                args = args[:-1]

        # build the path
        path = '/'.join([unicode_quote(unicode(arg).strip('/')) for arg in args
                         if arg is not None])
        if path:
            href += '/' + path

        # assemble the query string
        for k, v in kw.items():
            add_param(k.endswith('_') and k[:-1] or k, v)

        if params:
            href += '?' + unicode_urlencode(params)

        return href

    def __getattr__(self, name):
        if name not in self._derived:
            self._derived[name] = lambda *args, **kw: self(name, *args, **kw)
        return self._derived[name]

    def __add__(self, rhs):
        if rhs.startswith('/'):
            return self.base + rhs
        if rhs:
            return self.base + '/' + rhs
        return self.base or '/'


if __name__ == '__main__':
    import doctest, sys
    doctest.testmod(sys.modules[__name__])
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.