Skip to content

feat: explicit exports#10

Open
flying-sheep wants to merge 1 commit intomainfrom
pa/exports
Open

feat: explicit exports#10
flying-sheep wants to merge 1 commit intomainfrom
pa/exports

Conversation

@flying-sheep
Copy link
Copy Markdown
Member

@flying-sheep flying-sheep commented Apr 15, 2026

Also get rid of the __version__ attribute, I really want to discourage people from using that over importlib.metadata.version. Versions are properties of distributions (PyPI packages), not import packages, and there is a canonical way in the stdlib to retrieve them using the distribution name. This is often the same, but doing things right makes things way less confusing when it isn’t the same.

Also regarding __version_tuple__: If people want a structured version, they can depend on packaging and parse the version using packaging.version.Version. It’s extremely fast and all our packages import packaging anyway at import time.

@flying-sheep flying-sheep requested a review from ilia-kats April 15, 2026 14:46
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.47%. Comparing base (a77c3d6) to head (17bb3b5).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #10      +/-   ##
==========================================
+ Coverage   97.43%   97.47%   +0.04%     
==========================================
  Files           3        3              
  Lines         117      119       +2     
==========================================
+ Hits          114      116       +2     
  Misses          3        3              
Files with missing lines Coverage Δ
src/scverse_misc/__init__.py 100.00% <100.00%> (ø)
src/scverse_misc/_deprecated.py 100.00% <100.00%> (ø)
src/scverse_misc/_extensions.py 96.34% <100.00%> (+0.04%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ilia-kats
Copy link
Copy Markdown
Collaborator

I'd strongly prefer keeping __version__ and __version_tuple__ around. importlib.metadata tends to be quite a bit slower (e.g. astral-sh/ruff#15671), in addtion to multiple other reasons for keeping __version__ around (this discussion is quite illuminating). __version__ is also still mentioned in the official packaging guide.

If users of the package prefer importlib.metadata, they are free to use it, but keeping __version__ and __version_tuple__ around doesn't really cost anything.

Looks good otherwise.

@flying-sheep
Copy link
Copy Markdown
Member Author

flying-sheep commented Apr 16, 2026

I’m 100% convinced that accessing __version__ of other packages is almost always1 a bad idea, so I want to encourage people to not do that by reducing the number of packages that export it.

The 30ms flat delay (importing importlib.metadata the first time) is basically only relevant for CLIs implementing --version, and even there questionable (since it’s <100ms and therefore lag perception threshold).

So since we’re not a CLI, and therefore don’t actually need to use importlib.metadata to access our own version, and many of our packages do already import that package anyway (along with other, much slower things), I’m leaving it like that.

Details

If I don’t completely misremember, I wrote that part of the official packaging guide, and intentionally chose the wording “many projects also choose” to clearly point out that that’s not a standard.

I’ve read that discussion, and I’ve had long discussions with Isaac about this: he was focused on the niche use case “have multiple editable versions of packages in an environment and frequently switch between them via git switch”, which, uh, you could just do differently.

My firm opinion: anyone who wants runtime versions should engage with the standards process to get runtime metadata. The PyPA is very open to do this, but nobody ever cared enough to make a PEP.

Footnotes

  1. I defensively access it in session-info2 since I want to capture everything there, and as of 5 years ago some ancient conda packages still didn’t properly package standard metadata, but I haven’t seen it since and might remove that soon

@flying-sheep flying-sheep requested review from ilia-kats and removed request for ilia-kats April 16, 2026 10:28
@ilia-kats
Copy link
Copy Markdown
Collaborator

ilia-kats commented Apr 16, 2026

It's not just importing importlib.metadata. If I'm reading the code right it's reading and parsing the entire metadata file every time someone calls importlib.metadata.version. This is slower by a factor of 20 000 than simply accessing the __version__ attribute.

%timeit importlib.metadata.version("mudata")
232 μs ± 370 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

%timeit md.__version__
12.8 ns ± 0.00843 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)

EDIT: and may be even slower on network file systems, which are usually used in HPC environments.

@flying-sheep
Copy link
Copy Markdown
Member Author

flying-sheep commented Apr 16, 2026

And as you can see that’s absolutely neglegible time-wise. It also won’t hit the disk every time as e.g. Linux caches files in memory. Nevertheless scanpy caches its result for some reason. I should probably get rid of that.

If someone needs to have a check for scverse-misc’s version in a hot loop, they can cache it themselves after identifying it as a bottleneck in a benchmark. I’m very sure that won’t happen.

Can we merge this?

@flying-sheep flying-sheep requested review from ilia-kats and removed request for ilia-kats April 17, 2026 08:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants