Skip to content

Commit b6d204b

Browse files
committed
Replace bespoke logging facility with logging module, available since Python 2.3.
1 parent 45295fc commit b6d204b

15 files changed

+124
-245
lines changed

conftest.py

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import sys
33
import platform
44
import pathlib
5+
import logging
56

67
import pytest
78
import path
@@ -36,39 +37,20 @@ def needs_zlib():
3637
pytest.importorskip('zlib')
3738

3839

39-
# from jaraco.collections
40-
class Everything:
41-
def __contains__(self, other):
42-
return True
43-
44-
45-
class SavedLogs(list):
46-
def render(self, *levels):
47-
return [
48-
msg % args for level, msg, args in self if level in (levels or Everything())
49-
]
50-
51-
52-
@pytest.fixture
53-
def logs(monkeypatch):
54-
from distutils import log
55-
56-
logs = SavedLogs()
57-
log_levels = log.DEBUG, log.INFO, log.WARN, log.ERROR, log.FATAL
58-
59-
def _log(self, level, msg, args):
60-
self.logs.append((level, msg, args))
40+
@pytest.fixture(autouse=True)
41+
def log_everything():
42+
"""
43+
For tests, set the level on the logger to log everything.
44+
"""
45+
logging.getLogger('distutils').setLevel(0)
6146

62-
def save_log(self, level, msg, args):
63-
if level not in log_levels:
64-
raise ValueError(f'invalid log level {level}')
65-
if not isinstance(msg, str):
66-
raise TypeError(f'msg should be str, not {type(msg).__name__!r}')
67-
logs.append((level, msg, args))
6847

69-
monkeypatch.setattr(log.Log, '_log', save_log)
70-
monkeypatch.setattr(log._global_log, 'threshold', log.FATAL)
71-
return logs
48+
@pytest.fixture(autouse=True)
49+
def capture_log_at_info(caplog):
50+
"""
51+
By default, capture logs at INFO and greater.
52+
"""
53+
caplog.set_level(logging.INFO)
7254

7355

7456
def _save_cwd():
@@ -111,15 +93,6 @@ def temp_cwd(tmp_path):
11193
yield
11294

11395

114-
@pytest.fixture
115-
def threshold_warn():
116-
from distutils.log import set_threshold, WARN
117-
118-
orig = set_threshold(WARN)
119-
yield
120-
set_threshold(orig)
121-
122-
12396
@pytest.fixture
12497
def pypirc(request, save_env, distutils_managed_tempdir):
12598
from distutils.core import PyPIRCCommand

distutils/cmd.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
import os
99
import re
10+
import logging
1011

1112
from .errors import DistutilsOptionError
1213
from . import util, dir_util, file_util, archive_util, dep_util, log
@@ -179,10 +180,7 @@ def run(self):
179180
"abstract method -- subclass %s must override" % self.__class__
180181
)
181182

182-
def announce(self, msg, level=1):
183-
"""If the current verbosity level is of greater than or equal to
184-
'level' print 'msg' to stdout.
185-
"""
183+
def announce(self, msg, level=logging.DEBUG):
186184
log.log(level, msg)
187185

188186
def debug_print(self, msg):

distutils/log.py

Lines changed: 18 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,37 @@
1-
"""A simple log mechanism styled after PEP 282."""
1+
"""
2+
A simple log mechanism styled after PEP 282.
23
3-
# The class here is styled after PEP 282 so that it could later be
4-
# replaced with a standard Python logging implementation.
4+
Retained for compatibility and should not be used.
5+
"""
56

6-
import sys
7+
import logging
78

8-
DEBUG = 1
9-
INFO = 2
10-
WARN = 3
11-
ERROR = 4
12-
FATAL = 5
139

10+
DEBUG = logging.DEBUG
11+
INFO = logging.INFO
12+
WARN = logging.WARN
13+
ERROR = logging.ERROR
14+
FATAL = logging.FATAL
1415

