Open
Description
- cattrs version: 23.2.3
- Python version: 3.11.5
- Operating System: Windows 10
Description
I am trying to create a union type which uses an existing key to determine the type to use.
Looking at an example object, the "type" key word is used by the application to set up the correct type of device, and I want to use it to enable additional configuration settings:
{
"device": {
"type": "special",
"hostname": "hostname",
"port": 1234
}
}
When I use configure_tagged_union(..., tag_name="type" ...)
, the "type" key seems to be consumed and is no longer available for the Device data class. This is causing a key error during the structure process.
What do I need to do to keep the "type" data available and use it for the tagged union?
What I Did
Example code:
import attrs
from cattrs import Converter
from cattrs.strategies import configure_tagged_union
@attrs.define
class SpecialDevice:
hostname: str
port: int
type: str
@attrs.define
class StandardDevice:
hostname: str
type: str
Device = SpecialDevice | StandardDevice
@attrs.define
class Settings:
device: Device
def tag_generator(t) -> str:
return {
SpecialDevice: "special",
StandardDevice: "standard"
}[t]
c = Converter()
configure_tagged_union(Device, c, tag_name="type", tag_generator=tag_generator, default=StandardDevice)
settings = c.structure(
{
"device": {
"type": "special",
"hostname": "hostname",
"port": 1234
}
}, Settings)
print(settings)
Traceback:
+ Exception Group Traceback (most recent call last):
| File "AppData\Roaming\JetBrains\PyCharm2023.3\scratches\scratch.py", line 36, in <module>
| settings = c.structure(
| ^^^^^^^^^^^^
| File ".virtualenvs\gantry-control-1-NYP4DbyD\Lib\site-packages\cattrs\converters.py", line 332, in structure
| return self._structure_func.dispatch(cl)(obj, cl)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "<cattrs generated structure __main__.Settings>", line 9, in structure_Settings
| cattrs.errors.ClassValidationError: While structuring Settings (1 sub-exception)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "<cattrs generated structure __main__.Settings>", line 5, in structure_Settings
| File ".virtualenvs\gantry-control-1-NYP4DbyD\Lib\site-packages\cattrs\converters.py", line 632, in _structure_union
| return handler(obj, union)
| ^^^^^^^^^^^^^^^^^^^
| File ".virtualenvs\gantry-control-1-NYP4DbyD\Lib\site-packages\cattrs\strategies\_unions.py", line 106, in structure_tagged_union
| return _tag_to_hook[val.pop(_tag_name)](val)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File ".virtualenvs\gantry-control-1-NYP4DbyD\Lib\site-packages\cattrs\strategies\_unions.py", line 57, in structure_union_member
| return _h(val, _cl)
| ^^^^^^^^^^^^
| File "<cattrs generated structure __main__.SpecialDevice>", line 19, in structure_SpecialDevice
| cattrs.errors.ClassValidationError: While structuring SpecialDevice (1 sub-exception)
| Structuring class Settings @ attribute device
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "<cattrs generated structure __main__.SpecialDevice>", line 15, in structure_SpecialDevice
| KeyError: 'type'
| Structuring class SpecialDevice @ attribute type
+------------------------------------