Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow any iterable of strings #1

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from schema import And, Optional, Or, Schema

from Utils import get_fuzzy_results
from Utils import get_fuzzy_results, is_iterable_of_str

if typing.TYPE_CHECKING:
from BaseClasses import PlandoOptions
Expand Down Expand Up @@ -766,7 +766,7 @@ class VerifyKeys(metaclass=FreezeValidKeys):
value: typing.Any

@classmethod
def verify_keys(cls, data: typing.List[str]):
def verify_keys(cls, data: typing.Iterable[str]):
Jouramie marked this conversation as resolved.
Show resolved Hide resolved
if cls.valid_keys:
data = set(data)
dataset = set(word.casefold() for word in data) if cls.valid_keys_casefold else set(data)
Expand Down Expand Up @@ -857,7 +857,7 @@ def from_text(cls, text: str):

@classmethod
def from_any(cls, data: typing.Any):
if isinstance(data, (list, set, frozenset, tuple)):
if is_iterable_of_str(data):
cls.verify_keys(data)
return cls(data)
return cls.from_text(str(data))
Expand All @@ -883,7 +883,7 @@ def from_text(cls, text: str):

@classmethod
def from_any(cls, data: typing.Any):
if isinstance(data, (list, set, frozenset, tuple)):
if is_iterable_of_str(data):
cls.verify_keys(data)
return cls(data)
return cls.from_text(str(data))
Expand Down
11 changes: 11 additions & 0 deletions Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from argparse import Namespace
from settings import Settings, get_settings
from typing import BinaryIO, Coroutine, Optional, Set, Dict, Any, Union
from typing_extensions import TypeGuard
from yaml import load, load_all, dump

try:
Expand Down Expand Up @@ -966,3 +967,13 @@ def __bool__(self):

def __len__(self):
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]`) """
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)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ certifi>=2023.11.17
cython>=3.0.8
cymem>=2.0.8
orjson>=3.9.10
typing-extensions>=4.7.0
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if it's already there as a transitive dependency of the WebHost (for Flask-Limiter), I'm not a fan. TypeGuard is available in typing since python 3.10, so I would rather have this marked as required for python less than 3.10.

I think something like that would work:

typing-extensions>=4.7.0; python_version < '3.10'

Since typing-extensions won't be an explicit dependency for 3.10+, since it could be removed from transitive dependencies, TypeGuard could be imported with something like

try:
  from typing import TypeGuard
except ImportError:
  from typing_extensions import TypeGuard

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems like adding complication for no benefit.

It's not like the usefulness of typing_extensions will go away at 3.10
There are also new features in 3.11 that would be useful (Required NotRequired Self)
and 3.12 (@override) and 3.13 (ReadOnly)
and there will be usefulness in 3.14, 3.15, 3.16...

No matter what version of Python we're on, it will be useful.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, then I guess there is no point fighting against this dependency

Loading