hotkeys: use Alt-m for amend on macOS
[git-cola.git] / qtpy / _utils.py
blobec851fabf5435995400d138b441cecf91f80edf6
1 # -----------------------------------------------------------------------------
2 # Copyright © 2023- The Spyder Development Team
4 # Released under the terms of the MIT License
5 # (see LICENSE.txt for details)
6 # -----------------------------------------------------------------------------
8 """Provides utility functions for use by QtPy itself."""
9 from functools import wraps
10 from typing import TYPE_CHECKING
12 import qtpy
14 if TYPE_CHECKING:
15 from qtpy.QtWidgets import QAction
18 def _wrap_missing_optional_dep_error(
19 attr_error,
21 import_error,
22 wrapper=qtpy.QtModuleNotInstalledError,
23 **wrapper_kwargs,
25 """Create a __cause__-chained wrapper error for a missing optional dep."""
26 qtpy_error = wrapper(**wrapper_kwargs)
27 import_error.__cause__ = attr_error
28 qtpy_error.__cause__ = import_error
29 return qtpy_error
32 def getattr_missing_optional_dep(name, module_name, optional_names):
33 """Wrap AttributeError in a special error if it matches."""
34 attr_error = AttributeError(
35 f"module {module_name!r} has no attribute {name!r}",
37 if name in optional_names:
38 return _wrap_missing_optional_dep_error(
39 attr_error,
40 **optional_names[name],
42 return attr_error
45 def possibly_static_exec(cls, *args, **kwargs):
46 """Call `self.exec` when `self` is given or a static method otherwise."""
47 if not args and not kwargs:
48 # A special case (`cls.exec_()`) to avoid the function resolving error
49 return cls.exec()
50 if isinstance(args[0], cls):
51 if len(args) == 1 and not kwargs:
52 # A special case (`self.exec_()`) to avoid the function resolving error
53 return args[0].exec()
54 return args[0].exec(*args[1:], **kwargs)
56 return cls.exec(*args, **kwargs)
59 def possibly_static_exec_(cls, *args, **kwargs):
60 """Call `self.exec` when `self` is given or a static method otherwise."""
61 if not args and not kwargs:
62 # A special case (`cls.exec()`) to avoid the function resolving error
63 return cls.exec_()
64 if isinstance(args[0], cls):
65 if len(args) == 1 and not kwargs:
66 # A special case (`self.exec()`) to avoid the function resolving error
67 return args[0].exec_()
68 return args[0].exec_(*args[1:], **kwargs)
70 return cls.exec_(*args, **kwargs)
73 def add_action(self, *args, old_add_action):
74 """Re-order arguments of `addAction` to backport compatibility with Qt>=6.3."""
75 from qtpy.QtCore import QObject
76 from qtpy.QtGui import QIcon, QKeySequence
78 action: QAction
79 icon: QIcon
80 text: str
81 shortcut: QKeySequence | QKeySequence.StandardKey | str | int
82 receiver: QObject
83 member: bytes
84 if all(
85 isinstance(arg, t)
86 for arg, t in zip(
87 args,
89 str,
90 (QKeySequence, QKeySequence.StandardKey, str, int),
91 QObject,
92 bytes,
96 if len(args) == 2:
97 text, shortcut = args
98 action = old_add_action(self, text)
99 action.setShortcut(shortcut)
100 elif len(args) == 3:
101 text, shortcut, receiver = args
102 action = old_add_action(self, text, receiver)
103 action.setShortcut(shortcut)
104 elif len(args) == 4:
105 text, shortcut, receiver, member = args
106 action = old_add_action(self, text, receiver, member, shortcut)
107 else:
108 return old_add_action(self, *args)
109 return action
110 if all(
111 isinstance(arg, t)
112 for arg, t in zip(
113 args,
115 QIcon,
116 str,
117 (QKeySequence, QKeySequence.StandardKey, str, int),
118 QObject,
119 bytes,
123 if len(args) == 3:
124 icon, text, shortcut = args
125 action = old_add_action(self, icon, text)
126 action.setShortcut(QKeySequence(shortcut))
127 elif len(args) == 4:
128 icon, text, shortcut, receiver = args
129 action = old_add_action(self, icon, text, receiver)
130 action.setShortcut(QKeySequence(shortcut))
131 elif len(args) == 5:
132 icon, text, shortcut, receiver, member = args
133 action = old_add_action(
134 self,
135 icon,
136 text,
137 receiver,
138 member,
139 QKeySequence(shortcut),
141 else:
142 return old_add_action(self, *args)
143 return action
144 return old_add_action(self, *args)
147 def static_method_kwargs_wrapper(func, from_kwarg_name, to_kwarg_name):
149 Helper function to manage `from_kwarg_name` to `to_kwarg_name` kwargs name changes in static methods.
151 Makes static methods accept the `from_kwarg_name` kwarg as `to_kwarg_name`.
154 @staticmethod
155 @wraps(func)
156 def _from_kwarg_name_to_kwarg_name_(*args, **kwargs):
157 if from_kwarg_name in kwargs:
158 kwargs[to_kwarg_name] = kwargs.pop(from_kwarg_name)
159 return func(*args, **kwargs)
161 return _from_kwarg_name_to_kwarg_name_