@@ -60,35 +60,75 @@ def test_ptr(field_type, num_default, outer_type, m_attr):
60
60
@pytest .mark .xfail (
61
61
"env.PYPY" , reason = "gc after `del field_co_own` is apparently deferred"
62
62
)
63
- @pytest .mark .parametrize ("m_attr" , ("m_uqmp" , "m_uqcp" ))
64
- def test_uqp (m_attr , msg ):
65
- m_attr_disown = m_attr + "_disown"
63
+ @pytest .mark .parametrize ("m_attr_disown" , ("m_uqmp_disown" , "m_uqcp_disown" ))
64
+ def test_uqp (m_attr_disown , msg ):
66
65
outer = m .Outer ()
67
- assert getattr (outer , m_attr ) is None
68
66
assert getattr (outer , m_attr_disown ) is None
69
- field = m .Field ()
70
- field .num = 39
71
- setattr (outer , m_attr_disown , field )
67
+ field_orig = m .Field ()
68
+ field_orig .num = 39
69
+ setattr (outer , m_attr_disown , field_orig )
72
70
with pytest .raises (ValueError ) as excinfo :
73
- field .num
71
+ field_orig .num
74
72
assert (
75
73
msg (excinfo .value )
76
74
== "Missing value for wrapped C++ type: Python instance was disowned."
77
75
)
78
- field_co_own = getattr (outer , m_attr )
79
- assert getattr (outer , m_attr ).num == 39
80
- assert field_co_own .num == 39
81
- # TODO: needs work.
82
- # with pytest.raises(RuntimeError) as excinfo:
83
- # getattr(outer, m_attr_disown)
84
- # assert (
85
- # msg(excinfo.value)
86
- # == "Invalid unique_ptr: another instance owns this pointer already."
87
- # )
88
- del field_co_own
89
- field_excl_own = getattr (outer , m_attr_disown )
90
- assert getattr (outer , m_attr ) is None
91
- assert field_excl_own .num == 39
76
+ field_retr1 = getattr (outer , m_attr_disown )
77
+ assert getattr (outer , m_attr_disown ) is None
78
+ assert field_retr1 .num == 39
79
+ field_retr1 .num = 93
80
+ setattr (outer , m_attr_disown , field_retr1 )
81
+ with pytest .raises (ValueError ):
82
+ field_retr1 .num
83
+ field_retr2 = getattr (outer , m_attr_disown )
84
+ assert field_retr2 .num == 93
85
+
86
+
87
+ def _dereference (proxy , xxxattr , * args , ** kwargs ):
88
+ obj = object .__getattribute__ (proxy , "__obj" )
89
+ field_name = object .__getattribute__ (proxy , "__field_name" )
90
+ field = getattr (obj , field_name )
91
+ assert field is not None
92
+ try :
93
+ return xxxattr (field , * args , ** kwargs )
94
+ finally :
95
+ setattr (obj , field_name , field )
96
+
97
+
98
+ class unique_ptr_field_proxy_poc (object ): # noqa: N801
99
+ def __init__ (self , obj , field_name ):
100
+ object .__setattr__ (self , "__obj" , obj )
101
+ object .__setattr__ (self , "__field_name" , field_name )
102
+
103
+ def __getattr__ (self , * args , ** kwargs ):
104
+ return _dereference (self , getattr , * args , ** kwargs )
105
+
106
+ def __setattr__ (self , * args , ** kwargs ):
107
+ return _dereference (self , setattr , * args , ** kwargs )
108
+
109
+ def __delattr__ (self , * args , ** kwargs ):
110
+ return _dereference (self , delattr , * args , ** kwargs )
111
+
112
+
113
+ @pytest .mark .parametrize ("m_attr_disown" , ("m_uqmp_disown" , "m_uqcp_disown" ))
114
+ def test_unique_ptr_field_proxy_poc (m_attr_disown , msg ):
115
+ outer = m .Outer ()
116
+ field_orig = m .Field ()
117
+ field_orig .num = 45
118
+ setattr (outer , m_attr_disown , field_orig )
119
+ field_proxy = unique_ptr_field_proxy_poc (outer , m_attr_disown )
120
+ assert field_proxy .num == 45
121
+ assert field_proxy .num == 45
122
+ with pytest .raises (AttributeError ):
123
+ field_proxy .xyz
124
+ assert field_proxy .num == 45
125
+ field_proxy .num = 82
126
+ assert field_proxy .num == 82
127
+ field_proxy = unique_ptr_field_proxy_poc (outer , m_attr_disown )
128
+ assert field_proxy .num == 82
129
+ with pytest .raises (AttributeError ):
130
+ del field_proxy .num
131
+ assert field_proxy .num == 82
92
132
93
133
94
134
@pytest .mark .parametrize ("m_attr" , ("m_shmp" , "m_shcp" ))
0 commit comments