Implicit outputs from module invocations. Usually users do not interact with `OutputCollection` directly, but via `InvocationContext.add_{summary, state_update, module_output}()`.
| 249 | |
| 250 | |
| 251 | class OutputCollection(NamedTuple): |
| 252 | """Implicit outputs from module invocations. |
| 253 | |
| 254 | Usually users do not interact with `OutputCollection` directly, but via |
| 255 | `InvocationContext.add_{summary, state_update, module_output}()`. |
| 256 | """ |
| 257 | |
| 258 | summaries: NestedTensor |
| 259 | state_updates: NestedTensor |
| 260 | module_outputs: NestedTensor |
| 261 | |
| 262 | def __contains__(self, name: str) -> bool: |
| 263 | return name in self.summaries |
| 264 | |
| 265 | def add_child(self, name: str) -> "OutputCollection": |
| 266 | if not re.fullmatch("^[a-z][a-z0-9_]*$", name): |
| 267 | raise ValueError(f'Invalid child name "{name}"') |
| 268 | if name in self: |
| 269 | raise OutputConflictError(f"{name} already present") |
| 270 | child = new_output_collection() |
| 271 | self.summaries[name] = child.summaries |
| 272 | self.state_updates[name] = child.state_updates |
| 273 | self.module_outputs[name] = child.module_outputs |
| 274 | return child |
| 275 | |
| 276 | def update(self, collection: "OutputCollection"): |
| 277 | self.summaries.update(**collection.summaries) |
| 278 | self.state_updates.update(**collection.state_updates) |
| 279 | self.module_outputs.update(**collection.module_outputs) |
| 280 | |
| 281 | |
| 282 | def new_output_collection(): |
no outgoing calls