1# Copyright (C) 2008 Canonical Ltd
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17"""Custom module finder for entire package"""
18
19import modulefinder
20import os
21import sys
22
23
24class CustomModuleFinder(modulefinder.ModuleFinder):
25    """Custom module finder for processing python packages,
26    e.g. brz plugins packages.
27
28    :param  path:   list of directories to search for modules;
29                    if not specified, python standard library only is used.
30    """
31
32    def __init__(self, path=None, debug=0, excludes=[], replace_paths=[]):
33        if path is None:
34            path = [os.path.dirname(os.__file__)]    # only python std lib
35        modulefinder.ModuleFinder.__init__(
36            self, path, debug, excludes, replace_paths)
37
38    def run_package(self, package_path):
39        """Recursively process each module in package with run_script method.
40
41        :param  package_path:   path to package directory.
42        """
43        stack = [package_path]
44        while stack:
45            curdir = stack.pop(0)
46            py = os.listdir(curdir)
47            for i in py:
48                full = os.path.join(curdir, i)
49                if os.path.isdir(full):
50                    init = os.path.join(full, '__init__.py')
51                    if os.path.isfile(init):
52                        stack.append(full)
53                    continue
54                if not i.endswith('.py'):
55                    continue
56                if i == 'setup.py':     # skip
57                    continue
58                self.run_script(full)
59
60    def get_result(self):
61        """Return 2-tuple: (list of packages, list of modules)"""
62        keys = sorted(self.modules.keys())
63        mods = []
64        packs = []
65        for key in keys:
66            m = self.modules[key]
67            if not m.__file__:      # skip builtins
68                continue
69            if m.__path__:
70                packs.append(key)
71            elif key != '__main__':
72                mods.append(key)
73        return (packs, mods)
74
75
76if __name__ == '__main__':
77    package = sys.argv[1]
78
79    mf = CustomModuleFinder()
80    mf.run_package(package)
81
82    packs, mods = mf.get_result()
83
84    print('Packages:')
85    print(packs)
86
87    print('Modules:')
88    print(mods)
89