python-attrs / python-attrs/cattrs
Structure when input is already partially structured
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 159
- Avg merge
- 12h 21m
- Merged PRs (30d)
- 6
Description
- cattrs version: 0.9.0
- Python version: 3.7.5
- Operating System: Mac OSX
Description
I am attempting to structure a blob of data into a recursive structure, where part of the blob has already been structured. When it reaches a key that already has a structured value, it errors out. After reading through the documentation it's unclear how to get around this issue.
What I would expect to happen is if a given key already has (valid) structured data, it includes it as is, rather than attempting to (and failing to) structure it.
I'm not sure if I am missing an obvious workaround (converter or hook?), or if this would require a PR to run a check of some sort before attempting to structure a sub-element.
What I Did
This is a minimal example:
from attr import dataclass
from cattr import structure, unstructure
@dataclass(auto_attribs=True)
class B:
name: str
@dataclass(auto_attribs=True)
class A:
name: str
subber: B
dx = {
"name": "alphas",
"subber": {
"name": "subclass"
}
}
a = structure(dx, A)
print(a)
b = structure(dx.get("subber"), B)
print(b)
dy = {
"name": "tau",
"subber": unstructure(b)
}
a2 = structure(dy, A)
print(a2)
dz = {
"name": "omega",
"subber": b
}
a3 = structure(dz, A)
The above produces the following output:
A(name='alphas', subber=B(name='subclass'))
B(name='subclass')
A(name='tau', subber=B(name='subclass'))
Traceback (most recent call last):
File "/Users/nford/Library/Preferences/IntelliJIdea2019.2/scratches/dc.py", line 46, in <module>
a3 = structure(dz, A)
File "/Users/nford/echelon/rolevp/echelon/.venv/lib/python3.7/site-packages/cattr/converters.py", line 178, in structure
return self._structure_func.dispatch(cl)(obj, cl)
File "/Users/nford/echelon/rolevp/echelon/.venv/lib/python3.7/site-packages/cattr/converters.py", line 298, in structure_attrs_fromdict
conv_obj[name] = dispatch(type_)(val, type_)
File "/Users/nford/echelon/rolevp/echelon/.venv/lib/python3.7/site-packages/cattr/converters.py", line 285, in structure_attrs_fromdict
conv_obj = obj.copy() # Dict of converted parameters.
AttributeError: 'B' object has no attribute 'copy'
But what I am hoping to achieve is:
A(name='alpha', subber=B(name='subclass'))
B(name='subclass')
A(name='tau', subber=B(name='subclass'))
A(name='omega', subber=B(name='subclass'))
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the structure entry point and structure_attrs_fromdict in cattr/converters.py, using the minimal example to reproduce the failure when subber is already a B instance. Trace how nested values are dispatched and verify that the completed behavior preserves valid structured values while retaining existing dictionary handling.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100