Skip to content

Commit a8daa7c

Browse files
committed
Use logging instead of warnings
Problems with the `warnings` module: * Undesirable output in tests, although it could be filtered out. * Output unsuited for users: shows source code of Python-dotenv. Users don't know what to do with that. * Rather meant for programming issues (e.g. deprecation) rather than runtime issues (file not found). Problems with the `logging` module: * Slightly less easy to test, unlike warnings with `catch_warnings(record=True)`, because you need to use the `mock` package for compatibility with Python 2. Despite this last issue, I think it makes more sense to use the `logging` module as a base for warnings. Of course, `logging` is not suited to all forms of output, so this change doesn't mean `logging` has to be used everywhere. For instance, if we want to improve the output of the `dotenv` CLI later, we might want to use `print`, `click.echo` or other printing facilities.
1 parent 558d435 commit a8daa7c

File tree

4 files changed

+14
-12
lines changed

4 files changed

+14
-12
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ typing; python_version<"3.5"
33
click
44
flake8>=2.2.3
55
ipython
6+
mock
67
pytest-cov
78
pytest>=3.9
89
sh>=1.09

src/dotenv/main.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import shutil
99
import sys
1010
import tempfile
11-
import warnings
1211
from collections import OrderedDict
1312
from contextlib import contextmanager
1413

@@ -64,7 +63,7 @@ def _get_stream(self):
6463
yield stream
6564
else:
6665
if self.verbose:
67-
warnings.warn("File doesn't exist {}".format(self.dotenv_path)) # type: ignore
66+
logger.warning("File doesn't exist %s", self.dotenv_path)
6867
yield StringIO('')
6968

7069
def dict(self):
@@ -107,7 +106,7 @@ def get(self, key):
107106
return data[key]
108107

109108
if self.verbose:
110-
warnings.warn("key %s not found in %s." % (key, self.dotenv_path)) # type: ignore
109+
logger.warning("Key %s not found in %s.", key, self.dotenv_path)
111110

112111
return None
113112

@@ -147,7 +146,7 @@ def set_key(dotenv_path, key_to_set, value_to_set, quote_mode="always"):
147146
"""
148147
value_to_set = value_to_set.strip("'").strip('"')
149148
if not os.path.exists(dotenv_path):
150-
warnings.warn("can't write to %s - it doesn't exist." % dotenv_path) # type: ignore
149+
logger.warning("Can't write to %s - it doesn't exist.", dotenv_path)
151150
return None, key_to_set, value_to_set
152151

153152
if " " in value_to_set:
@@ -179,7 +178,7 @@ def unset_key(dotenv_path, key_to_unset, quote_mode="always"):
179178
If the given key doesn't exist in the .env, fails
180179
"""
181180
if not os.path.exists(dotenv_path):
182-
warnings.warn("can't delete from %s - it doesn't exist." % dotenv_path) # type: ignore
181+
logger.warning("Can't delete from %s - it doesn't exist.", dotenv_path)
183182
return None, key_to_unset
184183

185184
removed = False
@@ -191,7 +190,7 @@ def unset_key(dotenv_path, key_to_unset, quote_mode="always"):
191190
dest.write(mapping.original.string)
192191

193192
if not removed:
194-
warnings.warn("key %s not removed from %s - key doesn't exist." % (key_to_unset, dotenv_path)) # type: ignore
193+
logger.warning("Key %s not removed from %s - key doesn't exist.", key_to_unset, dotenv_path)
195194
return None, key_to_unset
196195

197196
return removed, key_to_unset

tests/test_core.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
import os
66
import sys
77
import textwrap
8-
import warnings
98

9+
import logging
10+
import mock
1011
import pytest
1112
import sh
1213

@@ -25,12 +26,12 @@ def restore_os_environ():
2526

2627

2728
def test_warns_if_file_does_not_exist():
28-
with warnings.catch_warnings(record=True) as w:
29+
logger = logging.getLogger("dotenv.main")
30+
31+
with mock.patch.object(logger, "warning") as mock_warning:
2932
load_dotenv('.does_not_exist', verbose=True)
3033

31-
assert len(w) == 1
32-
assert w[0].category is UserWarning
33-
assert str(w[0].message) == "File doesn't exist .does_not_exist"
34+
mock_warning.assert_called_once_with("File doesn't exist %s", ".does_not_exist")
3435

3536

3637
def test_find_dotenv(tmp_path):

tox.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
envlist = lint,py{27,34,35,36,37,38,34-no-typing},pypy,pypy3,manifest,coverage-report
33

44
[testenv]
5-
deps =
5+
deps =
6+
mock
67
pytest
78
coverage
89
sh

0 commit comments

Comments
 (0)