def secure_filename(filename):
    r"""Borrowed from :mod:`werkzeug.utils`, under the BSD 3-clause license.

    Pass it a filename and it will return a secure version of it.  This
    filename can then safely be stored on a regular file system and passed
    to :func:`os.path.join`.  The filename returned is an ASCII only string
    for maximum portability.

    On windows systems the function also makes sure that the file is not
    named after one of the special device files.

    >>> secure_filename("My cool movie.mov")
    'My_cool_movie.mov'
    >>> secure_filename("../../../etc/passwd")
    'etc_passwd'
    >>> secure_filename(u'i contain cool \xfcml\xe4uts.txt')
    'i_contain_cool_umlauts.txt'

    The function might return an empty filename.  It's your responsibility
    to ensure that the filename is unique and that you generate random
    filename if the function returned an empty one.

    :param filename: the filename to secure
    """
    _filename_ascii_strip_re = re.compile(r'[^A-Za-z0-9_.-]')
    _windows_device_files = ('CON', 'AUX', 'COM1', 'COM2', 'COM3', 'COM4',
                             'LPT1', 'LPT2', 'LPT3', 'PRN', 'NUL')
    if isinstance(filename, text_type):
        from unicodedata import normalize
        filename = normalize('NFKD', filename).encode('ascii', 'ignore')
        if not PY2:
            filename = filename.decode('ascii')
    for sep in os.path.sep, os.path.altsep:
        if sep:
            filename = filename.replace(sep, ' ')
    filename = str(_filename_ascii_strip_re.sub('', '_'.join(
                   filename.split()))).strip('._')

    # on nt a couple of special files are present in each folder.  We
    # have to ensure that the target file is not such a filename.  In
    # this case we prepend an underline
    if os.name == 'nt' and filename and \
       filename.split('.')[0].upper() in _windows_device_files:
        filename = '_' + filename

    return filename
def find_many_example_files(
        top_directory_name, shuffled=True, first_spc_date_string=None,
        last_spc_date_string=None, first_batch_number=None,
        last_batch_number=None, raise_error_if_any_missing=True):
    """Looks for many files with input examples.

    :param top_directory_name: See doc for `find_example_file`.
    :param shuffled: Same.
    :param first_spc_date_string: [used only if `shuffled = False`]
        First SPC date (format "yyyymmdd").  This method will look for all SPC
        dates from `first_spc_date_string`...`last_spc_date_string`.
    :param last_spc_date_string: See above.
    :param first_batch_number: [used only if `shuffled = True`]
        First batch number (integer).  This method will look for all batches
        from `first_batch_number`...`last_batch_number`.
    :param last_batch_number: See above.
    :param raise_error_if_any_missing: Boolean flag.  If *any* desired file is
        not found and `raise_error_if_any_missing = True`, this method will
        error out.
    :return: example_file_names: 1-D list of paths to example files.
    :raises: ValueError: if no files are found.
    """

    error_checking.assert_is_boolean(shuffled)

    if shuffled:
        error_checking.assert_is_integer(first_batch_number)
        error_checking.assert_is_integer(last_batch_number)
        error_checking.assert_is_geq(first_batch_number, 0)
        error_checking.assert_is_geq(last_batch_number, first_batch_number)

        example_file_pattern = (
            '{0:s}/batches{1:s}-{1:s}/input_examples_batch{1:s}.nc'
        ).format(top_directory_name, BATCH_NUMBER_REGEX)

        example_file_names = glob.glob(example_file_pattern)

        if len(example_file_names) > 0:
            batch_numbers = numpy.array(
                [_file_name_to_batch_number(f) for f in example_file_names],
                dtype=int)
            good_indices = numpy.where(numpy.logical_and(
                batch_numbers >= first_batch_number,
                batch_numbers <= last_batch_number
            ))[0]

            example_file_names = [example_file_names[k] for k in good_indices]

        if len(example_file_names) == 0:
            error_string = (
                'Cannot find any files with batch number from {0:d}...{1:d}.'
            ).format(first_batch_number, last_batch_number)
            raise ValueError(error_string)

        return example_file_names

    spc_date_strings = time_conversion.get_spc_dates_in_range(
        first_spc_date_string=first_spc_date_string,
        last_spc_date_string=last_spc_date_string)

    example_file_names = []
    for this_spc_date_string in spc_date_strings:
        this_file_name = find_example_file(
            top_directory_name=top_directory_name, shuffled=False,
            spc_date_string=this_spc_date_string,
            raise_error_if_missing=raise_error_if_any_missing)

        if not os.path.isfile(this_file_name):
            continue
        example_file_names.append(this_file_name)

    if len(example_file_names) == 0:
        error_string = (
            'Cannot find any file with SPC date from {0:s} to {1:s}.'
        ).format(first_spc_date_string, last_spc_date_string)

        raise ValueError(error_string)

    return example_file_names