11# Automated tests for the `coloredlogs' package.
22#
33# Author: Peter Odding <peter@peterodding.com>
4- # Last Change: February 14 , 2020
4+ # Last Change: February 15 , 2020
55# URL: https://coloredlogs.readthedocs.io
66
77"""Automated tests for the `coloredlogs` package."""
2020# External dependencies.
2121from humanfriendly .compat import StringIO
2222from humanfriendly .terminal import ANSI_COLOR_CODES , ansi_style , ansi_wrap
23- from humanfriendly .testing import PatchedItem , TestCase , retry
23+ from humanfriendly .testing import PatchedAttribute , PatchedItem , TestCase , retry
2424from humanfriendly .text import format , random_string
2525from mock import MagicMock
2626
4646 set_level ,
4747 walk_propagation_tree ,
4848)
49+ from coloredlogs .demo import demonstrate_colored_logging
4950from coloredlogs .syslog import SystemLogging , match_syslog_handler
5051from coloredlogs .converter import (
5152 ColoredCronMailer ,
@@ -415,42 +416,42 @@ def test_html_conversion(self):
415416 '<code>plain text followed by <span style="color:{css}">{name}</span> text</code>' ,
416417 css = EIGHT_COLOR_PALETTE [ansi_code ], name = color_name ,
417418 )
418- self .assertEquals (expected_html , convert (ansi_encoded_text ))
419+ self .assertEqual (expected_html , convert (ansi_encoded_text ))
419420 # Check conversion of bright colored text.
420421 expected_html = '<code><span style="color:#FF0">bright yellow</span></code>'
421- self .assertEquals (expected_html , convert (ansi_wrap ('bright yellow' , color = 'yellow' , bright = True )))
422+ self .assertEqual (expected_html , convert (ansi_wrap ('bright yellow' , color = 'yellow' , bright = True )))
422423 # Check conversion of text with a background color.
423424 expected_html = '<code><span style="background-color:#DE382B">red background</span></code>'
424- self .assertEquals (expected_html , convert (ansi_wrap ('red background' , background = 'red' )))
425+ self .assertEqual (expected_html , convert (ansi_wrap ('red background' , background = 'red' )))
425426 # Check conversion of text with a bright background color.
426427 expected_html = '<code><span style="background-color:#F00">bright red background</span></code>'
427- self .assertEquals (expected_html , convert (ansi_wrap ('bright red background' , background = 'red' , bright = True )))
428+ self .assertEqual (expected_html , convert (ansi_wrap ('bright red background' , background = 'red' , bright = True )))
428429 # Check conversion of text that uses the 256 color mode palette as a foreground color.
429430 expected_html = '<code><span style="color:#FFAF00">256 color mode foreground</span></code>'
430- self .assertEquals (expected_html , convert (ansi_wrap ('256 color mode foreground' , color = 214 )))
431+ self .assertEqual (expected_html , convert (ansi_wrap ('256 color mode foreground' , color = 214 )))
431432 # Check conversion of text that uses the 256 color mode palette as a background color.
432433 expected_html = '<code><span style="background-color:#AF0000">256 color mode background</span></code>'
433- self .assertEquals (expected_html , convert (ansi_wrap ('256 color mode background' , background = 124 )))
434+ self .assertEqual (expected_html , convert (ansi_wrap ('256 color mode background' , background = 124 )))
434435 # Check that invalid 256 color mode indexes don't raise exceptions.
435436 expected_html = '<code>plain text expected</code>'
436- self .assertEquals (expected_html , convert ('\x1b [38;5;256mplain text expected\x1b [0m' ))
437+ self .assertEqual (expected_html , convert ('\x1b [38;5;256mplain text expected\x1b [0m' ))
437438 # Check conversion of bold text.
438439 expected_html = '<code><span style="font-weight:bold">bold text</span></code>'
439- self .assertEquals (expected_html , convert (ansi_wrap ('bold text' , bold = True )))
440+ self .assertEqual (expected_html , convert (ansi_wrap ('bold text' , bold = True )))
440441 # Check conversion of underlined text.
441442 expected_html = '<code><span style="text-decoration:underline">underlined text</span></code>'
442- self .assertEquals (expected_html , convert (ansi_wrap ('underlined text' , underline = True )))
443+ self .assertEqual (expected_html , convert (ansi_wrap ('underlined text' , underline = True )))
443444 # Check conversion of strike-through text.
444445 expected_html = '<code><span style="text-decoration:line-through">strike-through text</span></code>'
445- self .assertEquals (expected_html , convert (ansi_wrap ('strike-through text' , strike_through = True )))
446+ self .assertEqual (expected_html , convert (ansi_wrap ('strike-through text' , strike_through = True )))
446447 # Check conversion of inverse text.
447448 expected_html = '<code><span style="background-color:#FFC706;color:#000">inverse</span></code>'
448- self .assertEquals (expected_html , convert (ansi_wrap ('inverse' , color = 'yellow' , inverse = True )))
449+ self .assertEqual (expected_html , convert (ansi_wrap ('inverse' , color = 'yellow' , inverse = True )))
449450 # Check conversion of URLs.
450451 for sample_text in 'www.python.org' , 'http://coloredlogs.rtfd.org' , 'https://coloredlogs.rtfd.org' :
451452 sample_url = sample_text if '://' in sample_text else ('http://' + sample_text )
452453 expected_html = '<code><a href="%s" style="color:inherit">%s</a></code>' % (sample_url , sample_text )
453- self .assertEquals (expected_html , convert (sample_text ))
454+ self .assertEqual (expected_html , convert (sample_text ))
454455 # Check that the capture pattern for URLs doesn't match ANSI escape
455456 # sequences and also check that the short hand for the 0 reset code is
456457 # supported. These are tests for regressions of bugs found in
@@ -464,7 +465,7 @@ def test_html_conversion(self):
464465 'https://coloredlogs.readthedocs.io'
465466 '</a></span>></code>'
466467 )
467- self .assertEquals (expected_html , convert (ansi_encoded_text ))
468+ self .assertEqual (expected_html , convert (ansi_encoded_text ))
468469
469470 def test_output_interception (self ):
470471 """Test capturing of output from external commands."""
@@ -538,6 +539,44 @@ def test_explicit_usage_message(self):
538539 """Test that the usage message is shown when ``--help`` is given."""
539540 assert 'Usage:' in main ('coloredlogs' , '--help' , capture = True )
540541
542+ def test_custom_record_factory (self ):
543+ """
544+ Test that custom LogRecord factories are supported.
545+
546+ This test is a bit convoluted because the logging module suppresses
547+ exceptions. We monkey patch the method suspected of encountering
548+ exceptions so that we can tell after it was called whether any
549+ exceptions occurred (despite the exceptions not propagating).
550+ """
551+ if not hasattr (logging , 'getLogRecordFactory' ):
552+ return self .skipTest ("this test requires Python >= 3.2" )
553+
554+ exceptions = []
555+ original_method = ColoredFormatter .format
556+ original_factory = logging .getLogRecordFactory ()
557+
558+ def custom_factory (* args , ** kwargs ):
559+ record = original_factory (* args , ** kwargs )
560+ record .custom_attribute = 0xdecafbad
561+ return record
562+
563+ def custom_method (* args , ** kw ):
564+ try :
565+ return original_method (* args , ** kw )
566+ except Exception as e :
567+ exceptions .append (e )
568+ raise
569+
570+ with PatchedAttribute (ColoredFormatter , 'format' , custom_method ):
571+ logging .setLogRecordFactory (custom_factory )
572+ try :
573+ demonstrate_colored_logging ()
574+ finally :
575+ logging .setLogRecordFactory (original_factory )
576+
577+ # Ensure that no exceptions were triggered.
578+ assert not exceptions
579+
541580
542581def check_contents (filename , contents , match ):
543582 """Check if a line in a file contains an expected string."""
0 commit comments