Repository: IAMconsortium/pyam
Pull request #263 (2019-08-20 11:38:32)

Fix adjusting log level called with uninitialized logger

gidden: Hi @zikolach, happy to merge this as is. Is it possible to write a test that fails under the current master? We obviously don't have this edge case in our current test suite (or else it would have failed).

danielhuppmann: not sure how easy it is to write a test that is guaranteed to be called first for all `pyam`...
gidden: > 
> 
> not sure how easy it is to write a test that is guaranteed to be called first for all `pyam`...

I thought so as well, but a quick test:

```
def test_foo():
    with adjust_log_level():
	print('foo')

```

```
$ pytest tests/test_logger.py 
============================================================================== test session starts ===============================================================================
platform linux -- Python 3.7.3, pytest-4.4.0, py-1.8.0, pluggy-0.9.0
Matplotlib: 3.0.3
Freetype: 2.9.1
rootdir: /home/gidden/work/iiasa/pyam
plugins: mpl-0.10, cov-2.6.1
collected 2 items                                                                                                                                                                

tests/test_logger.py F.                                                                                                                                                    [100%]

==================================================================================== FAILURES ====================================================================================
____________________________________________________________________________________ test_foo ____________________________________________________________________________________

    def test_foo():
>       with adjust_log_level():

tests/test_logger.py:6: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../miniconda3/envs/pyam37/lib/python3.7/contextlib.py:112: in __enter__
    return next(self.gen)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

level = 'ERROR'

    @contextmanager
    def adjust_log_level(level='ERROR'):
        """Context manager to change log level"""
>       old_level = _LOGGER.getEffectiveLevel()
E       AttributeError: 'NoneType' object has no attribute 'getEffectiveLevel'

../../../.local/lib/python3.7/site-packages/pyam_iamc-0.2.0+13.gd2fa051-py3.7.egg/pyam/logger.py:21: AttributeError
======================================================================= 1 failed, 1 passed in 0.26 seconds =======================================================================
```
coveralls: 
[![Coverage Status](https://coveralls.io/builds/25236828/badge)](https://coveralls.io/builds/25236828)

Coverage increased (+0.006%) to 88.093% when pulling **6fefab299dc5152f086021178e37264131579fac on quickfix/adjust-logger-level** into **d2fa051caf2e31a3d58d87dccbb0ddb1fae4e056 on master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/25236828/badge)](https://coveralls.io/builds/25236828)

Coverage increased (+0.006%) to 88.093% when pulling **6fefab299dc5152f086021178e37264131579fac on quickfix/adjust-logger-level** into **d2fa051caf2e31a3d58d87dccbb0ddb1fae4e056 on master**.


Patch:
diff --git a/pyam/logger.py b/pyam/logger.py
index 080e5a2..4ed5432 100644
--- a/pyam/logger.py
+++ b/pyam/logger.py
@@ -1,5 +1,5 @@
-from contextlib import contextmanager
 import logging
+from contextlib import contextmanager
 
 # globally accessible logger
 _LOGGER = None
@@ -18,7 +18,8 @@ def logger():
 @contextmanager
 def adjust_log_level(level='ERROR'):
     """Context manager to change log level"""
-    old_level = _LOGGER.getEffectiveLevel()
-    _LOGGER.setLevel(level)
+    _logger = logger()
+    old_level = _logger.getEffectiveLevel()
+    _logger.setLevel(level)
     yield
-    _LOGGER.setLevel(old_level)
+    _logger.setLevel(old_level)


Test patch:
diff --git a/tests/test_logger.py b/tests/test_logger.py
index c5e90e0..3c52cf0 100644
--- a/tests/test_logger.py
+++ b/tests/test_logger.py
@@ -1,5 +1,6 @@
-from pyam import logger
-from pyam.logger import adjust_log_level
+import sys
+
+from pyam.logger import logger, adjust_log_level
 
 
 def test_context_adjust_log_level():
@@ -7,3 +8,11 @@ def test_context_adjust_log_level():
     with adjust_log_level():
         assert logger().getEffectiveLevel() == 40
     assert logger().getEffectiveLevel() == 20
+
+
+def test_adjusting_level_for_not_initialized_logger():
+    # de-initialize logger to simulate adjust_log_level called before logger
+    pyam_logger = sys.modules['pyam.logger']
+    pyam_logger._LOGGER = None
+    with adjust_log_level():
+        pass