Skip to content

DOC/TST: console and unicode formatting support roundtrip - #19571

Merged
astrofrog merged 6 commits into
astropy:mainfrom
Julian-Harbeck:doc-units-formatting
May 5, 2026
Merged

astrofrog merged 6 commits into
astropy:mainfrom
Julian-Harbeck:doc-units-formatting

Conversation

@Julian-Harbeck

Copy link
Copy Markdown
Contributor

Description

This pull request just moves the console and unicode sections in the Built-In Formats section of Units and Quantities/String Representations of Units and Quantities and adds a test. Previously they both were listed as able to write, but not read, so not supporting a round trip like u.Unit(unit.to_string(format="console")). unicode seems to be fixed since #11827 (thanks @dhomeier), but for console I did not find the PR on the spot, nevertheless it seems to work since the added test works.

Fixes #

  • 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.

@dhomeier
dhomeier requested a review from mhvk April 13, 2026 18:08
mhvk
mhvk previously requested changes Apr 21, 2026

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is not quite right: the test that you added to only shows that a single unit name written out with console will roundtrip. But round-tripping is more than that: composite units should also roundtrip. This is not the case for all possibilities, though:

fluxunit = u.erg / (u.cm ** 2 * u.s)
u.Unit(fluxunit.to_string('console', fraction='inline')) == fluxunit
# True
u.Unit(fluxunit.to_string('console', fraction='multiline')) == fluxunit
# ValueError: ' erg  
------
s cm^2' did not parse as unit: Invalid character at col 6 If this is meant to be a custom unit, define it with 'u.def_unit'. To have it recognized inside a file reader or other code, enable it with 'u.add_enabled_units'. For details, see https://docs.astropy.org/en/latest/units/combining_and_defining.html

If one were to make things round-trip, we'd need a parser that understands how fractions can be typeset in different ways. This is not horribly hard, but not clear it is very useful either.

Given the above, I think we could still do the small addition to the test function, though at some level superfluous (for a single unit, the output is identical to generic). But the docs should not be changed.

Anyway, my sense would be to close, or have a different PR that explain better why those units are for output only.

@Julian-Harbeck

Copy link
Copy Markdown
Contributor Author

@mhvk Good point, I have forgotten to check multiline roundtrip (my usecase is to support JSON roundtrip and I used there console with inline for the serialization), however inline seems to work also for composite units? I think there still would be a benefit of clarifying that this works? The test could be expanded to also include composite units or would you prefer an additional test for that?

@mhvk

mhvk commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

@Julian-Harbeck - I think it would certainly be good to clarify that console can be read back if using no fraction or fraction='inline'.

I think what could work is if in your test case, you also add something like

self.check_roundtrip_decompose(unit, output_format="console", fraction="inline")

and perhaps the same for unicode.

Obviously, this would require adjusting the definition of RoundTripBase.check_roundtrip_decompose to take ouput_format and perhaps pass on all extra **kwargs.

If those tests indeed all pass for fraction=None and fraction='inline', then I think we can add this to the docs. My tendency would be to just explain it inside the part of output formats.

@mhvk mhvk added this to the v8.0.0 milestone Apr 21, 2026
@Julian-Harbeck

Copy link
Copy Markdown
Contributor Author

Great, then I will request another review from you when I implemented these changes.

@astrofrog

Copy link
Copy Markdown
Member

@Julian-Harbeck - just to check, will you have time to implement the fixes today?

@Julian-Harbeck

Copy link
Copy Markdown
Contributor Author

@astrofrog Yes will try so in the evening, did not had much time the last week. I would put the change log entry under units because the changed test is located there? There does not seem to be a doc section, so it the one in units enough or is that considered a type other change that should go into the main directory?

@pllim

pllim commented May 1, 2026

Copy link
Copy Markdown
Member

I don't think this needs a change log.

@mhvk , are you able to re-review since you requested changes? Thanks! 🙏

@Julian-Harbeck

Copy link
Copy Markdown
Contributor Author

@mhvk I moved the documentation of console and unicode back where it was before but changed the header of the section so that writing is possible for all formats below, but parsing depends on the the format. I then added another point in console that parsing is possible for fraction being set to None or inline but not multiline.

For the test I opted to add an additional test for a composite unit to be tested with different output_formats and fraction formats. I did not adapted your suggestion of just adding the following line to test_roundtrip, because for all units that are being tested there the string representation is the same for all flavours of fraction:

self.check_roundtrip_decompose(unit, output_format="console", fraction="inline")

If you or @pllim would know what fails during the doc build I am happy to implement it. I guess it has something to do with the additional code line I added to demonstrade the roundtrip in console format?

Comment thread docs/units/format.rst Resolved
@dhomeier

dhomeier commented May 2, 2026 •

Copy link
Copy Markdown
Contributor

Maybe forget about the comment on the docstring, there seems to be an issue related to IPython 9.13:
– oh well, already identified in #19594. Could you check if you have that PR, or rebase otherwise (probably have to do the latter, as the branch is flagged as non up-to-date)?

@astrofrog
astrofrog force-pushed the doc-units-formatting branch from f59ec6b to 744d36b Compare May 2, 2026 15:18
@astrofrog

