def test_dynamic_attributes():
    from pybind11_tests import DynamicClass, CppDerivedDynamicClass

    instance = DynamicClass()
    if hasattr(instance, "foo"):
        raise AssertionError
    if "foo" in dir(instance):
        raise AssertionError

    # Dynamically add attribute
    instance.foo = 42
    if not hasattr(instance, "foo"):
        raise AssertionError
    if instance.foo != 42:
        raise AssertionError
    if "foo" not in dir(instance):
        raise AssertionError

    # __dict__ should be accessible and replaceable
    if "foo" not in instance.__dict__:
        raise AssertionError
    instance.__dict__ = {"bar": True}
    if hasattr(instance, "foo"):
        raise AssertionError
    if not hasattr(instance, "bar"):
        raise AssertionError

    with pytest.raises(TypeError) as excinfo:
        instance.__dict__ = []
    if str(excinfo.value
           ) != "__dict__ must be set to a dictionary, not a 'list'":
        raise AssertionError

    cstats = ConstructorStats.get(DynamicClass)
    if cstats.alive() != 1:
        raise AssertionError
    del instance
    if cstats.alive() != 0:
        raise AssertionError

    # Derived classes should work as well
    class PythonDerivedDynamicClass(DynamicClass):
        pass

    for cls in CppDerivedDynamicClass, PythonDerivedDynamicClass:
        derived = cls()
        derived.foobar = 100
        if derived.foobar != 100:
            raise AssertionError

        if cstats.alive() != 1:
            raise AssertionError
        del derived
        if cstats.alive() != 0:
            raise AssertionError
def test_dynamic_attributes():
    from pybind11_tests import DynamicClass, CppDerivedDynamicClass

    instance = DynamicClass()
    assert not hasattr(instance, "foo")
    assert "foo" not in dir(instance)

    # Dynamically add attribute
    instance.foo = 42
    assert hasattr(instance, "foo")
    assert instance.foo == 42
    assert "foo" in dir(instance)

    # __dict__ should be accessible and replaceable
    assert "foo" in instance.__dict__
    instance.__dict__ = {"bar": True}
    assert not hasattr(instance, "foo")
    assert hasattr(instance, "bar")

    with pytest.raises(TypeError) as excinfo:
        instance.__dict__ = []
    assert str(
        excinfo.value) == "__dict__ must be set to a dictionary, not a 'list'"

    cstats = ConstructorStats.get(DynamicClass)
    assert cstats.alive() == 1
    del instance
    assert cstats.alive() == 0

    # Derived classes should work as well
    class PythonDerivedDynamicClass(DynamicClass):
        pass

    for cls in CppDerivedDynamicClass, PythonDerivedDynamicClass:
        derived = cls()
        derived.foobar = 100
        assert derived.foobar == 100

        assert cstats.alive() == 1
        del derived
        assert cstats.alive() == 0
def test_dynamic_attributes():
    from pybind11_tests import DynamicClass, CppDerivedDynamicClass

    instance = DynamicClass()
    assert not hasattr(instance, "foo")
    assert "foo" not in dir(instance)

    # Dynamically add attribute
    instance.foo = 42
    assert hasattr(instance, "foo")
    assert instance.foo == 42
    assert "foo" in dir(instance)

    # __dict__ should be accessible and replaceable
    assert "foo" in instance.__dict__
    instance.__dict__ = {"bar": True}
    assert not hasattr(instance, "foo")
    assert hasattr(instance, "bar")

    with pytest.raises(TypeError) as excinfo:
        instance.__dict__ = []
    assert str(excinfo.value) == "__dict__ must be set to a dictionary, not a 'list'"

    cstats = ConstructorStats.get(DynamicClass)
    assert cstats.alive() == 1
    del instance
    assert cstats.alive() == 0

    # Derived classes should work as well
    class PythonDerivedDynamicClass(DynamicClass):
        pass

    for cls in CppDerivedDynamicClass, PythonDerivedDynamicClass:
        derived = cls()
        derived.foobar = 100
        assert derived.foobar == 100

        assert cstats.alive() == 1
        del derived
        assert cstats.alive() == 0