Skip to content

Conversation

@emmanuel-ferdman
Copy link
Contributor

PR Summary

The Container.attach() method was incorrectly typed as returning str | tuple[str | None, str | None] | ... but it actually returns bytes. When stream=True, it returns a CancellableStream[bytes] that yields bytes objects on iteration. This caused false positive errors when users called .decode() on the output, since mypy thought the values were str (which has no .decode() method). So this PR adds proper overloads for both Container.attach() and ContainerApiMixin.attach() based on the stream and demux parameters:

  • stream=False, demux=Falsebytes
  • stream=False, demux=Truetuple[bytes | None, bytes | None]
  • stream=True, demux=FalseCancellableStream[bytes]
  • stream=True, demux=TrueCancellableStream[tuple[bytes | None, bytes | None]]

Please note that tests follow the "less is more" rule of the the project so minimal.

Fixes #15143

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
@github-actions

This comment has been minimized.

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

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

Thanks, looks good! A suggestion for the tests, though.

Comment on lines 6 to 8
def check_attach_stream(c: Container) -> None:
for line in c.attach(stdout=True, stderr=True, stream=True, logs=True):
line.decode("utf-8")
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test can be simplified and "typified", and extended:

Suggested change
def check_attach_stream(c: Container) -> None:
for line in c.attach(stdout=True, stderr=True, stream=True, logs=True):
line.decode("utf-8")
c: Container
assert_type(c.attach(), bytes)
assert_type(c.attach(stream=False), bytes)
for line in c.attach(stream=True):
assert_type(line, bytes)

Copy link
Contributor Author

@emmanuel-ferdman emmanuel-ferdman Dec 20, 2025

Choose a reason for hiding this comment

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

Thank you for the review! The suggested code fails pyright CI because c: Container without assignment is seen as an unbound variable. Pyright reports: "c" is unbound (reportUnboundVariable). To fix this, we need to wrap it in a function with a parameter, which is how other tests handle cases where instances can't be easily constructed:

def check_attach(c: Container) -> None:
    assert_type(c.attach(), bytes)
    assert_type(c.attach(stream=False), bytes)
    for line in c.attach(stream=True):
        assert_type(line, bytes)

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

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.

docker: Wrong type in Container.attach()

2 participants