Skip to content

Clarify exception message for non-quantity input to ufuncs#16878

Merged
mhvk merged 1 commit intoastropy:mainfrom
mhvk:units-better-error-message-for-unitless-input
Aug 25, 2024
Merged

Clarify exception message for non-quantity input to ufuncs#16878
mhvk merged 1 commit intoastropy:mainfrom
mhvk:units-better-error-message-for-unitless-input

Conversation

@mhvk
Copy link
Copy Markdown
Contributor

@mhvk mhvk commented Aug 25, 2024

This pull request is to improve the puzzling error message one can get if passing in both numbers and quantities to ufuncs, by adding an explanation (on purpose, the exception type and start of the message are not changed, to ensure this is not an API change -- there were tests in the unit package relying on it). cc @maxnoe

Before:

from erfa.ufunc import s2p
import astropy.units as u
s2p(0.5, 0.5, 5 * u.km)
AttributeError: 'NoneType' object has no attribute 'get_converter'

Now

AttributeError: 'NoneType' object has no attribute 'get_converter' (input without a 'unit' attribute? Such input is treated as dimensionless and cannot be converted to rad).

Fixes #16873

  • By checking this box, the PR author has requested that maintainers do NOT use the "Squash and Merge" button. Maintainers should respect this when possible; however, the final decision is at the discretion of the maintainer that merges the PR.

@github-actions
Copy link
Copy Markdown
Contributor

Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.

  • Do the proposed changes actually accomplish desired goals?
  • Do the proposed changes follow the Astropy coding guidelines?
  • Are tests added/updated as required? If so, do they follow the Astropy testing guidelines?
  • Are docs added/updated as required? If so, do they follow the Astropy documentation guidelines?
  • Is rebase and/or squash necessary? If so, please provide the author with appropriate instructions. Also see instructions for rebase and squash.
  • Did the CI pass? If no, are the failures related? If you need to run daily and weekly cron jobs as part of the PR, please apply the "Extra CI" label. Codestyle issues can be fixed by the bot.
  • Is a change log needed? If yes, did the change log check pass? If no, add the "no-changelog-entry-needed" label. If this is a manual backport, use the "skip-changelog-checks" label unless special changelog handling is necessary.
  • Is this a big PR that makes a "What's new?" entry worthwhile and if so, is (1) a "what's new" entry included in this PR and (2) the "whatsnew-needed" label applied?
  • At the time of adding the milestone, if the milestone set requires a backport to release branch(es), apply the appropriate "backport-X.Y.x" label(s) before merge.

Copy link
Copy Markdown
Member

@nstarman nstarman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! The parenthetical improves the error message a lot.
I would suggest adding a TODO item to convert this to an Exception Note (https://docs.python.org/3/tutorial/errors.html#enriching-exceptions-with-notes) for py3.11+. This is a nearly tailor-made example.


def test_s2p_not_all_quantity(self):
# Test for a useful error message - see gh-16873.
# Non-quantity input should be treated as dimensioness and thus cannot
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Non-quantity input should be treated as dimensioness and thus cannot
# Non-quantity input should be treated as dimensionless and thus cannot

def test_s2p_not_all_quantity(self):
# Test for a useful error message - see gh-16873.
# Non-quantity input should be treated as dimensioness and thus cannot
# be converted to radian.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# be converted to radian.
# be converted to radians.

"""Test unit errors when dimensionless parameters are used"""

msg = "'NoneType' object has no attribute 'get_converter'"
msg = "'NoneType'.*no attribute 'get_converter'.*treated as dimensionless"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nifty! I forgot about the regex-capable input.


def test_sin_with_quantity_out(self):
# Test for a useful error message - see gh-16873.
# Non-quantity input should be treated as dimensioness and thus cannot
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Non-quantity input should be treated as dimensioness and thus cannot
# Non-quantity input should be treated as dimensionless and thus cannot

def test_sin_with_quantity_out(self):
# Test for a useful error message - see gh-16873.
# Non-quantity input should be treated as dimensioness and thus cannot
# be converted to radian.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# be converted to radian.
# be converted to radians.

@mhvk mhvk force-pushed the units-better-error-message-for-unitless-input branch from f5efc6d to 9918f83 Compare August 25, 2024 19:56
@mhvk
Copy link
Copy Markdown
Contributor Author

mhvk commented Aug 25, 2024

I would suggest adding a TODO item to convert this to an Exception Note (https://docs.python.org/3/tutorial/errors.html#enriching-exceptions-with-notes) for py3.11+. This is a nearly tailor-made example.

Very nice! I went ahead and just used it, with a version check that makes the new exception message match it also for python < 3.11. Also did the other small stuff (how did I not see those??)

@mhvk mhvk enabled auto-merge August 25, 2024 19:59
try:
converter = from_unit.get_converter(to_unit)
except AttributeError as e:
# Check for lack of unit only now, to avoid delay for cases where a unit
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double unit here (last word in this line, first in the next)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, another typo, thanks for catching it... Fix in #16881

@mhvk mhvk merged commit eaeaa5b into astropy:main Aug 25, 2024
mhvk added a commit to mhvk/astropy that referenced this pull request Aug 26, 2024
pllim added a commit that referenced this pull request Aug 26, 2024
…itless-input-fixup

Fix comment added in gh-16878 [skip ci]
f"as dimensionless and cannot be converted to {to_unit}."
)
if sys.version_info >= (3, 11):
e.add_note(note)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Belated comment: I don't know how to feel about having error behavior be different based on Python version. But probably okay for this one case. 🤷‍♀️

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did check that the actual error message is exactly identical -- I thought it was easier to do it like this rather than wait for our minimum version of python to be 3.11.

But, actually, aren't we dropping support of python 3.10 by October (following SPEC 0)? If so, isn't this OK regardless?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why is "exotic archs" on Python 3.12 failing? See #16878 (review)

"""Test unit errors when dimensionless parameters are used"""

msg = "'NoneType' object has no attribute 'get_converter'"
msg = "'NoneType'.*no attribute 'get_converter'.*\n.*treated as dimensionless"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

      def test_unit_errors(self):
          """Test unit errors when dimensionless parameters are used"""
      
          msg = "'NoneType'.*no attribute 'get_converter'.*\n.*treated as dimensionless"
  >       with pytest.raises(AttributeError, match=msg):
  E       AssertionError: Regex pattern did not match.
  E        Regex: "'NoneType'.*no attribute 'get_converter'.*\n.*treated as dimensionless"
  E        Input: "'NoneType' object has no attribute 'get_converter'"
  
  astropy/units/tests/test_quantity_erfa_ufuncs.py:546: AssertionError

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyways, I opened #16884 as follow-up issue that would block v7.0 release. If no one has idea how to fix, my proposal would be to revert the exception behavior changes (but keep your clearer message). Thanks!

@mhvk mhvk deleted the units-better-error-message-for-unitless-input branch February 17, 2025 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

erfa.p2s does not accept units except for distance

4 participants