Skip to content

simplify key_list#1214

Merged
ryneeverett merged 1 commit into
GothenburgBitFactory:developfrom
Lotram:refactor-key-list
May 28, 2026
Merged

simplify key_list#1214
ryneeverett merged 1 commit into
GothenburgBitFactory:developfrom
Lotram:refactor-key-list

Conversation

@Lotram
Copy link
Copy Markdown
Collaborator

@Lotram Lotram commented May 19, 2026

Simplify "key_list" type (and rename it)

Copy link
Copy Markdown
Collaborator

@ryneeverett ryneeverett left a comment

Choose a reason for hiding this comment

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

Is it required (or best practice) for type checking to declare the broadest possible type that a function can accept, even if the type is actually always much narrower? It strikes me as odd that unique_key_sets has a different type in every function: Iterable[Iterable[str]], Iterable[tuple[str, ...]], Iterable[Sequence[str]], set[tuple[str, ...]].

Comment thread bugwarrior/db.py
@Lotram
Copy link
Copy Markdown
Collaborator Author

Lotram commented May 25, 2026

Is it required (or best practice) for type checking to declare the broadest possible type that a function can accept, even if the type is actually always much narrower? It strikes me as odd that unique_key_sets has a different type in every function: Iterable[Iterable[str]], Iterable[tuple[str, ...]], Iterable[Sequence[str]], set[tuple[str, ...]].

First a bit of theory:
It's usually considered a good idea to keep the input type generic for containers, when we know which methods are actually used.
In the contrary, it's usually a good idea to be as specific as possible for return types.
This is related to covariance and contravariance concepts and, the fact that a callable is covariant in the return type, but contravariant in the arguments.
It's sometimes refered to as Robustness principle (or Postel's law) applied to typing.

That's why I'm trying to be generic with the inputs (e.g. unique_key_sets: Iterable[Iterable[str]] in get_managed_task_uuids, since for only loop over each item exactly once, nothing else) and specific with the outputs ( build_unique_key_sets's return type is set[tuple[str, ...]]) .

That said,

  1. I should have used something more generic for unique_key_sets in make_unique_identifier
  2. I could have used Collection instead of Sequence
  3. for the sake of simplicity, I could use the same type for all function parameters (e.g. Iterable[Collection[str]], or even use the specific type set[tuple[str, ...]]. We can't use Iterable[Iterable[str]] for some parameters, as we loop over it multiple times, so a simple generator wouldn't work

Sidenote: I think UNIQUE_KEY should be a frozenset instead of a tuple, but that's really nitpicking

@ryneeverett
Copy link
Copy Markdown
Collaborator

Thanks for the theory, that makes a lot of sense!

Sidenote: I think UNIQUE_KEY should be a frozenset instead of a tuple, but that's really nitpicking

There was a time when pythonistas considered best practice to be to default to the most common data types and only use the more esoteric ones when doing so served a particular purpose. Perhaps this norm has changed as Python has moved further away from its scripting language roots and static analysis has gotten more thorough and useful.

@Lotram
Copy link
Copy Markdown
Collaborator Author

Lotram commented May 27, 2026

only use the more esoteric ones when doing so served a particular purpose

I don't see frozenset as esoteric 😅 . To me, it's simply the immutable, thus hashable, version of a set, exactly like a tuple being the hashable version of a list.

UNIQUE_KEY looks like it should be a set (order does not matter, values shouldn't be duplicated), but since it needs to be hashable (to be used inside another set), I suggest a frozenset.

But once again, that does not really matter here, let's keep a tuple for now.

@Lotram Lotram force-pushed the refactor-key-list branch from 4dd0ae7 to 9973776 Compare May 27, 2026 17:08
@Lotram Lotram force-pushed the refactor-key-list branch from 9973776 to ad42432 Compare May 28, 2026 07:46
@ryneeverett ryneeverett merged commit da8dc66 into GothenburgBitFactory:develop May 28, 2026
8 checks passed
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