Repository navigation
convert NamedTuples to @dataclass #38
Description
Activity
If I recall correctly, we favor
NamedTuplewhenever possible so that the underlying data structure is guaranteed to be immutable by default. We use@dataclasseswhen mutability is required.
ReplacingNamedTupleby@dataclassesmay not alter the program behavior though it may prevent the type-checker from detecting potential bugs caused by mutations.That said if that causes problems for the wrapper you are writing, we could change this convention. I see that
@dataclasseswere introduced in python 3.7 and that they also support immutability via thefrozenflag, so I wonder if it was meant to fully replaceNamedTuplethough the doc does not clarify: https://docs.python.org/3/library/dataclasses.htmlAhh, that's great reasoning. A big part of the project I'm working on is letting users modify generated models such as adding nodes, updating vulnerability descriptions, etc. This would be easier (albeit riskier) to do with mutable
@dataclassesbut perhapsfrozen@dataclasseswould strike a good balance.Also,
@dataclasseshave been a lot easier for me to serialize into JSON as opposed toNamedTuples, which did not yield me good results. It might be that they were not designed with that functionality in mind. On my end, I had to change a coupleNamedTuplesinto@dataclassesto be able to send data over to the frontend. (I tried using the YAML serializer but that brought me a few problems, unfortunately.)Jonathan Esteban (@jonabox) Have you tried the
orjsonserialization package (https://github.com/ijl/orjson/) mentioned in one of the answers to the stackoverflow article you cited? According to the doc it handlesNameTuplescorrectly.Not quite, I ended up changing
NamedTuplesinto@dataclasses(), some of them frozen. I then added an encode method to these classes to fine-control thejson.dumps()output. For example:@dataclass(frozen=True) class CachedCredential(): """Encodes a machine-port-credential triplet""" node: NodeID port: PortName credential: CredentialID def encode(self): return dataclasses.asdict(self) cachedCredential = CachedCredential(node="client", port="TCP", credential="TCP-credential" ) json.dumps(cachedCredential, default=lambda x: x.encode()) # returns {"node": "client", "port": "TCP", "credential": "TCP-credential"}
I might still try orjson, and get back with any findings, but those slight modifications have worked really well for me so far.
Hi, I'm creating a frontend wrapper for this project and noticed that NamedTuple and @dataclasses are used almost interchangeably in model.py. I was wondering why that's the case and if it would be possible to just change all NamedTuples to @dataclasses. This would make the model more consistent. I tried changing it for a couple classes and didn't notice anything breaking.