Repository: ipython/traitlets (python)

Issue:
Use Parent Log If Exists
I'd like to see the default `log` attribute of a `LoggingConfigurable` be the parent log, rather than the global traitlets log, if the parent is also a LoggingConfigurable.

```python
class LoggingConfigurable(...):
    ...

    log = Instance('logging.Logger')
    @default('log')
    def _log_default(self):
        # (vvv) new behavior (vvv)
        if isinstance(self.parent, LoggingConfigurable):
            return self.parent.log
        # (^^^) new behavior (^^^)
        from traitlets import log
        return log.get_logger()
```

If that sounds okay I can open a merge request with those two lines added.

Pull request:
Use log from parent in LoggingConfigurable.
Closes #514.

Ping @minrk.

Patch:
diff --git a/traitlets/config/configurable.py b/traitlets/config/configurable.py
index 05495d3..7768033 100644
--- a/traitlets/config/configurable.py
+++ b/traitlets/config/configurable.py
@@ -435,6 +435,8 @@ class LoggingConfigurable(Configurable):
     log = Instance('logging.Logger')
     @default('log')
     def _log_default(self):
+        if isinstance(self.parent, LoggingConfigurable):
+            return self.parent.log
         from traitlets import log
         return log.get_logger()
 


Test patch:
diff --git a/traitlets/config/tests/test_configurable.py b/traitlets/config/tests/test_configurable.py
index 3ba3c9e..800dca8 100644
--- a/traitlets/config/tests/test_configurable.py
+++ b/traitlets/config/tests/test_configurable.py
@@ -16,7 +16,7 @@ from traitlets.config.configurable import (
     LoggingConfigurable,
     SingletonConfigurable,
 )
-
+from traitlets.log import get_logger
 from traitlets.traitlets import (
     Integer, Float, Unicode, List, Dict, Set, Enum, FuzzyEnum,
     CaselessStrEnum, _deprecations_shown, validate,
@@ -335,6 +335,31 @@ class TestSingletonConfigurable(TestCase):
         self.assertEqual(SingletonConfigurable._instance, None)
 
 
+class TestLoggingConfigurable(TestCase):
+
+    def test_parent_logger(self):
+        class Parent(LoggingConfigurable): pass
+        class Child(LoggingConfigurable): pass
+        log = get_logger().getChild("TestLoggingConfigurable")
+
+        parent = Parent(log=log)
+        child = Child(parent=parent)
+        self.assertEqual(parent.log, log)
+        self.assertEqual(child.log, log)
+
+        parent = Parent()
+        child = Child(parent=parent, log=log)
+        self.assertEqual(parent.log, get_logger())
+        self.assertEqual(child.log, log)
+
+    def test_parent_not_logging_configurable(self):
+        class Parent(Configurable): pass
+        class Child(LoggingConfigurable): pass
+        parent = Parent()
+        child = Child(parent=parent)
+        self.assertEqual(child.log, get_logger())
+
+
 class MyParent(Configurable):
     pass