Repository: dapr/python-sdk

Issue:
invoke_binding call shouldn't require the data parameter

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/dapr/python-sdk/pull/400?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr) Report
> Merging [#400](https://codecov.io/gh/dapr/python-sdk/pull/400?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr) (9bbb161) into [master](https://codecov.io/gh/dapr/python-sdk/commit/d783ed2538bac6b464a5f1678b202e9edf69d7c8?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr) (d783ed2) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##           master     #400   +/-   ##
=======================================
  Coverage   89.41%   89.41%           
=======================================
  Files          55       55           
  Lines        2448     2448           
=======================================
  Hits         2189     2189           
  Misses        259      259           
```


| [Impacted Files](https://codecov.io/gh/dapr/python-sdk/pull/400?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr) | Coverage Δ | |
|---|---|---|
| [dapr/clients/\_\_init\_\_.py](https://codecov.io/gh/dapr/python-sdk/pull/400/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr#diff-ZGFwci9jbGllbnRzL19faW5pdF9fLnB5) | `96.77% <ø> (ø)` | |
| [dapr/clients/grpc/client.py](https://codecov.io/gh/dapr/python-sdk/pull/400/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr#diff-ZGFwci9jbGllbnRzL2dycGMvY2xpZW50LnB5) | `88.20% <ø> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/dapr/python-sdk/pull/400?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/dapr/python-sdk/pull/400?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr). Last update [d783ed2...9bbb161](https://codecov.io/gh/dapr/python-sdk/pull/400?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dapr).


Patch:
diff --git a/dapr/clients/__init__.py b/dapr/clients/__init__.py
index fb4d223..c871e5f 100644
--- a/dapr/clients/__init__.py
+++ b/dapr/clients/__init__.py
@@ -89,7 +89,7 @@ class DaprClient(DaprGrpcClient):
             self,
             app_id: str,
             method_name: str,
-            data: Union[bytes, str, GrpcMessage],
+            data: Union[bytes, str, GrpcMessage] = '',
             content_type: Optional[str] = None,
             metadata: Optional[MetadataTuple] = None,
             http_verb: Optional[str] = None,
diff --git a/dapr/clients/grpc/client.py b/dapr/clients/grpc/client.py
index 631e44c..5627f1a 100644
--- a/dapr/clients/grpc/client.py
+++ b/dapr/clients/grpc/client.py
@@ -151,7 +151,7 @@ class DaprGrpcClient:
             self,
             app_id: str,
             method_name: str,
-            data: Union[bytes, str, GrpcMessage],
+            data: Union[bytes, str, GrpcMessage] = '',
             content_type: Optional[str] = None,
             metadata: Optional[MetadataTuple] = None,
             http_verb: Optional[str] = None,
@@ -219,8 +219,8 @@ class DaprGrpcClient:
         Args:
             app_id (str): the callee app id
             method (str): the method name which is called
-            data (bytes or :obj:`google.protobuf.message.Message`): bytes or Message for data
-                which will send to id
+            data (bytes or :obj:`google.protobuf.message.Message`, optional): bytes
+                or Message for data which will be sent to app id
             metadata (tuple, optional, DEPRECATED): gRPC custom metadata
             http_verb (str, optional): http method verb to call HTTP callee application
             http_querystring (tuple, optional): the tuple to represent query string
@@ -259,7 +259,7 @@ class DaprGrpcClient:
             self,
             binding_name: str,
             operation: str,
-            data: Union[bytes, str],
+            data: Union[bytes, str] = '',
             binding_metadata: Dict[str, str] = {},
             metadata: Optional[MetadataTuple] = None) -> BindingResponse:
         """Invokes the output binding with the specified operation.
@@ -285,7 +285,7 @@ class DaprGrpcClient:
         Args:
             binding_name (str): the name of the binding as defined in the components
             operation (str): the operation to perform on the binding
-            data (bytes or str): bytes or str for data which will sent to the binding
+            data (bytes or str, optional): bytes or str for data which will sent to the binding
             binding_metadata (dict, optional): Dapr metadata for output binding
             metadata (tuple, optional, DEPRECATED): gRPC custom metadata
 


Test patch:
diff --git a/tests/clients/test_dapr_grpc_client.py b/tests/clients/test_dapr_grpc_client.py
index bdab774..0f22f6f 100644
--- a/tests/clients/test_dapr_grpc_client.py
+++ b/tests/clients/test_dapr_grpc_client.py
@@ -86,6 +86,24 @@ class DaprGrpcClientTests(unittest.TestCase):
         self.assertEqual(3, len(resp.headers))
         self.assertEqual(['value1'], resp.headers['hkey1'])
 
+    def test_invoke_method_no_data(self):
+        dapr = DaprGrpcClient(f'localhost:{self.server_port}')
+        resp = dapr.invoke_method(
+            app_id='targetId',
+            method_name='bytes',
+            content_type="text/plain",
+            metadata=(
+                ('key1', 'value1'),
+                ('key2', 'value2'),
+            ),
+            http_verb='PUT',
+        )
+
+        self.assertEqual(b'', resp.data)
+        self.assertEqual("text/plain", resp.content_type)
+        self.assertEqual(3, len(resp.headers))
+        self.assertEqual(['value1'], resp.headers['hkey1'])
+
     def test_invoke_method_async(self):
         dapr = DaprClient(f'localhost:{self.server_port}')
         dapr.invocation_client = None  # force to use grpc client
@@ -158,6 +176,17 @@ class DaprGrpcClientTests(unittest.TestCase):
         self.assertEqual({}, resp.binding_metadata)
         self.assertEqual(0, len(resp.headers))
 
+    def test_invoke_binding_no_data(self):
+        dapr = DaprGrpcClient(f'localhost:{self.server_port}')
+        resp = dapr.invoke_binding(
+            binding_name='binding',
+            operation='create',
+        )
+
+        self.assertEqual(b'', resp.data)
+        self.assertEqual({}, resp.binding_metadata)
+        self.assertEqual(0, len(resp.headers))
+
     def test_invoke_binding_no_create(self):
         dapr = DaprGrpcClient(f'localhost:{self.server_port}')
         resp = dapr.invoke_binding(