Skip to content

Improve type definition of FlattenableItems for better type narrowing#511

Open
hirosassa wants to merge 2 commits into
m3dev:masterfrom
hirosassa:type-flattenable-items
Open

Improve type definition of FlattenableItems for better type narrowing#511
hirosassa wants to merge 2 commits into
m3dev:masterfrom
hirosassa:type-flattenable-items

Conversation

@hirosassa
Copy link
Copy Markdown
Collaborator

What I did

Replace Iterable with concrete collection types (list, tuple) in the FlattenableItems recursive type alias to enable proper type narrowing after isinstance checks.

# before
FlattenableItems = T | Iterable[FlattenableItems[T]] | dict[str, FlattenableItems[T]]

# after
FlattenableItems = T | list[FlattenableItems[T]] | tuple[FlattenableItems[T], ...] | dict[str, FlattenableItems[T]]

Since dict, list, and tuple are disjoint, type checkers can now correctly narrow the type after isinstance(x, dict), resolving many false positives in Pyright and other modern type checker tools.

Motivation

The original Iterable union prevented type narrowing because dict is a subtype of Iterable, making the branches overlap.
This caused Pyright to report errors on dict indexing, return types, and argument types across task.py, utils.py, and gcs_obj_metadata_client.py.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refines the FlattenableItems recursive type alias to use concrete container types (list, tuple, dict) instead of Iterable, enabling modern type checkers (e.g., Pyright) to correctly narrow types after isinstance checks (notably distinguishing dict from other containers).

Changes:

  • Updated FlattenableItems in gokart/utils.py to use list/tuple/dict for improved type narrowing.
  • Adjusted map_flattenable_items / related branches to align runtime/type-checking behavior with the new alias.
  • Added casts and updated type-handling logic in task.py and gcs_obj_metadata_client.py to satisfy stricter typing and narrowing.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
gokart/utils.py Updates FlattenableItems definition and narrows map_flattenable_items container handling.
gokart/task.py Tweaks requires() return typing and adds a cast for required_task_outputs mapping.
gokart/gcs_obj_metadata_client.py Removes Iterable-based narrowing; uses `list
Comments suppressed due to low confidence (1)

gokart/gcs_obj_metadata_client.py:136

  • The TypeError message says "dict, or iterable of RequiredTaskOutput", but this branch now only accepts list | tuple (and dict). Please update the message to match the supported input types so callers aren't misled when debugging.
        elif isinstance(required_task_outputs, list | tuple):
            return [GCSObjectMetadataClient._get_serialized_string(ro) for ro in required_task_outputs]
        else:
            raise TypeError(
                f'Unsupported type for required_task_outputs: {type(required_task_outputs)}. '
                'It should be RequiredTaskOutput, dict, or iterable of RequiredTaskOutput.'
            )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread gokart/utils.py
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