mirror of
https://github.com/pybind/pybind11.git
synced 2025-01-19 01:15:52 +00:00
init
This commit is contained in:
parent
e7c9b90739
commit
aa74fbefd7
@ -1329,6 +1329,15 @@ object object_or_cast(T &&o) {
|
||||
return pybind11::cast(std::forward<T>(o));
|
||||
}
|
||||
|
||||
// Declared in pytypes.h:
|
||||
// Written here so make_caster<T> can be used
|
||||
template <typename D>
|
||||
template <typename T>
|
||||
str_attr_accessor object_api<D>::attr_with_type(const char *key) const {
|
||||
annotations()[key] = make_caster<T>::name.text;
|
||||
return {derived(), key};
|
||||
};
|
||||
|
||||
// Placeholder type for the unneeded (and dead code) static variable in the
|
||||
// PYBIND11_OVERRIDE_OVERRIDE macro
|
||||
struct override_unused {};
|
||||
|
@ -113,6 +113,10 @@ public:
|
||||
/// See above (the only difference is that the key is provided as a string literal)
|
||||
str_attr_accessor attr(const char *key) const;
|
||||
|
||||
// attr_with_type is implemented in cast.h:
|
||||
template <typename T>
|
||||
str_attr_accessor attr_with_type(const char *key) const;
|
||||
|
||||
/** \rst
|
||||
Matches * unpacking in Python, e.g. to unpack arguments out of a ``tuple``
|
||||
or ``list`` for a function call. Applying another * to the result yields
|
||||
@ -182,6 +186,9 @@ public:
|
||||
/// Get or set the object's docstring, i.e. ``obj.__doc__``.
|
||||
str_attr_accessor doc() const;
|
||||
|
||||
// TODO: Make read only?
|
||||
str_attr_accessor annotations() const;
|
||||
|
||||
/// Return the object's current reference count
|
||||
ssize_t ref_count() const {
|
||||
#ifdef PYPY_VERSION
|
||||
@ -2558,6 +2565,16 @@ str_attr_accessor object_api<D>::doc() const {
|
||||
return attr("__doc__");
|
||||
}
|
||||
|
||||
template <typename D>
|
||||
str_attr_accessor object_api<D>::annotations() const {
|
||||
str_attr_accessor annotations_dict = attr("__annotations__");
|
||||
// Create dict automatically
|
||||
if (!isinstance<dict>(annotations_dict)){
|
||||
annotations_dict = dict();
|
||||
}
|
||||
return annotations_dict;
|
||||
}
|
||||
|
||||
template <typename D>
|
||||
handle object_api<D>::get_type() const {
|
||||
return type::handle_of(derived());
|
||||
|
@ -82,6 +82,12 @@ class Optional : public object {
|
||||
using object::object;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Final : public object {
|
||||
PYBIND11_OBJECT_DEFAULT(Final, object, PyObject_Type)
|
||||
using object::object;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TypeGuard : public bool_ {
|
||||
using bool_::bool_;
|
||||
@ -205,6 +211,11 @@ struct handle_type_name<typing::Optional<T>> {
|
||||
static constexpr auto name = const_name("Optional[") + make_caster<T>::name + const_name("]");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct handle_type_name<typing::Final<T>> {
|
||||
static constexpr auto name = const_name("Final[") + make_caster<T>::name + const_name("]");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct handle_type_name<typing::TypeGuard<T>> {
|
||||
static constexpr auto name = const_name("TypeGuard[") + make_caster<T>::name + const_name("]");
|
||||
|
@ -998,4 +998,22 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
#else
|
||||
m.attr("defined_PYBIND11_TEST_PYTYPES_HAS_RANGES") = false;
|
||||
#endif
|
||||
|
||||
m.attr_with_type<py::typing::List<int>>("list_int") = py::list();
|
||||
m.attr_with_type<py::typing::Set<py::str>>("set_str") = py::set();
|
||||
|
||||
|
||||
struct Empty {};
|
||||
py::class_<Empty>(m, "EmptyAnnotationClass");
|
||||
|
||||
struct Point {
|
||||
float x;
|
||||
py::dict dict_str_int;
|
||||
};
|
||||
auto point = py::class_<Point>(m, "Point");
|
||||
point.attr_with_type<float>("x");
|
||||
point.attr_with_type<py::typing::Dict<py::str, int>>("dict_str_int") = py::dict();
|
||||
|
||||
m.attr_with_type<py::typing::Final<int>>("CONST_INT") = 3;
|
||||
|
||||
}
|
||||
|
@ -1101,3 +1101,23 @@ def test_list_ranges(tested_list, expected):
|
||||
def test_dict_ranges(tested_dict, expected):
|
||||
assert m.dict_iterator_default_initialization()
|
||||
assert m.transform_dict_plus_one(tested_dict) == expected
|
||||
|
||||
|
||||
def test_module_attribute_types() -> None:
|
||||
module_annotations = m.__annotations__
|
||||
|
||||
assert module_annotations['list_int'] == 'list[int]'
|
||||
assert module_annotations['set_str'] == 'set[str]'
|
||||
|
||||
|
||||
def test_class_attribute_types() -> None:
|
||||
empty_annotations = m.EmptyAnnotationClass.__annotations__
|
||||
annotations = m.Point.__annotations__
|
||||
|
||||
assert empty_annotations == {}
|
||||
assert annotations['x'] == 'float'
|
||||
assert annotations['dict_str_int'] == 'dict[str, int]'
|
||||
|
||||
def test_final_annotation() -> None:
|
||||
module_annotations = m.__annotations__
|
||||
assert module_annotations['CONST_INT'] == 'Final[int]'
|
||||
|
Loading…
Reference in New Issue
Block a user