Coverage for django_query_capture/presenter/pretty.py: 100%

26 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-11-20 10:20 +0000

1import sqlparse 

2from pygments import highlight 

3from pygments.formatters.terminal256 import TerminalTrueColorFormatter 

4from pygments.lexers.sql import SqlLexer 

5from tabulate import tabulate 

6 

7from django_query_capture.presenter.base import BasePresenter 

8from django_query_capture.settings import get_config 

9from django_query_capture.utils import colorize, get_stack_prefix 

10 

11 

12class PrettyPresenter(BasePresenter): 

13 """ 

14 Outputs all elements of [ClassifiedQuery][classify.ClassifiedQuery] with formatting.<br> 

15 termscolor: [https://github.com/django/django/blob/main/django/utils/termcolors.py](https://github.com/django/django/blob/main/django/utils/termcolors.py)<br> 

16 tabulate: [https://github.com/astanin/python-tabulate#table-format](https://github.com/astanin/python-tabulate#table-format) <br> 

17 pygments: [https://pygments.org/styles/](https://pygments.org/styles/) 

18 """ 

19 

20 @staticmethod 

21 def print_sql(sql: str) -> None: 

22 print( 

23 highlight( 

24 sqlparse.format(sql, reindent=True, keyword_case="upper"), 

25 SqlLexer(), 

26 TerminalTrueColorFormatter( 

27 style=get_config()["PRETTY"]["SQL_COLOR_FORMAT"] 

28 ), 

29 ) 

30 ) 

31 

32 def get_stats_table(self, is_warning: bool = False) -> str: 

33 return colorize( 

34 tabulate( 

35 [ 

36 [ 

37 self.classified_query["read"], 

38 self.classified_query["writes"], 

39 self.classified_query["total"], 

40 f"{self.classified_query['total_duration']:.2f}", 

41 self.classified_query["most_common_duplicate"][1] 

42 if self.classified_query["most_common_duplicate"] 

43 else 0, 

44 self.classified_query["most_common_similar"][1] 

45 if self.classified_query["most_common_similar"] 

46 else 0, 

47 ] 

48 ], 

49 [ 

50 "read", 

51 "writes", 

52 "total", 

53 "total_duration", 

54 "most_common_duplicates", 

55 "most_common_similar", 

56 ], 

57 tablefmt=get_config()["PRETTY"]["TABLE_FORMAT"], 

58 ), 

59 is_warning, 

60 ) 

61 

62 def print(self) -> None: 

63 is_warning = self.classified_query["has_over_threshold"] 

64 print("\n" + self.get_stats_table(is_warning)) 

65 

66 for captured_query in self.classified_query["slow_captured_queries"]: 

67 print( 

68 f'{get_stack_prefix(captured_query)} Slow {captured_query["duration"]:.2f} seconds' 

69 ) 

70 self.print_sql(captured_query["sql"]) 

71 

72 for captured_query, count in self.classified_query[ 

73 "duplicates_counter_over_threshold" 

74 ].items(): 

75 print(f"{get_stack_prefix(captured_query)} Repeated {count} times") 

76 self.print_sql(captured_query["sql"]) 

77 

78 for captured_query, count in self.classified_query[ 

79 "similar_counter_over_threshold" 

80 ].items(): 

81 print(f"{get_stack_prefix(captured_query)} Similar {count} times") 

82 self.print_sql(captured_query["raw_sql"])