~ubuntu-branches/ubuntu/natty/flup/natty

« back to all changes in this revision

Viewing changes to flup/resolver/importingmodule.py

  • Committer: Bazaar Package Importer
  • Author(s): Kai Hendry
  • Date: 2007-09-12 20:22:04 UTC
  • mfrom: (1.2.1 upstream) (4 gutsy)
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20070912202204-fg63etr9vzaf8hea
* New upstream release
* http://www.saddi.com/software/news/archives/58-flup-1.0-released.html
* Added a note in the description that people should probably start thinking
  of moving to modwsgi.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2002, 2005 Allan Saddi <allan@saddi.com>
2
 
# All rights reserved.
3
 
#
4
 
# Redistribution and use in source and binary forms, with or without
5
 
# modification, are permitted provided that the following conditions
6
 
# are met:
7
 
# 1. Redistributions of source code must retain the above copyright
8
 
#    notice, this list of conditions and the following disclaimer.
9
 
# 2. Redistributions in binary form must reproduce the above copyright
10
 
#    notice, this list of conditions and the following disclaimer in the
11
 
#    documentation and/or other materials provided with the distribution.
12
 
#
13
 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
 
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
 
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17
 
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
 
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
 
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
 
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
 
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
 
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
 
# SUCH DAMAGE.
24
 
#
25
 
# $Id: importingmodule.py 1837 2006-01-15 18:20:37Z asaddi $
26
 
 
27
 
__author__ = 'Allan Saddi <allan@saddi.com>'
28
 
__version__ = '$Revision: 1837 $'
29
 
 
30
 
import sys
31
 
import os
32
 
import imp
33
 
 
34
 
from resolver import *
35
 
 
36
 
__all__ = ['ImportingModuleResolver']
37
 
 
38
 
class NoDefault(object):
39
 
    pass
40
 
 
41
 
class ImportingModuleResolver(Resolver):
42
 
    """
43
 
    Constructor takes a directory name or a list of directories. Interprets
44
 
    the first two components of PATH_INFO as 'module/function'. Modules
45
 
    are imported as needed and must reside in the directories specified.
46
 
    Module and function names beginning with underscore are ignored.
47
 
 
48
 
    If the 'module' part of PATH_INFO is missing, it is assumed to be
49
 
    self.default_module.
50
 
 
51
 
    If the 'function' part of PATH_INFO is missing, it is assumed to be
52
 
    self.index_page.
53
 
 
54
 
    Upon successful resolution, appends the module and function names to
55
 
    SCRIPT_NAME and updates PATH_INFO as the remaining components of the path.
56
 
 
57
 
    NB: I would recommend explicitly setting all modules' __all__ list.
58
 
    Otherwise, be sure all the names of module-level callables that you
59
 
    don't want exported begin with underscore.
60
 
    """
61
 
    # No default module by default.
62
 
    default_module = None
63
 
    index_page = 'index'
64
 
 
65
 
    def __init__(self, path, defaultModule=NoDefault, index=NoDefault):
66
 
        self.path = path
67
 
        if defaultModule is not NoDefault:
68
 
            self.default_module = defaultModule
69
 
        if index is not NoDefault:
70
 
            self.index_page = index
71
 
 
72
 
    def resolve(self, request, redirect=False):
73
 
        path_info = request.pathInfo.split(';')[0]
74
 
        path_info = path_info.split('/')
75
 
 
76
 
        assert len(path_info) > 0
77
 
        assert not path_info[0]
78
 
 
79
 
        while len(path_info) < 3:
80
 
            path_info.append('')
81
 
 
82
 
        module_name, func_name = path_info[1:3]
83
 
 
84
 
        if not module_name:
85
 
            module_name = self.default_module
86
 
 
87
 
        if not func_name:
88
 
            func_name = self.index_page
89
 
 
90
 
        module = None
91
 
        if module_name and (module_name[0] != '_' or redirect) and \
92
 
           not module_name.count('.'):
93
 
            module = _import_module(module_name, path=self.path)
94
 
 
95
 
        if module is not None:
96
 
            if func_name and (func_name[0] != '_' or redirect):
97
 
                module_all = getattr(module, '__all__', None)
98
 
                if module_all is None or func_name in module_all or redirect:
99
 
                    func = getattr(module, func_name, None)
100
 
                    if callable(func):
101
 
                        self._updatePath(request, 2)
102
 
                        return func
103
 
 
104
 
        return None
105
 
 
106
 
def _import_module(name, path=None):
107
 
    """
108
 
    Imports a module. If path is None, module will be searched for in
109
 
    sys.path. If path is given (which may be a single string or a list),
110
 
    the module will only be searched for in those directories.
111
 
    """
112
 
    if path is not None and type(path) is not list:
113
 
        path = [path]
114
 
 
115
 
    module = sys.modules.get(name)
116
 
    if module is not None:
117
 
        module_file = getattr(module, '__file__')
118
 
        if module_file is None or \
119
 
               (path is not None and os.path.dirname(module_file) not in path):
120
 
            return None
121
 
 
122
 
        return module
123
 
 
124
 
    fp, pathname, description = imp.find_module(name, path)
125
 
    try:
126
 
        return imp.load_module(name, fp, pathname, description)
127
 
    finally:
128
 
        if fp:
129
 
            fp.close()