Skip to content

feat: fully type donfig and ship py.typed - #149

Merged
djhoese merged 14 commits into
pytroll:mainfrom
maxrjones:full-typing
Aug 3, 2026
Merged

feat: fully type donfig and ship py.typed#149
djhoese merged 14 commits into
pytroll:mainfrom
maxrjones:full-typing

Conversation

@maxrjones

Copy link
Copy Markdown
Contributor

This is PR three out of four in a sequence to support downstream use cases. It improves typing via:

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.46%. Comparing base (7b90e4d) to head (d2ccb82).
⚠️ Report is 87 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #149      +/-   ##
==========================================
+ Coverage   98.28%   98.46%   +0.18%     
==========================================
  Files           6        6              
  Lines         759      784      +25     
==========================================
+ Hits          746      772      +26     
+ Misses         13       12       -1     
Flag Coverage Δ
unittests 98.46% <100.00%> (+0.18%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread donfig/config_obj.py Outdated
Comment thread pyproject.toml

@djhoese djhoese left a comment

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.

This looks good to me. Thanks for doing it. I'm not sure I entirely understand or am comfortable with the changes to self.defaults, but I think I mostly have problems with the previously allowed behavior of in-place modifications. I left some comments inline.

Comment thread donfig/config_obj.py
):
config: MutableMapping[str, Any],
lock: SerializableLock | contextlib.AbstractContextManager[Any],
deprecations: Mapping[str, str | None],

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.

Hm I wonder why this was a MutableMapping before. Good catch.

Comment thread donfig/config_obj.py Outdated
Comment thread donfig/config_obj.py Outdated
@djhoese djhoese added the enhancement New feature or request label Jul 24, 2026
@djhoese djhoese self-assigned this Jul 24, 2026
@djhoese

djhoese commented Jul 27, 2026

Copy link
Copy Markdown
Member

Any other changes needed on this or ready for merge?

@maxrjones

Copy link
Copy Markdown
Contributor Author

Any other changes needed on this or ready for merge?

I pushed a couple clean up changes. I think this PR is now ready for merge.

@djhoese

djhoese commented Jul 28, 2026

Copy link
Copy Markdown
Member

Ah sorry, I merged your other PR first and now there are conflicts. Do you mind fixing those? Rebasing would be nice if you're feeling brave 😉

@djhoese

djhoese commented Jul 28, 2026

Copy link
Copy Markdown
Member

Just curious, what lead to the simplification/restriction to dict in some of those last changes? General philosophy I should keep in mind? I don't disagree with 95% of the changes, but the other 5% didn't seem strictly necessary (although I'm fine keeping them). Just curious.

Comment thread donfig/config_obj.py
Comment thread donfig/config_obj.py
@maxrjones

Copy link
Copy Markdown
Contributor Author

hey, sorry for stepping back from this - I was busy with ESIP last week.

Just curious, what lead to the simplification/restriction to dict in some of those last changes? General philosophy I should keep in mind? I don't disagree with 95% of the changes, but the other 5% didn't seem strictly necessary (although I'm fine keeping them). Just curious.

I considered three options here:

  1. Keep old: MutableMapping[str, Any] -> Mapping[str, Any] (what the annotations said before).
  2. A TypeVar bound to MutableMapping (def update(old: T, ...) -> T), which is maximally faithful.
  3. Plain dict -> dict, which is what dask's config.update does.

I went with 3 mainly because it matched dask's choice, so it seemed battle-tested, but there were a couple of supporting reasons:

  • The old return type of Mapping was unhelpful since the function returns the (mutated) old you passed in, and every real caller treats the result as a dict. Returning Mapping forces typed callers to cast or lose mutability. Narrowing a return type is always compatible.
  • Typing old as dict is what lets Config.config and to_dict() be dict[str, Any] instead of MutableMapping, which is the type downstream users probably want to see there.
  • It's honest about the implementation below the root: nested merges do old[k] = {}, so any nested structure comes out as plain dicts regardless of what container you passed in.
  • It's not a breaking change in practice since donfig only ships py.typed as of this branch, so type checkers never consumed the old MutableMapping annotation. Runtime behavior is the same before and after the PR.

In general TypeVar is the true "correct" abstract option, but I went with dict because it was simpler for a code-base that's introducing a lot more typing. The generalization is that read-only parameters get the widest type that works (Mapping), mutate-and-return values get the concrete type everyone uses (dict) unless a TypeVar earns its keep.

@djhoese

djhoese commented Aug 3, 2026

Copy link
Copy Markdown
Member

I'm ok with the dict usage for now. I agree that TypeVar would be nice to have but maybe in a future PR/release.

def test_paths_accepts_any_sequence(monkeypatch):
monkeypatch.setenv("MYPKG_CONFIG", "foo-bar")
config = Config("mypkg", paths=("/etc/mypkg",))
assert config.paths == ["/etc/mypkg", "foo-bar"]

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.

Removed because it asserted tuple support, which contradicts the declared paths: list[str]

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, but is there a reason Sequence wouldn't 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.

Sequence + a runtime check against a bare str (which is natively a Sequence) would work. I can change this if you prefer that option?

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.

Nah, let's leave it for now. This PR has seen enough work.

Side question: Have I been doing too much agentic coding or am I talking to your AI in these comments?

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 have typed my comments to you with my human digits 😆

I do often run my responses by Claude first with an "is this accurate?" which might be injecting some bot-ness into my phrasing; I should probably cut that out and just be more confident.

At the same time, I have a long history of failing the "am I a bot tests" when trying to sign up for accounts (I still cannot get into facebook marketplace 😞), so it might not actually be anything different that I'm doing now...

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.

Haha perfect

@djhoese
djhoese merged commit 3ffae21 into pytroll:main Aug 3, 2026
13 checks passed
@maxrjones
maxrjones deleted the full-typing branch August 3, 2026 19:19
@djhoese

djhoese commented Aug 3, 2026

Copy link
Copy Markdown
Member

I've lost count. Do you have more PRs planned? Then I assume you'd like a release after that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants