Repository: sdss/clu

Issue:
Avoid child commands to finish parent
Child commands should not finish or fail the parent command, I think. Instead `finish` can probably be output as `info` and `fail` as `error`.

Also, not set the command running again if it already is.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/sdss/clu/pull/88?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss) Report
> Merging [#88](https://codecov.io/gh/sdss/clu/pull/88?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss) (02fbd38) into [main](https://codecov.io/gh/sdss/clu/commit/c61db5fce3dcf5b7700f78217ff9057f4e3697af?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss) (c61db5f) will **increase** coverage by `0.1%`.
> The diff coverage is `100.0%`.

[![Impacted file tree graph](https://codecov.io/gh/sdss/clu/pull/88/graphs/tree.svg?width=650&height=150&src=pr&token=HMjFocCIql&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss)](https://codecov.io/gh/sdss/clu/pull/88?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss)

```diff
@@           Coverage Diff           @@
##            main     #88     +/-   ##
=======================================
+ Coverage   91.4%   91.4%   +0.1%     
=======================================
  Files         14      14             
  Lines       1726    1731      +5     
  Branches     265     268      +3     
=======================================
+ Hits        1577    1582      +5     
  Misses        71      71             
  Partials      78      78             
```


| [Impacted Files](https://codecov.io/gh/sdss/clu/pull/88?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss) | Coverage Δ | |
|---|---|---|
| [python/clu/command.py](https://codecov.io/gh/sdss/clu/pull/88/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss#diff-cHl0aG9uL2NsdS9jb21tYW5kLnB5) | `90.4% <100.0%> (+0.4%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/sdss/clu/pull/88?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss).
> **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=sdss)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/sdss/clu/pull/88?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss). Last update [c61db5f...02fbd38](https://codecov.io/gh/sdss/clu/pull/88?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sdss). 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=sdss).


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a58e639..1535cef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
 # Changelog
 
+## Next version
+
+### ✨ Improved
+
+* [#77](https://github.com/sdss/clu/issues/77) Child commands will never emit ``:`` or ``f`` messages that may be confused as the parent being done.
+
+
 ## 1.1.2 - May 31, 2021
 
 ### 🔧 Fixed
diff --git a/python/clu/actor.py b/python/clu/actor.py
index 8c80281..8a29502 100644
--- a/python/clu/actor.py
+++ b/python/clu/actor.py
@@ -424,7 +424,7 @@ class JSONActor(ClickParser, TCPBaseActor):
 async def multiline(command: Command, on: bool):
     """Set multiline mode for the transport."""
 
-    transport: CustomTransportType = getattr(command, "transport", None)
+    transport = getattr(command, "transport", None)
     if not transport:
         return command.fail("The command has no transport.")
 
diff --git a/python/clu/command.py b/python/clu/command.py
index a10688b..686a1c1 100644
--- a/python/clu/command.py
+++ b/python/clu/command.py
@@ -265,6 +265,14 @@ class BaseCommand(
 
         command = self if not self.parent else self.parent
 
+        # If the parent has a command, do not output : or f since it would
+        # confuse the stream and potentially Tron.
+        if self.parent:
+            if message_code == ":":
+                message_code = "i"
+            elif message_code == "f":
+                message_code = "e"
+
         self.actor.write(
             message_code,
             message=message,


Test patch:
diff --git a/tests/test_command.py b/tests/test_command.py
index a920549..6d37678 100644
--- a/tests/test_command.py
+++ b/tests/test_command.py
@@ -86,6 +86,30 @@ def test_child_command_write(command):
     )
 
 
+def test_child_command_finished(command):
+
+    child = Command(command_string="new-command", parent=command)
+
+    child.finish(text="Finished")
+    command.actor.write.assert_called_with(
+        "i", message={}, text="Finished", command=command, broadcast=False, **{}
+    )
+
+    assert child.status.did_succeed
+
+
+def test_child_command_failed(command):
+
+    child = Command(command_string="new-command", parent=command)
+
+    child.fail(error="Failed")
+    command.actor.write.assert_called_with(
+        "e", message={}, error="Failed", command=command, broadcast=False, **{}
+    )
+
+    assert child.status.did_fail
+
+
 def test_write_str(command):
 
     command.write("i", "hello")