1#############################################################################
2##
3## Copyright (C) 2020 The Qt Company Ltd.
4## Contact: https://www.qt.io/licensing/
5##
6## This file is part of the test suite of Qt for Python.
7##
8## $QT_BEGIN_LICENSE:GPL-EXCEPT$
9## Commercial License Usage
10## Licensees holding valid commercial Qt licenses may use this file in
11## accordance with the commercial license agreement provided with the
12## Software or, alternatively, in accordance with the terms contained in
13## a written agreement between you and The Qt Company. For licensing terms
14## and conditions see https://www.qt.io/terms-conditions. For further
15## information use the contact form at https://www.qt.io/contact-us.
16##
17## GNU General Public License Usage
18## Alternatively, this file may be used under the terms of the GNU
19## General Public License version 3 as published by the Free Software
20## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21## included in the packaging of this file. Please review the following
22## information to ensure the GNU General Public License requirements will
23## be met: https://www.gnu.org/licenses/gpl-3.0.html.
24##
25## $QT_END_LICENSE$
26##
27#############################################################################
28
29
30import os
31import sys
32
33
34def get_dir_env_var(var_name):
35    """Return a directory set by an environment variable"""
36    result = os.environ.get(var_name)
37    if not result:
38        raise ValueError('{} is not set!'.format(var_name))
39    if not os.path.isdir(result):
40        raise ValueError('{} is not a directory!'.format(result))
41    return result
42
43
44def get_build_dir():
45    """
46    Return the env var `BUILD_DIR`.
47    If not set (interactive mode), take the last build history entry.
48    """
49    try:
50        return get_dir_env_var('BUILD_DIR')
51    except ValueError:
52        look_for = "testing"
53        here = os.path.dirname(__file__)
54        while look_for not in os.listdir(here):
55            here = os.path.dirname(here)
56            if len(here) <= 3:
57                raise SystemError(look_for + " not found!")
58        try:
59            sys.path.insert(0, here)
60            from testing.buildlog import builds
61            if not builds.history:
62                raise
63            return builds.history[-1].build_dir
64        finally:
65            del sys.path[0]
66
67
68def _prepend_path_var(var_name, paths):
69    """Prepend additional paths to a path environment variable
70       like PATH, LD_LIBRARY_PATH"""
71    old_paths = os.environ.get(var_name)
72    new_paths = os.pathsep.join(paths)
73    if old_paths:
74        new_paths += '{}{}'.format(os.pathsep, old_paths)
75    os.environ[var_name] = new_paths
76
77
78def add_python_dirs(python_dirs):
79    """Add directories to the Python path unless present.
80       Care is taken that the added directories come before
81       site-packages."""
82    new_paths = []
83    for python_dir in python_dirs:
84        new_paths.append(python_dir)
85        if python_dir in sys.path:
86            sys.path.remove(python_dir)
87    sys.path[:0] = new_paths
88
89
90def add_lib_dirs(lib_dirs):
91    """Add directories to the platform's library path."""
92    if sys.platform == 'win32':
93        if sys.version_info >= (3, 8, 0):
94            for lib_dir in lib_dirs:
95                os.add_dll_directory(lib_dir)
96        else:
97            _prepend_path_var('PATH', lib_dirs)
98    else:
99        _prepend_path_var('LD_LIBRARY_PATH', lib_dirs)
100
101
102def shiboken_paths(include_shiboken_tests=False):
103    """Return a tuple of python directories/lib directories to be set for
104       using the shiboken2 module from the build directory or running the
105       shiboken tests depending on a single environment variable BUILD_DIR
106       pointing to the build directory."""
107    src_dir = os.path.dirname(os.path.abspath(__file__))
108    python_dirs = []
109    if include_shiboken_tests:
110        python_dirs.append(src_dir)  # For py3kcompat
111    shiboken_dir = os.path.join(get_build_dir(), 'shiboken2')
112    python_dirs.append(os.path.join(shiboken_dir, 'shibokenmodule'))
113    lib_dirs = [os.path.join(shiboken_dir, 'libshiboken')]
114    if include_shiboken_tests:
115        shiboken_test_dir = os.path.join(shiboken_dir, 'tests')
116        for module in ['minimal', 'sample', 'smart', 'other']:
117            module_dir = os.path.join(shiboken_test_dir, module + 'binding')
118            python_dirs.append(module_dir)
119            lib_dir = os.path.join(shiboken_test_dir, 'lib' + module)
120            lib_dirs.append(lib_dir)
121    return (python_dirs, lib_dirs)
122
123
124def init_paths():
125    """Sets the correct import paths (Python modules and C++ library
126       paths) for testing shiboken depending on a single
127       environment variable BUILD_DIR pointing to the build
128       directory."""
129    paths = shiboken_paths(True)
130    add_python_dirs(paths[0])
131    add_lib_dirs(paths[1])
132