Repository: amoffat/sh

Issue:
Need way for await sh.command to return RunningCommand
I'm finally porting [Carthage](https://github.com/hadron/carthage)  from sh 1.x to sh 2.x. We had our own hack to enable async for sh, and we had a lot of code that did things like
```python
result = await sh.ssh(...)
```
And then for example looked at `result.stdout`.
So, part of this can be handled by setting `_return_cmd=True`, but the definition of `RunningCommand.__await__` is hard-coded to return `str(self)`.
Obviously, I can do something like
```python
result = sh.ssh(...)
await result
```
But that feels clumsy.
I'd like a kwarg that returns a RunningCommand even on async await.
My preference would be to try and convince you that `_return_cmd` should affect await as well as __call__, but if you are concerned about the API instability, I'm happy with anything that I can pass into bake.

Thanks for your consideration.

Discussion:
@amoffat: I think that's a reasonable request, and the way the api should work. The fact that it doesn't seems to be incorrect behavior. Do you feel comfortable making this change?@hartmans: 
Yes. I'll send in a pull request tomorrow.
The change is trivial, learning your test system enough to propose tests
will take most of the time.
But I've been working with sh long enough I should go learn the test
system anyway.


Solution patch:
diff --git a/sh.py b/sh.py
index d52d8b6..b02d6e1 100644
--- a/sh.py
+++ b/sh.py
@@ -889,7 +889,10 @@ class RunningCommand:
     def __await__(self):
         async def wait_for_completion():
             await self.aio_output_complete.wait()
-            return str(self)
+            if self.call_args["return_cmd"]:
+                return self
+            else:
+                return str(self)
 
         return wait_for_completion().__await__()
 


Test patch:
diff --git a/tests/sh_test.py b/tests/sh_test.py
index 8a87fd6..0fe0311 100644
--- a/tests/sh_test.py
+++ b/tests/sh_test.py
@@ -1732,7 +1732,7 @@ print("hello")
         py = create_tmp_test("""exit(34)""")
 
         async def producer():
-            await python(py.name, _async=True)
+            await python(py.name, _async=True, _return_cmd=False)
 
         self.assertRaises(sh.ErrorReturnCode_34, asyncio.run, producer())
 
@@ -1786,6 +1786,22 @@ exit(34)
 
         self.assertRaises(sh.ErrorReturnCode_34, asyncio.run, producer())
 
+    def test_async_return_cmd(self):
+        py = create_tmp_test(
+            """
+import sys
+sys.exit(0)
+"""
+        )
+
+        async def main():
+            result = await python(py.name, _async=True, _return_cmd=True)
+            self.assertIsInstance(result, sh.RunningCommand)
+            result_str = await python(py.name, _async=True, _return_cmd=False)
+            self.assertIsInstance(result_str, str)
+
+        asyncio.run(main())
+
     def test_handle_both_out_and_err(self):
         py = create_tmp_test(
             """