# Path: paratemp/tools.py
# class _BlankStream(object):
#     """
#     A class for use when not actually wanting to write to a file.
#     """
# 
#     def write(self, string):
#         pass
# 
#     def fileno(self):
#         return 0  # Not sure if this works. Maybe None would be better
# 
#     def flush(self):
#         pass
# 
# Path: paratemp/exceptions.py
# class InputError(Exception):
#     """Exception raised for errors in the input.
# 
#     Attributes:
#         expr -- input expression in which the error occurred
#         msg  -- explanation of the error
#     """
# 
#     def __init__(self, expr, msg):
#         self.expr = expr
#         self.msg = msg
# 
#     def __str__(self):
#         output = 'Incorrect input "{}". {}'.format(self.expr, self.msg)
#         return repr(output)
# 
# Path: paratemp/tools.py
# @contextmanager
# def cd(new_dir):
#     prev_dir = os.getcwd()
#     os.chdir(os.path.expanduser(new_dir))
#     try:
#         yield
#     finally:
#         os.chdir(prev_dir)
# 
# def copy_no_overwrite(src, dst, silent=False):
#     exists = False
#     if os.path.isdir(src):
#         raise OSError(errno.EISDIR, "Is a directory: {}".format(src))
#     elif os.path.isdir(dst):
#         if os.path.isfile(os.path.join(dst, os.path.basename(src))):
#             exists = True
#     elif os.path.isfile(dst):
#         exists = True
#     if exists:
#         if silent:
#             return dst
#         else:
#             raise OSError(errno.EEXIST, "File already exists", dst)
#     else:
#         return shutil.copy(src, dst)


import errno
import glob
import os
import pathlib
import py
import re
import subprocess
import warnings
from typing import Callable, Iterable, Match
from paratemp.tools import _BlankStream
from paratemp.exceptions import InputError
from paratemp.tools import cd, copy_no_overwrite
    from glob import glob
    from gromacs.tools import Trjconv
        This file is not changed.
    :param str n_plu_out: Name of the PLUMED file to be written. This file
        will be overwritten if it already exists.
    :type change_keys: set[str] or Iterable[str]
    :param change_keys: Keywords to look for in lines that should be changed.
        Note, these need to be found space separated in the lines to be changed.
    :type num_updater: Callable[[Match], str]
    :param num_updater: Default: _update_num. A function that takes a
        re.MatchObject and returns a str. The match object will have two (
        three including the full match) groups. The first will be a
        pre-string that should be returned as-is, and the second will be a
        string of an int that should be changed based on how the atom indices
        have changed.
    :type num_updater_kwargs: dict or None
    :param num_updater_kwargs: Default: None. If this is None (default),
        num_updater will be used as is.
        If this is given, the dict will be expanded as kwargs to num_updater.
    :type delete_keys: set[str] or Iterable[str]
    :param delete_keys: Keywords to look for in lines that should be deleted.
        Note, these need to be found space separated in the lines to be deleted.
    :param bool equil: Default: False. If True, other specified changes can be
        made to produce PLUMED input suitable for equilibration before a
        production run
    :param dict equil_changes: Default: None. dict with changes to make for
        equilibration PLUMED input. Note, the keys in this dict must match an
        appropriate key in change_keys for this to work currently.
        In this module, d_equil_repls is an example of a dict for this argument.
    :return: None
    """
    if equil and equil_changes is None:

# Path: paratemp/tools.py
# class _BlankStream(object):
#     """
#     A class for use when not actually wanting to write to a file.
#     """
# 
#     def write(self, string):
#         pass
# 
#     def fileno(self):
#         return 0  # Not sure if this works. Maybe None would be better
# 
#     def flush(self):
#         pass
# 
# Path: paratemp/exceptions.py
# class InputError(Exception):
#     """Exception raised for errors in the input.
# 
#     Attributes:
#         expr -- input expression in which the error occurred
#         msg  -- explanation of the error
#     """
# 
#     def __init__(self, expr, msg):
#         self.expr = expr
#         self.msg = msg
# 
#     def __str__(self):
#         output = 'Incorrect input "{}". {}'.format(self.expr, self.msg)
#         return repr(output)
# 
# Path: paratemp/tools.py
# @contextmanager
# def cd(new_dir):
#     prev_dir = os.getcwd()
#     os.chdir(os.path.expanduser(new_dir))
#     try:
#         yield
#     finally:
#         os.chdir(prev_dir)
# 
# def copy_no_overwrite(src, dst, silent=False):
#     exists = False
#     if os.path.isdir(src):
#         raise OSError(errno.EISDIR, "Is a directory: {}".format(src))
#     elif os.path.isdir(dst):
#         if os.path.isfile(os.path.join(dst, os.path.basename(src))):
#             exists = True
#     elif os.path.isfile(dst):
#         exists = True
#     if exists:
#         if silent:
#             return dst
#         else:
#             raise OSError(errno.EEXIST, "File already exists", dst)
#     else:
#         return shutil.copy(src, dst)


# Path: paratemp/sim_setup/sim_setup.py
import errno
import glob
import os
import pathlib
import py
import re
import subprocess
import warnings
from typing import Callable, Iterable, Match
from paratemp.tools import _BlankStream
from paratemp.exceptions import InputError
from paratemp.tools import cd, copy_no_overwrite
    from glob import glob
    from gromacs.tools import Trjconv

        This file is not changed.
    :param str n_plu_out: Name of the PLUMED file to be written. This file
        will be overwritten if it already exists.
    :type change_keys: set[str] or Iterable[str]
    :param change_keys: Keywords to look for in lines that should be changed.
        Note, these need to be found space separated in the lines to be changed.
    :type num_updater: Callable[[Match], str]
    :param num_updater: Default: _update_num. A function that takes a
        re.MatchObject and returns a str. The match object will have two (
        three including the full match) groups. The first will be a
        pre-string that should be returned as-is, and the second will be a
        string of an int that should be changed based on how the atom indices
        have changed.
    :type num_updater_kwargs: dict or None
    :param num_updater_kwargs: Default: None. If this is None (default),
        num_updater will be used as is.
        If this is given, the dict will be expanded as kwargs to num_updater.
    :type delete_keys: set[str] or Iterable[str]
    :param delete_keys: Keywords to look for in lines that should be deleted.
        Note, these need to be found space separated in the lines to be deleted.
    :param bool equil: Default: False. If True, other specified changes can be
        made to produce PLUMED input suitable for equilibration before a
        production run
    :param dict equil_changes: Default: None. dict with changes to make for
        equilibration PLUMED input. Note, the keys in this dict must match an
        appropriate key in change_keys for this to work currently.
        In this module, d_equil_repls is an example of a dict for this argument.
    :return: None
    """
    if equil and equil_changes is None:

        raise InputError("None", "equil_changes must be defined when equil is " "True")