[issue40583] Runtime type annotation mutation leads to inconsistent behavior
New submission from Saumitro Dasgupta : Adding type annotations at runtime may lead to inconsistent results. Consider the following example: class Base: base: int class Alpha(Base): pass class Beta(Base): foobar: int # Case 1: This mutates Base's __annotations__ Alpha.__annotations__['injected'] = bool assert Alpha.__annotations__ is Base.__annotations__ # Case 2: This mutates Beta's own copy of __annotations__ Beta.__annotations__['injected'] = bool Such mutations of __annotations__ seem to be perfectly legal (https://www.python.org/dev/peps/pep-0526/#runtime-effects-of-type-annotations). However: 1. In case 1, this leads to the accidental mutation of Base's annotations. Not entirely certain if that's expected, but seems undesirable. 2. There are further differences when looking at `__dict__['__annotations__']`: for Alpha, there is no __annotations__ entry in __dict__. However, for Beta, it's set to `{'foobar': , 'injected': }`. This discrepancy leads to further inconsistent results. In particular, when transforming these classes to dataclasses, which specifically looks at __dict__['__annotations__'](https://github.com/python/cpython/blob/3.8/Lib/dataclasses.py#L856). Converting Alpha to a dataclass leads to no fields. Converting Beta to a dataclass leads to two fields (foobar and injected). It's worth noting that typing.get_type_hints produces reasonable results here. -- components: Interpreter Core, Library (Lib) messages: 368569 nosy: Saumitro Dasgupta priority: normal severity: normal status: open title: Runtime type annotation mutation leads to inconsistent behavior type: behavior versions: Python 3.8 ___ Python tracker <https://bugs.python.org/issue40583> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40583] Runtime type annotation mutation leads to inconsistent behavior
Saumitro Dasgupta added the comment: In my opinion, the main problem here is the element of surprise. Given a statement like this: foo.__annotations__['injected'] = bool the expressed intent is "extend this object's annotations". It's surprising that it can sometimes result in accidental mutation of the base's annotations. This surprise may manifest downstream in other parts of the standard library (like dataclasses in the example above), which can be a bit cryptic. As a performance optimization, it makes sense. However, the element of surprise probably can be improved upon. For instance: - Explicitly disallow accidental mutation by presenting the parent's dict via a MappingProxy - Use a "copy-on-write" mechanism -- ___ Python tracker <https://bugs.python.org/issue40583> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40583] Runtime type annotation mutation leads to inconsistent behavior
Saumitro Dasgupta added the comment: I'd argue that the situation is a bit different from class variables here, since __annotations__ is indirectly brought into existence by the presence of statically-established type annotations. You can be perfectly aware of how class variables work yet find this surprising, since you'd have to be aware of the additional bit of detail pointed out by Ivan above. -- ___ Python tracker <https://bugs.python.org/issue40583> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40583] Runtime type annotation mutation leads to inconsistent behavior
Saumitro Dasgupta added the comment: Fair enough. If that's the consensus, I'll close the issue. -- ___ Python tracker <https://bugs.python.org/issue40583> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40583] Runtime type annotation mutation leads to inconsistent behavior
Change by Saumitro Dasgupta : -- resolution: -> wont fix stage: -> resolved status: open -> closed ___ Python tracker <https://bugs.python.org/issue40583> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com