prototype

This commit is contained in:
Michael Carlstrom 2024-07-26 10:03:06 -04:00
parent 8e7307f069
commit bb829344b5
4 changed files with 90 additions and 1 deletions

View File

@ -182,6 +182,10 @@ public:
/// Get or set the object's docstring, i.e. ``obj.__doc__``.
str_attr_accessor doc() const;
/// Get or set the object's type_params, i.e. ``obj.__type_params__``.
str_attr_accessor type_params() const;
/// Return the object's current reference count
ssize_t ref_count() const {
#ifdef PYPY_VERSION
@ -2534,6 +2538,11 @@ str_attr_accessor object_api<D>::doc() const {
return attr("__doc__");
}
template <typename D>
str_attr_accessor object_api<D>::type_params() const {
return attr("__type_params__");
}
template <typename D>
handle object_api<D>::get_type() const {
return type::handle_of(derived());

View File

@ -115,7 +115,7 @@ class Literal : public object {
PYBIND11_OBJECT_DEFAULT(Literal, object, PyObject_Type)
};
// Example syntax for creating a TypeVar.
// Example syntax for creating a type annotation of a TypeVar, ParamSpec, and TypeVarTuple.
// typedef typing::TypeVar<"T"> TypeVarT;
template <StringLiteral>
class TypeVar : public object {
@ -124,6 +124,41 @@ class TypeVar : public object {
};
#endif
template <typename T>
class TypeVarObject : public object {
PYBIND11_OBJECT_DEFAULT(TypeVarObject, object, PyObject_Type)
using object::object;
TypeVarObject(const char *name){
attr("__name__") = name;
attr("__bound__") = make_caster<T>;
attr("__constraints__") = pybind11::make_tuple();
}
// TypeVarObject(const char *name, py::typing::Tuple<pybind11::type, pybind11::ellipse> tuple){
// attr("__name__") = name;
// attr("__bound__") = py::none();
// attr("__constraints__") = tuple;
// }
};
class ParamSpec : public object {
PYBIND11_OBJECT_DEFAULT(ParamSpec, object, PyObject_Type)
using object::object;
ParamSpec(const char *name){
attr("__name__") = name;
attr("__bound__") = pybind11::none();
}
};
class TypeVarTuple : public object {
PYBIND11_OBJECT_DEFAULT(TypeVarTuple, object, PyObject_Type)
using object::object;
TypeVarTuple(const char *name){
attr("__name__") = name;
}
};
PYBIND11_NAMESPACE_END(typing)
PYBIND11_NAMESPACE_BEGIN(detail)

View File

@ -923,4 +923,21 @@ TEST_SUBMODULE(pytypes, m) {
#else
m.attr("defined_PYBIND11_TYPING_H_HAS_STRING_LITERAL") = false;
#endif
struct TypeVarObject {};
py::class_<TypeVarObject>(m, "TypeVarObject").type_params() = py::make_tuple(py::typing::TypeVarObject<int>("T"));
struct ParamSpec {};
py::class_<ParamSpec>(m, "ParamSpec").type_params() = py::make_tuple(py::typing::ParamSpec("P"));
struct TypeVarTuple {};
py::class_<TypeVarTuple>(m, "TypeVarTuple").type_params() = py::make_tuple(py::typing::TypeVarTuple("T"));
struct NoTypeParams {};
struct TypeParams {};
py::class_<NoTypeParams>(m, "NoTypeParams");
// TODO: Use custom objects
py::class_<TypeParams>(m, "TypeParams").type_params() = py::make_tuple("foo", 3, py::none());
m.def("type_params", []() -> void {}).type_params() = py::make_tuple("foo", 3, py::none());
}

View File

@ -4,6 +4,7 @@ import contextlib
import sys
import types
from typing import TypeVar
import pytest
import env
@ -1048,3 +1049,30 @@ def test_typevar(doc):
assert doc(m.annotate_listT_to_T) == "annotate_listT_to_T(arg0: list[T]) -> T"
assert doc(m.annotate_object_to_T) == "annotate_object_to_T(arg0: object) -> T"
def test_typevar_object():
assert len(m.TypeVarObject.__type_params__) == 1
type_var = m.TypeVarObject.__type_params__[0]
assert type_var.__name__ == "T"
assert type_var.__bound__ == int
assert type_var.__constraints__ == ()
def test_param_spec():
assert len(m.ParamSpec.__type_params__) == 1
param_spec = m.ParamSpec.__type_params__[0]
assert param_spec.__name__ == "P"
assert param_spec.__bound__ == None
def test_type_var_tuple():
assert len(m.TypeVarTuple.__type_params__) == 1
type_var_tuple = m.TypeVarTuple.__type_params__[0]
assert type_var_tuple.__name__ == "T"
with pytest.raises(AttributeError):
param_spec.__bound__
def test_type_params():
assert m.NoTypeParams.__type_params__ == ()
assert m.TypeParams.__type_params__ == ("foo", 3, None)
assert m.type_params.__type_params__ == ("foo", 3, None)