/
niceSOFT
/
swig
Обзор
Документация
Войти
/
niceSOFT
/
swig
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Examples/test-suite/python/doxygen_constructors_runme.py
100 строк
5 KB
William S Fulton
Complete the Python 2 removal and fix issues found reviewing it
07 июл 2026, 01:50
07 июл 2026, 01:50
2598574
Код
Авторство
О чём код?
import doxygen_constructors import inspect import comment_verifier from swig_test_utils import swig_check, swig_assert_raises def check_ab(obj, a, b): """Assert the constructor stored a and b correctly on the C++ instance.""" swig_check(obj.get_a(), a) swig_check(obj.get_b(), b) # Constructor docstrings reach __init__ in both -builtin and non-builtin. comment_verifier.check(inspect.getdoc(doxygen_constructors.ClassZeroArg.__init__), "Zero arg ctor doc.") comment_verifier.check(inspect.getdoc(doxygen_constructors.ClassOneArg.__init__), "One arg ctor doc.") comment_verifier.check(inspect.getdoc(doxygen_constructors.ClassTwoArg.__init__), "Two arg ctor doc.") comment_verifier.check(inspect.getdoc(doxygen_constructors.ClassKwArg.__init__), "Kwarg ctor doc.") # Positional construction; argument values reach the C++ members. doxygen_constructors.ClassZeroArg() swig_check(doxygen_constructors.ClassOneArg(11).get_a(), 11) check_ab(doxygen_constructors.ClassTwoArg(11, 2.5), 11, 2.5) check_ab(doxygen_constructors.ClassKwArg(11, 22), 11, 22) # Wrong arg count raises TypeError, identical between wrapping modes. with swig_assert_raises(TypeError): doxygen_constructors.ClassZeroArg(1) with swig_assert_raises(TypeError): doxygen_constructors.ClassOneArg() with swig_assert_raises(TypeError): doxygen_constructors.ClassOneArg(1, 2) with swig_assert_raises(TypeError): doxygen_constructors.ClassTwoArg(1) with swig_assert_raises(TypeError): doxygen_constructors.ClassTwoArg(1, 2.0, 3) # Without %feature("kwargs"), kwarg handling diverges between wrapping modes (long standing SWIG # behaviour, not specific to doxygen): the non-builtin shadow __init__ is a Python function and # accepts kwargs natively, while the builtin tp_init C wrapper only accepts positional args. The # %feature("kwargs") path below is where the two modes are expected to behave identically. # With %feature("kwargs"), kwarg order does not affect which value binds to which name, # and mixed positional/kwarg works. check_ab(doxygen_constructors.ClassKwArg(a=11, b=22), 11, 22) check_ab(doxygen_constructors.ClassKwArg(b=22, a=11), 11, 22) # reversed kwarg order check_ab(doxygen_constructors.ClassKwArg(11, b=22), 11, 22) # mixed positional + kwarg # Unknown kwarg name and missing arg both raise TypeError, identical in both modes. with swig_assert_raises(TypeError): doxygen_constructors.ClassKwArg(c=1, d=2) with swig_assert_raises(TypeError): doxygen_constructors.ClassKwArg(a=1) # Direct instantiation Cls(args) calls the tp_init slot and bypasses tp_dict["__init__"] # altogether, so it does not exercise the descriptor SWIG installs under -builtin to carry # the doxygen docstring. super().__init__() from a Python subclass is the realistic path # that does an attribute lookup and lands on that descriptor. The subclasses below run # that path for positional and keyword args. class TwoArgSubclass(doxygen_constructors.ClassTwoArg): def __init__(self, a, b, label): super().__init__(a, b) self.label = label class KwArgSubclass(doxygen_constructors.ClassKwArg): def __init__(self, **kw): super().__init__(**kw) sub = TwoArgSubclass(11, 2.5, "subclass-tag") swig_check(sub.get_a(), 11) swig_check(sub.get_b(), 2.5) swig_check(sub.label, "subclass-tag") check_ab(KwArgSubclass(a=11, b=22), 11, 22) check_ab(KwArgSubclass(b=22, a=11), 11, 22) # Confirm the descriptor SWIG installed actually replaced CPython's auto-installed slot # wrapper. PyType_Ready's add_operators populates tp_dict["__init__"] with a # wrapper_descriptor (type(object.__init__)) whose docstring is the fixed generic # "Initialize self." string. PyDescr_NewMethod produces a method_descriptor # (type(list.append)). Combined with the docstring checks above and the super().__init__() # calls above, this proves the wrapper is the call path under -builtin and not the default # slot wrapper. # Note: # >>> type(list.append).__name__ # 'method_descriptor' # >>> type(object.__init__).__name__ # 'wrapper_descriptor' if doxygen_constructors.is_python_builtin(): swig_check(type(doxygen_constructors.ClassZeroArg.__init__).__name__, "method_descriptor") swig_check(type(doxygen_constructors.ClassTwoArg.__init__).__name__, "method_descriptor") swig_check(type(doxygen_constructors.ClassKwArg.__init__).__name__, "method_descriptor") # Control: ClassNoDoc has no doxygen comment on its constructor, so SWIG does not emit # the __init__ descriptor override and PyType_Ready's auto-installed slot wrapper stays # in place. Its descriptor type matches type(object.__init__) and differs from the # documented classes above. swig_check(type(doxygen_constructors.ClassNoDoc.__init__).__name__, "wrapper_descriptor") swig_check(type(doxygen_constructors.ClassNoDoc.__init__), type(object.__init__)) swig_check(type(doxygen_constructors.ClassKwArg.__init__), type(list.append))