@@ -116,131 +116,138 @@ with the new value as the first argument.
116
116
117
117
There are two (related) APIs for adding events to dataclasses:
118
118
119
- 1 . Add a [ ` SignalGroupDescriptor ` ] [ psygnal.SignalGroupDescriptor ] as a class attribute.
119
+ ### 1. Use ` SignalGroupDescriptor `
120
120
121
- !!! example
121
+ [ ` SignalGroupDescriptor ` ] [ psygnal.SignalGroupDescriptor ] is designed to be used
122
+ as a class attribute on a dataclass-like object, and, when accessed on an
123
+ instance of that class, will return a [ ` SignalGroup ` ] [ psygnal.SignalGroup ] with
124
+ signals for each field in the class.
122
125
123
- === "dataclasses"
126
+ !!! example
124
127
125
- ```python
126
- from typing import ClassVar
127
- from psygnal import SignalGroupDescriptor
128
- from dataclasses import dataclass
128
+ === "dataclasses"
129
129
130
- @dataclass
131
- class Person:
132
- name: str
133
- age: int = 0
134
- events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
135
- ```
130
+ ```python
131
+ from typing import ClassVar
132
+ from psygnal import SignalGroupDescriptor
133
+ from dataclasses import dataclass
136
134
137
- === "pydantic"
135
+ @dataclass
136
+ class Person:
137
+ name: str
138
+ age: int = 0
139
+ events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
140
+ ```
138
141
139
- ```python
140
- from typing import ClassVar
141
- from psygnal import SignalGroupDescriptor
142
- from pydantic import BaseModel
142
+ === "pydantic"
143
143
144
- class Person(BaseModel):
145
- name: str
146
- age: int = 0
147
- events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
148
- ```
144
+ ```python
145
+ from typing import ClassVar
146
+ from psygnal import SignalGroupDescriptor
147
+ from pydantic import BaseModel
149
148
150
- *for a fully evented subclass of pydantic's `BaseModel`, see also
151
- [`EventedModel`](./API/model.md)*
149
+ class Person(BaseModel):
150
+ name: str
151
+ age: int = 0
152
+ events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
153
+ ```
152
154
153
- === "msgspec"
155
+ *for a fully evented subclass of pydantic's `BaseModel`, see also
156
+ [`EventedModel`](./model.md)*
154
157
155
- ```python
156
- from typing import ClassVar
157
- from psygnal import SignalGroupDescriptor
158
- import msgspec
158
+ === "msgspec"
159
159
160
- class Person(msgspec.Struct):
161
- name: str
162
- age: int = 0
163
- events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
164
- ```
160
+ ```python
161
+ from typing import ClassVar
162
+ from psygnal import SignalGroupDescriptor
163
+ import msgspec
165
164
166
- === "attrs"
165
+ class Person(msgspec.Struct):
166
+ name: str
167
+ age: int = 0
168
+ events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
169
+ ```
167
170
168
- ```python
169
- from typing import ClassVar
170
- from psygnal import SignalGroupDescriptor
171
- from attrs import define
171
+ === "attrs"
172
172
173
- @define
174
- class Person:
175
- name: str
176
- age: int = 0
177
- events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
178
- ```
173
+ ```python
174
+ from typing import ClassVar
175
+ from psygnal import SignalGroupDescriptor
176
+ from attrs import define
179
177
180
- 2 . Decorate the class with the [ ` @evented ` decorator] [ psygnal.evented ] .
178
+ @define
179
+ class Person:
180
+ name: str
181
+ age: int = 0
182
+ events: ClassVar[SignalGroupDescriptor] = SignalGroupDescriptor()
183
+ ```
181
184
182
- > _ Under the hood, this just adds the ` SignalGroupDescriptor ` as a class
183
- > attribute named "events" for you, as shown above). Prefer the class
184
- > attribute pattern to the decorator when in doubt._
185
+ ### 2. Use the ` @evented ` decorator
185
186
186
- !!! example
187
+ The [ ` @evented ` ] [ psygnal.evented ] decorator can be added to any dataclass-like
188
+ class. Under the hood, this just adds the ` SignalGroupDescriptor ` as a class
189
+ attribute for you (named "events" by default), as shown above. Prefer the class
190
+ attribute pattern to the decorator when in doubt, as it is more explicit and
191
+ leads to better type checking.
187
192
188
- === "dataclasses"
193
+ !!! example
189
194
190
- ```python
191
- from psygnal import evented
192
- from dataclasses import dataclass
195
+ === "dataclasses"
193
196
194
- @evented
195
- @dataclass
196
- class Person:
197
- name: str
198
- age: int = 0
199
- ```
197
+ ```python
198
+ from psygnal import evented
199
+ from dataclasses import dataclass
200
200
201
- === "pydantic"
201
+ @evented
202
+ @dataclass
203
+ class Person:
204
+ name: str
205
+ age: int = 0
206
+ ```
202
207
203
- ```python
204
- from psygnal import evented
205
- from pydantic import BaseModel
208
+ === "pydantic"
206
209
207
- @evented
208
- class Person(BaseModel):
209
- name: str
210
- age: int = 0
211
- ```
210
+ ```python
211
+ from psygnal import evented
212
+ from pydantic import BaseModel
212
213
213
- *for a fully evented subclass of pydantic's `BaseModel`, see also
214
- [`EventedModel`](./API/model.md)*
214
+ @evented
215
+ class Person(BaseModel):
216
+ name: str
217
+ age: int = 0
218
+ ```
215
219
216
- === "msgspec"
220
+ *for a fully evented subclass of pydantic's `BaseModel`, see also
221
+ [`EventedModel`](./model.md)*
217
222
218
- ```python
219
- from psygnal import evented
220
- import msgspec
223
+ === "msgspec"
221
224
222
- @evented
223
- class Person(msgspec.Struct):
224
- name: str
225
- age: int = 0
226
- ```
225
+ ```python
226
+ from psygnal import evented
227
+ import msgspec
228
+
229
+ @evented
230
+ class Person(msgspec.Struct):
231
+ name: str
232
+ age: int = 0
233
+ ```
227
234
228
- === "attrs"
235
+ === "attrs"
236
+
237
+ ```python
238
+ from psygnal import evented
239
+ from attrs import define
229
240
230
- ```python
231
- from psygnal import evented
232
- from attrs import define
241
+ @evented
242
+ @define
243
+ class Person:
244
+ name: str
245
+ age: int = 0
246
+ ```
233
247
234
- @evented
235
- @define
236
- class Person:
237
- name: str
238
- age: int = 0
239
- ```
240
-
241
- !!! tip
242
- by default, the ` SignalGroup ` instance is named ` 'events' ` , but this can be
243
- changed by passing a ` events_namespace ` argument to the ` @evented ` decorator)
248
+ !!! tip
249
+ by default, the ` SignalGroup ` instance is named ` 'events' ` , but this can be
250
+ changed by passing a ` events_namespace ` argument to the ` @evented ` decorator)
244
251
245
252
Using any of the above, you can now connect callbacks to the change events
246
253
of any field on the object (there will be a signal instance in the ` events `
@@ -270,7 +277,7 @@ def on_any_change(info: EmissionInfo):
270
277
print (f " field { info.signal.name!r } changed to { info.args} " )
271
278
```
272
279
273
- see the [ API documentation] ( ./API/evented.md ) for for more details.
280
+ see the [ API documentation] ( reference/psygnal/ ) for for more details.
274
281
275
282
## Type annotating evented dataclasses
276
283
0 commit comments