15-
class Log:
16-
def __init__(self, threshold=WARN):
17-
self.threshold = threshold
18-
19-
def _log(self, level, msg, args):
20-
if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
21-
raise ValueError('%s wrong log level' % str(level))
22-
23-
if level >= self.threshold:
24-
if args:
25-
msg = msg % args
26-
if level in (WARN, ERROR, FATAL):
27-
stream = sys.stderr
28-
else:
29-
stream = sys.stdout
30-
try:
31-
stream.write('%s\n' % msg)
32-
except UnicodeEncodeError:
33-
# emulate backslashreplace error handler
34-
encoding = stream.encoding
35-
msg = msg.encode(encoding, "backslashreplace").decode(encoding)
36-
stream.write('%s\n' % msg)
37-
stream.flush()
38-
39-
def log(self, level, msg, *args):
40-
self._log(level, msg, args)
41-
42-
def debug(self, msg, *args):
43-
self._log(DEBUG, msg, args)
44-
45-
def info(self, msg, *args):
46-
self._log(INFO, msg, args)
47-
48-
def warn(self, msg, *args):
49-
self._log(WARN, msg, args)
50-
51-
def error(self, msg, *args):
52-
self._log(ERROR, msg, args)
53-
54-
def fatal(self, msg, *args):
55-
self._log(FATAL, msg, args)
56-
57-
58-
_global_log = Log()
16+
_global_log = logging.getLogger('distutils')
5917
log = _global_log.log
6018
debug = _global_log.debug
6119
info = _global_log.info
62-
warn = _global_log.warn
20+
warn = _global_log.warning
6321
error = _global_log.error
6422
fatal = _global_log.fatal
6523

6624

6725
def set_threshold(level):
68-
# return the old threshold for use from tests
69-
old = _global_log.threshold
70-
_global_log.threshold = level
71-
return old
26+
orig = _global_log.level
27+
_global_log.setLevel(level)
28+
return orig
7229

7330

7431
def set_verbosity(v):
7532
if v <= 0:
76-
set_threshold(WARN)
33+
set_threshold(logging.WARN)
7734
elif v == 1:
78-
set_threshold(INFO)
35+
set_threshold(logging.INFO)
7936
elif v >= 2:
80-
set_threshold(DEBUG)
37+
set_threshold(logging.DEBUG)

distutils/tests/test_build_py.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def test_dir_in_package_data(self):
150150
except DistutilsFileError:
151151
self.fail("failed package_data when data dir includes a dir")
152152

153-
def test_dont_write_bytecode(self, logs):
153+
def test_dont_write_bytecode(self, caplog):
154154
# makes sure byte_compile is not used
155155
dist = self.create_dist()[1]
156156
cmd = build_py(dist)
@@ -164,7 +164,7 @@ def test_dont_write_bytecode(self, logs):
164164
finally:
165165
sys.dont_write_bytecode = old_dont_write_bytecode
166166

167-
assert 'byte-compiling is disabled' in logs.render()[0]
167+
assert 'byte-compiling is disabled' in caplog.records[0].message
168168

