1515import typing
1616import typing_extensions
1717from collections import defaultdict
18- from collections .abc import Iterator
18+ from collections .abc import Iterator , Sequence , MutableSequence
19+ from collections .abc import Mapping , MutableMapping , Set , MutableSet
1920from dataclasses import is_dataclass
2021from typing import TypeVar , Generic , Any , ClassVar , Optional , NewType , Union , Hashable , Callable
2122
@@ -563,30 +564,50 @@ def is_opt_dataclass(typ: Any) -> bool:
563564@cache
564565def is_list (typ : type [Any ]) -> bool :
565566 """
566- Test if the type is `list`.
567+ Test if the type is `list`, `collections.abc.Sequence`, or `collections.abc.MutableSequence` .
567568
568569 >>> is_list(list[int])
569570 True
570571 >>> is_list(list)
571572 True
573+ >>> is_list(Sequence[int])
574+ True
575+ >>> is_list(Sequence)
576+ True
577+ >>> is_list(MutableSequence[int])
578+ True
579+ >>> is_list(MutableSequence)
580+ True
572581 """
573- try :
574- return issubclass ( get_origin ( typ ), list ) # type: ignore
575- except TypeError :
576- return typ is list
582+ origin = get_origin ( typ )
583+ if origin is None :
584+ return typ in ( list , Sequence , MutableSequence )
585+ return origin in ( list , Sequence , MutableSequence )
577586
578587
579588@cache
580589def is_bare_list (typ : type [Any ]) -> bool :
581590 """
582- Test if the type is `list` without type args.
591+ Test if the type is `list`/`collections.abc.Sequence`/`collections.abc.MutableSequence`
592+ without type args.
583593
584594 >>> is_bare_list(list[int])
585595 False
586596 >>> is_bare_list(list)
587597 True
598+ >>> is_bare_list(Sequence[int])
599+ False
600+ >>> is_bare_list(Sequence)
601+ True
602+ >>> is_bare_list(MutableSequence[int])
603+ False
604+ >>> is_bare_list(MutableSequence)
605+ True
588606 """
589- return typ is list
607+ origin = get_origin (typ )
608+ if origin in (list , Sequence , MutableSequence ):
609+ return not type_args (typ )
610+ return typ in (list , Sequence , MutableSequence )
590611
591612
592613@cache
@@ -633,32 +654,49 @@ def is_variable_tuple(typ: type[Any]) -> bool:
633654@cache
634655def is_set (typ : type [Any ]) -> bool :
635656 """
636- Test if the type is ` set` or `frozenset` .
657+ Test if the type is set-like .
637658
638659 >>> is_set(set[int])
639660 True
640661 >>> is_set(set)
641662 True
642663 >>> is_set(frozenset[int])
643664 True
665+ >>> from collections.abc import Set, MutableSet
666+ >>> is_set(Set[int])
667+ True
668+ >>> is_set(Set)
669+ True
670+ >>> is_set(MutableSet[int])
671+ True
672+ >>> is_set(MutableSet)
673+ True
644674 """
645675 try :
646- return issubclass (get_origin (typ ), (set , frozenset )) # type: ignore
676+ return issubclass (get_origin (typ ), (set , frozenset , Set , MutableSet )) # type: ignore[arg-type]
647677 except TypeError :
648- return typ in (set , frozenset )
678+ return typ in (set , frozenset , Set , MutableSet )
649679
650680
651681@cache
652682def is_bare_set (typ : type [Any ]) -> bool :
653683 """
654- Test if the type is `set` without type args.
684+ Test if the type is `set`/`frozenset`/`Set`/`MutableSet` without type args.
655685
656686 >>> is_bare_set(set[int])
657687 False
658688 >>> is_bare_set(set)
659689 True
690+ >>> from collections.abc import Set, MutableSet
691+ >>> is_bare_set(Set)
692+ True
693+ >>> is_bare_set(MutableSet)
694+ True
660695 """
661- return typ in (set , frozenset )
696+ origin = get_origin (typ )
697+ if origin in (set , frozenset , Set , MutableSet ):
698+ return not type_args (typ )
699+ return typ in (set , frozenset , Set , MutableSet )
662700
663701
664702@cache
@@ -680,32 +718,52 @@ def is_frozen_set(typ: type[Any]) -> bool:
680718@cache
681719def is_dict (typ : type [Any ]) -> bool :
682720 """
683- Test if the type is dict.
721+ Test if the type is dict-like .
684722
685723 >>> is_dict(dict[int, int])
686724 True
687725 >>> is_dict(dict)
688726 True
689727 >>> is_dict(defaultdict[int, int])
690728 True
729+ >>> from collections.abc import Mapping, MutableMapping
730+ >>> is_dict(Mapping[str, int])
731+ True
732+ >>> is_dict(Mapping)
733+ True
734+ >>> is_dict(MutableMapping[str, int])
735+ True
736+ >>> is_dict(MutableMapping)
737+ True
691738 """
692739 try :
693- return issubclass (get_origin (typ ), (dict , defaultdict )) # type: ignore
740+ return issubclass (
741+ get_origin (typ ), (dict , defaultdict , Mapping , MutableMapping ) # type: ignore[arg-type]
742+ )
694743 except TypeError :
695- return typ in (dict , defaultdict )
744+ return typ in (dict , defaultdict , Mapping , MutableMapping )
696745
697746
747+ @cache
698748@cache
699749def is_bare_dict (typ : type [Any ]) -> bool :
700750 """
701- Test if the type is `dict` without type args.
751+ Test if the type is `dict`/`Mapping`/`MutableMapping` without type args.
702752
703753 >>> is_bare_dict(dict[int, str])
704754 False
705755 >>> is_bare_dict(dict)
706756 True
757+ >>> from collections.abc import Mapping, MutableMapping
758+ >>> is_bare_dict(Mapping)
759+ True
760+ >>> is_bare_dict(MutableMapping)
761+ True
707762 """
708- return typ is dict
763+ origin = get_origin (typ )
764+ if origin in (dict , Mapping , MutableMapping ):
765+ return not type_args (typ )
766+ return typ in (dict , Mapping , MutableMapping )
709767
710768
711769@cache
0 commit comments