@@ -58,11 +58,33 @@ def find_file_capabilities(
5858 return FileCapabilities (features , matches , len (file_features ))
5959
6060
61+ @dataclass
62+ class Capabilities :
63+ matches : MatchResults
64+ feature_counts : StaticFeatureCounts | DynamicFeatureCounts
65+ library_functions : Optional [tuple [LibraryFunction , ...]] = None
66+
67+
68+ def find_capabilities (ruleset : RuleSet , extractor : FeatureExtractor , disable_progress = None , ** kwargs ) -> Capabilities :
69+ from capa .capabilities .static import find_static_capabilities
70+ from capa .capabilities .dynamic import find_dynamic_capabilities
71+
72+ if isinstance (extractor , StaticFeatureExtractor ):
73+ # for the time being, extractors are either static or dynamic.
74+ # Remove this assertion once that has changed
75+ assert not isinstance (extractor , DynamicFeatureExtractor )
76+ return find_static_capabilities (ruleset , extractor , disable_progress = disable_progress , ** kwargs )
77+ if isinstance (extractor , DynamicFeatureExtractor ):
78+ return find_dynamic_capabilities (ruleset , extractor , disable_progress = disable_progress , ** kwargs )
79+
80+ raise ValueError (f"unexpected extractor type: { extractor .__class__ .__name__ } " )
81+
82+
6183def is_static_limitation_rule (r : Rule ) -> bool :
6284 return r .meta .get ("namespace" , "" ) == "internal/limitation/static"
6385
6486
65- def has_static_limitation (rules : RuleSet , capabilities : MatchResults , is_standalone = True ) -> bool :
87+ def has_static_limitation (rules : RuleSet , capabilities : Capabilities | FileCapabilities , is_standalone = True ) -> bool :
6688
6789 file_limitation_rules = list (filter (lambda r : is_static_limitation_rule (r ), rules .rules .values ()))
6890
@@ -73,16 +95,16 @@ def is_dynamic_limitation_rule(r: Rule) -> bool:
7395 return r .meta .get ("namespace" , "" ) == "internal/limitation/dynamic"
7496
7597
76- def has_dynamic_limitation (rules : RuleSet , capabilities : MatchResults , is_standalone = True ) -> bool :
98+ def has_dynamic_limitation (rules : RuleSet , capabilities : Capabilities | FileCapabilities , is_standalone = True ) -> bool :
7799
78100 dynamic_limitation_rules = list (filter (lambda r : is_dynamic_limitation_rule (r ), rules .rules .values ()))
79101 return has_limitation (dynamic_limitation_rules , capabilities , is_standalone )
80102
81103
82- def has_limitation (rules : list , capabilities : MatchResults , is_standalone : bool ) -> bool :
104+ def has_limitation (rules : list , capabilities : Capabilities | FileCapabilities , is_standalone : bool ) -> bool :
83105
84106 for rule in rules :
85- if rule .name not in capabilities :
107+ if rule .name not in capabilities . matches :
86108 continue
87109 logger .warning ("-" * 80 )
88110 for line in rule .meta .get ("description" , "" ).split ("\n " ):
@@ -96,25 +118,3 @@ def has_limitation(rules: list, capabilities: MatchResults, is_standalone: bool)
96118 # bail on first file limitation
97119 return True
98120 return False
99-
100-
101- @dataclass
102- class Capabilities :
103- matches : MatchResults
104- feature_counts : StaticFeatureCounts | DynamicFeatureCounts
105- library_functions : Optional [tuple [LibraryFunction , ...]] = None
106-
107-
108- def find_capabilities (ruleset : RuleSet , extractor : FeatureExtractor , disable_progress = None , ** kwargs ) -> Capabilities :
109- from capa .capabilities .static import find_static_capabilities
110- from capa .capabilities .dynamic import find_dynamic_capabilities
111-
112- if isinstance (extractor , StaticFeatureExtractor ):
113- # for the time being, extractors are either static or dynamic.
114- # Remove this assertion once that has changed
115- assert not isinstance (extractor , DynamicFeatureExtractor )
116- return find_static_capabilities (ruleset , extractor , disable_progress = disable_progress , ** kwargs )
117- if isinstance (extractor , DynamicFeatureExtractor ):
118- return find_dynamic_capabilities (ruleset , extractor , disable_progress = disable_progress , ** kwargs )
119-
120- raise ValueError (f"unexpected extractor type: { extractor .__class__ .__name__ } " )
0 commit comments