aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__feature__.py
blob: ece3d2edb007b632cf8aa3dd5d5d107646dd70f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#############################################################################
##
## Copyright (C) 2020 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################

from __future__ import print_function, absolute_import

"""
__feature__.py

This is the feature file for the Qt for Python project. There is some
similarity to Python's `__future__` file, but also some distinction.

The normal usage is like

    from __feature__ import <feature_name> [, ...]
    ...

Alternatively, there is the `set_selection` function which uses select_id's
and takes an optional `mod_name` parameter.

The select id `-1` has the spectial meaning "ignore this module".
"""

import sys

all_feature_names = [
    "snake_case",
    "true_property",
    "_feature_04",
    "_feature_08",
    "_feature_10",
    "_feature_20",
    "_feature_40",
    "_feature_80",
]

__all__ = ["all_feature_names", "set_selection", "info"] + all_feature_names

snake_case = 0x01
true_property = 0x02
_feature_04 = 0x04
_feature_08 = 0x08
_feature_10 = 0x10
_feature_20 = 0x20
_feature_40 = 0x40
_feature_80 = 0x80

# let's remove the dummies for the normal user
_really_all_feature_names = all_feature_names[:]
all_feature_names = list(_ for _ in all_feature_names if not _.startswith("_"))

# Install an import hook that controls the `__feature__` import.
"""
Note: This are two imports.
>>> import dis
>>> def test():
...     from __feature__ import snake_case
...
>>> dis.dis(test)
  2           0 LOAD_CONST               1 (0)
              2 LOAD_CONST               2 (('snake_case',))
              4 IMPORT_NAME              0 (__feature__)
              6 IMPORT_FROM              1 (snake_case)
              8 STORE_FAST               0 (snake_case)
             10 POP_TOP
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE
"""
# XXX build an improved C version? I guess not.
def _import(name, *args, **kwargs):
    # PYSIDE-1368: The `__name__` attribute does not need to exist in all modules.
    # PYSIDE-1398: sys._getframe(1) may not exist when embedding.
    calling_frame = _cf = sys._getframe().f_back
    importing_module = _cf.f_globals.get("__name__", "__main__") if _cf else "__main__"
    existing = pyside_feature_dict.get(importing_module, 0)

    if name == "__feature__" and args[2]:
        __init__()

        # This is an `import from` statement that corresponds to `IMPORT_NAME`.
        # The following `IMPORT_FROM` will handle errors. (Confusing, ofc.)
        flag = 0
        for feature in args[2]:
            if feature in _really_all_feature_names:
                flag |= globals()[feature]
            else:
                raise SyntaxError("PySide feature {} is not defined".format(feature))

        flag |= existing & 255 if isinstance(existing, int) and existing >= 0 else 0
        pyside_feature_dict[importing_module] = flag

        if importing_module == "__main__":
            # We need to add all modules here which should see __feature__.
            pyside_feature_dict["rlcompleter"] = flag

        # Initialize feature (multiple times allowed) and clear cache.
        sys.modules["PySide2.QtCore"].__init_feature__()
        return sys.modules["__feature__"]

    if name.split(".")[0] == "PySide2":
        # This is a module that imports PySide2.
        flag = existing if isinstance(existing, int) else 0
    else:
        # This is some other module. Ignore it in switching.
        flag = -1
    pyside_feature_dict[importing_module] = flag
    return original_import(name, *args, **kwargs)

_is_initialized = False

def __init__():
    global _is_initialized
    if not _is_initialized:
        # use _one_ recursive import...
        import PySide2.QtCore
        # Initialize all prior imported modules
        for name in sys.modules:
            pyside_feature_dict.setdefault(name, -1)


def set_selection(select_id, mod_name=None):
    """
    Internal use: Set the feature directly by Id.
    Id == -1: ignore this module in switching.
    """
    mod_name = mod_name or sys._getframe(1).f_globals['__name__']
    __init__()
    # Reset the features to the given id
    flag = 0
    if isinstance(select_id, int):
        flag = select_id & 255
    pyside_feature_dict[mod_name] = flag
    sys.modules["PySide2.QtCore"].__init_feature__()
    return _current_selection(flag)


def info(mod_name=None):
    """
    Internal use: Return the current selection
    """
    mod_name = mod_name or sys._getframe(1).f_globals['__name__']
    flag = pyside_feature_dict.get(mod_name, 0)
    return _current_selection(flag)


def _current_selection(flag):
    names = []
    if flag >= 0:
        for idx, name in enumerate(_really_all_feature_names):
            if (1 << idx) & flag:
                names.append(name)
    return names

#eof