Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SkyCoord class is Iterable, yet raises exception when trying to iterate scalars. #16172

Closed
dobos opened this issue Mar 6, 2024 · 7 comments
Closed

Comments

@dobos
Copy link

dobos commented Mar 6, 2024

Description

As of version 5.2.2, isinstance(SkyCoord(10, 10, unit=u.degree), Iterable) evaluates to True and member functions __iter__ and __len__ are present, hasattr(c, '__len__') evaluates to True. Yet calls to __iter__ or __len__ result in an exception when only a single pair of coordinates is wrapped.

Expected behavior

Either make sure that __iter__ and __len__ are not present when SkyCoord is just a single pair of coordinates, or implement the iterator over that single value. Throwing an exception from __len__ or __iter__ is not how other Python libraries work. Since testing if an object is an instance of Iterable translates to something like hasattr(c, '__iter__'), implementing the single-element iterator is easier, or the scalar SkyCoord should be monkey-patched somehow by explicitly removing the functions from the object. The issue probably affects all classes that inherit from ShapedLikeNDArray.

How to Reproduce

  1. Run the code below with the latest version of astropy installed.
from collections.abc import Iterable
from astropy.coordinates import SkyCoord
import astropy.units as u

cc = SkyCoord(0 * u.deg, 0 * u.deg)
if isinstance(cc, Iterable):
  for c in cc:     # __iter__ will throw an exception
    print(c)

Versions

import platform; print(platform.platform())
import sys; print("Python", sys.version)
import astropy; print("astropy", astropy.__version__)
import numpy; print("Numpy", numpy.__version__)
import erfa; print("pyerfa", erfa.__version__)
try:
    import scipy
    print("Scipy", scipy.__version__)
except ImportError:
    print("Scipy not installed")
try:
    import matplotlib
    print("Matplotlib", matplotlib.__version__)
except ImportError:
    print("Matplotlib not installed")
Linux-4.18.0-348.20.1.el8_5.x86_64-x86_64-with-glibc2.28
Python 3.10.9 | packaged by conda-forge | (main, Feb  2 2023, 20:20:04) [GCC 11.3.0]
astropy 5.2.2
Numpy 1.24.4
pyerfa 2.0.0.2
Scipy 1.10.1
Matplotlib 3.7.1

EDIT: xref #5481

@dobos dobos added the Bug label Mar 6, 2024
Copy link

github-actions bot commented Mar 6, 2024

Welcome to Astropy 👋 and thank you for your first issue!

A project member will respond to you as soon as possible; in the meantime, please double-check the guidelines for submitting issues and make sure you've provided the requested details.

GitHub issues in the Astropy repository are used to track bug reports and feature requests; If your issue poses a question about how to use Astropy, please instead raise your question in the Astropy Discourse user forum and close this issue.

If you feel that this issue has not been responded to in a timely manner, please send a message directly to the development mailing list. If the issue is urgent or sensitive in nature (e.g., a security vulnerability) please send an e-mail directly to the private e-mail feedback@astropy.org.

@mhvk
Copy link
Contributor

mhvk commented Mar 6, 2024

SkyCoord (and Time and Quantity) share this behaviour with numpy ndarray:

In [1]: import numpy as np

In [2]: from collections.abc import Iterable

In [3]: a = np.array(0)

In [4]: isinstance(a, Iterable)
Out[4]: True

In [5]: iter(a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [5], line 1
----> 1 iter(a)

TypeError: iteration over a 0-d array

This is an unfortunate consequence of python's ideas of what makes something iterable not being a good match to arrays, where one really wants to distinguish shape () from shape (1,).

Anyway, regardless of what one thinks about the logic, astropy will have to continue to follow numpy in this regard, so I'll mark this issue as close? and upstream fix required.

p.s. Internally, we use utils.isiterable to test whether or not something can be iterated (which does a simple try/except around iter()).

Copy link

github-actions bot commented Mar 7, 2024

Hi humans 👋 - this issue was labeled as Close? approximately 8 hours ago. If you think this issue should not be closed, a maintainer should remove the Close? label - otherwise, I will close this issue in 7 days.

If you believe I commented on this issue incorrectly, please report this here

@neutrinoceros
Copy link
Contributor

Kinda related, see numpy/numpy#19833 for a precedent.

@eerovaher
Copy link
Member

This is an exact duplicate of #13172

@mhvk
Copy link
Contributor

mhvk commented Mar 7, 2024

Well, at least we independently give the same feedback and advice!

Copy link

I'm going to close this issue as per my previous message, but if you feel that this issue should stay open, then feel free to re-open and remove the Close? label.

If this is the first time I am commenting on this issue, or if you believe I closed this issue incorrectly, please report this here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants