AttributeError: '_HeaderCommentaryCards' object has no attribute 'keys'
See original GitHub issueDescription
The _HeaderCommentaryCards
class is registered as a Mapping
(via its parent _CardAccessor
, here), but has no method keys()
. Therefore, when using isinstance
to check if a commentary card instance is a mapping before using a Mapping
method such as keys()
leads to an error. This seems true for _CardAccessor
and its two subclasses (_HeaderCommentaryCards
and _HeaderComments
). I encountered this bug in a code that parses a header and treats each value differently depending on its type (in the munch package, but I reproduced a simple example below).
Is this behaviour expected, in which case using hasattr
or try/except
instead of isinstance
in the client code would fix the issue ?
If this is indeed a bug in astropy, I’d be happy to help, although I don’t have prior experience with astropy development.
Expected behavior
I think the expected behaviour would be that _HeaderCommentaryCards
is treated as a Sequence, according to this section of the documentation. It seems that having keys would be useful in the case of _HeaderComments
, and for _CardAccessor
itself I do not know. I am not very experienced with the inner workings of astropy
so I might be wrong on the expected behaviour. But in any case it seems the object should either be recognized as a mapping and have keys, or be registered as a sequence if it does not have keys. (There is a TODO comment about dict/list methods for CardAccessor
in the source code.)
Actual behavior
_HeaderCommentaryCards
(and all _CardAccessor
instances) are regognized as mappings, but have no keys()
method. This results in an error: AttributeError: '_HeaderCommentaryCards' object has no attribute 'keys'
.
Steps to Reproduce
- Read or create a header with commentary cards.
- Iterate trough keys (iterating items does not reproduce because it parses commentary card values one at a time).
- Check if keys are instances of mapping.
- If true, try to access access their
keys()
method.
from typing import Mapping
from astropy.io import fits
hdr = fits.Header()
hdr['SOMEKEY'] = 'somevalue' # regular value, no error
# NOTE: Commenting all of the commentary keys removes the issue
hdr['HISTORY'] = 'history1'
hdr['HISTORY'] = 'history2'
hdr[''] = 'blank1'
hdr[''] = 'blank2'
hdr['COMMENT'] = 'A comment'
hdr['COMMENT'] = 'Another comment'
for k in hdr.keys():
if isinstance(hdr[k], Mapping):
k.keys()
System Details
Linux-5.12.11-300.fc34.x86_64-x86_64-with-glibc2.33 Python 3.9.5 (default, May 14 2021, 00:00:00) [GCC 11.1.1 20210428 (Red Hat 11.1.1-1)] Numpy 1.20.3 astropy 4.3.dev1751+gf911ec116 Scipy 1.7.0 Matplotlib 3.4.2
Issue Analytics
- State:
- Created 2 years ago
- Comments:8 (5 by maintainers)
Top GitHub Comments
I started a discussion about this hoping to get a bit more insight… https://discuss.python.org/t/mapping-abc-and-friends-are-the-mixin-methods-required-to-satisfy-the-interface/9499
@vandalt I believe your understanding is correct, and it tracks with what I wrote here: https://discuss.python.org/t/mapping-abc-and-friends-are-the-mixin-methods-required-to-satisfy-the-interface/9499/3?u=embray
I just wish this were made more clear in the documentation.
I think I will just remove the
Mapping
.register calls. I don’t think they’re providing any necessary value.