Glad that bug got fixed! – but where are we on the documentation question. It seems there are two options:
- This is a supported feature of Python
or
- This is an implementation detail that may or may not be supported in other versions / implementations of Python.
I think not documenting it is a clearly bad idea.
If (1) then it should be documented so other implementations know that it needs to be supported. And some clarity on exactly what is supported would be good.
if (2) then it needs to be documented so users are warned that they are relying on an implementation detail.
Given that there is code in the wild that uses this feature, and has for years, I think (1) is probably the way to go.
That leaves a clear definition of what “this” is. Here’s a stab at it:
In all instances where a python name is specified/stored in a container or variable, the name must be a string, but may be a non-valid python identifier.
Examples:
__dict__
and **kwargs
may not have non-string keys, but may have non-valid strings as identifiers (e.g. "this-name"
).
getattr()
and setattr()
will except only strings, but those may not be valid identifiers. (e.g. setattr(obj, "this-name", value
)
As for the “wild side of Unicode” – I have no idea how to define or describe that – but it would be good to do so – at least to say that the results may be undefined.
Along those lines – I recall a fairly recent conversation somewhere (maybe python-dev?) about the normalization of Unicode in identifiers – e.g. various versions of letters that are essentially a font different (like Blackboard Bold) are normalized to the same letter by the interpreter:
In [6]: ℂhris = 5
In [7]: Chris
Out[7]: 5
(that C is "\u2102"
in the first instance, and a regular C in the second)
But this transformation is not done by setattr()
, nor I assume (Not tested) by any direct setting to dict and the like.
In [14]: setattr(obj, "ℂhris", 5)
In [15]: getattr(obj, "Chris")
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-15-ddf0ae72b865> in <module>
----> 1 getattr(obj, "Chris")
AttributeError: 'Dummy' object has no attribute 'Chris'
In [16]: getattr(obj, "ℂhris")
Out[16]: 5
This should probably be documented as well.