Skip to content

cosmo: annotate types & fix docs - #18546

Merged
eerovaher merged 13 commits into
astropy:mainfrom
nstarman:cosmo/api/ret_types
Sep 11, 2025
Merged

eerovaher merged 13 commits into
astropy:mainfrom
nstarman:cosmo/api/ret_types

Conversation

@nstarman

@nstarman nstarman commented Aug 24, 2025 •

Copy link
Copy Markdown
Member

Just filling out some of the type annotations.

@nstarman nstarman self-assigned this Aug 24, 2025
@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.

@github-actions

Copy link
Copy Markdown
Contributor

👋 Thank you for your draft pull request! Do you know that you can use [ci skip] or [skip ci] in your commit messages to skip running continuous integration tests until you are ready?

@nstarman nstarman changed the title Cosmo/api/ret types cosmo: annotate types Aug 24, 2025
@nstarman nstarman added this to the v7.2.0 milestone Aug 24, 2025
@nstarman nstarman moved this from Triage to In Progress in Cosmology, the Expansion Aug 24, 2025
@nstarman
nstarman requested a review from neutrinoceros August 24, 2025 01:08
@nstarman
nstarman marked this pull request as ready for review August 24, 2025 01:30
@nstarman
nstarman requested a review from a team as a code owner August 24, 2025 01:30
@pllim pllim added the typing related to type annotations label Aug 25, 2025
@nstarman

nstarman commented Sep 2, 2025

Copy link
Copy Markdown
Member Author

@pllim Cool new label :)

@nstarman
nstarman requested a review from eerovaher September 2, 2025 14:54
@pllim

pllim commented Sep 2, 2025

Copy link
Copy Markdown
Member

The typing label isn't new and I didn't create it. 😉

Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/core.py Resolved
# ===============================================================

def __equiv__(self, other):
def __equiv__(self, other: Any, /) -> bool:

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.

According to the docstring

Suggested change
def __equiv__(self, other: Any, /) -> bool:
def __equiv__(self, other: Cosmology, /) -> bool:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Changed to Any and updated the docs (and PR title)

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.

It is not obvious to me that the docstring was wrong.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

__equiv__, like __eq__, can accept any input object and returns NotImplemented if it's not compatible. Like __eq__, I've put the return type as bool only. Since __equiv__ isn't a builtin dunder method this could be adjusted...

Comment thread astropy/cosmology/_src/flrw/base.py Resolved
Comment thread astropy/cosmology/_src/flrw/base.py Resolved
Comment thread astropy/cosmology/_src/typing.py Resolved
Comment thread astropy/cosmology/_src/utils.py Resolved
Comment thread astropy/cosmology/_src/utils.py Resolved
@nstarman nstarman changed the title cosmo: annotate types cosmo: annotate types & fix docs Sep 2, 2025
@nstarman
nstarman force-pushed the cosmo/api/ret_types branch from e027c03 to 9a95cba Compare September 2, 2025 21:31
Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/core.py Outdated
Comment on lines 222 to 225
def clone(self, *, meta: CosmoMeta | None = None, **kwargs: Any) -> "Cosmology":
"""Returns a copy of this object with updated parameters, as specified.

This cannot be used to change the type of the cosmology, so ``clone()``

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.

Why is the return type not Self?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A good Q. When a FlatCosmologyMixin is added then clone(to_nonflat=True) changes the type, so Self would be wrong.

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 right now it's Self.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Where?

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.

Right now the annotation says "Cosmology", but according to the docstring the return type is actually Self.

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.

The docstring still says

This cannot be used to change the type of the cosmology

so why isn't the return type Self?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Because this isn't true for subclasses, e.g. anything that inherits from FlatCosmologyMixin.

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 then you need to update the docstring.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

✅

Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/core.py Resolved
# ===============================================================

def __equiv__(self, other):
def __equiv__(self, other: Any, /) -> bool:

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.

It is not obvious to me that the docstring was wrong.

Comment on lines +71 to +77
class HasShape(Protocol):
shape: tuple[int, ...]


def aszarr(
z: Number | np.generic | HasShape | ArrayLike,
) -> Number | np.generic | NDArray[Any]:

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.

Are you trying to write down what this function is supposed to do?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As opposed to does?
The Number | np.generic captures

if isinstance(z, (Number, np.generic)): # scalars
return z

HasShape is for
elif hasattr(z, "shape"): # ducktypes NumPy array

ArrayLike is for
return Quantity(z, cu.redshift).value

The return type is imperfect, but close enough for practical purposes.

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.

You should be using overloads here to distinguish scalars from arrays.

If you want to support more array libraries than just numpy then you should actually use the Array API instead of relying on hacks like hasattr(z, "shape").

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You should be using overloads here to distinguish scalars from arrays.

The plan is to move to the Array API so then scalars will be arrays.

def aszarr(x: ArrayLike) -> Array: ...

If you want to support more array libraries than just numpy then you should actually use the Array API instead of relying on hacks like hasattr(z, "shape").

Older code. Eventual updates planned. HasShape is private.

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.

Shouldn't you use overloads to distinguish scalars from arrays? Or will Array API take care of that too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No need. def aszarr(x: ArrayLike) -> Array: ... will cover it all after followups.

@nstarman nstarman Sep 8, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Though I guess maybe the overload

@overload
def aszarr[T: Array](x: T) -> T: ...
@overload
def aszarr(x: ArrayLike) -> Array: ...

would be even better. But this is all for followup.

def deprecated_keywords(*kws, since):
def deprecated_keywords(
*kws: str, since: str | float | tuple[str | float, ...]
) -> Callable[[Callable[P, R]], Callable[P, R]]:

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.

Have you checked this with a type checker?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This or its usage?

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.

Have you type checked cosmology?

@nstarman nstarman Sep 9, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes. We are so far from passing 😆. Which is why I'd love to have a CI step so I could consistently target individual files to make them always pass. Running mypy on my own is not a viable long-term solution.

Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/core.py Resolved
Comment thread astropy/cosmology/_src/flrw/base.py Resolved
Comment thread astropy/cosmology/_src/flrw/base.py Resolved
@nstarman
nstarman force-pushed the cosmo/api/ret_types branch from 2f26fb9 to 2d47e48 Compare September 9, 2025 16:56
@github-project-automation github-project-automation Bot moved this from In Progress to Reviewer approved in Cosmology, the Expansion Sep 10, 2025
@eerovaher
eerovaher merged commit 653cb50 into astropy:main Sep 11, 2025
@github-project-automation github-project-automation Bot moved this from Reviewer approved to Done in Cosmology, the Expansion Sep 11, 2025
@nstarman
nstarman deleted the cosmo/api/ret_types branch September 11, 2025 23:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants