Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/error.py: 90%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

69 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) Philippe Biondi <phil@secdev.org> 

5 

6""" 

7Logging subsystem and basic exception class. 

8""" 

9 

10############################# 

11# Logging subsystem # 

12############################# 

13 

14 

15import logging 

16import traceback 

17import time 

18 

19from scapy.consts import WINDOWS 

20 

21# Typing imports 

22from logging import LogRecord 

23from typing import ( 

24 Any, 

25 Dict, 

26 Tuple, 

27) 

28 

29 

30class Scapy_Exception(Exception): 

31 pass 

32 

33 

34class ScapyInvalidPlatformException(Scapy_Exception): 

35 pass 

36 

37 

38class ScapyNoDstMacException(Scapy_Exception): 

39 pass 

40 

41 

42class ScapyFreqFilter(logging.Filter): 

43 def __init__(self): 

44 # type: () -> None 

45 logging.Filter.__init__(self) 

46 self.warning_table = {} # type: Dict[int, Tuple[float, int]] # noqa: E501 

47 

48 def filter(self, record): 

49 # type: (LogRecord) -> bool 

50 from scapy.config import conf 

51 # Levels below INFO are not covered 

52 if record.levelno <= logging.INFO: 

53 return True 

54 wt = conf.warning_threshold 

55 if wt > 0: 

56 stk = traceback.extract_stack() 

57 caller = 0 # type: int 

58 for _, l, n, _ in stk: 

59 if n == 'warning': 

60 break 

61 caller = l 

62 tm, nb = self.warning_table.get(caller, (0, 0)) 

63 ltm = time.time() 

64 if ltm - tm > wt: 

65 tm = ltm 

66 nb = 0 

67 else: 

68 if nb < 2: 

69 nb += 1 

70 if nb == 2: 

71 record.msg = "more " + str(record.msg) 

72 else: 

73 return False 

74 self.warning_table[caller] = (tm, nb) 

75 return True 

76 

77 

78class ScapyColoredFormatter(logging.Formatter): 

79 """A subclass of logging.Formatter that handles colors.""" 

80 levels_colored = { 

81 'DEBUG': 'reset', 

82 'INFO': 'reset', 

83 'WARNING': 'bold+yellow', 

84 'ERROR': 'bold+red', 

85 'CRITICAL': 'bold+white+bg_red' 

86 } 

87 

88 def format(self, record): 

89 # type: (LogRecord) -> str 

90 message = super(ScapyColoredFormatter, self).format(record) 

91 from scapy.config import conf 

92 message = conf.color_theme.format( 

93 message, 

94 self.levels_colored[record.levelname] 

95 ) 

96 return message 

97 

98 

99if WINDOWS: 

100 # colorama is bundled within IPython, but 

101 # logging.StreamHandler will be overwritten when called, 

102 # so we can't wait for IPython to call it 

103 try: 

104 import colorama 

105 colorama.init() 

106 except ImportError: 

107 pass 

108 

109# get Scapy's master logger 

110log_scapy = logging.getLogger("scapy") 

111log_scapy.propagate = False 

112# override the level if not already set 

113if log_scapy.level == logging.NOTSET: 

114 log_scapy.setLevel(logging.WARNING) 

115# add a custom handler controlled by Scapy's config 

116_handler = logging.StreamHandler() 

117_handler.setFormatter( 

118 ScapyColoredFormatter( 

119 "%(levelname)s: %(message)s", 

120 ) 

121) 

122log_scapy.addHandler(_handler) 

123# logs at runtime 

124log_runtime = logging.getLogger("scapy.runtime") 

125log_runtime.addFilter(ScapyFreqFilter()) 

126# logs in interactive functions 

127log_interactive = logging.getLogger("scapy.interactive") 

128log_interactive.setLevel(logging.DEBUG) 

129# logs when loading Scapy 

130log_loading = logging.getLogger("scapy.loading") 

131 

132 

133def warning(x, *args, **kargs): 

134 # type: (str, *Any, **Any) -> None 

135 """ 

136 Prints a warning during runtime. 

137 """ 

138 log_runtime.warning(x, *args, **kargs)