-
-
Notifications
You must be signed in to change notification settings - Fork 385
How to rename attributes and still support the old name of it? #417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Do you need it for init or just access? You could solve access easily by adding a property that returns the value of the new name. |
For init |
you should then use your new name as an attribute and create a property with the old one, right? |
The problem is that the old JSON has the old attribute. I load the JSON to the dict and then I use the dict with cattrs to create the attr annotated class. Normally I would modify the |
This sounds like a feature for cattrs rather than attrs TBH? cc @Tinche |
@hynek It would feel more like attrs as I am trying to make the old and the new interfaces of the class compatible. Something like an 'alias' for attr.ib would be great here IMO. |
This sounds more like a problem for cattrs than attrs. I would just write a loading function manually that checks the dict for the old value and register it as a structure hook in cattrs. |
Think about this use case - you update a Python lib that you develop and that uses the attrs. You update it by changing some attribute name. This would break the old clients (users) of the lib as they won't be able to initialize a class with the old attribute name. Normally you would write init (that accepts the old name) and add a @Property getter so it wouldn't break for the users. cattrs and dict and json is just one of the use cases. |
Right, but you phrased the initial description as a JSON problem. :-) Mapping JSON schema names to python object attributes is what's not But I think I understand that there could be a feature for keyword argument aliases in the generated |
I'm kibitzing, but the solution proposed in #393 seems relevant. Support for a user-defined |
I have the same problem as the original post. I'm using cattrs to populate attrs classes from JSON. Some of the JSON keys have different names from the class attributes. https://pypi.org/project/related/ uses |
Maybe the solution is to have two separate converters: one for the old attribute names, and one for the new ones. import json
import attr
from cattr.gen import make_dict_structure_fn, override
from cattr.preconf.json import make_converter
@attr.define
class Person:
full_name: str
old_converter = make_converter()
old_converter.register_structure_hook(Person, make_dict_structure_fn(
Person, old_converter, full_name=override(rename='fullName')))
old_json = '{"fullName": "John Doe"}'
old_converter.structure(json.loads(old_json), Person)
# Person(full_name='John Doe')
new_converter = make_converter()
new_json = '{"full_name": "John Doe"}'
new_converter.structure(json.loads(new_json), Person)
# Person(full_name='John Doe') |
And @TomGoBravo, for nested attributes, which I'm assuming come from a composition of objects of different classes, you can register converter hooks for each separate class: import json
import attr
from cattr.gen import make_dict_structure_fn, override
from cattr.preconf.json import make_converter
@attr.define
class Job:
role: str
@attr.define
class Person:
full_name: str
job: Job
old_converter = make_converter()
old_converter.register_structure_hook(Job, make_dict_structure_fn(
Job, old_converter, role=override(rename='roleName')))
old_converter.register_structure_hook(Person, make_dict_structure_fn(
Person, old_converter, full_name=override(rename='fullName')))
old_json = '{"fullName": "Roger Wilco", "job": {"roleName": "janitor"}}'
old_converter.structure(json.loads(old_json), Person)
# Person(full_name='Roger Wilco', job=Job(role='janitor')) |
what @ericbn suggested have runtime penalty the is not nececery if the the new attributed was added to |
The case that I ran into was that I needed to rename a variable but I still would like to support the old JSON that used the old name.
Basically, I am looking for some kind of hook if the old attribute is supplied, use it for the new name, but do not use that old name anywhere else. I mostly use cattrs to do the loading/dumping of the classes.
The text was updated successfully, but these errors were encountered: