@@ -196,10 +196,14 @@ reveal_type(c.attr) # revealed: Unknown
196
196
197
197
## Behind the scenes
198
198
199
+ > TODO: This test is currently disabled pending
200
+ > [ an upstream Salsa fix] ( https://github.com/salsa-rs/salsa/pull/741 ) . Once that has been merged,
201
+ > re-enable this test by changing the language codes below back to ` py ` .
202
+
199
203
In this section, we trace through some of the steps that make properties work. We start with a
200
204
simple class ` C ` and a property ` attr ` :
201
205
202
- ``` py
206
+ ``` ignore
203
207
class C:
204
208
def __init__(self):
205
209
self._attr: int = 0
@@ -216,7 +220,7 @@ class C:
216
220
Next, we create an instance of ` C ` . As we have seen above, accessing ` attr ` on the instance will
217
221
return an ` int ` :
218
222
219
- ``` py
223
+ ``` ignore
220
224
c = C()
221
225
222
226
reveal_type(c.attr) # revealed: int
@@ -226,7 +230,7 @@ Behind the scenes, when we write `c.attr`, the first thing that happens is that
226
230
up the symbol ` attr ` on the meta-type of ` c ` , i.e. the class ` C ` . We can emulate this static lookup
227
231
using ` inspect.getattr_static ` , to see that ` attr ` is actually an instance of the ` property ` class:
228
232
229
- ``` py
233
+ ``` ignore
230
234
from inspect import getattr_static
231
235
232
236
attr_property = getattr_static(C, "attr")
@@ -237,7 +241,7 @@ The `property` class has a `__get__` method, which makes it a descriptor. It als
237
241
method, which means that it is a * data* descriptor (if there is no setter, ` __set__ ` is still
238
242
available but yields an ` AttributeError ` at runtime).
239
243
240
- ``` py
244
+ ``` ignore
241
245
reveal_type(type(attr_property).__get__) # revealed: <wrapper-descriptor `__get__` of `property` objects>
242
246
reveal_type(type(attr_property).__set__) # revealed: <wrapper-descriptor `__set__` of `property` objects>
243
247
```
@@ -246,22 +250,22 @@ When we access `c.attr`, the `__get__` method of the `property` class is called,
246
250
property object itself as the first argument, and the class instance ` c ` as the second argument. The
247
251
third argument is the "owner" which can be set to ` None ` or to ` C ` in this case:
248
252
249
- ``` py
253
+ ``` ignore
250
254
reveal_type(type(attr_property).__get__(attr_property, c, C)) # revealed: int
251
255
reveal_type(type(attr_property).__get__(attr_property, c, None)) # revealed: int
252
256
```
253
257
254
258
Alternatively, the above can also be written as a method call:
255
259
256
- ``` py
260
+ ``` ignore
257
261
reveal_type(attr_property.__get__(c, C)) # revealed: int
258
262
```
259
263
260
264
When we access ` attr ` on the class itself, the descriptor protocol is also invoked, but the instance
261
265
argument is set to ` None ` . When ` instance ` is ` None ` , the call to ` property.__get__ ` returns the
262
266
property instance itself. So the following expressions are all equivalent
263
267
264
- ``` py
268
+ ``` ignore
265
269
reveal_type(attr_property) # revealed: property
266
270
reveal_type(C.attr) # revealed: property
267
271
reveal_type(attr_property.__get__(None, C)) # revealed: property
@@ -271,7 +275,7 @@ reveal_type(type(attr_property).__get__(attr_property, None, C)) # revealed: pr
271
275
When we set the property using ` c.attr = "a" ` , the ` __set__ ` method of the property class is called.
272
276
This attribute access desugars to
273
277
274
- ``` py
278
+ ``` ignore
275
279
type(attr_property).__set__(attr_property, c, "a")
276
280
277
281
# error: [call-non-callable] "Call of wrapper descriptor `property.__set__` failed: calling the setter failed"
@@ -280,7 +284,7 @@ type(attr_property).__set__(attr_property, c, 1)
280
284
281
285
which is also equivalent to the following expressions:
282
286
283
- ``` py
287
+ ``` ignore
284
288
attr_property.__set__(c, "a")
285
289
# error: [call-non-callable]
286
290
attr_property.__set__(c, 1)
@@ -293,7 +297,7 @@ C.attr.__set__(c, 1)
293
297
Properties also have ` fget ` and ` fset ` attributes that can be used to retrieve the original getter
294
298
and setter functions, respectively.
295
299
296
- ``` py
300
+ ``` ignore
297
301
reveal_type(attr_property.fget) # revealed: Literal[attr]
298
302
reveal_type(attr_property.fget(c)) # revealed: int
299
303
0 commit comments