def _extract_collection_base_type(collection_object_type, exception_if_none: bool = True,<EOL>resolve_fwd_refs: bool = True) -> Tuple[Type, Optional[Type]]:
contents_item_type = None<EOL>contents_key_type = None<EOL>check_var(collection_object_type, var_types=type, var_name='<STR_LIT>')<EOL>is_tuple = False<EOL>if is_tuple_type(collection_object_type):  <EOL><INDENT>is_tuple = True<EOL>__args = get_args(collection_object_type, evaluate=True)<EOL>if len(__args) > <NUM_LIT:0>:<EOL><INDENT>contents_item_type = __args<EOL><DEDENT><DEDENT>elif issubclass(collection_object_type, Mapping):  <EOL><INDENT>if is_generic_type(collection_object_type):<EOL><INDENT>__args = get_args(collection_object_type, evaluate=True)<EOL>if len(__args) > <NUM_LIT:0>:<EOL><INDENT>contents_key_type, contents_item_type = __args<EOL>if not issubclass(contents_key_type, str):<EOL><INDENT>raise TypeError('<STR_LIT>'<EOL>'<STR_LIT>' + str(contents_key_type) + '<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT><DEDENT><DEDENT><DEDENT>elif issubclass(collection_object_type, Iterable):  <EOL><INDENT>if is_generic_type(collection_object_type):<EOL><INDENT>__args = get_args(collection_object_type, evaluate=True)<EOL>if len(__args) > <NUM_LIT:0>:<EOL><INDENT>contents_item_type, = __args<EOL><DEDENT><DEDENT><DEDENT>elif issubclass(collection_object_type, dict) or issubclass(collection_object_type, list)or issubclass(collection_object_type, tuple) or issubclass(collection_object_type, set):<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>raise AttributeError('<STR_LIT>' + str(collection_object_type)<EOL>+ '<STR_LIT>')<EOL><DEDENT>try:<EOL><INDENT>if contents_item_type is None or contents_item_type is Parameter.empty:<EOL><INDENT>raise TypeInformationRequiredError.create_for_collection_items(collection_object_type, contents_item_type)<EOL><DEDENT>elif is_tuple:<EOL><INDENT>resolved = []<EOL>for t in contents_item_type:<EOL><INDENT>if contents_item_type is None or contents_item_type is Parameter.empty:<EOL><INDENT>raise TypeInformationRequiredError.create_for_collection_items(collection_object_type, t)<EOL><DEDENT>if resolve_fwd_refs:<EOL><INDENT>t = resolve_forward_ref(t)<EOL><DEDENT>resolved.append(t)<EOL>if not is_valid_pep484_type_hint(t):<EOL><INDENT>raise InvalidPEP484TypeHint.create_for_collection_items(collection_object_type, t)<EOL><DEDENT><DEDENT>if resolve_fwd_refs:<EOL><INDENT>contents_item_type = tuple(resolved)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if resolve_fwd_refs:<EOL><INDENT>contents_item_type = resolve_forward_ref(contents_item_type)<EOL><DEDENT>if not is_valid_pep484_type_hint(contents_item_type):<EOL><INDENT>raise InvalidPEP484TypeHint.create_for_collection_items(collection_object_type, contents_item_type)<EOL><DEDENT><DEDENT><DEDENT>except TypeInformationRequiredError as e:<EOL><INDENT>if exception_if_none:<EOL><INDENT>raise e.with_traceback(e.__traceback__)<EOL><DEDENT><DEDENT>return contents_item_type, contents_key_type<EOL>
Utility method to extract the base item type from a collection/iterable item type.
Throws
* a TypeError if the collection_object_type a Dict with non-string keys.
* an AttributeError if the collection_object_type is actually not a collection
* a TypeInformationRequiredError if somehow the inner type can't be found from the collection type (either if dict,
list, set, tuple were used instead of their typing module equivalents (Dict, List, Set, Tuple), or if the latter
were specified without inner content types (as in Dict instead of Dict[str, Foo])

:param collection_object_type:
:return: a tuple containing the collection's content type (which may itself be a Tuple in case of a Tuple) and the
collection's content key type for dicts (or None)