Skip to content

Commit de37877

Browse files
hallvictoriaVictoria Hallgavin-aguiar
authored
fix: small memory leak (#223)
* changing default {} to None * mypy fixes --------- Co-authored-by: Victoria Hall <[email protected]> Co-authored-by: gavin-aguiar <[email protected]>
1 parent ff2e803 commit de37877

File tree

5 files changed

+59
-34
lines changed

5 files changed

+59
-34
lines changed

azure/functions/decorators/function_app.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ def app_script_file(self) -> str:
333333
return self._app_script_file
334334

335335
def function_name(self, name: str,
336-
setting_extra_fields: Dict[str, Any] = {},
336+
setting_extra_fields: Optional[Dict[str, Any]] = None,
337337
) -> Callable[..., Any]:
338338
"""Optional: Sets name of the :class:`Function` object. If not set,
339339
it will default to the name of the method name.
@@ -343,6 +343,8 @@ def function_name(self, name: str,
343343
additional setting fields
344344
:return: Decorator function.
345345
"""
346+
if setting_extra_fields is None:
347+
setting_extra_fields = {}
346348

347349
@self._configure_function_builder
348350
def wrap(fb):
@@ -437,8 +439,8 @@ def route(self,
437439
methods: Optional[
438440
Union[Iterable[str], Iterable[HttpMethod]]] = None,
439441
auth_level: Optional[Union[AuthLevel, str]] = None,
440-
trigger_extra_fields: Dict[str, Any] = {},
441-
binding_extra_fields: Dict[str, Any] = {}
442+
trigger_extra_fields: Optional[Dict[str, Any]] = None,
443+
binding_extra_fields: Optional[Dict[str, Any]] = None
442444
) -> Callable[..., Any]:
443445
"""The route decorator adds :class:`HttpTrigger` and
444446
:class:`HttpOutput` binding to the :class:`FunctionBuilder` object
@@ -469,6 +471,10 @@ def route(self,
469471
json. For example,
470472
>>> data_type='STRING' # 'dataType': 'STRING' in binding json
471473
"""
474+
if trigger_extra_fields is None:
475+
trigger_extra_fields = {}
476+
if binding_extra_fields is None:
477+
binding_extra_fields = {}
472478

473479
@self._configure_function_builder
474480
def wrap(fb):
@@ -3197,7 +3203,7 @@ def retry(self,
31973203
delay_interval: Optional[str] = None,
31983204
minimum_interval: Optional[str] = None,
31993205
maximum_interval: Optional[str] = None,
3200-
setting_extra_fields: Dict[str, Any] = {},
3206+
setting_extra_fields: Optional[Dict[str, Any]] = None,
32013207
) -> Callable[..., Any]:
32023208
"""The retry decorator adds :class:`RetryPolicy` to the function
32033209
settings object for building :class:`Function` object used in worker
@@ -3219,6 +3225,8 @@ def retry(self,
32193225
additional setting fields.
32203226
:return: Decorator function.
32213227
"""
3228+
if setting_extra_fields is None:
3229+
setting_extra_fields = {}
32223230

32233231
@self._configure_function_builder
32243232
def wrap(fb):

azure/functions/extension/app_extension_base.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ def post_function_load_app_level(cls,
6262
# DO NOT decorate this with @abc.abstractstatismethod
6363
# since implementation by subclass is not mandatory
6464
@classmethod
65-
def pre_invocation_app_level(cls,
66-
logger: Logger,
67-
context: Context,
68-
func_args: typing.Dict[str, object] = {},
69-
*args,
70-
**kwargs) -> None:
65+
def pre_invocation_app_level(
66+
cls,
67+
logger: Logger,
68+
context: Context,
69+
func_args: typing.Optional[typing.Dict[str, object]] = None,
70+
*args,
71+
**kwargs) -> None:
7172
"""This must be implemented as a @staticmethod. It will be called right
7273
before a customer's function is being executed.
7374
@@ -90,13 +91,14 @@ def pre_invocation_app_level(cls,
9091
# DO NOT decorate this with @abc.abstractstatismethod
9192
# since implementation by subclass is not mandatory
9293
@classmethod
93-
def post_invocation_app_level(cls,
94-
logger: Logger,
95-
context: Context,
96-
func_args: typing.Dict[str, object] = {},
97-
func_ret: typing.Optional[object] = None,
98-
*args,
99-
**kwargs) -> None:
94+
def post_invocation_app_level(
95+
cls,
96+
logger: Logger,
97+
context: Context,
98+
func_args: typing.Optional[typing.Dict[str, object]] = None,
99+
func_ret: typing.Optional[object] = None,
100+
*args,
101+
**kwargs) -> None:
100102
"""This must be implemented as a @staticmethod. It will be called right
101103
after a customer's function is being executed.
102104

azure/functions/extension/func_extension_base.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ def post_function_load(self,
8686

8787
# DO NOT decorate this with @abc.abstractmethod
8888
# since implementation by subclass is not mandatory
89-
def pre_invocation(self,
90-
logger: Logger,
91-
context: Context,
92-
func_args: typing.Dict[str, object] = {},
93-
*args,
94-
**kwargs) -> None:
89+
def pre_invocation(
90+
self,
91+
logger: Logger,
92+
context: Context,
93+
func_args: typing.Optional[typing.Dict[str, object]] = None,
94+
*args,
95+
**kwargs) -> None:
9596
"""This hook will be called right before customer's function
9697
is being executed.
9798
@@ -113,13 +114,14 @@ def pre_invocation(self,
113114

114115
# DO NOT decorate this with @abc.abstractmethod
115116
# since implementation by subclass is not mandatory
116-
def post_invocation(self,
117-
logger: Logger,
118-
context: Context,
119-
func_args: typing.Dict[str, object] = {},
120-
func_ret: typing.Optional[object] = None,
121-
*args,
122-
**kwargs) -> None:
117+
def post_invocation(
118+
self,
119+
logger: Logger,
120+
context: Context,
121+
func_args: typing.Optional[typing.Dict[str, object]] = None,
122+
func_ret: typing.Optional[object] = None,
123+
*args,
124+
**kwargs) -> None:
123125
"""This hook will be called right after a customer's function
124126
is executed.
125127

azure/functions/timer.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010

1111
class TimerRequest(azf_abc.TimerRequest):
1212

13-
def __init__(self, *, past_due: bool = False, schedule_status: dict = {},
14-
schedule: dict = {}) -> None:
13+
def __init__(self, *, past_due: bool = False,
14+
schedule_status: typing.Optional[dict] = None,
15+
schedule: typing.Optional[dict] = None) -> None:
1516
self.__past_due = past_due
16-
self.__schedule_status = schedule_status
17-
self.__schedule = schedule
17+
self.__schedule_status = schedule_status if schedule_status else {}
18+
self.__schedule = schedule if schedule else {}
1819

1920
@property
2021
def past_due(self) -> bool:

tests/test_timer.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ def test_timer_initialize_without_args(self):
4444
self.assertEqual(schedule_status, test_timer.schedule_status)
4545
self.assertEqual(schedule, test_timer.schedule)
4646

47+
def test_timer_initialize_empty_dicts(self):
48+
# given
49+
past_due = False
50+
51+
# when
52+
test_timer = timer.TimerRequest()
53+
54+
# then
55+
self.assertEqual(past_due, test_timer.past_due)
56+
self.assertEqual({}, test_timer.schedule_status)
57+
self.assertEqual({}, test_timer.schedule)
58+
4759
def test_timer_no_implementation_exception(self):
4860
# given
4961
datum: Datum = Datum(value="test", type='string')

0 commit comments

Comments
 (0)