diff --git a/azurefunctions-extensions-base/azurefunctions/extensions/base/__init__.py b/azurefunctions-extensions-base/azurefunctions/extensions/base/__init__.py index cf1eb24..a6abbf3 100644 --- a/azurefunctions-extensions-base/azurefunctions/extensions/base/__init__.py +++ b/azurefunctions-extensions-base/azurefunctions/extensions/base/__init__.py @@ -1,6 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +from .grpcClientType import GrpcClientType from .meta import ( Datum, InConverter, @@ -31,6 +32,7 @@ "get_binding_registry", "ModuleTrackerMeta", "RequestTrackerMeta", + "GrpcClientType", "ResponseTrackerMeta", "HttpV2FeatureChecker", "ResponseLabels", diff --git a/azurefunctions-extensions-base/azurefunctions/extensions/base/grpcClientType.py b/azurefunctions-extensions-base/azurefunctions/extensions/base/grpcClientType.py new file mode 100644 index 0000000..03f851f --- /dev/null +++ b/azurefunctions-extensions-base/azurefunctions/extensions/base/grpcClientType.py @@ -0,0 +1,7 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + + +class GrpcClientType: + def __init__(self, *, data: dict = None): + self._data = data or {} diff --git a/azurefunctions-extensions-base/azurefunctions/extensions/base/meta.py b/azurefunctions-extensions-base/azurefunctions/extensions/base/meta.py index a771a9f..1535c69 100644 --- a/azurefunctions-extensions-base/azurefunctions/extensions/base/meta.py +++ b/azurefunctions-extensions-base/azurefunctions/extensions/base/meta.py @@ -6,7 +6,7 @@ import json from typing import Any, Dict, Mapping, Optional, Tuple, Union, get_args, get_origin -from . import sdkType, utils +from . import grpcClientType, sdkType, utils class Datum: @@ -99,6 +99,15 @@ def check_supported_type(cls, annotation: type) -> bool: # An iterable who only has one inner type and is a subclass of SdkType return cls._is_iterable_supported_type(annotation) + @classmethod + def check_supported_grpc_client_type(cls, annotation: type) -> bool: + if annotation is None: + return False + + # The annotation is a class/type (not an object) - not iterable + return (isinstance(annotation, type) + and issubclass(annotation, grpcClientType.GrpcClientType)) + @classmethod def _is_iterable_supported_type(cls, annotation: type) -> bool: # Check base type from type hint. Ex: List from List[SdkType] diff --git a/azurefunctions-extensions-base/tests/test_meta.py b/azurefunctions-extensions-base/tests/test_meta.py index cb493ff..6dca666 100644 --- a/azurefunctions-extensions-base/tests/test_meta.py +++ b/azurefunctions-extensions-base/tests/test_meta.py @@ -6,6 +6,7 @@ from unittest.mock import patch from azurefunctions.extensions.base import meta, sdkType +from azurefunctions.extensions.base.grpcClientType import GrpcClientType class TestMeta(unittest.TestCase): @@ -162,6 +163,21 @@ class MockIndexedFunction: self.assertTrue(registry.check_supported_type(set[sdkType.SdkType])) self.assertFalse(registry.check_supported_type(dict[str, sdkType.SdkType])) + def test_registry_grpc_client(self): + registry = meta.get_binding_registry() + self.assertIsInstance(registry, type(meta._ConverterMeta)) + self.assertIsNone(registry.get("test")) + + class MockIndexedFunction: + _bindings = {} + _trigger = None + + self.assertEqual(registry.get_raw_bindings(MockIndexedFunction, []), ([], {})) + + self.assertFalse(registry.check_supported_grpc_client_type(None)) + self.assertFalse(registry.check_supported_grpc_client_type("hello")) + self.assertTrue(registry.check_supported_grpc_client_type(GrpcClientType)) + def test_decode_typed_data(self): # Case 1: data is None self.assertIsNone(