Skip to content

[Python][Typeguard] Part 3 - Add Typeguard to AIO stack in tests#40217

Closed
asheshvidyut wants to merge 13 commits intogrpc:masterfrom
asheshvidyut:feature/type-hints/typeguard-aio-stack-part-3
Closed

[Python][Typeguard] Part 3 - Add Typeguard to AIO stack in tests#40217
asheshvidyut wants to merge 13 commits intogrpc:masterfrom
asheshvidyut:feature/type-hints/typeguard-aio-stack-part-3

Conversation

@asheshvidyut
Copy link
Member

@asheshvidyut asheshvidyut commented Jul 15, 2025

Description

Part 3 of Add Typeguard to AIO stack - runs only in tests, fixes type hints for grpc.aio._utils and grpc.aio._call

Fixes -

  1. Changed serializer parameters to Optional:

BEFORE

def __init__(
    self,
    # ...
    request_serializer: SerializingFunction,
    response_deserializer: DeserializingFunction,
    # ...
) -> None:

AFTER

def __init__(
    self,
    # ...
    request_serializer: Optional[SerializingFunction],
    response_deserializer: Optional[DeserializingFunction],
    # ...
) -> None:
  1. Enhanced Metadata Type Checking in _channel.py -> Improved metadata type validation: This is a bug fix as the per stack trace mentioned in the comment below - [Python][Typeguard] Part 3 - Add Typeguard to AIO stack in tests #40217 (comment)

BEFORE

if not isinstance(metadata, Metadata) and isinstance(metadata, tuple):
    metadata = Metadata.from_tuple(metadata)

AFTER

if not isinstance(metadata, Metadata) and isinstance(
    metadata, Sequence
):
    metadata = Metadata.from_tuple(tuple(metadata))

Testing

CI

Related work

@@ -24,27 +24,14 @@
# Temporarily disable most hooks due to type annotation issues
# install_import_hook('grpc.aio')
# install_import_hook('grpc.aio._channel')
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this also be uncommented now since you're adding type annotations to _channel.py?

Copy link
Member Author

Choose a reason for hiding this comment

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


