Repository: Azure/azure-functions-python-library

Issue:
[FeatureRequest] Add timer trigger for Python Programming Model V2
Add an alias for schedule.


Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/Azure/azure-functions-python-library/pull/172?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) Report
> Merging [#172](https://codecov.io/gh/Azure/azure-functions-python-library/pull/172?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) (f7b7044) into [dev](https://codecov.io/gh/Azure/azure-functions-python-library/commit/cc3fd5d13770244bdcc1030be608c81d50df1ad2?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) (cc3fd5d) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##              dev     #172   +/-   ##
=======================================
  Coverage   90.25%   90.25%           
=======================================
  Files          51       51           
  Lines        2995     2996    +1     
  Branches      796      796           
=======================================
+ Hits         2703     2704    +1     
  Misses        215      215           
  Partials       77       77           
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `90.22% <100.00%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/Azure/azure-functions-python-library/pull/172?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) | Coverage Δ | |
|---|---|---|
| [azure/functions/decorators/function\_app.py](https://codecov.io/gh/Azure/azure-functions-python-library/pull/172?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-YXp1cmUvZnVuY3Rpb25zL2RlY29yYXRvcnMvZnVuY3Rpb25fYXBwLnB5) | `99.44% <100.00%> (+<0.01%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure)

gavin-aguiar: We would need to update all our public docs too with this name alternative. 
cc: @shreyabatra4 

Patch:
diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py
index ac06b36..deb9054 100644
--- a/azure/functions/decorators/function_app.py
+++ b/azure/functions/decorators/function_app.py
@@ -399,14 +399,14 @@ class TriggerApi(DecoratorApi, ABC):
 
         return wrap
 
-    def schedule(self,
-                 arg_name: str,
-                 schedule: str,
-                 run_on_startup: Optional[bool] = None,
-                 use_monitor: Optional[bool] = None,
-                 data_type: Optional[Union[DataType, str]] = None,
-                 **kwargs: Any) -> Callable[..., Any]:
-        """The schedule decorator adds :class:`TimerTrigger` to the
+    def timer_trigger(self,
+                      arg_name: str,
+                      schedule: str,
+                      run_on_startup: Optional[bool] = None,
+                      use_monitor: Optional[bool] = None,
+                      data_type: Optional[Union[DataType, str]] = None,
+                      **kwargs: Any) -> Callable[..., Any]:
+        """The schedule or timer decorator adds :class:`TimerTrigger` to the
         :class:`FunctionBuilder` object
         for building :class:`Function` object used in worker function
         indexing model. This is equivalent to defining TimerTrigger
@@ -448,6 +448,8 @@ class TriggerApi(DecoratorApi, ABC):
 
         return wrap
 
+    schedule = timer_trigger
+
     def service_bus_queue_trigger(
             self,
             arg_name: str,


Test patch:
diff --git a/tests/decorators/test_decorators.py b/tests/decorators/test_decorators.py
index c613721..5dea1c2 100644
--- a/tests/decorators/test_decorators.py
+++ b/tests/decorators/test_decorators.py
@@ -65,7 +65,7 @@ class TestFunctionsApp(unittest.TestCase):
         self.assertTrue(isinstance(func.get_trigger(), HttpTrigger))
         self.assertTrue(func.get_trigger().route, "dummy")
 
-    def test_timer_trigger_default_args(self):
+    def test_schedule_trigger_default_args(self):
         app = self.func_app
 
         @app.schedule(arg_name="req", schedule="dummy_schedule")
@@ -86,7 +86,7 @@ class TestFunctionsApp(unittest.TestCase):
             ]
         })
 
-    def test_timer_trigger_full_args(self):
+    def test_schedule_trigger_full_args(self):
         app = self.func_app
 
         @app.schedule(arg_name="req", schedule="dummy_schedule",
@@ -112,6 +112,53 @@ class TestFunctionsApp(unittest.TestCase):
             ]
         })
 
+    def test_timer_trigger_default_args(self):
+        app = self.func_app
+
+        @app.timer_trigger(arg_name="req", schedule="dummy_schedule")
+        def dummy_func():
+            pass
+
+        func = self._get_user_function(app)
+        self.assertEqual(func.get_function_name(), "dummy_func")
+        assert_json(self, func, {
+            "scriptFile": "function_app.py",
+            "bindings": [
+                {
+                    "name": "req",
+                    "type": TIMER_TRIGGER,
+                    "direction": BindingDirection.IN,
+                    "schedule": "dummy_schedule"
+                }
+            ]
+        })
+
+    def test_timer_trigger_full_args(self):
+        app = self.func_app
+
+        @app.timer_trigger(arg_name="req", schedule="dummy_schedule",
+                           run_on_startup=False, use_monitor=False,
+                           data_type=DataType.STRING, dummy_field='dummy')
+        def dummy():
+            pass
+
+        func = self._get_user_function(app)
+        assert_json(self, func, {
+            "scriptFile": "function_app.py",
+            "bindings": [
+                {
+                    "name": "req",
+                    "type": TIMER_TRIGGER,
+                    "dataType": DataType.STRING,
+                    "direction": BindingDirection.IN,
+                    'dummyField': 'dummy',
+                    "schedule": "dummy_schedule",
+                    "runOnStartup": False,
+                    "useMonitor": False
+                }
+            ]
+        })
+
     def test_route_default_args(self):
         app = self.func_app