Skip to content

Commit 5db063b

Browse files
authoredMar 18, 2025··
ref: make SearchConfig generic on its allow_boolean setting (#87291)
this will be used in a future PR to make parse_search_config properly exclude ParenExpression / QueryOp when parse_boolean=False <!-- Describe your PR here. -->
1 parent a06172d commit 5db063b

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed
 

‎src/sentry/api/event_search.py

+31-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from collections.abc import Callable, Generator, Mapping, Sequence
77
from dataclasses import asdict, dataclass, field
88
from datetime import datetime
9-
from typing import TYPE_CHECKING, Any, Literal, NamedTuple, TypeIs, Union
9+
from typing import TYPE_CHECKING, Any, Literal, NamedTuple, TypeIs, Union, overload
1010

1111
from django.utils.functional import cached_property
1212
from parsimonious.exceptions import IncompleteParseError
@@ -574,8 +574,8 @@ def __str__(self) -> str:
574574
return f"{self.key.name}{self.operator}{self.value.raw_value}"
575575

576576

577-
@dataclass
578-
class SearchConfig:
577+
@dataclass # pycqa/pycodestyle#1277
578+
class SearchConfig[TAllowBoolean: (Literal[True], Literal[False]) = Literal[True]]: # noqa: E251
579579
"""
580580
Configures how the search parser interprets a search query
581581
"""
@@ -604,7 +604,7 @@ class SearchConfig:
604604
is_filter_translation: Mapping[str, tuple[str, Any]] = field(default_factory=dict)
605605

606606
# Enables boolean filtering (AND / OR)
607-
allow_boolean = True
607+
allow_boolean: TAllowBoolean = True # type: ignore[assignment] # python/mypy#18812
608608

609609
# Allows us to specify an allowlist of keys we will accept for this search.
610610
# If empty, allow all keys.
@@ -619,8 +619,32 @@ class SearchConfig:
619619
# Whether to wrap free_text_keys in asterisks
620620
wildcard_free_text: bool = False
621621

622+
@overload
622623
@classmethod
623-
def create_from(cls, search_config: SearchConfig, **overrides):
624+
def create_from[
625+
TBool: (Literal[True], Literal[False])
626+
](
627+
cls: type[SearchConfig[Any]],
628+
search_config: SearchConfig[Any],
629+
*,
630+
allow_boolean: TBool,
631+
**overrides: Any,
632+
) -> SearchConfig[TBool]: ...
633+
634+
@overload
635+
@classmethod
636+
def create_from[
637+
TBool: (Literal[True], Literal[False])
638+
](
639+
cls: type[SearchConfig[Any]],
640+
search_config: SearchConfig[TBool],
641+
**overrides: Any,
642+
) -> SearchConfig[TBool]: ...
643+
644+
@classmethod
645+
def create_from(
646+
cls: type[SearchConfig[Any]], search_config: SearchConfig[Any], **overrides: Any
647+
) -> SearchConfig[Any]:
624648
config = cls(**asdict(search_config))
625649
for key, val in overrides.items():
626650
setattr(config, key, val)
@@ -632,7 +656,7 @@ class SearchVisitor(NodeVisitor):
632656

633657
def __init__(
634658
self,
635-
config: SearchConfig,
659+
config: SearchConfig[Any],
636660
params: ParamsType | None = None,
637661
get_field_type: Callable[[str], str | None] | None = None,
638662
get_function_result_type: Callable[[str], str | None] | None = None,
@@ -1333,7 +1357,7 @@ def generic_visit(self, node, children):
13331357
def parse_search_query(
13341358
query: str,
13351359
*,
1336-
config: SearchConfig | None = None,
1360+
config: SearchConfig[Any] | None = None,
13371361
params=None,
13381362
get_field_type: Callable[[str], str | None] | None = None,
13391363
get_function_result_type: Callable[[str], str | None] | None = None,

0 commit comments

Comments
 (0)
Please sign in to comment.