Message326044
It's working as intended. locals() and vars() simply returns the current frame's f_locals. In functions, modifying this usually accomplishes nothing useful because the code object has OPTIMIZED and NEWLOCALS flags set, meaning local variables are looked up or set via the LOAD_FAST and STORE_FAST opcodes (respectively) which doesn't even look in the f_locals mapping. In this case, vars() and locals() will build a new dict[*] and fill it with the frame's fastlocals and unpack any closure cells into it.
The code object used for class bodies however is special and actually *does* use the mapping in f_locals, which for for classes ultimately built by builtins.__build_class__ (aka classes built with a `class` statement) will be whatever the metaclass's __prepare__ returns, which in the case of enums is an enum._EnumDict instance.
So that's why metaclasses are so powerful. You don't even need to use a dictionary subclass as the class namespace, since the STORE_NAME opcode will use PyObject_SetItem; however type.__new__ will make you cast it to a dict, and even the dict that is wrapped by a MappingProxy after the class has been created will be a copy anyway.
So anyway, there's nothing actually wrong with the current behavior. dict.update never calls `self.__getitem__`, and since `_EnumDict.__setitem__` is where all of the magic happens regular dict.update won't trigger it. I agree though that adding an update method would be nice though and can be done in just a few lines of code.
import enum
import sys
def local_update(it=(), **kws):
self = sys._getframe(1).f_locals
d = dict(it, **kws)
for k, v in d.items():
self[k] = v
class MyEnum(enum.Enum):
local_update(a=1, b=2)
assert MyEnum.a.value == 1
[*] it doesn't actually build a new one every time but the only practical purpose with the NEWLOCALS code.co_code flag set is for introspection with vars(), locals(), and sys._getframe |
|
Date |
User |
Action |
Args |
2018-09-21 21:26:46 | bup | set | recipients:
+ bup, ethan.furman, Antony.Lee, josh.r |
2018-09-21 21:26:46 | bup | set | messageid: <1537565206.14.0.956365154283.issue34750@psf.upfronthosting.co.za> |
2018-09-21 21:26:46 | bup | link | issue34750 messages |
2018-09-21 21:26:46 | bup | create | |
|