import copy


def deepcopy_mask(obj, memo, mask=None):
    """Generalized method for deep copies of objects.

    Certain types of attributes cannot be copied naively by `copy.deepcopy`;
    for example, `threading.Lock` objects. These may be manually specified in
    the `mask` argument.

    Args:
        obj (object): The object to be copied.
        mask (Dict[str, object]): Attributes to be replaced manually.
            Keys are attribute names and values are new attribute values.
        memo (dict): Tracks already copied objects to prevent a recursive loop.
            See the documentation for the standard module `copy`.
    """
    if mask is None:
        mask = {}
    cls = obj.__class__
    # copy object
    clone = cls.__new__(cls)
    memo[id(obj)] = clone
    # copy object attributes
    for k, v in obj.__dict__.items():
        if k in mask:
            setattr(clone, k, mask[k])
        else:
            setattr(clone, k, copy.deepcopy(v, memo))
    return clone