Skip to content

Commit 1ea47fb

Browse files
committed
Move rich binding implementations from the worker
Per Azure/azure-functions-python-worker#409, the rich binding implementations are now in the library.
1 parent 0b249b6 commit 1ea47fb

File tree

11 files changed

+1440
-0
lines changed

11 files changed

+1440
-0
lines changed

azure/functions/__init__.py

+15
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,23 @@
66
from ._http import HttpResponse # NoQA
77
from ._queue import QueueMessage # NoQA
88
from ._servicebus import ServiceBusMessage # NoQA
9+
from .meta import get_binding_registry # NoQA
10+
11+
# Import binding implementations to register them
12+
from . import blob # NoQA
13+
from . import cosmosdb # NoQA
14+
from . import eventgrid # NoQA
15+
from . import eventhub # NoQA
16+
from . import http # NoQA
17+
from . import queue # NoQA
18+
from . import servicebus # NoQA
19+
from . import timer # NoQA
20+
921

1022
__all__ = (
23+
# Functions
24+
'get_binding_registry',
25+
1126
# Generics.
1227
'Context',
1328
'Out',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
# Imported from https://github.com/ilevkivskyi/typing_inspect/blob/168fa6f7c5c55f720ce6282727211cf4cf6368f6/typing_inspect.py
2+
# Author: Ivan Levkivskyi
3+
# License: MIT
4+
5+
"""Defines experimental API for runtime inspection of types defined
6+
in the standard "typing" module.
7+
8+
Example usage::
9+
from typing_inspect import is_generic_type
10+
"""
11+
12+
# NOTE: This module must support Python 2.7 in addition to Python 3.x
13+
14+
import sys
15+
NEW_TYPING = sys.version_info[:3] >= (3, 7, 0) # PEP 560
16+
if NEW_TYPING:
17+
import collections.abc
18+
19+
20+
if NEW_TYPING:
21+
from typing import (
22+
Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias
23+
)
24+
else:
25+
from typing import (
26+
Callable, CallableMeta, Union, _Union, TupleMeta, TypeVar,
27+
_ClassVar, GenericMeta,
28+
)
29+
30+
31+
# from mypy_extensions import _TypedDictMeta
32+
33+
34+
def _gorg(cls):
35+
"""This function exists for compatibility with old typing versions."""
36+
assert isinstance(cls, GenericMeta)
37+
if hasattr(cls, '_gorg'):
38+
return cls._gorg
39+
while cls.__origin__ is not None:
40+
cls = cls.__origin__
41+
return cls
42+
43+
44+
def is_generic_type(tp):
45+
"""Test if the given type is a generic type. This includes Generic itself, but
46+
excludes special typing constructs such as Union, Tuple, Callable, ClassVar.
47+
Examples::
48+
49+
is_generic_type(int) == False
50+
is_generic_type(Union[int, str]) == False
51+
is_generic_type(Union[int, T]) == False
52+
is_generic_type(ClassVar[List[int]]) == False
53+
is_generic_type(Callable[..., T]) == False
54+
55+
is_generic_type(Generic) == True
56+
is_generic_type(Generic[T]) == True
57+
is_generic_type(Iterable[int]) == True
58+
is_generic_type(Mapping) == True
59+
is_generic_type(MutableMapping[T, List[int]]) == True
60+
is_generic_type(Sequence[Union[str, bytes]]) == True
61+
"""
62+
if NEW_TYPING:
63+
return (isinstance(tp, type) and issubclass(tp, Generic) or
64+
isinstance(tp, _GenericAlias) and
65+
tp.__origin__ not in (Union, tuple, ClassVar, collections.abc.Callable))
66+
return (isinstance(tp, GenericMeta) and not
67+
isinstance(tp, (CallableMeta, TupleMeta)))
68+
69+
70+
def is_callable_type(tp):
71+
"""Test if the type is a generic callable type, including subclasses
72+
excluding non-generic types and callables.
73+
Examples::
74+
75+
is_callable_type(int) == False
76+
is_callable_type(type) == False
77+
is_callable_type(Callable) == True
78+
is_callable_type(Callable[..., int]) == True
79+
is_callable_type(Callable[[int, int], Iterable[str]]) == True
80+
class MyClass(Callable[[int], int]):
81+
...
82+
is_callable_type(MyClass) == True
83+
84+
For more general tests use callable(), for more precise test
85+
(excluding subclasses) use::
86+
87+
get_origin(tp) is collections.abc.Callable # Callable prior to Python 3.7
88+
"""
89+
if NEW_TYPING:
90+
return (tp is Callable or isinstance(tp, _GenericAlias) and
91+
tp.__origin__ is collections.abc.Callable or
92+
isinstance(tp, type) and issubclass(tp, Generic) and
93+
issubclass(tp, collections.abc.Callable))
94+
return type(tp) is CallableMeta
95+
96+
97+
def is_tuple_type(tp):
98+
"""Test if the type is a generic tuple type, including subclasses excluding
99+
non-generic classes.
100+
Examples::
101+
102+
is_tuple_type(int) == False
103+
is_tuple_type(tuple) == False
104+
is_tuple_type(Tuple) == True
105+
is_tuple_type(Tuple[str, int]) == True
106+
class MyClass(Tuple[str, int]):
107+
...
108+
is_tuple_type(MyClass) == True
109+
110+
For more general tests use issubclass(..., tuple), for more precise test
111+
(excluding subclasses) use::
112+
113+
get_origin(tp) is tuple # Tuple prior to Python 3.7
114+
"""
115+
if NEW_TYPING:
116+
return (tp is Tuple or isinstance(tp, _GenericAlias) and
117+
tp.__origin__ is tuple or
118+
isinstance(tp, type) and issubclass(tp, Generic) and
119+
issubclass(tp, tuple))
120+
return type(tp) is TupleMeta
121+
122+
123+
def is_union_type(tp):
124+
"""Test if the type is a union type. Examples::
125+
126+
is_union_type(int) == False
127+
is_union_type(Union) == True
128+
is_union_type(Union[int, int]) == False
129+
is_union_type(Union[T, int]) == True
130+
"""
131+
if NEW_TYPING:
132+
return (tp is Union or
133+
isinstance(tp, _GenericAlias) and tp.__origin__ is Union)
134+
return type(tp) is _Union
135+
136+
137+
def is_typevar(tp):
138+
"""Test if the type represents a type variable. Examples::
139+
140+
is_typevar(int) == False
141+
is_typevar(T) == True
142+
is_typevar(Union[T, int]) == False
143+
"""
144+
145+
return type(tp) is TypeVar
146+
147+
148+
def is_classvar(tp):
149+
"""Test if the type represents a class variable. Examples::
150+
151+
is_classvar(int) == False
152+
is_classvar(ClassVar) == True
153+
is_classvar(ClassVar[int]) == True
154+
is_classvar(ClassVar[List[T]]) == True
155+
"""
156+
if NEW_TYPING:
157+
return (tp is ClassVar or
158+
isinstance(tp, _GenericAlias) and tp.__origin__ is ClassVar)
159+
return type(tp) is _ClassVar
160+
161+
162+
def get_last_origin(tp):
163+
"""Get the last base of (multiply) subscripted type. Supports generic types,
164+
Union, Callable, and Tuple. Returns None for unsupported types.
165+
Examples::
166+
167+
get_last_origin(int) == None
168+
get_last_origin(ClassVar[int]) == None
169+
get_last_origin(Generic[T]) == Generic
170+
get_last_origin(Union[T, int][str]) == Union[T, int]
171+
get_last_origin(List[Tuple[T, T]][int]) == List[Tuple[T, T]]
172+
get_last_origin(List) == List
173+
"""
174+
if NEW_TYPING:
175+
raise ValueError('This function is only supported in Python 3.6,'
176+
' use get_origin instead')
177+
sentinel = object()
178+
origin = getattr(tp, '__origin__', sentinel)
179+
if origin is sentinel:
180+
return None
181+
if origin is None:
182+
return tp
183+
return origin
184+
185+
186+
def get_origin(tp):
187+
"""Get the unsubscripted version of a type. Supports generic types, Union,
188+
Callable, and Tuple. Returns None for unsupported types. Examples::
189+
190+
get_origin(int) == None
191+
get_origin(ClassVar[int]) == None
192+
get_origin(Generic) == Generic
193+
get_origin(Generic[T]) == Generic
194+
get_origin(Union[T, int]) == Union
195+
get_origin(List[Tuple[T, T]][int]) == list # List prior to Python 3.7
196+
"""
197+
if NEW_TYPING:
198+
if isinstance(tp, _GenericAlias):
199+
return tp.__origin__ if tp.__origin__ is not ClassVar else None
200+
if tp is Generic:
201+
return Generic
202+
return None
203+
if isinstance(tp, GenericMeta):
204+
return _gorg(tp)
205+
if is_union_type(tp):
206+
return Union
207+
208+
return None
209+
210+
211+
def get_parameters(tp):
212+
"""Return type parameters of a parameterizable type as a tuple
213+
in lexicographic order. Parameterizable types are generic types,
214+
unions, tuple types and callable types. Examples::
215+
216+
get_parameters(int) == ()
217+
get_parameters(Generic) == ()
218+
get_parameters(Union) == ()
219+
get_parameters(List[int]) == ()
220+
221+
get_parameters(Generic[T]) == (T,)
222+
get_parameters(Tuple[List[T], List[S_co]]) == (T, S_co)
223+
get_parameters(Union[S_co, Tuple[T, T]][int, U]) == (U,)
224+
get_parameters(Mapping[T, Tuple[S_co, T]]) == (T, S_co)
225+
"""
226+
if NEW_TYPING:
227+
if (isinstance(tp, _GenericAlias) or
228+
isinstance(tp, type) and issubclass(tp, Generic) and
229+
tp is not Generic):
230+
return tp.__parameters__
231+
return ()
232+
if (
233+
is_generic_type(tp) or is_union_type(tp) or
234+
is_callable_type(tp) or is_tuple_type(tp)
235+
):
236+
return tp.__parameters__ if tp.__parameters__ is not None else ()
237+
return ()
238+
239+
240+
def get_last_args(tp):
241+
"""Get last arguments of (multiply) subscripted type.
242+
Parameters for Callable are flattened. Examples::
243+
244+
get_last_args(int) == ()
245+
get_last_args(Union) == ()
246+
get_last_args(ClassVar[int]) == (int,)
247+
get_last_args(Union[T, int]) == (T, int)
248+
get_last_args(Iterable[Tuple[T, S]][int, T]) == (int, T)
249+
get_last_args(Callable[[T], int]) == (T, int)
250+
get_last_args(Callable[[], int]) == (int,)
251+
"""
252+
if NEW_TYPING:
253+
raise ValueError('This function is only supported in Python 3.6,'
254+
' use get_args instead')
255+
if is_classvar(tp):
256+
return (tp.__type__,) if tp.__type__ is not None else ()
257+
if (
258+
is_generic_type(tp) or is_union_type(tp) or
259+
is_callable_type(tp) or is_tuple_type(tp)
260+
):
261+
return tp.__args__ if tp.__args__ is not None else ()
262+
return ()
263+
264+
265+
def _eval_args(args):
266+
"""Internal helper for get_args."""
267+
res = []
268+
for arg in args:
269+
if not isinstance(arg, tuple):
270+
res.append(arg)
271+
elif is_callable_type(arg[0]):
272+
if len(arg) == 2:
273+
res.append(Callable[[], arg[1]])
274+
elif arg[1] is Ellipsis:
275+
res.append(Callable[..., arg[2]])
276+
else:
277+
res.append(Callable[list(arg[1:-1]), arg[-1]])
278+
else:
279+
res.append(type(arg[0]).__getitem__(arg[0], _eval_args(arg[1:])))
280+
return tuple(res)
281+
282+
283+
def get_args(tp, evaluate=None):
284+
"""Get type arguments with all substitutions performed. For unions,
285+
basic simplifications used by Union constructor are performed.
286+
On versions prior to 3.7 if `evaluate` is False (default),
287+
report result as nested tuple, this matches
288+
the internal representation of types. If `evaluate` is True
289+
(or if Python version is 3.7 or greater), then all
290+
type parameters are applied (this could be time and memory expensive).
291+
Examples::
292+
293+
get_args(int) == ()
294+
get_args(Union[int, Union[T, int], str][int]) == (int, str)
295+
get_args(Union[int, Tuple[T, int]][str]) == (int, (Tuple, str, int))
296+
297+
get_args(Union[int, Tuple[T, int]][str], evaluate=True) == \
298+
(int, Tuple[str, int])
299+
get_args(Dict[int, Tuple[T, T]][Optional[int]], evaluate=True) == \
300+
(int, Tuple[Optional[int], Optional[int]])
301+
get_args(Callable[[], T][int], evaluate=True) == ([], int,)
302+
"""
303+
if NEW_TYPING:
304+
if evaluate is not None and not evaluate:
305+
raise ValueError('evaluate can only be True in Python 3.7')
306+
if isinstance(tp, _GenericAlias):
307+
res = tp.__args__
308+
if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis:
309+
res = (list(res[:-1]), res[-1])
310+
return res
311+
return ()
312+
if is_classvar(tp):
313+
return (tp.__type__,)
314+
if (
315+
is_generic_type(tp) or is_union_type(tp) or
316+
is_callable_type(tp) or is_tuple_type(tp)
317+
):
318+
tree = tp._subs_tree()
319+
if isinstance(tree, tuple) and len(tree) > 1:
320+
if not evaluate:
321+
return tree[1:]
322+
res = _eval_args(tree[1:])
323+
if get_origin(tp) is Callable and res[0] is not Ellipsis:
324+
res = (list(res[:-1]), res[-1])
325+
return res
326+
return ()
327+
328+
329+
def get_generic_type(obj):
330+
"""Get the generic type of an object if possible, or runtime class otherwise.
331+
Examples::
332+
333+
class Node(Generic[T]):
334+
...
335+
type(Node[int]()) == Node
336+
get_generic_type(Node[int]()) == Node[int]
337+
get_generic_type(Node[T]()) == Node[T]
338+
get_generic_type(1) == int
339+
"""
340+
341+
gen_type = getattr(obj, '__orig_class__', None)
342+
return gen_type if gen_type is not None else type(obj)
343+
344+
345+
def get_generic_bases(tp):
346+
"""Get generic base types of a type or empty tuple if not possible.
347+
Example::
348+
349+
class MyClass(List[int], Mapping[str, List[int]]):
350+
...
351+
MyClass.__bases__ == (List, Mapping)
352+
get_generic_bases(MyClass) == (List[int], Mapping[str, List[int]])
353+
"""
354+
355+
return getattr(tp, '__orig_bases__', ())
356+
357+
358+
def typed_dict_keys(td):
359+
"""If td is a TypedDict class, return a dictionary mapping the typed keys to types.
360+
Otherwise, return None. Examples::
361+
362+
class TD(TypedDict):
363+
x: int
364+
y: int
365+
class Other(dict):
366+
x: int
367+
y: int
368+
369+
typed_dict_keys(TD) == {'x': int, 'y': int}
370+
typed_dict_keys(dict) == None
371+
typed_dict_keys(Other) == None
372+
"""
373+
if isinstance(td, _TypedDictMeta):
374+
return td.__annotations__.copy()
375+
return None

0 commit comments

Comments
 (0)