code: def _parse_ent_types(
      ent_types: Optional[str | Collection[str]], which: str
  ) -> Optional[str | set[str]]:
      if not ent_types:
          return None
      elif isinstance(ent_types, str):
          ent_types = ent_types.upper()
          # replace the shorthand numeric case by its corresponding constant
          if ent_types == "NUMERIC":
              return constants.NUMERIC_ENT_TYPES
          else:
              return ent_types
      elif isinstance(ent_types, (set, frozenset, list, tuple)):
          ent_types = {ent_type.upper() for ent_type in ent_types}
          # again, replace the shorthand numeric case by its corresponding constant
          # and include it in the set in case other types are specified
          if any(ent_type == "NUMERIC" for ent_type in ent_types):
              return ent_types.union(constants.NUMERIC_ENT_TYPES)
          else:
              return ent_types
      else:
          raise TypeError(
              errors.type_invalid_msg(
                  f"{which}_types",
                  type(ent_types),
                  Optional[Union[str, Collection[str]]],
              )
          )
  
file_path: textacy/src/textacy/extract/basics.py
imports: from __future__ import annotations
  from functools import partial
  from typing import Collection, Iterable, Optional, Union
  from cytoolz import itertoolz
  from spacy.parts_of_speech import DET
  from spacy.tokens import Span, Token
  from ..None import constants, errors, types, utils
label_desc: Use image node_id 4 for calling a global function with example usage: _parse_ent_types(ent_types, which) and returns: None, constants, ent_types, ent_types, ent_types