|
|
Subscribe / Log in / New account

Improving Python's SimpleNamespace

Improving Python's SimpleNamespace

Posted Apr 29, 2020 17:18 UTC (Wed) by NYKevin (subscriber, #129325)
Parent article: Improving Python's SimpleNamespace

Honestly, SimpleNamespace has always struck me as a weird class. It feels like a dict() playing dress-up as a "real" object. But I've never understood why that is considered useful or desirable. If you have a particular schema in mind, then surely dataclasses (or attrs) are more useful than SimpleNamespace, and if you don't, then you probably ought to be using a dict instead, to call attention to the fact that d['key'] can throw. I suppose it might be useful as a shortcut for "I would use dataclasses but I don't actually need their functionality" - but then you really ought to document the schema somewhere else, and I don't think that actually saves you all that much work. dataclasses do not take a lot of typing to create, after all.

(I'm also not a huge fan of JSON's object_hook, since it's slightly too dumb to actually deal with complicated JSON object structures correctly - the type of an object is context-sensitive and needs to be recursively deduced based on the parent type, unless you were clever and preemptively tagged all of your JSON objects with a type hint. Unfortunately, I don't see that sort of tagging much in practice. So you end up just converting everything to dicts and then manually parsing it into the actual object type. A declarative way of writing these schemata, and passing them directly to json.load(), would be Nice To Have. Perhaps just pass the dataclass of the root object as an argument or something like that? dataclasses already have all the introspection support required for json to figure the rest out on its own.)


to post comments

Improving Python's SimpleNamespace

Posted Apr 29, 2020 19:44 UTC (Wed) by martin.langhoff (subscriber, #61417) [Link] (2 responses)

In some languages, simple-ish objects and dicts are used (almost) interchangeably. Some folks "fold" this into their coding style. I've seen it done in PHP and in JS.

In other words -- it's dynamic typing, applied to complex variables.

Just like dynamic typing, it works well for small projects, breaks down eventually because they are not the same thing.

Improving Python's SimpleNamespace

Posted Apr 29, 2020 22:03 UTC (Wed) by NYKevin (subscriber, #129325) [Link] (1 responses)

Dynamically-typed JSON seems like a really Bad Idea to me. JSON is an interaction point with the outside world, and very likely to contain untrusted (or only marginally trusted) data. At a bare minimum, you should be checking the types of the parsed objects, recursively in all sub-objects. Otherwise, it's ridiculously easy for an attacker to cause all sorts of headaches. Consider:

>>> ham = json.loads(r'{"eggs": 5}')
>>> ham['eggs'] * 1000000000  # Convert seconds to nanoseconds
5000000000
>>> spam = json.loads(r'{"eggs": [1, 2, 3]}')
>>> spam['eggs'] * 1000000000  # Convert tiny list to MemoryError

And I'm sure there are more "interesting" examples than just OOMing the client. But by the time you're doing recursive type checking, it's really hard to justify not using a "real" statically-checkable type like a dataclass. The only excuse I can think of is that the standard library lacks a facility to do it automatically, which is a shame because I could probably bang that out in an hour or two (with the bulk of that time devoted to re-normalizing the weird type objects in typing.py back into classes that you can hand to isinstance()).

Improving Python's SimpleNamespace

Posted Apr 30, 2020 7:11 UTC (Thu) by smurf (subscriber, #17840) [Link]

That's true, and a JsonSchemaDict that enforces not storing nonsense into it would be a superb idea (assuming it doesn't exist already), but this is orthogonal to the current discussion.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds