diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py index 1102bc36..62937996 100644 --- a/azure/functions/decorators/function_app.py +++ b/azure/functions/decorators/function_app.py @@ -1,7 +1,6 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. import json -import typing from typing import Callable, Dict, List, Optional, Union, Iterable from azure.functions.decorators.blob import BlobTrigger, BlobInput, BlobOutput @@ -192,29 +191,33 @@ class FunctionApp: """ def __init__(self, - wsgi_app=None, - asgi_app=None, - app_kwargs: typing.Dict = {}, - auth_level: Union[AuthLevel, str] = AuthLevel.FUNCTION): + http_auth_level: Union[AuthLevel, str] = AuthLevel.FUNCTION, + **kwargs): """Constructor of :class:`FunctionApp` object. - - :param wsgi_app: wsgi app object, defaults to None. - :param asgi_app: asgi app object, defaults to None. - :param app_kwargs: dict of :meth:`route` param names and values for - custom configuration of wsgi/asgi app, default to {}. - :param auth_level: defaults to AuthLevel.FUNCTION, takes str or - AuthLevel + To integrate your asgi or wsgi application into python function, + specify either of below variables as a keyword argument: + `asgi_app` - the actual asgi application to integrate into python + function. + `wsgi_app` - the actual wsgi application to integrate into python + function. + + :param http_auth_level: defaults to AuthLevel.FUNCTION, takes str or + AuthLevel. + :param kwargs: Extra arguments passed to :func:`__init__`. """ self._function_builders: List[FunctionBuilder] = [] self._app_script_file: str = SCRIPT_FILE_NAME - self._auth_level = AuthLevel[auth_level] \ - if isinstance(auth_level, str) else auth_level + self._auth_level = AuthLevel[http_auth_level] \ + if isinstance(http_auth_level, str) else http_auth_level + + wsgi_app = kwargs.get("wsgi_app", None) + asgi_app = kwargs.get("asgi_app", None) if wsgi_app is not None: - self._add_http_app(WsgiMiddleware(wsgi_app), app_kwargs) + self._add_http_app(WsgiMiddleware(wsgi_app)) if asgi_app is not None: - self._add_http_app(AsgiMiddleware(asgi_app), app_kwargs) + self._add_http_app(AsgiMiddleware(asgi_app)) @property def app_script_file(self) -> str: @@ -296,28 +299,18 @@ def decorator(): return wrap def _add_http_app(self, - http_middleware: Union[AsgiMiddleware, WsgiMiddleware], - app_kwargs: typing.Dict) -> None: + http_middleware: Union[ + AsgiMiddleware, WsgiMiddleware]) -> None: """Add a Wsgi or Asgi app integrated http function. :param http_middleware: :class:`AsgiMiddleware` or :class:`WsgiMiddleware` instance. - :param app_kwargs: dict of :meth:`route` param names and values for - custom configuration of wsgi/asgi app. :return: None """ - methods = app_kwargs.get('methods', (method for method in HttpMethod)) - trigger_arg_data_type = app_kwargs.get('trigger_arg_data_type', - None) - output_arg_data_type = app_kwargs.get('output_arg_data_type', - None) - auth_level = app_kwargs.get('auth_level', None) - - @self.route(methods=methods, - auth_level=auth_level, - trigger_arg_data_type=trigger_arg_data_type, - output_arg_data_type=output_arg_data_type, + + @self.route(methods=(method for method in HttpMethod), + auth_level=self.auth_level, route="/{*route}") def http_app_func(req: HttpRequest, context: Context): return http_middleware.handle(req, context) @@ -326,8 +319,6 @@ def route(self, route: Optional[str] = None, trigger_arg_name: str = 'req', binding_arg_name: str = '$return', - trigger_arg_data_type: Optional[Union[DataType, str]] = None, - output_arg_data_type: Optional[Union[DataType, str]] = None, methods: Optional[ Union[Iterable[str], Iterable[HttpMethod]]] = None, auth_level: Optional[Union[AuthLevel, str]] = None) -> Callable: @@ -348,10 +339,6 @@ def route(self, defaults to 'req'. :param binding_arg_name: Argument name for :class:`HttpResponse`, defaults to '$return'. - :param trigger_arg_data_type: Defines how Functions runtime should - treat the trigger_arg_name value. - :param output_arg_data_type: Defines how Functions runtime should - treat the binding_arg_name value. :param methods: A tuple of the HTTP methods to which the function responds. :param auth_level: Determines what keys, if any, need to be present @@ -368,18 +355,11 @@ def decorator(): fb.add_trigger(trigger=HttpTrigger( name=trigger_arg_name, - data_type=parse_singular_param_to_enum( - trigger_arg_data_type, - DataType), methods=parse_iterable_param_to_enums(methods, HttpMethod), auth_level=parse_singular_param_to_enum(auth_level, AuthLevel), route=route)) - fb.add_binding(binding=HttpOutput( - name=binding_arg_name, - data_type=parse_singular_param_to_enum( - output_arg_data_type, - DataType))) + fb.add_binding(binding=HttpOutput(name=binding_arg_name)) return fb return decorator() @@ -433,7 +413,7 @@ def decorator(): return wrap - def on_service_bus_queue_change( + def service_bus_queue_trigger( self, arg_name: str, connection: str, @@ -442,7 +422,7 @@ def on_service_bus_queue_change( access_rights: Optional[Union[AccessRights, str]] = None, is_sessions_enabled: Optional[bool] = None, cardinality: Optional[Union[Cardinality, str]] = None) -> Callable: - """The on_service_bus_queue_change decorator adds + """The service_bus_queue_trigger decorator adds :class:`ServiceBusQueueTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining ServiceBusQueueTrigger @@ -537,7 +517,7 @@ def decorator(): return wrap - def on_service_bus_topic_change( + def service_bus_topic_trigger( self, arg_name: str, connection: str, @@ -547,7 +527,7 @@ def on_service_bus_topic_change( access_rights: Optional[Union[AccessRights, str]] = None, is_sessions_enabled: Optional[bool] = None, cardinality: Optional[Union[Cardinality, str]] = None) -> Callable: - """The on_service_bus_topic_change decorator adds + """The service_bus_topic_trigger decorator adds :class:`ServiceBusTopicTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining ServiceBusTopicTrigger @@ -648,12 +628,12 @@ def decorator(): return wrap - def on_queue_change(self, - arg_name: str, - queue_name: str, - connection: str, - data_type: Optional[DataType] = None) -> Callable: - """The on_queue_change decorator adds :class:`QueueTrigger` to the + def queue_trigger(self, + arg_name: str, + queue_name: str, + connection: str, + data_type: Optional[DataType] = None) -> Callable: + """The queue_trigger decorator adds :class:`QueueTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining QueueTrigger @@ -731,15 +711,18 @@ def decorator(): return wrap - def on_event_hub_message(self, - arg_name: str, - connection: str, - event_hub_name: str, - data_type: Optional[Union[DataType, str]] = None, - cardinality: Optional[ - Union[Cardinality, str]] = None, - consumer_group: Optional[str] = None) -> Callable: - """The on_event_hub_message decorator adds :class:`EventHubTrigger` + def event_hub_message_trigger(self, + arg_name: str, + connection: str, + event_hub_name: str, + data_type: Optional[ + Union[DataType, str]] = None, + cardinality: Optional[ + Union[Cardinality, str]] = None, + consumer_group: Optional[ + str] = None) -> Callable: + """The event_hub_message_trigger decorator adds + :class:`EventHubTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining EventHubTrigger @@ -825,32 +808,32 @@ def decorator(): return wrap - def on_cosmos_db_update(self, - arg_name: str, - database_name: str, - collection_name: str, - connection_string_setting: str, - lease_collection_name: Optional[str] = None, - lease_connection_string_setting: Optional[ - str] = None, - lease_database_name: Optional[str] = None, - create_lease_collection_if_not_exists: Optional[ - bool] = None, - leases_collection_throughput: Optional[int] = None, - lease_collection_prefix: Optional[str] = None, - checkpoint_interval: Optional[int] = None, - checkpoint_document_count: Optional[int] = None, - feed_poll_delay: Optional[int] = None, - lease_renew_interval: Optional[int] = None, - lease_acquire_interval: Optional[int] = None, - lease_expiration_interval: Optional[int] = None, - max_items_per_invocation: Optional[int] = None, - start_from_beginning: Optional[bool] = None, - preferred_locations: Optional[str] = None, - data_type: Optional[ - Union[DataType, str]] = None) -> \ + def cosmos_db_trigger(self, + arg_name: str, + database_name: str, + collection_name: str, + connection_string_setting: str, + lease_collection_name: Optional[str] = None, + lease_connection_string_setting: Optional[ + str] = None, + lease_database_name: Optional[str] = None, + create_lease_collection_if_not_exists: Optional[ + bool] = None, + leases_collection_throughput: Optional[int] = None, + lease_collection_prefix: Optional[str] = None, + checkpoint_interval: Optional[int] = None, + checkpoint_document_count: Optional[int] = None, + feed_poll_delay: Optional[int] = None, + lease_renew_interval: Optional[int] = None, + lease_acquire_interval: Optional[int] = None, + lease_expiration_interval: Optional[int] = None, + max_items_per_invocation: Optional[int] = None, + start_from_beginning: Optional[bool] = None, + preferred_locations: Optional[str] = None, + data_type: Optional[ + Union[DataType, str]] = None) -> \ Callable: - """The on_cosmos_db_update decorator adds :class:`CosmosDBTrigger` + """The cosmos_db_trigger decorator adds :class:`CosmosDBTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining CosmosDBTrigger @@ -1074,13 +1057,13 @@ def decorator(): return wrap - def on_blob_change(self, - arg_name: str, - path: str, - connection: str, - data_type: Optional[DataType] = None) -> Callable: + def blob_trigger(self, + arg_name: str, + path: str, + connection: str, + data_type: Optional[DataType] = None) -> Callable: """ - The on_blob_change decorator adds :class:`BlobTrigger` to the + The blob_change_trigger decorator adds :class:`BlobTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining BlobTrigger diff --git a/docs/ProgModelSpec.pyi b/docs/ProgModelSpec.pyi index 278c22b2..54b6db74 100644 --- a/docs/ProgModelSpec.pyi +++ b/docs/ProgModelSpec.pyi @@ -16,6 +16,23 @@ class FunctionApp: Ref: https://aka.ms/azure-function-ref """ + def __init__(self, + http_auth_level: Union[AuthLevel, str] = AuthLevel.FUNCTION, + **kwargs): + """Constructor of :class:`FunctionApp` object. + To integrate your asgi or wsgi application into python function, + specify either of below variables as a keyword argument: + `asgi_app` - the actual asgi application to integrate into python + function. + `wsgi_app` - the actual wsgi application to integrate into python + function. + + :param http_auth_level: defaults to AuthLevel.FUNCTION, takes str or + AuthLevel. + :param kwargs: Extra arguments passed to :func:`__init__`. + """ + pass + def function_name(self, name: str) -> Callable: """Set name of the :class:`Function` object. @@ -42,8 +59,6 @@ class FunctionApp: route: Optional[str] = None, trigger_arg_name: str = 'req', binding_arg_name: str = '$return', - trigger_arg_data_type: Optional[Union[DataType, str]] = None, - output_arg_data_type: Optional[Union[DataType, str]] = None, methods: Optional[ Union[Iterable[str], Iterable[HttpMethod]]] = None, auth_level: Optional[Union[AuthLevel, str]] = None) -> Callable: @@ -107,7 +122,7 @@ class FunctionApp: """ pass - def on_service_bus_queue_change( + def service_bus_queue_trigger( self, arg_name: str, connection: str, @@ -116,7 +131,7 @@ class FunctionApp: access_rights: Optional[Union[AccessRights, str]] = None, is_sessions_enabled: Optional[bool] = None, cardinality: Optional[Union[Cardinality, str]] = None) -> Callable: - """The on_service_bus_queue_change decorator adds + """The service_bus_queue_trigger decorator adds :class:`ServiceBusQueueTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining ServiceBusQueueTrigger @@ -173,7 +188,7 @@ class FunctionApp: """ pass - def on_service_bus_topic_change( + def service_bus_topic_trigger( self, arg_name: str, connection: str, @@ -183,7 +198,7 @@ class FunctionApp: access_rights: Optional[Union[AccessRights, str]] = None, is_sessions_enabled: Optional[bool] = None, cardinality: Optional[Union[Cardinality, str]] = None) -> Callable: - """The on_service_bus_topic_change decorator adds + """The service_bus_topic_trigger decorator adds :class:`ServiceBusTopicTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining ServiceBusTopicTrigger @@ -248,7 +263,7 @@ class FunctionApp: queue_name: str, connection: str, data_type: Optional[DataType] = None) -> Callable: - """The on_queue_change decorator adds :class:`QueueTrigger` to the + """The queue_trigger decorator adds :class:`QueueTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining QueueTrigger @@ -296,7 +311,7 @@ class FunctionApp: """ pass - def on_event_hub_message(self, + def event_hub_message_trigger(self, arg_name: str, connection: str, event_hub_name: str, @@ -304,7 +319,7 @@ class FunctionApp: cardinality: Optional[ Union[Cardinality, str]] = None, consumer_group: Optional[str] = None) -> Callable: - """The on_event_hub_message decorator adds :class:`EventHubTrigger` + """The event_hub_message_trigger decorator adds :class:`EventHubTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining EventHubTrigger @@ -357,7 +372,7 @@ class FunctionApp: """ pass - def on_cosmos_db_update(self, + def cosmos_db_trigger(self, arg_name: str, database_name: str, collection_name: str, @@ -382,7 +397,7 @@ class FunctionApp: data_type: Optional[ Union[DataType, str]] = None) -> \ Callable: - """The on_cosmos_db_update decorator adds :class:`CosmosDBTrigger` + """The cosmos_db_trigger decorator adds :class:`CosmosDBTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining CosmosDBTrigger @@ -534,13 +549,13 @@ class FunctionApp: """ pass - def on_blob_change(self, - arg_name: str, - path: str, - connection: str, - data_type: Optional[DataType] = None) -> Callable: + def blob_change_trigger(self, + arg_name: str, + path: str, + connection: str, + data_type: Optional[DataType] = None) -> Callable: """ - The on_blob_change decorator adds :class:`BlobTrigger` to the + The blob_change_trigger decorator adds :class:`BlobTrigger` to the :class:`FunctionBuilder` object for building :class:`Function` object used in worker function indexing model. This is equivalent to defining BlobTrigger diff --git a/tests/decorators/test_decorators.py b/tests/decorators/test_decorators.py index 6872ab43..d349c973 100644 --- a/tests/decorators/test_decorators.py +++ b/tests/decorators/test_decorators.py @@ -141,8 +141,6 @@ def test_route_with_all_args(self): app = self.func_app @app.route(trigger_arg_name='trigger_name', binding_arg_name='out', - trigger_arg_data_type=DataType.STRING, - output_arg_data_type=DataType.STRING, methods=(HttpMethod.GET, HttpMethod.PATCH), auth_level=AuthLevel.FUNCTION, route='dummy_route') def dummy(): @@ -155,7 +153,6 @@ def dummy(): { "direction": BindingDirection.IN, "type": HTTP_TRIGGER, - "dataType": DataType.STRING, "name": "trigger_name", "authLevel": AuthLevel.FUNCTION, "route": "dummy_route", @@ -165,7 +162,6 @@ def dummy(): }, { "direction": BindingDirection.OUT, - "dataType": DataType.STRING, "type": HTTP_OUTPUT, "name": "out", } @@ -175,8 +171,8 @@ def dummy(): def test_queue_default_args(self): app = self.func_app - @app.on_queue_change(arg_name="req", queue_name="dummy_queue", - connection="dummy_conn") + @app.queue_trigger(arg_name="req", queue_name="dummy_queue", + connection="dummy_conn") @app.write_queue(arg_name="out", queue_name="dummy_out_queue", connection="dummy_out_conn") def dummy(): @@ -204,9 +200,9 @@ def dummy(): def test_queue_full_args(self): app = self.func_app - @app.on_queue_change(arg_name="req", queue_name="dummy_queue", - connection="dummy_conn", - data_type=DataType.STRING) + @app.queue_trigger(arg_name="req", queue_name="dummy_queue", + connection="dummy_conn", + data_type=DataType.STRING) @app.write_queue(arg_name="out", queue_name="dummy_out_queue", connection="dummy_out_conn", data_type=DataType.STRING) @@ -237,9 +233,9 @@ def dummy(): def test_service_bus_queue_default_args(self): app = self.func_app - @app.on_service_bus_queue_change(arg_name="req", - connection="dummy_conn", - queue_name="dummy_queue") + @app.service_bus_queue_trigger(arg_name="req", + connection="dummy_conn", + queue_name="dummy_queue") @app.write_service_bus_queue(arg_name='res', connection='dummy_out_conn', queue_name='dummy_out_queue') @@ -270,13 +266,13 @@ def dummy(): def test_service_bus_queue_full_args(self): app = self.func_app - @app.on_service_bus_queue_change(arg_name="req", - connection="dummy_conn", - queue_name="dummy_queue", - data_type=DataType.STREAM, - access_rights=AccessRights.MANAGE, - is_sessions_enabled=True, - cardinality=Cardinality.MANY) + @app.service_bus_queue_trigger(arg_name="req", + connection="dummy_conn", + queue_name="dummy_queue", + data_type=DataType.STREAM, + access_rights=AccessRights.MANAGE, + is_sessions_enabled=True, + cardinality=Cardinality.MANY) @app.write_service_bus_queue(arg_name='res', connection='dummy_out_conn', queue_name='dummy_out_queue', @@ -315,10 +311,10 @@ def dummy(): def test_service_bus_topic_default_args(self): app = self.func_app - @app.on_service_bus_topic_change(arg_name='req', - connection='dummy_conn', - topic_name='dummy_topic', - subscription_name='dummy_sub') + @app.service_bus_topic_trigger(arg_name='req', + connection='dummy_conn', + topic_name='dummy_topic', + subscription_name='dummy_sub') @app.write_service_bus_topic(arg_name='res', connection='dummy_conn', topic_name='dummy_topic', subscription_name='dummy_sub') @@ -351,14 +347,14 @@ def dummy(): def test_service_bus_topic_full_args(self): app = self.func_app - @app.on_service_bus_topic_change(arg_name='req', - connection='dummy_conn', - topic_name='dummy_topic', - subscription_name='dummy_sub', - data_type=DataType.STRING, - access_rights=AccessRights.LISTEN, - is_sessions_enabled=False, - cardinality=Cardinality.MANY) + @app.service_bus_topic_trigger(arg_name='req', + connection='dummy_conn', + topic_name='dummy_topic', + subscription_name='dummy_sub', + data_type=DataType.STRING, + access_rights=AccessRights.LISTEN, + is_sessions_enabled=False, + cardinality=Cardinality.MANY) @app.write_service_bus_topic(arg_name='res', connection='dummy_conn', topic_name='dummy_topic', subscription_name='dummy_sub', @@ -399,9 +395,9 @@ def dummy(): def test_event_hub_default_args(self): app = self.func_app - @app.on_event_hub_message(arg_name="req", - connection="dummy_connection", - event_hub_name="dummy_event_hub") + @app.event_hub_message_trigger(arg_name="req", + connection="dummy_connection", + event_hub_name="dummy_event_hub") @app.write_event_hub_message(arg_name="res", event_hub_name="dummy_event_hub", connection="dummy_connection") @@ -432,12 +428,12 @@ def dummy(): def test_event_hub_full_args(self): app = self.func_app - @app.on_event_hub_message(arg_name="req", - connection="dummy_connection", - event_hub_name="dummy_event_hub", - cardinality=Cardinality.ONE, - consumer_group="dummy_group", - data_type=DataType.UNDEFINED) + @app.event_hub_message_trigger(arg_name="req", + connection="dummy_connection", + event_hub_name="dummy_event_hub", + cardinality=Cardinality.ONE, + consumer_group="dummy_group", + data_type=DataType.UNDEFINED) @app.write_event_hub_message(arg_name="res", event_hub_name="dummy_event_hub", connection="dummy_connection", @@ -474,7 +470,7 @@ def dummy(): def test_cosmosdb_full_args(self): app = self.func_app - @app.on_cosmos_db_update( + @app.cosmos_db_trigger( arg_name="trigger", database_name="dummy_db", collection_name="dummy_collection", @@ -586,9 +582,9 @@ def dummy(): def test_cosmosdb_default_args(self): app = self.func_app - @app.on_cosmos_db_update(arg_name="trigger", database_name="dummy_db", - collection_name="dummy_collection", - connection_string_setting="dummy_str") + @app.cosmos_db_trigger(arg_name="trigger", database_name="dummy_db", + collection_name="dummy_collection", + connection_string_setting="dummy_str") @app.read_cosmos_db_documents(arg_name="in", database_name="dummy_in_db", collection_name="dummy_in_collection", @@ -753,7 +749,7 @@ def dummy(): }) def test_set_auth_level_for_http_functions(self): - app = FunctionApp(auth_level=AuthLevel.ANONYMOUS) + app = FunctionApp(http_auth_level=AuthLevel.ANONYMOUS) @app.route(auth_level=AuthLevel.ADMIN) def specify_auth_level(): @@ -815,8 +811,8 @@ def default_auth_level(): def test_blob_default_args(self): app = self.func_app - @app.on_blob_change(arg_name="req", path="dummy_path", - connection="dummy_conn") + @app.blob_trigger(arg_name="req", path="dummy_path", + connection="dummy_conn") @app.read_blob(arg_name="file", path="dummy_path", connection="dummy_conn") @app.write_blob(arg_name="out", path="dummy_out_path", @@ -853,9 +849,9 @@ def dummy(): def test_blob_trigger(self): app = self.func_app - @app.on_blob_change(arg_name="req", path="dummy_path", - data_type=DataType.STRING, - connection="dummy_conn") + @app.blob_trigger(arg_name="req", path="dummy_path", + data_type=DataType.STRING, + connection="dummy_conn") def dummy(): pass @@ -875,9 +871,9 @@ def dummy(): def test_blob_input_binding(self): app = self.func_app - @app.on_blob_change(arg_name="req", path="dummy_path", - data_type=DataType.STRING, - connection="dummy_conn") + @app.blob_trigger(arg_name="req", path="dummy_path", + data_type=DataType.STRING, + connection="dummy_conn") @app.read_blob(arg_name="file", path="dummy_in_path", connection="dummy_in_conn", data_type=DataType.STRING) @@ -900,9 +896,9 @@ def dummy(): def test_blob_output_binding(self): app = self.func_app - @app.on_blob_change(arg_name="req", path="dummy_path", - data_type=DataType.STRING, - connection="dummy_conn") + @app.blob_trigger(arg_name="req", path="dummy_path", + data_type=DataType.STRING, + connection="dummy_conn") @app.write_blob(arg_name="out", path="dummy_out_path", connection="dummy_out_conn", data_type=DataType.STRING) diff --git a/tests/decorators/test_function_app.py b/tests/decorators/test_function_app.py index 4262af97..ec62509a 100644 --- a/tests/decorators/test_function_app.py +++ b/tests/decorators/test_function_app.py @@ -204,10 +204,10 @@ def test_default_script_file_path(self): self.assertEqual(self.func_app.app_script_file, SCRIPT_FILE_NAME) def test_auth_level(self): - self.func_app = FunctionApp(auth_level='ANONYMOUS') + self.func_app = FunctionApp(http_auth_level='ANONYMOUS') self.assertEqual(self.func_app.auth_level, AuthLevel.ANONYMOUS) - self.func_app = FunctionApp(auth_level=AuthLevel.ADMIN) + self.func_app = FunctionApp(http_auth_level=AuthLevel.ADMIN) self.assertEqual(self.func_app.auth_level, AuthLevel.ADMIN) def test_get_no_functions(self): @@ -244,7 +244,6 @@ def test_add_asgi(self, add_http_app_mock): add_http_app_mock.assert_called_once() self.assertIsInstance(add_http_app_mock.call_args[0][0], AsgiMiddleware) - self.assertEqual(add_http_app_mock.call_args[0][1], {}) @mock.patch('azure.functions.decorators.function_app.FunctionApp' '._add_http_app') @@ -255,51 +254,38 @@ def test_add_wsgi(self, add_http_app_mock): add_http_app_mock.assert_called_once() self.assertIsInstance(add_http_app_mock.call_args[0][0], WsgiMiddleware) - self.assertEqual(add_http_app_mock.call_args[0][1], {}) - - @mock.patch('azure.functions.decorators.function_app.FunctionApp' - '._add_http_app') - def test_add_http_args(self, add_http_app_mock): - mock_wsgi_app = object() - app_kwargs = {"methods": ["GET"]} - FunctionApp(wsgi_app=mock_wsgi_app, app_kwargs=app_kwargs) - - self.assertEqual(add_http_app_mock.call_args[0][1], app_kwargs) def test_add_http_app(self): - app = FunctionApp(asgi_app=object(), - app_kwargs={"methods": ["GET"], - "auth_level": "ANONYMOUS", - "trigger_arg_data_type": - DataType.UNDEFINED, - "output_arg_data_type": - DataType.UNDEFINED}) + app = FunctionApp(asgi_app=object()) funcs = app.get_functions() self.assertEqual(len(funcs), 1) func = funcs[0] self.assertEqual(func.get_function_name(), "http_app_func") self.assertEqual(func.get_raw_bindings(), [ - '{"direction": "IN", "dataType": "UNDEFINED", "type": ' + '{"direction": "IN", "type": ' '"httpTrigger", "name": ' - '"req", "methods": ["GET"], "authLevel": "ANONYMOUS", "route": ' + '"req", "methods": ["GET", "POST", "DELETE", "HEAD", "PATCH", ' + '"PUT", "OPTIONS"], "authLevel": "FUNCTION", "route": ' '"/{*route}"}', - '{"direction": "OUT", "dataType": "UNDEFINED", "type": "http", ' + '{"direction": "OUT", "type": "http", ' '"name": ' '"$return"}']) self.assertEqual(func.get_bindings_dict(), { "bindings": [ { - "authLevel": AuthLevel.ANONYMOUS, - "dataType": DataType.UNDEFINED, + "authLevel": AuthLevel.FUNCTION, "direction": BindingDirection.IN, - "methods": [HttpMethod.GET], + "methods": [HttpMethod.GET, HttpMethod.POST, + HttpMethod.DELETE, + HttpMethod.HEAD, + HttpMethod.PATCH, + HttpMethod.PUT, HttpMethod.OPTIONS], "name": "req", "route": "/{*route}", "type": HTTP_TRIGGER }, { - "dataType": DataType.UNDEFINED, "direction": BindingDirection.OUT, "name": "$return", "type": HTTP_OUTPUT