diff --git a/python/cppyy/_cpython_cppyy.py b/python/cppyy/_cpython_cppyy.py index 304aeb51..fada4913 100644 --- a/python/cppyy/_cpython_cppyy.py +++ b/python/cppyy/_cpython_cppyy.py @@ -9,6 +9,7 @@ 'load_reflection_info', 'addressof', 'bind_object', + 'generate_typehints', 'nullptr', 'default', '_backend', @@ -188,6 +189,7 @@ def add_default_paths(): bind_object = _backend.bind_object nullptr = _backend.nullptr default = _backend.default +generate_typehints = _backend.generate_typehints def load_reflection_info(name): # with _stderr_capture() as err: diff --git a/python/cppyy/_pypy_cppyy.py b/python/cppyy/_pypy_cppyy.py index 78ad08a1..77f2619d 100644 --- a/python/cppyy/_pypy_cppyy.py +++ b/python/cppyy/_pypy_cppyy.py @@ -10,6 +10,7 @@ 'gbl', 'addressof', 'bind_object', + 'generate_typehints', 'nullptr', ] diff --git a/test/test_typehints.py b/test/test_typehints.py new file mode 100644 index 00000000..5727a132 --- /dev/null +++ b/test/test_typehints.py @@ -0,0 +1,102 @@ +from pytest import raises + + +class TestTypeHints: + def setup_class(cls): + import cppyy + + cppyy.cppdef( + r""" + namespace TypeHints { + int x = 10; + template + struct MyTKlass{ + T obj; + }; + struct MyKlass { + std::string name = "MyKlass"; + bool flag = false; + std::vector array = {}; + float callme(std::string a, bool b, std::vector c) { return 0.0f; } + template + T callme(T v) { return v; } + }; + typedef MyKlass Klass; + typedef MyTKlass KlassFloat; + float fn(std::string a, bool b, std::vector c) { return 0.0f; } + template + T tmpl_fn(T v) { return v; } + } // namespace TypeHints + int x = 10; + double y = 10; + unsigned short z = 10; + char a = 'a'; + signed char sa = 'a'; + unsigned char usa = 'a'; + template + struct MyTKlass{ + T obj; + }; + struct MyKlass { + std::string name = "MyKlass"; + bool flag = false; + std::vector array = {}; + float callme(std::string a, bool b, std::vector c) { return 0.0f; } + template + T callme(T v) { return v; } + template + static T s_callme(T v) { return v; } + }; + float callme(std::string a, bool b, std::vector c) { return 0.0f; } + template + T tmpl_fn(T v) { return v; } + typedef MyKlass Klass; + typedef MyTKlass KlassFloat; + """ + ) + + def test_invalids(self): + from cppyy import gbl, generate_typehints + + typehint = generate_typehints("x") + assert typehint.startswith("x: int\n") + typehint = generate_typehints("y") + assert typehint.startswith("y: float\n") + typehint = generate_typehints("z") + assert typehint.startswith("z: int\n") + typehint = generate_typehints("a") + assert typehint.startswith("a: str\n") + typehint = generate_typehints("sa") + assert typehint.startswith("sa: int\n") + typehint = generate_typehints("usa") + assert typehint.startswith("usa: int\n") + + typehint = generate_typehints("MyKlass") + assert "class MyKlass" in typehint + + typehint = generate_typehints("callme") + assert ( + '@overload\ndef callme(a: "std.string", b: bool, c: "std.vector[int]") -> float:\n' + in typehint + ) + + typehint = generate_typehints("Klass") + assert typehint.startswith("Klass = MyKlass\n") + + typehint = generate_typehints("KlassFloat") + assert typehint.startswith("KlassFloat = \"MyTKlass[float]\"\n") + + typehint = generate_typehints("MyTKlass") + assert "class MyTKlass[T]:" in typehint + assert "obj: T" in typehint + + + typehint = generate_typehints("TypeHints") + assert "class TypeHints:" in typehint + + with raises(TypeError) as err: + generate_typehints("unknown") + assert "Unknown Type" in str(err) + + with raises(TypeError) as err: + generate_typehints("TypeHints::x")