1111import yaml
1212import re
1313import string
14+ import copy
15+ import functools
1416
1517# from attackcti import attack_client
1618from colorama import init
@@ -62,13 +64,26 @@ class TestRules(unittest.TestCase):
6264 "rules-compliance" ,
6365 ]
6466
65- # Helper functions
66- def yield_next_rule_file_path (self , path_to_rules : list ) -> str :
67- for path_ in path_to_rules :
67+ @classmethod
68+ def setUpClass (cls ):
69+ cls ._rule_file_paths = []
70+ for path_ in cls .path_to_rules :
6871 for root , _ , files in os .walk (path_ ):
6972 for file in files :
7073 if file .endswith (".yml" ):
71- yield os .path .join (root , file )
74+ cls ._rule_file_paths .append (os .path .join (root , file ))
75+
76+ # Helper functions
77+ def yield_next_rule_file_path (self , path_to_rules : list ) -> str :
78+ if path_to_rules == self .path_to_rules and hasattr (self , "_rule_file_paths" ):
79+ for file_path in self ._rule_file_paths :
80+ yield file_path
81+ else :
82+ for path_ in path_to_rules :
83+ for root , _ , files in os .walk (path_ ):
84+ for file in files :
85+ if file .endswith (".yml" ):
86+ yield os .path .join (root , file )
7287
7388 def get_rule_part (self , file_path : str , part_name : str ):
7489 yaml_dicts = self .get_rule_yaml (file_path )
@@ -78,15 +93,14 @@ def get_rule_part(self, file_path: str, part_name: str):
7893
7994 return None
8095
81- def get_rule_yaml ( self , file_path : str ) -> dict :
82- data = []
83-
96+ @ staticmethod
97+ @ functools . lru_cache ( maxsize = None )
98+ def _read_rule_yaml ( file_path : str ) -> tuple :
8499 with open (file_path , encoding = "utf-8" ) as f :
85- yaml_parts = yaml .safe_load_all (f )
86- for part in yaml_parts :
87- data .append (part )
100+ return tuple (yaml .safe_load_all (f ))
88101
89- return data
102+ def get_rule_yaml (self , file_path : str ) -> dict :
103+ return [copy .deepcopy (part ) for part in self ._read_rule_yaml (file_path )]
90104
91105 # Tests
92106 def test_legal_trademark_violations (self ):
@@ -1146,7 +1160,7 @@ def test_re_invalid_escapes(self):
11461160 MAX_DEPTH = 3
11471161
11481162 def create_escape_allow_list ():
1149- """
1163+ r """
11501164 Create a list of characters that are allowed to be escaped.
11511165 1. Based on string.punctuation chars that would already be escaped by re.escape()
11521166 2. Followed by special chars like '\n', '\t', '\[0-9]' etc.
0 commit comments