Skip to content

Commit e83c300

Browse files
committed
Merge branch 'typechecking-recovery'
1 parent f607aa4 commit e83c300

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

sigma/rule/base.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
from dataclasses import dataclass, field
2-
from typing import Any, Dict, Optional, Tuple, List
2+
from typing import Any, Dict, Optional, Tuple, List, Type
33
from uuid import UUID
44
from datetime import date, datetime
5+
import datetime as dt
56
import yaml
67
import re
78
import sigma
89
import sigma.exceptions as sigma_exceptions
9-
from sigma.exceptions import SigmaRuleLocation
10+
from sigma.exceptions import SigmaError, SigmaRuleLocation
1011
from sigma.rule.attributes import SigmaLevel, SigmaRelated, SigmaRuleTag, SigmaStatus
12+
from sigma.conversion.state import ConversionState
1113

1214

1315
class SigmaYAMLLoader(yaml.SafeLoader):
1416
"""Custom YAML loader implementing additional functionality for Sigma."""
1517

16-
def construct_mapping(self, node, deep=...):
18+
def construct_mapping(self, node: yaml.MappingNode, deep: bool = False) -> Dict[Any, Any]:
1719
keys = set()
1820
for k, v in node.value:
19-
key = self.construct_object(k, deep=deep)
21+
key = self.construct_object(k, deep=deep) # type: ignore
2022
if key in keys:
2123
raise yaml.error.YAMLError("Duplicate key '{k}'")
2224
else:
@@ -38,8 +40,8 @@ class SigmaRuleBase:
3840
references: List[str] = field(default_factory=list)
3941
tags: List["sigma.rule.attributes.SigmaRuleTag"] = field(default_factory=list)
4042
author: Optional[str] = None
41-
date: Optional["datetime.date"] = None
42-
modified: Optional["datetime.date"] = None
43+
date: Optional["dt.date"] = None
44+
modified: Optional["dt.date"] = None
4345
fields: List[str] = field(default_factory=list)
4446
falsepositives: List[str] = field(default_factory=list)
4547
level: Optional["sigma.rule.attributes.SigmaLevel"] = None
@@ -55,12 +57,12 @@ class SigmaRuleBase:
5557
_conversion_result: Optional[List[Any]] = field(
5658
init=False, default=None, repr=False, compare=False
5759
)
58-
_conversion_states: Optional[List["sigma.conversion.state.ConversionState"]] = field(
60+
_conversion_states: Optional[List["ConversionState"]] = field(
5961
init=False, default=None, repr=False, compare=False
6062
)
6163
_output: bool = field(init=False, default=True, repr=False, compare=False)
6264

63-
def __post_init__(self):
65+
def __post_init__(self) -> None:
6466
for field in ("references", "tags", "fields", "falsepositives"):
6567
if self.__getattribute__(field) is None:
6668
self.__setattr__(field, [])
@@ -75,10 +77,10 @@ def __post_init__(self):
7577
@classmethod
7678
def from_dict(
7779
cls,
78-
rule: dict,
80+
rule: Dict[str, Any],
7981
collect_errors: bool = False,
8082
source: Optional[SigmaRuleLocation] = None,
81-
) -> Tuple[dict, List[Exception]]:
83+
) -> Tuple[Dict[str, Any], List[SigmaError]]:
8284
"""
8385
Convert Sigma rule base parsed in dict structure into kwargs dict that can be passed to the
8486
class instantiation of an object derived from the SigmaRuleBase class and the errors list.
@@ -90,7 +92,7 @@ class instantiation of an object derived from the SigmaRuleBase class and the er
9092
"""
9193
errors = []
9294

93-
def get_rule_as_date(name: str, exception_class) -> Optional[date]:
95+
def get_rule_as_date(name: str, exception_class: Type[SigmaError]) -> Optional[date]:
9496
"""
9597
Accepted string based date formats are in range 1000-01-01 .. 3999-12-31:
9698
* XXXX-XX-XX -- fully corresponds to yaml date format
@@ -99,21 +101,21 @@ def get_rule_as_date(name: str, exception_class) -> Optional[date]:
99101
2024-01-1, 24-1-24, 24/1/1, ...
100102
"""
101103
nonlocal errors, rule, source
102-
result = rule.get(name)
104+
value = rule.get(name)
103105
if (
104-
result is not None
105-
and not isinstance(result, date)
106-
and not isinstance(result, datetime)
106+
value is not None
107+
and not isinstance(value, date)
108+
and not isinstance(value, datetime)
107109
):
108110
error = True
109111
try:
110-
result = str(result) # forcifully convert whatever the type is into string
112+
value = str(value) # forcifully convert whatever the type is into string
111113
accepted_regexps = (
112114
"([1-3][0-9][0-9][0-9])-([01][0-9])-([0-3][0-9])", # 1000-01-01 .. 3999-12-31
113115
"([1-3][0-9][0-9][0-9])/([01]?[0-9])/([0-3]?[0-9])", # 1000/1/1, 1000/01/01 .. 3999/12/31
114116
)
115117
for date_regexp in accepted_regexps:
116-
matcher = re.fullmatch(date_regexp, result)
118+
matcher = re.fullmatch(date_regexp, value)
117119
if matcher:
118120
result = date(int(matcher[1]), int(matcher[2]), int(matcher[3]))
119121
error = False
@@ -123,10 +125,13 @@ def get_rule_as_date(name: str, exception_class) -> Optional[date]:
123125
if error:
124126
errors.append(
125127
exception_class(
126-
f"Rule {name} '{ result }' is invalid, use yyyy-mm-dd", source=source
128+
f"Rule {name} '{ value }' is invalid, use yyyy-mm-dd", source=source
127129
)
128130
)
129-
return result
131+
return None
132+
return result
133+
else:
134+
return value
130135

131136
# Rule identifier may be empty or must be valid UUID
132137
rule_id = rule.get("id")
@@ -358,12 +363,14 @@ def get_rule_as_date(name: str, exception_class) -> Optional[date]:
358363
)
359364

360365
@classmethod
361-
def from_yaml(cls, rule: str, collect_errors: bool = False) -> "SigmaRuleBase":
366+
def from_yaml(
367+
cls, rule: str, collect_errors: bool = False
368+
) -> Tuple[Dict[str, Any], List[SigmaError]]:
362369
"""Convert YAML input string with single document into SigmaRule object."""
363370
parsed_rule = yaml.load(rule, SigmaYAMLLoader)
364371
return cls.from_dict(parsed_rule, collect_errors)
365372

366-
def to_dict(self) -> dict:
373+
def to_dict(self) -> Dict[str, Any]:
367374
"""Convert rule object into dict."""
368375
d = {
369376
"title": self.title,

0 commit comments

Comments
 (0)