169169
def test_namespace_package_does_not_warn(self, caplog):
170170
"""

distutils/tests/test_config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646

4747

4848
@support.combine_markers
49-
@pytest.mark.usefixtures('threshold_warn')
5049
@pytest.mark.usefixtures('pypirc')
5150
class BasePyPIRCCommandTestCase(support.TempdirManager):
5251
pass

distutils/tests/test_dir_util.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,19 @@ def stuff(request, monkeypatch, distutils_managed_tempdir):
2626

2727

2828
class TestDirUtil(support.TempdirManager):
29-
def test_mkpath_remove_tree_verbosity(self, logs):
30-
29+
def test_mkpath_remove_tree_verbosity(self, caplog):
3130
mkpath(self.target, verbose=0)
32-
wanted = []
33-
assert logs.render() == wanted
31+
assert not caplog.records
3432
remove_tree(self.root_target, verbose=0)
3533

3634
mkpath(self.target, verbose=1)
3735
wanted = ['creating %s' % self.root_target, 'creating %s' % self.target]
38-
assert logs.render() == wanted
39-
logs.clear()
36+
assert caplog.messages == wanted
37+
caplog.clear()
4038

4139
remove_tree(self.root_target, verbose=1)
4240
wanted = ["removing '%s' (and everything under it)" % self.root_target]
43-
assert logs.render() == wanted
41+
assert caplog.messages == wanted
4442

4543
@pytest.mark.skipif("platform.system() == 'Windows'")
4644
def test_mkpath_with_custom_mode(self):
@@ -52,24 +50,24 @@ def test_mkpath_with_custom_mode(self):
5250
mkpath(self.target2, 0o555)
5351
assert stat.S_IMODE(os.stat(self.target2).st_mode) == 0o555 & ~umask
5452

55-
def test_create_tree_verbosity(self, logs):
53+
def test_create_tree_verbosity(self, caplog):
5654

5755
create_tree(self.root_target, ['one', 'two', 'three'], verbose=0)
58-
assert logs.render() == []
56+
assert caplog.messages == []
5957
remove_tree(self.root_target, verbose=0)
6058

6159
wanted = ['creating %s' % self.root_target]
6260
create_tree(self.root_target, ['one', 'two', 'three'], verbose=1)
63-
assert logs.render() == wanted
61+
assert caplog.messages == wanted
6462

6563
remove_tree(self.root_target, verbose=0)
6664

67-
def test_copy_tree_verbosity(self, logs):
65+
def test_copy_tree_verbosity(self, caplog):
6866

6967
mkpath(self.target, verbose=0)
7068

7169
copy_tree(self.target, self.target2, verbose=0)
72-
assert logs.render() == []
70+
assert caplog.messages == []
7371

7472
remove_tree(self.root_target, verbose=0)
7573

@@ -80,7 +78,7 @@ def test_copy_tree_verbosity(self, logs):
8078

8179
wanted = ['copying {} -> {}'.format(a_file, self.target2)]
8280
copy_tree(self.target, self.target2, verbose=1)
83-
assert logs.render() == wanted
81+
assert caplog.messages == wanted
8482

8583
remove_tree(self.root_target, verbose=0)
8684
remove_tree(self.target2, verbose=0)

distutils/tests/test_dist.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from distutils.cmd import Command
1515

1616
from distutils.tests import support
17-
from distutils import log
1817

1918

2019
pydistutils_cfg = '.' * (os.name == 'posix') + 'pydistutils.cfg'
@@ -236,7 +235,7 @@ def test_get_command_packages(self):
236235
def test_announce(self):
237236
# make sure the level is known
238237
dist = Distribution()
239-
with pytest.raises(ValueError):
238+
with pytest.raises(TypeError):
240239
dist.announce('ok', level='ok2')
241240

242241
def test_find_config_files_disable(self, temp_home):
@@ -367,15 +366,15 @@ def test_classifier(self):
367366
meta = self.format_metadata(dist)
368367
assert 'Metadata-Version: 1.1' in meta
369368

370-
def test_classifier_invalid_type(self, capsys):
369+
def test_classifier_invalid_type(self, caplog):
371370
attrs = {
372371
'name': 'Boa',
373372
'version': '3.0',
374373
'classifiers': ('Programming Language :: Python :: 3',),
375374
}
376375
d = Distribution(attrs)
377376
# should have warning about passing a non-list
378-
assert 'should be a list' in capsys.readouterr().err
377+
assert 'should be a list' in caplog.messages[0]
379378
# should be converted to a list
380379
assert isinstance(d.metadata.classifiers, list)
381380
assert d.metadata.classifiers == list(attrs['classifiers'])
@@ -389,15 +388,15 @@ def test_keywords(self):
389388
dist = Distribution(attrs)
390389
assert dist.get_keywords() == ['spam', 'eggs', 'life of brian']
391390

392-
def test_keywords_invalid_type(self, capsys):
391+
def test_keywords_invalid_type(self, caplog):
393392
attrs = {
394393
'name': 'Monty',
395394
'version': '1.0',
396395
'keywords': ('spam', 'eggs', 'life of brian'),
397396
}
398397
d = Distribution(attrs)
399398
# should have warning about passing a non-list
400-
assert 'should be a list' in capsys.readouterr().err
399+
assert 'should be a list' in caplog.messages[0]
401400
# should be converted to a list
402401
assert isinstance(d.metadata.keywords, list)
403402
assert d.metadata.keywords == list(attrs['keywords'])
@@ -411,15 +410,15 @@ def test_platforms(self):
411410
dist = Distribution(attrs)
412411
assert dist.get_platforms() == ['GNU/Linux', 'Some Evil Platform']
413412

414-
def test_platforms_invalid_types(self, capsys):
413+
def test_platforms_invalid_types(self, caplog):
415414
attrs = {
416415
'name': 'Monty',
417416
'version': '1.0',
418417
'platforms': ('GNU/Linux', 'Some Evil Platform'),
419418
}
420419
d = Distribution(attrs)
421420
# should have warning about passing a non-list
422-
assert 'should be a list' in capsys.readouterr().err
421+
assert 'should be a list' in caplog.messages[0]
423422
# should be converted to a list
424423
assert isinstance(d.metadata.platforms, list)
425424
assert d.metadata.platforms == list(attrs['platforms'])
@@ -472,8 +471,6 @@ def test_fix_help_options(self):
472471

473472
def test_show_help(self, request, capsys):
474473
# smoke test, just makes sure some help is displayed
475-
reset_log = functools.partial(log.set_threshold, log._global_log.threshold)
476-
request.addfinalizer(reset_log)
477474
dist = Distribution()
478475
sys.argv = []
479476
dist.help = 1

0 commit comments

Comments
 (0)