From a3125cb06e4bc142161e245a32fb0f34562fab8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bolduc?= <16137441+Jouramie@users.noreply.github.com> Date: Mon, 11 Mar 2024 19:30:14 -0400 Subject: [PATCH] Core: Fix OptionList and OptionSet to allow Iterable of Iterable (#2911) * fix, maybe * typegard for iterable of any * wow I'm so tired I just changed the method name without changing what it actually does... * also exclude bytes in is_iterable_but_str * apply pr comments * Update Utils.py Co-authored-by: Doug Hoskisson * Revert "also exclude bytes in is_iterable_but_str" This reverts commit cf087d2ee20727dbbe561c8c0f90aa85ef0a5d4b. --------- Co-authored-by: Doug Hoskisson --- Options.py | 8 ++++---- Utils.py | 11 ++++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Options.py b/Options.py index ff8ad11c..f19c042f 100644 --- a/Options.py +++ b/Options.py @@ -12,7 +12,7 @@ from dataclasses import dataclass from schema import And, Optional, Or, Schema -from Utils import get_fuzzy_results, is_iterable_of_str +from Utils import get_fuzzy_results, is_iterable_except_str if typing.TYPE_CHECKING: from BaseClasses import PlandoOptions @@ -847,7 +847,7 @@ class OptionList(Option[typing.List[typing.Any]], VerifyKeys): default: typing.Union[typing.List[typing.Any], typing.Tuple[typing.Any, ...]] = () supports_weighting = False - def __init__(self, value: typing.Iterable[str]): + def __init__(self, value: typing.Iterable[typing.Any]): self.value = list(deepcopy(value)) super(OptionList, self).__init__() @@ -857,7 +857,7 @@ class OptionList(Option[typing.List[typing.Any]], VerifyKeys): @classmethod def from_any(cls, data: typing.Any): - if is_iterable_of_str(data): + if is_iterable_except_str(data): cls.verify_keys(data) return cls(data) return cls.from_text(str(data)) @@ -883,7 +883,7 @@ class OptionSet(Option[typing.Set[str]], VerifyKeys): @classmethod def from_any(cls, data: typing.Any): - if is_iterable_of_str(data): + if is_iterable_except_str(data): cls.verify_keys(data) return cls(data) return cls.from_text(str(data)) diff --git a/Utils.py b/Utils.py index cea6405a..3c63b42c 100644 --- a/Utils.py +++ b/Utils.py @@ -713,7 +713,7 @@ def messagebox(title: str, text: str, error: bool = False) -> None: import ctypes style = 0x10 if error else 0x0 return ctypes.windll.user32.MessageBoxW(0, text, title, style) - + # fall back to tk try: import tkinter @@ -969,11 +969,8 @@ class RepeatableChain: return sum(len(iterable) for iterable in self.iterable) -def is_iterable_of_str(obj: object) -> TypeGuard[typing.Iterable[str]]: - """ but not a `str` (because technically, `str` is `Iterable[str]`) """ +def is_iterable_except_str(obj: object) -> TypeGuard[typing.Iterable[typing.Any]]: + """ `str` is `Iterable`, but that's not what we want """ if isinstance(obj, str): return False - if not isinstance(obj, typing.Iterable): - return False - obj_it: typing.Iterable[object] = obj - return all(isinstance(v, str) for v in obj_it) + return isinstance(obj, typing.Iterable)