# Copyright 2009 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

# NOTE: This is a generated file.  The original is in
# buildout-templates/_pythonpath.py.in

__metaclass__ = type

import new
import os
import site
import sys

stdlib_paths = [
    ${indented-stdlib-paths}
    ]
egg_paths = [
    ${indented-egg-paths}
    ]
site_dirs = [
    ${indented-dir-paths}
    ]

def set_path():
    # We need to remove any modules installed using the setuptools
    # namespace package approach that generates .pth files that mutate
    # sys.modules.  They can mask the namespace modules we actually
    # want. We will try to recognize these sorts of namespace modules by
    # looking for modules that do not have a __file__, like the ones
    # generated by these .pth files.  However, that's not good enough: some
    # C modules look like this.  We then look for any names in the
    # module that are not special Python names (__*__) that are also not
    # in sys.modules.  If any one of these exist, this is not a
    # namespace module.  Otherwise, it is a namespace module.  Moreover,
    # if there were any sys.modules names from the namespace module,
    # this _pythonpath module was imported too late: we should complain.
    #
    # If you have not seen the code in these .pth files, here's an
    # example.  It is all in one line in the .pth files, because of the
    # .pth syntax for this feature.
    #
    # import sys,new,os;
    # p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('lazr',));
    # ie = os.path.exists(os.path.join(p,'__init__.py'));
    # m = not ie and sys.modules.setdefault('lazr',new.module('lazr'));
    # mp = (m or []) and m.__dict__.setdefault('__path__',[]);
    # (p not in mp) and mp.append(p)
    #
    # Note that we will be mutating sys.modules, so we want to make sure to be
    # getting a copy, not an iterable.
    marker = object()
    for k, v in sys.modules.items():
        if k == '__main__' or not isinstance(v, new.module):
            # These are some special cases that we'll pass by.
            continue
        if getattr(v, '__file__', marker) is marker:
            # This is a .pth-generated namespace or C module.
            for name in dir(v):
                if not name.startswith('__') and not name.endswith('__'):
                    full_name = '.'.join((k, name))
                    if full_name in sys.modules:
                        # This is a .pth-generated namespace module that
                        # has had one of its sub-packages imported.
                        raise RuntimeError(
                            'Found unexpected module %s.  '
                            'Import _pythonpath earlier!' % (full_name,))
                    else:
                        # This is a C module or something like that.  Nothing
                        # to see here: move along.
                        break
            else:
                # It is a .pth-generated namespace module.  Remove it
                # so we can let our eggs make their own.
                del sys.modules[k]

    # We keep the very first path because that is typically the directory
    # of the file that imported us, which should continue to have precedence.
    sys.path[1:] = egg_paths
    sys.path.extend(stdlib_paths)
    # Add the site_dirs before `addsitedir` in case it has setuptools.
    sys.path.extend(site_dirs)
    # Process all buildout-controlled eggs before site-packages by importing
    # pkg_resources.  This is only important for namespace packages, so it may
    # not have been added, so ignore import errors.
    try:
        import pkg_resources
    except ImportError:
        pass
    # Process .pth files.
    for p in site_dirs:
        site.addsitedir(p)

    # Make subprocesses have the same environment.
    os.environ['PYTHONPATH'] = os.pathsep.join(sys.path)

    # Enable Storm's C extensions
    os.environ['STORM_CEXTENSIONS'] = '1'

    # We don't want to bother tests or logs with these.
    import warnings
    warnings.filterwarnings(
        'ignore',
        'Module .+ was already imported from .+, but .+ is being added.*',
        UserWarning)

try:
    # We try two smoke tests.  The first checks to see that lib has been
    # added.
    import lp
    # XXX gary 10-19-2009 bug 455737
    # The second wants to see if the egg paths have been added.  The
    # only reason this is necessary is because, as of this writing, our
    # buildbot configuration sets PYTHONPATH at one point to include
    # lib, but not the rest of the eggs.  This means that importing lp
    # will work, but importing ZConfig won't.  The right fix here is to
    # change our buildbot to not set PYTHONPATH.  That's not an option
    # at this instance in time because the LOSAs are swamped with
    # another task. We can remove this comment, the following import,
    # and ``sys.modules.pop('lp', None)`` below when buildbot's
    # configuration is changed.
    import ZConfig
except ImportError:
    sys.modules.pop('lp', None)
    set_path()
