Skip to content

Commit 2861dc2

Browse files
hallvictoriaVictoria Hall
and
Victoria Hall
authored
feat: Adding deferred bindings logs (#28)
* adding log array to dict repr * fixed tests * nested dict, different name * fixed tests --------- Co-authored-by: Victoria Hall <[email protected]>
1 parent e75b6d7 commit 2861dc2

File tree

4 files changed

+78
-16
lines changed

4 files changed

+78
-16
lines changed

azure-functions-extension-base/azure/functions/extension/base/meta.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def get(cls, binding_name):
8383
return cls._bindings.get(binding_name)
8484

8585
@classmethod
86-
def get_raw_bindings(cls, indexed_function, input_types) -> List[str]:
86+
def get_raw_bindings(cls, indexed_function, input_types):
8787
return utils.get_raw_bindings(indexed_function, input_types)
8888

8989
@classmethod

azure-functions-extension-base/azure/functions/extension/base/utils.py

+21-11
Original file line numberDiff line numberDiff line change
@@ -160,37 +160,44 @@ def data_type(self) -> Optional[int]:
160160
def direction(self) -> int:
161161
return self._direction.value
162162

163-
def get_dict_repr(binding, input_types) -> Dict:
163+
def get_dict_repr(binding, input_types):
164164
"""Build a dictionary of a particular binding. The keys are camel
165165
cased binding field names defined in `init_params` list and
166166
:class:`Binding` class. \n
167167
This method is invoked in function :meth:`get_raw_bindings` of class
168168
:class:`Function` to generate json dict for each binding.
169169
170-
:return: Dictionary representation of the binding.
170+
:return: Dictionary representation of the binding. Tuple representation
171+
of the binding in the format:
172+
((binding type, pytype), deferred bindings enabled)
171173
"""
172174
params = list(dict.fromkeys(getattr(binding, "init_params", [])))
175+
binding_info = {}
173176
for p in params:
174177
if p not in Binding.EXCLUDED_INIT_PARAMS:
175178
binding._dict[to_camel_case(p)] = getattr(binding, p, None)
176179

180+
if input_types.get(binding.name) is not None:
181+
pytype = input_types.get(binding.name).pytype
182+
else:
183+
pytype = None
177184
# Adding flag to signal to the host to send MBD object
178185
# 1. check if the binding is a supported type (blob, blobTrigger)
179186
# 2. check if the binding is an input binding
180187
# 3. check if the defined type is an SdkType
181188
if (
182189
binding.type in meta._ConverterMeta._bindings
183190
and binding.direction == 0
184-
and meta._ConverterMeta.check_supported_type(
185-
input_types.get(binding.name).pytype
186-
)
191+
and meta._ConverterMeta.check_supported_type(pytype)
187192
):
188193
binding._dict["properties"] = {"SupportsDeferredBinding": True}
194+
binding_info = {binding.name: {pytype: "True"}}
189195
# if it isn't, we set the flag to false
190196
else:
191197
binding._dict["properties"] = {"SupportsDeferredBinding": False}
198+
binding_info = {binding.name: {pytype: "False"}}
192199

193-
return binding._dict
200+
return binding._dict, binding_info
194201

195202

196203
def to_camel_case(snake_case_str: str):
@@ -238,8 +245,11 @@ def is_word(input_string: str) -> bool:
238245
return WORD_RE.match(input_string) is not None
239246

240247

241-
def get_raw_bindings(indexed_function, input_types) -> List[str]:
242-
return [
243-
json.dumps(Binding.get_dict_repr(b, input_types), cls=StringifyEnumJsonEncoder)
244-
for b in indexed_function._bindings
245-
]
248+
def get_raw_bindings(indexed_function, input_types):
249+
binding_dict_repr = []
250+
bindings_logs = {}
251+
for b in indexed_function._bindings:
252+
dict_repr, logs = Binding.get_dict_repr(b, input_types)
253+
binding_dict_repr.append(json.dumps(dict_repr, cls=StringifyEnumJsonEncoder))
254+
bindings_logs.update(logs)
255+
return binding_dict_repr, bindings_logs

azure-functions-extension-base/tests/test_meta.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class MockIndexedFunction:
146146
_bindings = {}
147147
_trigger = None
148148

149-
self.assertEqual(registry.get_raw_bindings(MockIndexedFunction, []), [])
149+
self.assertEqual(registry.get_raw_bindings(MockIndexedFunction, []), ([], {}))
150150

151151
self.assertFalse(registry.check_supported_type(None))
152152
self.assertFalse(registry.check_supported_type("hello"))

azure-functions-extension-base/tests/test_utils.py

+55-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ def test_get_dict_repr_sdk(self):
5656
# Create test indexed_function
5757
mock_indexed_functions = MockFunction(bindings=[mock_blob])
5858

59-
dict_repr = utils.get_raw_bindings(mock_indexed_functions, mock_input_types)
59+
dict_repr, logs = utils.get_raw_bindings(
60+
mock_indexed_functions, mock_input_types
61+
)
6062
self.assertEqual(
6163
dict_repr,
6264
[
@@ -67,6 +69,8 @@ def test_get_dict_repr_sdk(self):
6769
],
6870
)
6971

72+
self.assertEqual(logs, {"client": {sdkType.SdkType: "True"}})
73+
7074
def test_get_dict_repr_non_sdk(self):
7175
# Create mock blob
7276
meta._ConverterMeta._bindings = {"blob"}
@@ -87,7 +91,9 @@ def test_get_dict_repr_non_sdk(self):
8791
# Create test indexed_function
8892
mock_indexed_functions = MockFunction(bindings=[mock_blob])
8993

90-
dict_repr = utils.get_raw_bindings(mock_indexed_functions, mock_input_types)
94+
dict_repr, logs = utils.get_raw_bindings(
95+
mock_indexed_functions, mock_input_types
96+
)
9197
self.assertEqual(
9298
dict_repr,
9399
[
@@ -97,6 +103,48 @@ def test_get_dict_repr_non_sdk(self):
97103
'{"SupportsDeferredBinding": false}}'
98104
],
99105
)
106+
self.assertEqual(logs, {"blob": {bytes: "False"}})
107+
108+
def test_get_dict_repr_binding_name_none(self):
109+
# Create mock blob
110+
meta._ConverterMeta._bindings = {"blob"}
111+
112+
# Create test binding
113+
mock_blob = utils.Binding(
114+
name="blob",
115+
direction=utils.BindingDirection.IN,
116+
data_type=None,
117+
type="blob",
118+
)
119+
120+
mock_http = utils.Binding(
121+
name="$return",
122+
direction=utils.BindingDirection.OUT,
123+
data_type=None,
124+
type="httpResponse",
125+
)
126+
127+
# Create test input_types dict
128+
mock_input_types = {
129+
"blob": MockParamTypeInfo(binding_name="blobTrigger", pytype=bytes)
130+
}
131+
132+
# Create test indexed_function
133+
mock_indexed_functions = MockFunction(bindings=[mock_blob, mock_http])
134+
135+
dict_repr, logs = utils.get_raw_bindings(
136+
mock_indexed_functions, mock_input_types
137+
)
138+
self.assertEqual(
139+
dict_repr,
140+
[
141+
'{"direction": "IN", "dataType": null, "type": "blob", '
142+
'"properties": {"SupportsDeferredBinding": false}}',
143+
'{"direction": "OUT", "dataType": null, "type": "httpResponse", '
144+
'"properties": {"SupportsDeferredBinding": false}}',
145+
],
146+
)
147+
self.assertEqual(logs, {"$return": {None: "False"}, "blob": {bytes: "False"}})
100148

101149
def test_get_dict_repr_init_params(self):
102150
# Create mock blob
@@ -121,7 +169,9 @@ def test_get_dict_repr_init_params(self):
121169
# Create test indexed_function
122170
mock_indexed_functions = MockFunction(bindings=[mock_blob])
123171

124-
dict_repr = utils.get_raw_bindings(mock_indexed_functions, mock_input_types)
172+
dict_repr, logs = utils.get_raw_bindings(
173+
mock_indexed_functions, mock_input_types
174+
)
125175
self.assertEqual(
126176
dict_repr,
127177
[
@@ -131,6 +181,8 @@ def test_get_dict_repr_init_params(self):
131181
],
132182
)
133183

184+
self.assertEqual(logs, {"client": {sdkType.SdkType: "True"}})
185+
134186
def test_binding_data_type(self):
135187
mock_blob = utils.Binding(
136188
name="blob",

0 commit comments

Comments
 (0)