def _create_rpc_error(
initial_metadata: Metadata, status: cygrpc.AioRpcStatus
initial_metadata: Union[Metadata, Tuple[MetadatumType, ...]],
Copy link
Contributor

Choose a reason for hiding this comment

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

Have you tried using MetadataType instead of this: https://github.com/grpc/grpc/blob/master/src/python/grpcio/grpc/aio/_typing.py#L38

It's something we already have predefined and is almost the same as this Union type you are using here, so might be good to check using that

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for this. Good thought.

if not isinstance(metadata, Metadata) and isinstance(metadata, tuple):
metadata = Metadata.from_tuple(metadata)
if not isinstance(metadata, Metadata) and isinstance(
metadata, (tuple, list)
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought Metadata was expected to be of tuple format. Is there any test or function in our codebase where we see a list?

Copy link
Member Author

Choose a reason for hiding this comment

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

ERROR: test_from_client_to_server_with_list (src.python.grpcio_tests.tests_aio.unit.metadata_test.TestMetadata)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/google/home/asheshvidyut/.cache/bazel/_bazel_asheshvidyut/37ab11cdf3f320a86e32407534188cd9/sandbox/linux-sandbox/123/execroot/com_github_grpc_grpc/bazel-out/k8-fastbuild/bin/src/python/grpcio_tests/tests_aio/unit/metadata_test.runfiles/com_github_grpc_grpc/src/python/grpcio_tests/tests_aio/unit/_test_base.py", line 31, in wrapper
    return loop.run_until_complete(f(*args, **kwargs))
  File "/usr/local/google/home/asheshvidyut/.pyenv/versions/3.8.20/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/usr/local/google/home/asheshvidyut/.cache/bazel/_bazel_asheshvidyut/37ab11cdf3f320a86e32407534188cd9/sandbox/linux-sandbox/123/execroot/com_github_grpc_grpc/bazel-out/k8-fastbuild/bin/src/python/grpcio_tests/tests_aio/unit/metadata_test.runfiles/com_github_grpc_grpc/src/python/grpcio_tests/tests_aio/unit/metadata_test.py", line 259, in test_from_client_to_server_with_list
    call = multicallable(
  File "/usr/local/google/home/asheshvidyut/.cache/bazel/_bazel_asheshvidyut/37ab11cdf3f320a86e32407534188cd9/sandbox/linux-sandbox/123/execroot/com_github_grpc_grpc/bazel-out/k8-fastbuild/bin/src/python/grpcio_tests/tests_aio/unit/metadata_test.runfiles/com_github_grpc_grpc/src/python/grpcio/grpc/aio/_channel.py", line 152, in __call__
    call = UnaryUnaryCall(
  File "/usr/local/google/home/asheshvidyut/.cache/bazel/_bazel_asheshvidyut/37ab11cdf3f320a86e32407534188cd9/sandbox/linux-sandbox/123/execroot/com_github_grpc_grpc/bazel-out/k8-fastbuild/bin/src/python/grpcio_tests/tests_aio/unit/metadata_test.runfiles/com_github_grpc_grpc/src/python/grpcio/grpc/aio/_call.py", line 555, in __init__
    def __init__(
  File "/usr/local/google/home/asheshvidyut/.cache/bazel/_bazel_asheshvidyut/37ab11cdf3f320a86e32407534188cd9/sandbox/linux-sandbox/123/execroot/com_github_grpc_grpc/bazel-out/k8-fastbuild/bin/src/python/grpcio_tests/tests_aio/unit/metadata_test.runfiles/grpc_python_dependencies_typeguard/site-packages/typeguard/_functions.py", line 135, in check_argument_types
    check_type_internal(value, annotation, memo)
  File "/usr/local/google/home/asheshvidyut/.cache/bazel/_bazel_asheshvidyut/37ab11cdf3f320a86e32407534188cd9/sandbox/linux-sandbox/123/execroot/com_github_grpc_grpc/bazel-out/k8-fastbuild/bin/src/python/grpcio_tests/tests_aio/unit/metadata_test.runfiles/grpc_python_dependencies_typeguard/site-packages/typeguard/_checkers.py", line 779, in check_type_internal
    raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
typeguard.TypeCheckError: argument "metadata" (list) is not an instance of grpc.aio._metadata.Metadata

Copy link
Member Author

Choose a reason for hiding this comment

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

^ This is the test which is failing because of list.

Copy link
Member

Choose a reason for hiding this comment

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

Since MetadataType can be a Sequence[MetadatumType], should we do isinstance(metadata, Sequence) check instead?

MetadataType = Union[Metadata, Sequence[MetadatumType]]

On one hand, this is closer to what we declare to support and will add support for any Sequence-based custom classes.
On another hand, str is technically a Sequence too.

@asheshvidyut asheshvidyut requested a review from sreenithi July 22, 2025 05:53
@asheshvidyut asheshvidyut requested a review from eugeneo as a code owner July 22, 2025 05:56
@asheshvidyut asheshvidyut added release notes: yes Indicates if PR needs to be in release notes and removed release notes: no Indicates if PR should not be in release notes labels Jul 22, 2025
Copy link
Member

@sergiitk sergiitk left a comment

Choose a reason for hiding this comment

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

LGTM overall, as long as remaining comments are addressed.

Also, if we're fixing typing errors in public API, please update the description to make clear for users that will refer to it later.

if not isinstance(metadata, Metadata) and isinstance(metadata, tuple):
metadata = Metadata.from_tuple(metadata)
if not isinstance(metadata, Metadata) and isinstance(
metadata, (tuple, list)
Copy link
Member

Choose a reason for hiding this comment

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

Since MetadataType can be a Sequence[MetadatumType], should we do isinstance(metadata, Sequence) check instead?

MetadataType = Union[Metadata, Sequence[MetadatumType]]

On one hand, this is closer to what we declare to support and will add support for any Sequence-based custom classes.
On another hand, str is technically a Sequence too.

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Jul 23, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@asheshvidyut asheshvidyut removed the request for review from ctiller July 23, 2025 15:22
@sergiitk sergiitk changed the title [Python] [Typeguard] Part 3 - Add Typeguard to AIO stack in tests [Python][Typeguard] Part 3 - Add Typeguard to AIO stack in tests Jul 24, 2025
@asheshvidyut asheshvidyut force-pushed the feature/type-hints/typeguard-aio-stack-part-3 branch from 641b18a to c4bf510 Compare July 24, 2025 09:20
ctiller pushed a commit that referenced this pull request Jul 24, 2025
)

### Description

Part 2 of Add Typeguard to AIO stack - runs only in tests, fixes type hints for  `grpc.aio._interceptor` and `grpc.aio._utils`

### Type hint for Public API change for Experimental API

**Fixing the error in public API** - `ClientCallDetails` where `method` was `str` but actually it should be `bytes`.

It was detected by `typeguard` as well.

### Testing

CI

### Related Work
- Part 1: #40201
- Part 3: #40217
- b/423755915

Closes #40215

This CL has changes from https://github.com/grpc/grpc/pull/40286/files because it was merged to master on Github without copybara.

COPYBARA_INTEGRATE_REVIEW=#40215 from asheshvidyut:feature/type-hints/typeguard-aio-stack-part-2 3fc7a9d
PiperOrigin-RevId: 786606656
@asheshvidyut asheshvidyut force-pushed the feature/type-hints/typeguard-aio-stack-part-3 branch from c4bf510 to 16db703 Compare July 24, 2025 18:18
asheshvidyut added a commit to asheshvidyut/grpc that referenced this pull request Jul 28, 2025
…c#40215)

Part 2 of Add Typeguard to AIO stack - runs only in tests, fixes type hints for  `grpc.aio._interceptor` and `grpc.aio._utils`

**Fixing the error in public API** - `ClientCallDetails` where `method` was `str` but actually it should be `bytes`.

It was detected by `typeguard` as well.

CI

- Part 1: grpc#40201
- Part 3: grpc#40217
- b/423755915

Closes grpc#40215

This CL has changes from https://github.com/grpc/grpc/pull/40286/files because it was merged to master on Github without copybara.

COPYBARA_INTEGRATE_REVIEW=grpc#40215 from asheshvidyut:feature/type-hints/typeguard-aio-stack-part-2 3fc7a9d
PiperOrigin-RevId: 786606656
asheshvidyut added a commit to asheshvidyut/grpc that referenced this pull request Jul 28, 2025
…c#40217)

Part 3 of Add Typeguard to AIO stack - runs only in tests, fixes type hints for  `grpc.aio._utils` and `grpc.aio._call`

CI

* Part1: grpc#40201
* Part2: grpc#40215

Closes grpc#40217

This CL also has changes from https://github.com/grpc/grpc/pull/40286/files, because it was merged on Github without copybara.

COPYBARA_INTEGRATE_REVIEW=grpc#40217 from asheshvidyut:feature/type-hints/typeguard-aio-stack-part-3 cd82052
PiperOrigin-RevId: 786961247
@asheshvidyut asheshvidyut added this to the Python Type Hints Support milestone Aug 7, 2025
eugeneo pushed a commit to eugeneo/grpc that referenced this pull request Aug 11, 2025
…c#40217)

### Description

Part 3 of Add Typeguard to AIO stack - runs only in tests, fixes type hints for  `grpc.aio._utils` and `grpc.aio._call`

### Testing

CI

### Related work

* Part1: grpc#40201
* Part2: grpc#40215

Closes grpc#40217

This CL also has changes from https://github.com/grpc/grpc/pull/40286/files, because it was merged on Github without copybara.

COPYBARA_INTEGRATE_REVIEW=grpc#40217 from asheshvidyut:feature/type-hints/typeguard-aio-stack-part-3 cd82052
PiperOrigin-RevId: 786961247
paulosjca pushed a commit to paulosjca/grpc that referenced this pull request Aug 23, 2025
…c#40215)

### Description

Part 2 of Add Typeguard to AIO stack - runs only in tests, fixes type hints for  `grpc.aio._interceptor` and `grpc.aio._utils`

### Type hint for Public API change for Experimental API

**Fixing the error in public API** - `ClientCallDetails` where `method` was `str` but actually it should be `bytes`.

It was detected by `typeguard` as well.

### Testing

CI

### Related Work
- Part 1: grpc#40201
- Part 3: grpc#40217
- b/423755915

Closes grpc#40215

This CL has changes from https://github.com/grpc/grpc/pull/40286/files because it was merged to master on Github without copybara.

COPYBARA_INTEGRATE_REVIEW=grpc#40215 from asheshvidyut:feature/type-hints/typeguard-aio-stack-part-2 3fc7a9d
PiperOrigin-RevId: 786606656
paulosjca pushed a commit to paulosjca/grpc that referenced this pull request Aug 23, 2025
…c#40217)

### Description

Part 3 of Add Typeguard to AIO stack - runs only in tests, fixes type hints for  `grpc.aio._utils` and `grpc.aio._call`

### Testing

CI

### Related work

* Part1: grpc#40201
* Part2: grpc#40215

Closes grpc#40217

This CL also has changes from https://github.com/grpc/grpc/pull/40286/files, because it was merged on Github without copybara.

COPYBARA_INTEGRATE_REVIEW=grpc#40217 from asheshvidyut:feature/type-hints/typeguard-aio-stack-part-3 cd82052
PiperOrigin-RevId: 786961247
copybara-service bot pushed a commit that referenced this pull request Feb 18, 2026
…0226)

### Description

Last Part of Add Typeguard to AIO stack - runs only in tests, fixes type hints for AIO Stack
Change -

#### Type Annotation Update in Channel Constructor
File: _channel.py (line 330)
Before: credentials: `Optional[grpc.ChannelCredentials]`,
After: credentials: `Optional[cygrpc.ChannelCredentials]`,

Change:
Updated type hint from `grpc.ChannelCredentials` to `cygrpc.ChannelCredentials`

#### Metadata Class Method Enhancement
File: _metadata.py (around line 100-102)
Before: `def from_tuple(cls, raw_metadata: tuple):`
After: `def from_tuple(cls, raw_metadata: Union[tuple, Self]):`

#### `GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY`decode at Cython layer.
File: src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
Before: `GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY = (
  _GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY)`
After: `GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY = (
  _GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY).decode()`

### Testing

CI

### Related Work
 - Part 1: #40201
 - Part 2: #40215
 - Part 3: #40217
 - Part 5: #40278
 - b/423755915

Closes #40226

COPYBARA_INTEGRATE_REVIEW=#40226 from asheshvidyut:feature/type-hints/typeguard-aio-stack-part-4 70db2d6
PiperOrigin-RevId: 871724432
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants