  from lib.utils import FaceswapError
  
  from . import ImageAugmentation
  
  logger = logging.getLogger(__name__)  # pylint: disable=invalid-name
  
  _FACE_CACHES = dict()
  
  
  def _get_cache(side, filenames, config):
      """ Obtain a :class:`_Cache` object for the given side. If the object does not pre-exist then
      create it.
  
      Parameters
      ----------
      side: str
          `"a"` or `"b"`. The side of the model to obtain the cache for
      filenames: list
          The filenames of all the images. This can either be the full path or the base name. If the
          full paths are passed in, they are stripped to base name for use as the cache key.
      config: dict
          The user selected training configuration options
  
      Returns
      -------
      :class:`_Cache`
          The face meta information cache for the requested side
      """
      if not _FACE_CACHES.get(side):
          logger.debug("Creating cache. Side: %s", side)
          _FACE_CACHES[side] = _Cache(filenames, config)
      return _FACE_CACHES[side]
  
  
  def _check_reset(face_cache):
      """ Check whether a given cache needs to be reset because a face centering change has been
      detected in the other cache.
  
      Parameters
      ----------
      face_cache: :class:`_Cache`
          The cache object that is checking whether it should reset
  
      Returns
      -------
      bool
          ``True`` if the given object should reset the cache, otherwise ``False``
      """
      check_cache = next((cache for cache in _FACE_CACHES.values() if cache != face_cache), None)
      retval = check_cache if check_cache is None else check_cache.check_reset()
      return retval
  
  
  class _Cache():
      """ A thread safe mechanism for collecting and holding face meta information (masks, "
      "alignments data etc.) for multiple :class:`TrainingDataGenerator`s.
 
</s> remove     filenames: list
        The filenames of all the images. This can either be the full path or the base name. If the
        full paths are passed in, they are stripped to base name for use as the cache key.
 </s> add     model: :class:`~plugins.train.model.ModelBase`
        The model that this data generator is feeding </s> remove class _Cache():
    """ A thread safe mechanism for collecting and holding face meta information (masks, "
    "alignments data etc.) for multiple :class:`TrainingDataGenerator`s.
 </s> add logger = logging.getLogger(__name__)
ConfigType = Dict[str, Union[bool, int, float, str]]  # TODO Dataclass
BatchType = Tuple[np.ndarray, List[np.ndarray]] </s> remove         The user selected training configuration options
 </s> add         The configuration `dict` generated from :file:`config.train.ini` containing the trainer
        plugin configuration options.
    side: {'a' or 'b'}
        The side of the model that this iterator is for.
    images: list
        A list of image paths that will be used to compile the final augmented data from.
    batch_size: int
        The batch size for this iterator. Images will be returned in :class:`numpy.ndarray`
        objects of this size from the iterator. </s> remove         if set_flag:
            logger.warning("You are using legacy extracted faces but have selected '%s' centering "
                           "which is incompatible. Switching centering to 'legacy'",
                           self._centering)
        self._config["centering"] = "legacy"
        self._centering = "legacy"
        self._cache = {key: dict(cached=False) for key in self._cache}
        self._cache_full = False
        self._size = None
        if set_flag:
            self._has_reset = True

    def _add_aligned_face(self, filename, alignments, image_size):
        """ Add a :class:`lib.align.AlignedFace` object to the cache.
 </s> add         if not self._use_mask:
            return

        masks = np.array([face.get_training_masks() for face in detected_faces])
        batch[..., 3:] = masks

        logger.trace("side: %s, masks: %s, batch: %s",  # type: ignore
                     self._side, masks.shape, batch.shape)

    def _process_batch(self, filenames: List[str]) -> BatchType:
        """ Prepares data for feeding through subclassed methods.

        If this is the first time a face has been loaded, then it's meta data is extracted from the
        png header and added to :attr:`_face_cache` </s> remove     Each side may have up to 3 generators (training, preview and time-lapse). To conserve VRAM
    these need to share access to the same face information for the images they are processing.
 </s> add 
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
  from lib.utils import FaceswapError
  
  from . import ImageAugmentation
  
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
if sys.version_info < (3, 8):
    from typing_extensions import get_args, Literal
else:
    from typing import get_args, Literal
  
  
  class _Cache():
      """ A thread safe mechanism for collecting and holding face meta information (masks, "
      "alignments data etc.) for multiple :class:`TrainingDataGenerator`s.
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Data Augmentation update (#1263)

- lib.detected_face
    - Subclass Masks for Landmark based masks
    - Add training mask propery + methods to DetectedFace
  - lib.training_training
    - subclass TrainingDataGenerator for training and preview data
    - Split cache into own module
    - Reduce thread count to 1 to prevent image corruption + data re-use
    - Process on largest model input/output size rather than stored image size
    - Size and crop masks during caching stage
    - Implement ring buffer for data flow
    - Fix preview reload bug
  - augmentation
    - typing
    - switch color aug order
    - better initialization
    - Fix warp + landmark warp to correctly apply at different image scales
    - Slightly improved warp caching
    - Don't store whether image is_preview. Handle all data as training images implicitly
  - plugins.trainer: Typing and fixes to work with trainingdata refactor 
lib/training/generator.py