1# Copyright (C) 2017-2019 PyInstaller Development Team.
2# Copyright (C) 2016 Jason R Coombs <jaraco@jaraco.com>
3#
4# This file includes an almost complete copy of
5# pkg_resources/extern/__init__.py, taken from setuptools 28.6.1.
6# For PyInstaller the inly chane is to install a sub-class of VendorImporter.
7#
8# setuptools is licensed under the MIT License (expat) license:
9#
10# Permission is hereby granted, free of charge, to any person obtaining a copy
11# of this software and associated documentation files (the "Software"), to
12# deal in the Software without restriction, including without limitation the
13# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14# sell copies of the Software, and to permit persons to whom the Software is
15# furnished to do so, subject to the following conditions:
16#
17# The above copyright notice and this permission notice shall be included in
18# all copies or substantial portions of the Software.
19#
20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26# IN THE SOFTWARE.
27
28#--- Code of pkg_resources/extern/__init__.py starts here
29import sys
30
31class VendorImporter:
32    """
33    A PEP 302 meta path importer for finding optionally-vendored
34    or otherwise naturally-installed packages from root_name.
35    """
36
37    def __init__(self, root_name, vendored_names=(), vendor_pkg=None):
38        self.root_name = root_name
39        self.vendored_names = set(vendored_names)
40        self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor')
41
42    @property
43    def search_path(self):
44        """
45        Search first the vendor package then as a natural package.
46        """
47        yield self.vendor_pkg + '.'
48        yield ''
49
50    def find_module(self, fullname, path=None):
51        """
52        Return self when fullname starts with root_name and the
53        target module is one vendored through this importer.
54        """
55        root, base, target = fullname.partition(self.root_name + '.')
56        if root:
57            return
58        if not any(map(target.startswith, self.vendored_names)):
59            return
60        return self
61
62    def load_module(self, fullname):
63        """
64        Iterate over the search path to locate and load fullname.
65        """
66        root, base, target = fullname.partition(self.root_name + '.')
67        for prefix in self.search_path:
68            try:
69                extant = prefix + target
70                __import__(extant)
71                mod = sys.modules[extant]
72                sys.modules[fullname] = mod
73                # mysterious hack:
74                # Remove the reference to the extant package/module
75                # on later Python versions to cause relative imports
76                # in the vendor package to resolve the same modules
77                # as those going through this importer.
78                if sys.version_info > (3, 3):
79                    del sys.modules[extant]
80                return mod
81            except ImportError:
82                pass
83        else:
84            raise ImportError(
85                "The '{target}' package is required; "
86                "normally this is bundled with this package so if you get "
87                "this warning, consult the packager of your "
88                "distribution.".format(**locals())
89            )
90    def install(self):
91        """
92        Install this importer into sys.meta_path if not already present.
93        """
94        if self not in sys.meta_path:
95            sys.meta_path.append(self)
96
97#--- Code of pkg_resources/extern/__init__.py ends here
98
99class MyVendorImporter(VendorImporter):
100    @property
101    def search_path(self):
102        """
103        Only search the vendor package, and not a natural package.
104        """
105        yield self.vendor_pkg + '.'
106
107names = ('aaa', 'bbb', 'ccc')
108MyVendorImporter(__name__, names).install()
109