-
Notifications
You must be signed in to change notification settings - Fork 75
Expand file tree
/
Copy pathcore.py
More file actions
227 lines (182 loc) · 7.89 KB
/
Copy pathcore.py
File metadata and controls
227 lines (182 loc) · 7.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from abc import ABC, abstractmethod
from typing import Dict, Optional, Type
from .utils import to_camel_case, \
ABCBuildDictMeta, StringifyEnum
SCRIPT_FILE_NAME = "function_app.py"
# Enums
class BindingDirection(StringifyEnum):
"""Direction of the binding used in function.json"""
IN = 0
"""Input binding direction."""
OUT = 1
"""Output binding direction."""
INOUT = 2
"""Some bindings support a special binding direction. """
class DataType(StringifyEnum):
"""Data type of the binding used in function.json"""
"""Parse binding argument as undefined."""
UNDEFINED = 0
"""Parse binding argument as string."""
STRING = 1
"""Parse binding argument as binary."""
BINARY = 2
"""Parse binding argument as stream."""
STREAM = 3
class AuthLevel(StringifyEnum):
"""Azure HTTP authorization level, determines what keys, if any, need to
be present on the request in order to invoke the function. """
FUNCTION = "function"
"""A function-specific API key is required. This is the default value if
none is provided. """
ANONYMOUS = "anonymous"
"""No API key is required."""
ADMIN = "admin"
"""The master key is required."""
class Cardinality(StringifyEnum):
"""Used for all non-C# languages. Set to many in order to enable
batching. If omitted or set to one, a single message is passed to the
function. """
ONE = "one"
"""Singe message passed to the function."""
MANY = "many"
"""Multiple messaged passed to the function per invocation."""
class AccessRights(StringifyEnum):
"""Access rights for the connection string. The default is manage,
which indicates that the connection has the Manage permission. """
MANAGE = "manage"
"""Confers the right to manage the topology of the namespace, including
creating and deleting entities. """
LISTEN = "listen"
"""Confers the right to listen (relay) or receive (queue, subscriptions)
and all related message handling. """
class BlobSource(StringifyEnum):
"""Source of the blob trigger."""
EVENT_GRID = "EventGrid"
"""Event Grid is the source of the blob trigger."""
LOGS_AND_CONTAINER_SCAN = "LogsAndContainerScan"
"""Standard polling mechanism to detect changes in the container."""
class McpPropertyType(StringifyEnum):
"""MCP property types."""
INTEGER = "integer"
"""Integer type."""
FLOAT = "float"
"""Float type."""
STRING = "string"
"""String type."""
BOOLEAN = "boolean"
"""Boolean type."""
OBJECT = "object"
"""Object type."""
DATETIME = "string"
"""Datetime type represented as string."""
class Binding(ABC):
"""Abstract binding class which captures common attributes and
functions. :meth:`get_dict_repr` can auto generate the function.json for
every binding, the only restriction is ***ENSURE*** __init__ parameter
names of any binding class are snake case form of corresponding
attribute in function.json when new binding classes are created.
Ref: https://aka.ms/azure-function-binding-http """
EXCLUDED_INIT_PARAMS = {'self', 'kwargs', 'type', 'data_type', 'direction'}
@staticmethod
@abstractmethod
def get_binding_name() -> str:
pass
def __init__(self, name: str,
direction: BindingDirection,
data_type: Optional[DataType] = None,
type: Optional[str] = None): # NoQa
# For natively supported bindings, get_binding_name is always
# implemented, and for generic bindings, type is a required argument
# in decorator functions.
self.type = self.get_binding_name() \
if self.get_binding_name() is not None else type
self.name = name
self._direction = direction
self._data_type = data_type
self._dict = {
"direction": self._direction,
"dataType": self._data_type,
"type": self.type
}
@property
def data_type(self) -> Optional[int]:
return self._data_type.value if self._data_type else None
@property
def direction(self) -> int:
return self._direction.value
def get_dict_repr(self) -> Dict:
"""Build a dictionary of a particular binding. The keys are camel
cased binding field names defined in `init_params` list and
:class:`Binding` class. \n
This method is invoked in function :meth:`get_raw_bindings` of class
:class:`Function` to generate json dict for each binding.
:return: Dictionary representation of the binding.
"""
params = list(dict.fromkeys(getattr(self, 'init_params', [])))
for p in params:
if p not in Binding.EXCLUDED_INIT_PARAMS:
self._dict[to_camel_case(p)] = getattr(self, p, None)
return self._dict
class Trigger(Binding, ABC, metaclass=ABCBuildDictMeta):
"""Class representation of Azure Function Trigger. \n
Ref: https://aka.ms/functions-triggers-bindings-overview
"""
@staticmethod
def is_supported_trigger_type(trigger_instance: 'Trigger',
trigger_type: Type['Trigger']):
return isinstance(trigger_instance,
trigger_type) or trigger_instance.type == \
trigger_type.get_binding_name()
def __init__(self, name: str, data_type: Optional[DataType] = None,
type: Optional[str] = None) -> None:
super().__init__(direction=BindingDirection.IN,
name=name, data_type=data_type, type=type)
class InputBinding(Binding, ABC, metaclass=ABCBuildDictMeta):
"""Class representation of Azure Function Input Binding. \n
Ref: https://aka.ms/functions-triggers-bindings-overview
"""
def __init__(self, name: str, data_type: Optional[DataType] = None,
type: Optional[str] = None) -> None:
super().__init__(direction=BindingDirection.IN,
name=name, data_type=data_type, type=type)
class OutputBinding(Binding, ABC, metaclass=ABCBuildDictMeta):
"""Class representation of Azure Function Output Binding. \n
Ref: https://aka.ms/functions-triggers-bindings-overview
"""
def __init__(self, name: str, data_type: Optional[DataType] = None,
type: Optional[str] = None) -> None:
super().__init__(direction=BindingDirection.OUT,
name=name, data_type=data_type, type=type)
class Setting(ABC, metaclass=ABCBuildDictMeta):
""" Abstract class for all settings of a function app.
This class represents all the decorators that cannot be
classified as bindings or triggers. e.g function_name, retry etc.
"""
EXCLUDED_INIT_PARAMS = {'self', 'kwargs', 'setting_name'}
def __init__(self, setting_name: str) -> None:
self.setting_name = setting_name
self._dict: Dict = {
"setting_name": self.setting_name
}
def get_setting_name(self) -> str:
return self.setting_name
def get_dict_repr(self) -> Dict:
"""Build a dictionary of a particular binding. The keys are camel
cased binding field names defined in `init_params` list and
:class:`Binding` class. \n
This method is invoked in function :meth:`get_raw_bindings` of class
:class:`Function` to generate json dict for each binding.
:return: Dictionary representation of the binding.
"""
params = list(dict.fromkeys(getattr(self, 'init_params', [])))
for p in params:
if p not in Setting.EXCLUDED_INIT_PARAMS:
self._dict[p] = getattr(self, p, None)
return self._dict
def get_settings_value(self, settings_attribute_key: str) -> Optional[str]:
"""
Get the value of a particular setting attribute.
"""
return self.get_dict_repr().get(settings_attribute_key)