Copy link
Copy Markdown
Member

I did a rebase from the UI

@dhomeier

dhomeier commented May 2, 2026 •

Copy link
Copy Markdown
Contributor

Docs are building now, but I just noted that the very next example fails to read back for console on its representation of exponential notation. In a more minimal example:

>>> thz = u.THz.decompose().to_string('console', fraction=True)
>>> thz
'1*10^12 / s'
>>> u.Unit(thz)
Traceback (most recent call last):
…
ValueError: '1*10^12 / s' did not parse as unit: Syntax error parsing unit '1*10^12 / s'

so this caveat should also be added to the docs.
For future usage, maybe consider adding an exponential option to the console format, or would '1e12 / s' conflict with console usage in any way?

[
unit
for unit in u.__dict__.values()
if (isinstance(unit, UnitBase) and not isinstance(unit, PrefixUnit))

@Julian-Harbeck Julian-Harbeck May 3, 2026 •

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.

Prefix units like u.THz are also excluded from the roundtrip test although it seems to work for the default format:

>>> isinstance(u.THz, u.PrefixUnit)
True
>>> u.THz.decompose().to_string()
'1e+12 / s'
>>> u.Unit(u.THz.decompose().to_string())
Unit("1e+12 / s")

The issue seems to be with the decompose, the scale cannot be parsed back for console and unicode format. Without it works fine:

>>> u.Unit(u.THz.to_string(format="console"))
Unit("THz")
>>> u.Unit(u.THz.to_string(format="unicode"))
Unit("THz")

The question would be if that is a common enough usecase with first decomposing and then roundtripping?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For now, I guess it is a known limitation...

@astrofrog

Copy link
Copy Markdown
Member

@mhvk - is there any chance you could review this today? I'd like to make a decision on whether to merge this in before branching v8.0.x or postponing to 8.1.0

- Forward `kwargs` in `check_roundtrip`
- Add `test_composite_roundtrip` to test the roundtrip of a composite unit for different fraction and output formats
@astrofrog
astrofrog force-pushed the doc-units-formatting branch from 744d36b to 59fc7f2 Compare May 5, 2026 11:21

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With possible scales not round-tripping, I would tend to make the comment more leaning towards not recommending using the format for anything that could be read in later; see suggestion in-line.

Note that it may be fairly straightforward to adjust the general parser such that it understands scale factors, but best not attempt this in this PR (or re-milestone to 8.1).

[
unit
for unit in u.__dict__.values()
if (isinstance(unit, UnitBase) and not isinstance(unit, PrefixUnit))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For now, I guess it is a known limitation...

Comment thread docs/units/format.rst Outdated
------
s cm^2

The ``"console"`` format can also be parsed back to a |Unit| object, but

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think I'd tend to write a bit more with the suggestion that it should not be used for parsing. For instance

The ``"console"`` format is not meant to be parsed back to |Unit| objects, even
though it does generally work as long as no scale factors are present and one
does not use ``fraction="multiline"``.

I don't think there is a need to give an example unless we manage to make the non-multiline case always work.

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.

Changed to your text and removed the example.

@astrofrog

Copy link
Copy Markdown
Member

@mhvk just to check, are you agreeing with this going in 8.0.0 aside from the comment on the docs above?

@mhvk

mhvk commented May 5, 2026

Copy link
Copy Markdown
Contributor

Yes, I think the added test is a good one; we might as well check that round-tripping continues to work (and there is no reason for it not to!). I just wanted not to explicitly encourage using the format for storage, say, if the roundtripping is not yet perfect.

@mhvk
mhvk dismissed their stale review May 5, 2026 14:05

Main requested changed made.

@astrofrog

Copy link
Copy Markdown
Member

Ok so to confirm, can we merge this? (Branching shortly)

@dhomeier dhomeier left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed that the special cases of decomposition and long prefixes may be very uncommon, but relevant enough not to recommend this in general.
Also adding the respective functionality may still be worth the effort, but constitute new functionality IMO. While this PR as is could be considered a bugfix for inaccurate documentation, so can well go in for 8.0.0 (with or without the extra snippet).

Comment thread docs/units/format.rst Resolved

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, happy (with @dhomeier's suggestion even better but don't want to trigger CI just for that...)

@astrofrog

Copy link
Copy Markdown
Member

I'll apply @dhomeier's suggestion and will then merge immediately since there's no reason (famous last words) those changes should do anything to the CI

Co-authored-by: Derek Homeier <[email protected]>
@astrofrog
astrofrog merged commit 78b6ed3 into astropy:main May 5, 2026
10 of 13 checks passed
@pllim

pllim commented May 5, 2026

Copy link
Copy Markdown
Member

This broke RTD. Please check CI carefully before merge.

pllim added a commit to pllim/astropy that referenced this pull request May 5, 2026
@pllim

pllim commented May 5, 2026

Copy link
Copy Markdown
Member

I folded the fix into #19664

pllim added a commit that referenced this pull request May 5, 2026
* Remove redundant elif in fast_converters.pyx

* DOC: Fix formatting

introduced by #19571
@Julian-Harbeck

Copy link
Copy Markdown
Contributor Author

Thank you everyone for the helpful reviews to make this PR successful.

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.

5 participants