Skip to content

units.quantity_input with annotated Quantity type hint in a Union causes error #17017

@vandalt

Description

@vandalt

Description

Hi!

I'm not sure if this is a bug report or feature request for unsupported use case.

I have a case where an argument could be either a Quantity or a string that will later be converted to quantity. I tried type hinting with Union[Quantity["angle"], str], but this causes the error shown below when using a string as the argument. See the minimal example below for the error when using the units.quantity_input decorator.

My understanding of the issue is it comes from the QuantityInput decorator: non-quantity parts of the Union are set to False and then dropped from valid_targets before the decorator performs a check on the quantity. Then if the argument is not a quantity the check will fail because the string has no units.

Thank you!

Expected behavior

The behavior I would have expected is that non-quantity types are considered as part of the Union when validating the input. I could see two ways to fix/support this:

  1. Recognize other types parts of Union and check if the argument isinstance of one of them when it's not a Quantity
  2. When the type is a union, just drop validation, as would be the case with a non-annotated quantity. I think this is less desirable as it could let pass wrong units unexpectedly for users.

I could try implementing one of these if you think it is a good way forward.

How to Reproduce

  1. Install latest main branch from github
  2. Run the snippet below
  3. Get the error below the snippet

The code:

from typing import Union

import astropy.units as u
from astropy.units import Quantity


@u.quantity_input
def afun(length_or_str: Union[Quantity["length"], str]):
    print(f"Worked with {length_or_str}")

afun(1 * u.m)  # Works
afun("1m")  # Fails

The error:

Worked with 1.0 m
Traceback (most recent call last):
  File "/home/vandal/repos/astro/astropy/astropy/units/decorators.py", line 69, in _validate_arg_value
    if arg.unit.is_equivalent(allowed_unit, equivalencies=equivalencies):
       ^^^^^^^^
AttributeError: 'str' object has no attribute 'unit'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/vandal/repos/astro/astropy/quantity_input_minimal.py", line 12, in <module>
    afun("1m")  # Fails
    ^^^^^^^^^^
  File "/home/vandal/repos/astro/astropy/astropy/units/decorators.py", line 298, in wrapper
    _validate_arg_value(
  File "/home/vandal/repos/astro/astropy/astropy/units/decorators.py", line 78, in _validate_arg_value
    raise TypeError(
TypeError: Argument 'length_or_str' to function 'afun' has no 'unit' attribute. You should pass in an astropy Quantity instead.

Versions

import astropy
try:
    astropy.system_info()
except AttributeError:
    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")
# Paste the result here
platform
--------
platform.platform() = 'Linux-6.10.9-arch1-2-x86_64-with-glibc2.40'
platform.version() = '#1 SMP PREEMPT_DYNAMIC Tue, 10 Sep 2024 14:37:32 +0000'
platform.python_version() = '3.12.5'

packages
--------
astropy              7.0.0.dev436+g3b88b55dfc
numpy                2.0.0
scipy                1.14.0
matplotlib           3.9.1
pandas               2.2.2
pyerfa               2.0.1.4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions