Repository: astropy/astropy (Python)

Issue:
astropy 6.0.1 breaks using quantities as unit exponents
### Description

This works in astropy 6.0.0:

```
u.m**u.Quantity(2)
```

but raises an exception in astropy 6.0.1:

```
u.m**u.Quantity(2)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[2], line 1
----> 1 u.m**u.Quantity(2)

File ~/.local/conda/envs/gammapy-dev/lib/python3.11/site-packages/astropy/units/core.py:831, in UnitBase.__pow__(self, p)
    829 def __pow__(self, p):
    830     p = validate_power(p)
--> 831     return CompositeUnit(1, [self], [p], _error_check=False)

File ~/.local/conda/envs/gammapy-dev/lib/python3.11/site-packages/astropy/units/core.py:2341, in CompositeUnit.__init__(self, scale, bases, powers, decompose, decompose_bases, _error_check)
   2339         scale *= unit.scale**power
   2340         self._bases = unit.bases
-> 2341         self._powers = [
   2342             sanitize_power(operator.mul(*resolve_fractions(p, power)))
   2343             for p in unit.powers
   2344         ]
   2346     self._scale = sanitize_scale(scale)
   2347 else:
   2348     # Regular case: use inputs as preliminary scale, bases, and powers,
   2349     # then "expand and gather" identical bases, sanitize the scale, &c.

File ~/.local/conda/envs/gammapy-dev/lib/python3.11/site-packages/astropy/units/core.py:2342, in <listcomp>(.0)
   2339         scale *= unit.scale**power
   2340         self._bases = unit.bases
   2341         self._powers = [
-> 2342             sanitize_power(operator.mul(*resolve_fractions(p, power)))
   2343             for p in unit.powers
   2344         ]
   2346     self._scale = sanitize_scale(scale)
   2347 else:
   2348     # Regular case: use inputs as preliminary scale, bases, and powers,
   2349     # then "expand and gather" identical bases, sanitize the scale, &c.

File ~/.local/conda/envs/gammapy-dev/lib/python3.11/site-packages/astropy/units/utils.py:291, in sanitize_power(p)
    288 denom = getattr(p, "denominator", None)
    289 if denom is None:
    290     # This returns either a (simple) Fraction or the same float.
--> 291     p = maybe_simple_fraction(p)
    292     # If still a float, nothing more to be done.
    293     if isinstance(p, float):

File ~/.local/conda/envs/gammapy-dev/lib/python3.11/site-packages/astropy/units/utils.py:217, in maybe_simple_fraction(p, max_denominator)
    215 if p == 0 or p.__class__ is int or p.__class__ is Fraction:
    216     return p
--> 217 n, d = p.as_integer_ratio()
    218 a = n // d
    219 # Normally, start with 0,1 and 1,0; here we have applied first iteration.

File ~/.local/conda/envs/gammapy-dev/lib/python3.11/site-packages/astropy/units/quantity.py:1108, in Quantity.__getattr__(self, attr)
   1103 """
   1104 Quantities are able to directly convert to other units that
   1105 have the same physical type.
   1106 """
   1107 if not self._include_easy_conversion_members:
-> 1108     raise AttributeError(
   1109         f"'{self.__class__.__name__}' object has no '{attr}' member"
   1110     )
   1112 def get_virtual_unit_attribute():
   1113     registry = get_current_unit_registry().registry

AttributeError: 'Quantity' object has no 'as_integer_ratio' member
```



### Expected behavior

Bugfix releases don't introduce breaking changes

### How to Reproduce

```python
import astropy.units as u

u.m**u.Quantity(2)
```


### Versions

astropy 6.0.1



Discussion:
Bisected to:

```
$ git bisect start v6.0.1 v6.0.0
$ git bisect run python -c 'import astropy.units as u; u.m**u.Quantity(2)'
...

502b66716ac62f47580c6c7884a29164b22e55e0 is the first bad commit
commit 502b66716ac62f47580c6c7884a29164b22e55e0
Author: P. L. Lim <2090236+pllim@users.noreply.github.com>
Date:   Mon Feb 19 13:33:10 2024 -0500

    Backport PR #16058: BUG: ensure powers of units are consistently as simple as possible

 astropy/units/core.py               |  6 ++--
 astropy/units/tests/test_units.py   | 50 +++++++++++++++++++++++++++----
 astropy/units/utils.py              | 60 ++++++++++++++++++++++++++++---------
 docs/changes/units/16058.bugfix.rst |  5 ++++
 4 files changed, 100 insertions(+), 21 deletions(-)
 create mode 100644 docs/changes/units/16058.bugfix.rst
```
@pllim 
I was going to say that https://github.com/astropy/astropy/pull/16058 was the likely suspect but you've already confirmed it with a bisection. Thank you ! I'll take a look now and see if we can fix it simply or if we should revert #16058 instead.
found a simple fix, will open a PR in a minute
fixed in #16261 



Patch:
diff --git a/astropy/units/utils.py b/astropy/units/utils.py
index cf40f8318a00..c62e2f0b90e1 100644
--- a/astropy/units/utils.py
+++ b/astropy/units/utils.py
@@ -214,7 +214,7 @@ def maybe_simple_fraction(p, max_denominator=100):
     """
     if p == 0 or p.__class__ is int or p.__class__ is Fraction:
         return p
-    n, d = p.as_integer_ratio()
+    n, d = float(p).as_integer_ratio()
     a = n // d
     # Normally, start with 0,1 and 1,0; here we have applied first iteration.
     n0, d0 = 1, 0
diff --git a/docs/changes/units/16261.bugfix.rst b/docs/changes/units/16261.bugfix.rst
new file mode 100644
index 000000000000..ed5186b0cd30
--- /dev/null
+++ b/docs/changes/units/16261.bugfix.rst
@@ -0,0 +1,2 @@
+Using a dimensionless ``Quantity`` as an exponent works anew.
+In astropy 6.0.1 an exception was erroneously raised.


Test patch:
diff --git a/astropy/units/tests/test_quantity.py b/astropy/units/tests/test_quantity.py
index 1b1e571e9a46..746342512156 100644
--- a/astropy/units/tests/test_quantity.py
+++ b/astropy/units/tests/test_quantity.py
@@ -16,6 +16,7 @@
 from astropy.utils import isiterable, minversion
 from astropy.utils.compat import COPY_IF_NEEDED
 from astropy.utils.exceptions import AstropyWarning
+from astropy.utils.masked import Masked
 
 """ The Quantity class will represent a number + unit + uncertainty """
 
@@ -468,6 +469,16 @@ def test_power(self):
         assert_array_almost_equal(new_quantity.value, 1489.355288, decimal=7)
         assert new_quantity.unit == u.Unit("m^3")
 
+    @pytest.mark.parametrize(
+        "exponent_type",
+        [int, float, np.uint64, np.int32, np.float32, u.Quantity, Masked],
+    )
+    def test_quantity_as_power(self, exponent_type):
+        # raise unit to a dimensionless Quantity power
+        # regression test for https://github.com/astropy/astropy/issues/16260
+        q = u.m ** exponent_type(2)
+        assert q == u.m**2
+
     def test_matrix_multiplication(self):
         a = np.eye(3)
         q = a * u.m