Merge branch 'pybind:master' into master

This commit is contained in:
Steve R. Sun 2022-07-07 08:05:05 +08:00 committed by GitHub
commit 5ef5a14cfa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 235 additions and 66 deletions

View File

@ -30,6 +30,7 @@ jobs:
- '3.6' - '3.6'
- '3.9' - '3.9'
- '3.10' - '3.10'
- '3.11-dev'
- 'pypy-3.7' - 'pypy-3.7'
- 'pypy-3.8' - 'pypy-3.8'
- 'pypy-3.9' - 'pypy-3.9'
@ -185,8 +186,8 @@ jobs:
- python-version: "3.9" - python-version: "3.9"
python-debug: true python-debug: true
valgrind: true valgrind: true
# - python-version: "3.11-dev" - python-version: "3.11-dev"
# python-debug: false python-debug: false
name: "🐍 ${{ matrix.python-version }}${{ matrix.python-debug && '-dbg' || '' }} (deadsnakes)${{ matrix.valgrind && ' • Valgrind' || '' }} • x64" name: "🐍 ${{ matrix.python-version }}${{ matrix.python-debug && '-dbg' || '' }} (deadsnakes)${{ matrix.valgrind && ' • Valgrind' || '' }} • x64"
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -14,7 +14,7 @@ env:
jobs: jobs:
standard: standard:
name: "🐍 3.11 dev • ubuntu-latest • x64" name: "🐍 3.11 latest internals • ubuntu-latest • x64"
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: "contains(github.event.pull_request.labels.*.name, 'python dev')" if: "contains(github.event.pull_request.labels.*.name, 'python dev')"

View File

@ -14,44 +14,164 @@ IN DEVELOPMENT
Removed support for Python 2.7, Python 3.5, and MSVC 2015. Support for MSVC Removed support for Python 2.7, Python 3.5, and MSVC 2015. Support for MSVC
2017 is limited due to availability of CI runners; we highly recommend MSVC 2017 is limited due to availability of CI runners; we highly recommend MSVC
2019 or 2022 be used. 2019 or 2022 be used. Initial support added for Python 3.11.
New features: New features:
* ``py::anyset`` & ``py::frozenset`` were added, with copying (cast) to
``std::set`` (similar to ``set``).
`#3901 <https://github.com/pybind/pybind11/pull/3901>`_
* Support bytearray casting to string.
`#3707 <https://github.com/pybind/pybind11/pull/3707>`_
* ``type_caster<std::monostate>`` was added. ``std::monostate`` is a tag type * ``type_caster<std::monostate>`` was added. ``std::monostate`` is a tag type
that allows ``std::variant`` to act as an optional, or allows default that allows ``std::variant`` to act as an optional, or allows default
construction of a ``std::variant`` holding a non-default constructible type. construction of a ``std::variant`` holding a non-default constructible type.
`#3818 <https://github.com/pybind/pybind11/pull/3818>`_ `#3818 <https://github.com/pybind/pybind11/pull/3818>`_
* Support bytearray casting to string. * ``pybind11::capsule::set_name`` added to mutate the name of the capsule instance.
`#3707 <https://github.com/pybind/pybind11/pull/3707>`_ `#3866 <https://github.com/pybind/pybind11/pull/3866>`_
* NumPy: dtype constructor from type number added, accessors corresponding to
Python API ``dtype.num``, ``dtype.byteorder``, ``dtype.flags`` and
``dtype.alignment`` added.
`#3868 <https://github.com/pybind/pybind11/pull/3868>`_
Changes: Changes:
* Python 2 support was removed completely. * Python 3.6 is now the minimum supported version.
`#3688 <https://github.com/pybind/pybind11/pull/3688>`_ `#3688 <https://github.com/pybind/pybind11/pull/3688>`_
`#3719 <https://github.com/pybind/pybind11/pull/3719>`_
* The minimum version for MSVC is now 2017. * The minimum version for MSVC is now 2017.
`#3722 <https://github.com/pybind/pybind11/pull/3722>`_ `#3722 <https://github.com/pybind/pybind11/pull/3722>`_
* Fix issues with CPython 3.11 betas and add to supported test matrix.
`#3923 <https://github.com/pybind/pybind11/pull/3923>`_
* ``error_already_set`` is now safer and more performant, especially for
exceptions with long tracebacks, by delaying computation.
`#1895 <https://github.com/pybind/pybind11/pull/1895>`_
* Improve exception handling in python ``str`` bindings. * Improve exception handling in python ``str`` bindings.
`#3826 <https://github.com/pybind/pybind11/pull/3826>`_ `#3826 <https://github.com/pybind/pybind11/pull/3826>`_
* The bindings for capsules now have more consistent exception handling. * The bindings for capsules now have more consistent exception handling.
`#3825 <https://github.com/pybind/pybind11/pull/3825>`_ `#3825 <https://github.com/pybind/pybind11/pull/3825>`_
* Fix exception handling when ``pybind11::weakref()`` fails. * ``PYBIND11_OBJECT_CVT`` and ``PYBIND11_OBJECT_CVT_DEFAULT`` macro can now be
`#3739 <https://github.com/pybind/pybind11/pull/3739>`_ used to define classes in namespaces other than pybind11.
`#3797 <https://github.com/pybind/pybind11/pull/3797>`_
* Error printing code now uses ``PYBIND11_DETAILED_ERROR_MESSAGES`` instead of
requiring ``NDEBUG``, allowing use with release builds if desired.
`#3913 <https://github.com/pybind/pybind11/pull/3913>`_
Bug fixes: Bug fixes:
* ``PYBIND11_OBJECT_CVT`` and ``PYBIND11_OBJECT_CVT_DEFAULT`` macro can be used * Fix exception handling when ``pybind11::weakref()`` fails.
to define classes in namespaces other than pybind11. `#3739 <https://github.com/pybind/pybind11/pull/3739>`_
`#3797 <https://github.com/pybind/pybind11/pull/3797>`_
* ``module_::def_submodule`` was missing proper error handling. This is fixed now.
`#3973 <https://github.com/pybind/pybind11/pull/3973>`_
* The behavior or ``error_already_set`` was made safer and the highly opaque
"Unknown internal error occurred" message was replaced with a more helpful
message.
`#3982 <https://github.com/pybind/pybind11/pull/3982>`_
* ``error_already_set::what()`` now handles non-normalized exceptions correctly.
`#3971 <https://github.com/pybind/pybind11/pull/3971>`_
* Support older C++ compilers where filesystem is not yet part of the standard
library and is instead included in ``std::experimental::filesystem``.
`#3840 <https://github.com/pybind/pybind11/pull/3840>`_
* Fix ``-Wfree-nonheap-object`` warnings produced by GCC by avoiding returning
pointers to static objects with ``return_value_policy::take_ownership``.
`#3946 <https://github.com/pybind/pybind11/pull/3946>`_
* Fix cast from pytype rvalue to another pytype.
`#3949 <https://github.com/pybind/pybind11/pull/3949>`_
* ``pybind11::detail::get_internals()`` is now resilient to in-flight Python
exceptions.
`#3981 <https://github.com/pybind/pybind11/pull/3981>`_
* Arrays with a dimension of size 0 are now properly converted to dynamic Eigen
matrices (more common in NumPy 1.23).
`#4038 <https://github.com/pybind/pybind11/pull/4038>`_
* Avoid catching unrelated errors when importing NumPy.
`#3974 <https://github.com/pybind/pybind11/pull/3974>`_
Performance and style:
* Added an accessor overload of ``(object &&key)`` to reference steal the
object when using python types as keys. This prevents unnecessary reference
count overhead for attr, dictionary, tuple, and sequence look ups. Added
additional regression tests. Fixed a performance bug the caused accessor
assignments to potentially perform unnecessary copies.
`#3970 <https://github.com/pybind/pybind11/pull/3970>`_
* Perfect forward all args of ``make_iterator``.
`#3980 <https://github.com/pybind/pybind11/pull/3980>`_
* Avoid potential bug in pycapsule destructor by adding an ``error_guard`` to
one of the dtors.
`#3958 <https://github.com/pybind/pybind11/pull/3958>`_
* Optimize dictionary access in ``strip_padding`` for numpy.
`#3994 <https://github.com/pybind/pybind11/pull/3994>`_
* ``stl_bind.h`` bindings now take slice args as a const-ref.
`#3852 <https://github.com/pybind/pybind11/pull/3852>`_
* Made slice constructor more consistent, and improve performance of some
casters by allowing reference stealing.
`#3845 <https://github.com/pybind/pybind11/pull/3845>`_
* Change numpy dtype from_args method to use const ref.
`#3878 <https://github.com/pybind/pybind11/pull/3878>`_
* Follow rule of three to ensure ``PyErr_Restore`` is called only once.
`#3872 <https://github.com/pybind/pybind11/pull/3872>`_
* Added missing perfect forwarding for ``make_iterator`` functions.
`#3860 <https://github.com/pybind/pybind11/pull/3860>`_
* Optimize c++ to python function casting by using the rvalue caster.
`#3966 <https://github.com/pybind/pybind11/pull/3966>`_
* Avoid potential implicit copy/assignment constructors causing double free in
``strdup_gaurd``.
`#3905 <https://github.com/pybind/pybind11/pull/3905>`_
* Enable clang-tidy checks ``misc-definitions-in-headers``,
``modernize-loop-convert``, and ``modernize-use-nullptr``.
`#3881 <https://github.com/pybind/pybind11/pull/3881>`_
`#3988 <https://github.com/pybind/pybind11/pull/3988>`_
Build system improvements: Build system improvements:
* CMake: Fix file extension on Windows with cp36 and cp37 using FindPython.
`#3919 <https://github.com/pybind/pybind11/pull/3919>`_
* CMake: Support multiple Python targets (such as on vcpkg).
`#3948 <https://github.com/pybind/pybind11/pull/3948>`_
* CMake: Fix issue with NVCC on Windows.
`#3947 <https://github.com/pybind/pybind11/pull/3947>`_
* CMake: Drop the bitness check on cross compiles (like targeting WebAssembly
via Emscripten).
`#3959 <https://github.com/pybind/pybind11/pull/3959>`_
* Add MSVC builds in debug mode to CI. * Add MSVC builds in debug mode to CI.
`#3784 <https://github.com/pybind/pybind11/pull/3784>`_ `#3784 <https://github.com/pybind/pybind11/pull/3784>`_
@ -59,15 +179,20 @@ Build system improvements:
`#3732 <https://github.com/pybind/pybind11/pull/3732>`_, `#3732 <https://github.com/pybind/pybind11/pull/3732>`_,
`#3741 <https://github.com/pybind/pybind11/pull/3741>`_ `#3741 <https://github.com/pybind/pybind11/pull/3741>`_
* Avoid ``setup.py <command>`` usage in internal tests.
`#3734 <https://github.com/pybind/pybind11/pull/3734>`_
Backend and tidying up: Backend and tidying up:
* Remove idioms in code comments. Use inclusive language. * Remove idioms in code comments. Use more inclusive language.
`#3809 <https://github.com/pybind/pybind11/pull/3809>`_ `#3809 <https://github.com/pybind/pybind11/pull/3809>`_
* ``#include <iostream>`` was removed from the ``pybind11/stl.h`` header. Your
project may break if it has a transitive dependency on this include. The fix
is to "Include What You Use".
`#3928 <https://github.com/pybind/pybind11/pull/3928>`_
* Avoid ``setup.py <command>`` usage in internal tests.
`#3734 <https://github.com/pybind/pybind11/pull/3734>`_
Version 2.9.2 (Mar 29, 2022) Version 2.9.2 (Mar 29, 2022)
---------------------------- ----------------------------

View File

@ -345,9 +345,11 @@ struct type_record {
bases.append((PyObject *) base_info->type); bases.append((PyObject *) base_info->type);
if (base_info->type->tp_dictoffset != 0) { #if PY_VERSION_HEX < 0x030B0000
dynamic_attr = true; dynamic_attr |= base_info->type->tp_dictoffset != 0;
} #else
dynamic_attr |= (base_info->type->tp_flags & Py_TPFLAGS_MANAGED_DICT) != 0;
#endif
if (caster) { if (caster) {
base_info->implicit_casts.emplace_back(type, caster); base_info->implicit_casts.emplace_back(type, caster);

View File

@ -846,7 +846,7 @@ struct always_construct_holder {
/// Create a specialization for custom holder types (silently ignores std::shared_ptr) /// Create a specialization for custom holder types (silently ignores std::shared_ptr)
#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type, ...) \ #define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type, ...) \
namespace pybind11 { \ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) \
namespace detail { \ namespace detail { \
template <typename type> \ template <typename type> \
struct always_construct_holder<holder_type> : always_construct_holder<void, ##__VA_ARGS__> { \ struct always_construct_holder<holder_type> : always_construct_holder<void, ##__VA_ARGS__> { \
@ -855,7 +855,7 @@ struct always_construct_holder {
class type_caster<holder_type, enable_if_t<!is_shared_ptr<holder_type>::value>> \ class type_caster<holder_type, enable_if_t<!is_shared_ptr<holder_type>::value>> \
: public type_caster_holder<type, holder_type> {}; \ : public type_caster_holder<type, holder_type> {}; \
} \ } \
} PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
// PYBIND11_DECLARE_HOLDER_TYPE holder types: // PYBIND11_DECLARE_HOLDER_TYPE holder types:
template <typename base, typename holder> template <typename base, typename holder>
@ -1650,12 +1650,12 @@ handle type::handle_of() {
} }
#define PYBIND11_MAKE_OPAQUE(...) \ #define PYBIND11_MAKE_OPAQUE(...) \
namespace pybind11 { \ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) \
namespace detail { \ namespace detail { \
template <> \ template <> \
class type_caster<__VA_ARGS__> : public type_caster_base<__VA_ARGS__> {}; \ class type_caster<__VA_ARGS__> : public type_caster_base<__VA_ARGS__> {}; \
} \ } \
} PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
/// Lets you pass a type containing a `,` through a macro parameter without needing a separate /// Lets you pass a type containing a `,` through a macro parameter without needing a separate
/// typedef, e.g.: /// typedef, e.g.:

View File

@ -545,8 +545,12 @@ extern "C" inline int pybind11_clear(PyObject *self) {
inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
auto *type = &heap_type->ht_type; auto *type = &heap_type->ht_type;
type->tp_flags |= Py_TPFLAGS_HAVE_GC; type->tp_flags |= Py_TPFLAGS_HAVE_GC;
#if PY_VERSION_HEX < 0x030B0000
type->tp_dictoffset = type->tp_basicsize; // place dict at the end type->tp_dictoffset = type->tp_basicsize; // place dict at the end
type->tp_basicsize += (ssize_t) sizeof(PyObject *); // and allocate enough space for it type->tp_basicsize += (ssize_t) sizeof(PyObject *); // and allocate enough space for it
#else
type->tp_flags |= Py_TPFLAGS_MANAGED_DICT;
#endif
type->tp_traverse = pybind11_traverse; type->tp_traverse = pybind11_traverse;
type->tp_clear = pybind11_clear; type->tp_clear = pybind11_clear;

View File

@ -425,4 +425,4 @@ struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> {
PYBIND11_NAMESPACE_END(initimpl) PYBIND11_NAMESPACE_END(initimpl)
PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(pybind11) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -86,37 +86,6 @@ inline wchar_t *widen_chars(const char *safe_arg) {
return widened_arg; return widened_arg;
} }
/// Python 2.x/3.x-compatible version of `PySys_SetArgv`
inline void set_interpreter_argv(int argc, const char *const *argv, bool add_program_dir_to_path) {
// Before it was special-cased in python 3.8, passing an empty or null argv
// caused a segfault, so we have to reimplement the special case ourselves.
bool special_case = (argv == nullptr || argc <= 0);
const char *const empty_argv[]{"\0"};
const char *const *safe_argv = special_case ? empty_argv : argv;
if (special_case) {
argc = 1;
}
auto argv_size = static_cast<size_t>(argc);
// SetArgv* on python 3 takes wchar_t, so we have to convert.
std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
std::vector<std::unique_ptr<wchar_t[], wide_char_arg_deleter>> widened_argv_entries;
widened_argv_entries.reserve(argv_size);
for (size_t ii = 0; ii < argv_size; ++ii) {
widened_argv_entries.emplace_back(widen_chars(safe_argv[ii]));
if (!widened_argv_entries.back()) {
// A null here indicates a character-encoding failure or the python
// interpreter out of memory. Give up.
return;
}
widened_argv[ii] = widened_argv_entries.back().get();
}
auto *pysys_argv = widened_argv.get();
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
}
PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(detail)
/** \rst /** \rst
@ -146,9 +115,64 @@ inline void initialize_interpreter(bool init_signal_handlers = true,
pybind11_fail("The interpreter is already running"); pybind11_fail("The interpreter is already running");
} }
#if PY_VERSION_HEX < 0x030B0000
Py_InitializeEx(init_signal_handlers ? 1 : 0); Py_InitializeEx(init_signal_handlers ? 1 : 0);
detail::set_interpreter_argv(argc, argv, add_program_dir_to_path); // Before it was special-cased in python 3.8, passing an empty or null argv
// caused a segfault, so we have to reimplement the special case ourselves.
bool special_case = (argv == nullptr || argc <= 0);
const char *const empty_argv[]{"\0"};
const char *const *safe_argv = special_case ? empty_argv : argv;
if (special_case) {
argc = 1;
}
auto argv_size = static_cast<size_t>(argc);
// SetArgv* on python 3 takes wchar_t, so we have to convert.
std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
std::vector<std::unique_ptr<wchar_t[], detail::wide_char_arg_deleter>> widened_argv_entries;
widened_argv_entries.reserve(argv_size);
for (size_t ii = 0; ii < argv_size; ++ii) {
widened_argv_entries.emplace_back(detail::widen_chars(safe_argv[ii]));
if (!widened_argv_entries.back()) {
// A null here indicates a character-encoding failure or the python
// interpreter out of memory. Give up.
return;
}
widened_argv[ii] = widened_argv_entries.back().get();
}
auto *pysys_argv = widened_argv.get();
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
#else
PyConfig config;
PyConfig_InitIsolatedConfig(&config);
config.install_signal_handlers = init_signal_handlers ? 1 : 0;
PyStatus status = PyConfig_SetBytesArgv(&config, argc, const_cast<char *const *>(argv));
if (PyStatus_Exception(status)) {
// A failure here indicates a character-encoding failure or the python
// interpreter out of memory. Give up.
PyConfig_Clear(&config);
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg
: "Failed to prepare CPython");
}
status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status)) {
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg
: "Failed to init CPython");
}
if (add_program_dir_to_path) {
PyRun_SimpleString("import sys, os.path; "
"sys.path.insert(0, "
"os.path.abspath(os.path.dirname(sys.argv[0])) "
"if sys.argv and os.path.exists(sys.argv[0]) else '')");
}
#endif
} }
/** \rst /** \rst

View File

@ -19,6 +19,7 @@ classifiers =
Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
License :: OSI Approved :: BSD License License :: OSI Approved :: BSD License
Programming Language :: Python :: Implementation :: PyPy Programming Language :: Python :: Implementation :: PyPy
Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: CPython

View File

@ -1,4 +1,4 @@
build==0.7.0 build==0.8.0
numpy==1.21.5; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7" numpy==1.21.5; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6" numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
numpy==1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10" numpy==1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10"

View File

@ -1,9 +1,21 @@
import sys
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
from pybind11_tests import methods_and_attributes as m from pybind11_tests import methods_and_attributes as m
NO_GETTER_MSG = (
"unreadable attribute" if sys.version_info < (3, 11) else "object has no getter"
)
NO_SETTER_MSG = (
"can't set attribute" if sys.version_info < (3, 11) else "object has no setter"
)
NO_DELETER_MSG = (
"can't delete attribute" if sys.version_info < (3, 11) else "object has no deleter"
)
def test_methods_and_attributes(): def test_methods_and_attributes():
instance1 = m.ExampleMandA() instance1 = m.ExampleMandA()
@ -102,32 +114,32 @@ def test_properties():
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
dummy = instance.def_property_writeonly # unused var dummy = instance.def_property_writeonly # unused var
assert "unreadable attribute" in str(excinfo.value) assert NO_GETTER_MSG in str(excinfo.value)
instance.def_property_writeonly = 4 instance.def_property_writeonly = 4
assert instance.def_property_readonly == 4 assert instance.def_property_readonly == 4
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
dummy = instance.def_property_impossible # noqa: F841 unused var dummy = instance.def_property_impossible # noqa: F841 unused var
assert "unreadable attribute" in str(excinfo.value) assert NO_GETTER_MSG in str(excinfo.value)
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
instance.def_property_impossible = 5 instance.def_property_impossible = 5
assert "can't set attribute" in str(excinfo.value) assert NO_SETTER_MSG in str(excinfo.value)
def test_static_properties(): def test_static_properties():
assert m.TestProperties.def_readonly_static == 1 assert m.TestProperties.def_readonly_static == 1
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
m.TestProperties.def_readonly_static = 2 m.TestProperties.def_readonly_static = 2
assert "can't set attribute" in str(excinfo.value) assert NO_SETTER_MSG in str(excinfo.value)
m.TestProperties.def_readwrite_static = 2 m.TestProperties.def_readwrite_static = 2
assert m.TestProperties.def_readwrite_static == 2 assert m.TestProperties.def_readwrite_static == 2
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
dummy = m.TestProperties.def_writeonly_static # unused var dummy = m.TestProperties.def_writeonly_static # unused var
assert "unreadable attribute" in str(excinfo.value) assert NO_GETTER_MSG in str(excinfo.value)
m.TestProperties.def_writeonly_static = 3 m.TestProperties.def_writeonly_static = 3
assert m.TestProperties.def_readonly_static == 3 assert m.TestProperties.def_readonly_static == 3
@ -135,14 +147,14 @@ def test_static_properties():
assert m.TestProperties.def_property_readonly_static == 3 assert m.TestProperties.def_property_readonly_static == 3
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
m.TestProperties.def_property_readonly_static = 99 m.TestProperties.def_property_readonly_static = 99
assert "can't set attribute" in str(excinfo.value) assert NO_SETTER_MSG in str(excinfo.value)
m.TestProperties.def_property_static = 4 m.TestProperties.def_property_static = 4
assert m.TestProperties.def_property_static == 4 assert m.TestProperties.def_property_static == 4
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
dummy = m.TestProperties.def_property_writeonly_static dummy = m.TestProperties.def_property_writeonly_static
assert "unreadable attribute" in str(excinfo.value) assert NO_GETTER_MSG in str(excinfo.value)
m.TestProperties.def_property_writeonly_static = 5 m.TestProperties.def_property_writeonly_static = 5
assert m.TestProperties.def_property_static == 5 assert m.TestProperties.def_property_static == 5
@ -160,7 +172,7 @@ def test_static_properties():
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
dummy = instance.def_property_writeonly_static # noqa: F841 unused var dummy = instance.def_property_writeonly_static # noqa: F841 unused var
assert "unreadable attribute" in str(excinfo.value) assert NO_GETTER_MSG in str(excinfo.value)
instance.def_property_writeonly_static = 4 instance.def_property_writeonly_static = 4
assert instance.def_property_static == 4 assert instance.def_property_static == 4
@ -180,7 +192,7 @@ def test_static_properties():
properties_override = m.TestPropertiesOverride() properties_override = m.TestPropertiesOverride()
with pytest.raises(AttributeError) as excinfo: with pytest.raises(AttributeError) as excinfo:
del properties_override.def_readonly del properties_override.def_readonly
assert "can't delete attribute" in str(excinfo.value) assert NO_DELETER_MSG in str(excinfo.value)
def test_static_cls(): def test_static_cls():