# Path: monty/dev.py
# def deprecated(replacement=None, message=None, category=FutureWarning):
#     """
#     Decorator to mark classes or functions as deprecated,
#     with a possible replacement.
# 
#     Args:
#         replacement (callable): A replacement class or method.
#         message (str): A warning message to be displayed.
#         category (Warning): Choose the category of the warning to issue. Defaults
#             to FutureWarning. Another choice can be DeprecationWarning. NOte that
#             FutureWarning is meant for end users and is always shown unless silenced.
#             DeprecationWarning is meant for developers and is never shown unless
#             python is run in developmental mode or the filter is changed. Make
#             the choice accordingly.
# 
#     Returns:
#         Original function, but with a warning to use the updated class.
#     """
# 
#     def wrap(old):
#         def wrapped(*args, **kwargs):
#             msg = f"{old.__name__} is deprecated"
#             if replacement is not None:
#                 if isinstance(replacement, property):
#                     r = replacement.fget
#                 elif isinstance(replacement, (classmethod, staticmethod)):
#                     r = replacement.__func__
#                 else:
#                     r = replacement
#                 msg += f"; use {r.__name__} in {r.__module__} instead."
#             if message is not None:
#                 msg += "\n" + message
#             warnings.warn(msg, category=category, stacklevel=2)
#             return old(*args, **kwargs)
# 
#         return wrapped
# 
#     return wrap
# 
# Path: monty/fnmatch.py
# class WildCard:
#     """
#     This object provides an easy-to-use interface for filename matching with
#     shell patterns (fnmatch).
# 
#     >>> w = WildCard("*.nc|*.pdf")
#     >>> w.filter(["foo.nc", "bar.pdf", "hello.txt"])
#     ['foo.nc', 'bar.pdf']
# 
#     >>> w.filter("foo.nc")
#     ['foo.nc']
#     """
# 
#     def __init__(self, wildcard, sep="|"):
#         """
#         Initializes a WildCard.
# 
#         Args:
#             wildcard (str): String of tokens separated by sep. Each token
#                 represents a pattern.
#             sep (str): Separator for shell patterns.
#         """
#         self.pats = ["*"]
#         if wildcard:
#             self.pats = wildcard.split(sep)
# 
#     def __str__(self):
#         return f"<{self.__class__.__name__}, patterns = {self.pats}>"
# 
#     def filter(self, names):
#         """
#         Returns a list with the names matching the pattern.
#         """
#         names = list_strings(names)
# 
#         fnames = []
#         for f in names:
#             for pat in self.pats:
#                 if fnmatch.fnmatch(f, pat):
#                     fnames.append(f)
# 
#         return fnames
# 
#     def match(self, name):
#         """
#         Returns True if name matches one of the patterns.
#         """
#         for pat in self.pats:
#             if fnmatch.fnmatch(name, pat):
#                 return True
# 
#         return False
# 
# Path: monty/string.py
# def list_strings(arg):
#     """
#     Always return a list of strings, given a string or list of strings as
#     input.
# 
#     :Examples:
# 
#     >>> list_strings('A single string')
#     ['A single string']
# 
#     >>> list_strings(['A single string in a list'])
#     ['A single string in a list']
# 
#     >>> list_strings(['A','list','of','strings'])
#     ['A', 'list', 'of', 'strings']
#     """
#     if is_string(arg):
#         return [arg]
# 
#     return arg


import os
import shutil
from monty.dev import deprecated
from monty.fnmatch import WildCard
from monty.string import list_strings
        match_mode (str): "basename" if  match should be done on the basename.
            "abspath" for absolute path.

    Returns:
        (list of str): Absolute paths of the files.

    Examples::

        # Find all pdf and ps files starting from the current directory.
        find_exts(".", ("pdf", "ps"))

        # Find all pdf files, exclude hidden directories and dirs whose name
        # starts with `_`
        find_exts(".", "pdf", exclude_dirs="_*|.*")

        # Find all ps files, in the directories whose basename starts with
        # output.
        find_exts(".", "ps", include_dirs="output*"))
    """
    exts = list_strings(exts)

    # Handle file!
    if os.path.isfile(top):
        return [os.path.abspath(top)] if any(top.endswith(ext) for ext in exts) else []

    # Build shell-style wildcards.
    if exclude_dirs is not None:
        exclude_dirs = WildCard(exclude_dirs)

    if include_dirs is not None:

# Path: monty/dev.py
# def deprecated(replacement=None, message=None, category=FutureWarning):
#     """
#     Decorator to mark classes or functions as deprecated,
#     with a possible replacement.
# 
#     Args:
#         replacement (callable): A replacement class or method.
#         message (str): A warning message to be displayed.
#         category (Warning): Choose the category of the warning to issue. Defaults
#             to FutureWarning. Another choice can be DeprecationWarning. NOte that
#             FutureWarning is meant for end users and is always shown unless silenced.
#             DeprecationWarning is meant for developers and is never shown unless
#             python is run in developmental mode or the filter is changed. Make
#             the choice accordingly.
# 
#     Returns:
#         Original function, but with a warning to use the updated class.
#     """
# 
#     def wrap(old):
#         def wrapped(*args, **kwargs):
#             msg = f"{old.__name__} is deprecated"
#             if replacement is not None:
#                 if isinstance(replacement, property):
#                     r = replacement.fget
#                 elif isinstance(replacement, (classmethod, staticmethod)):
#                     r = replacement.__func__
#                 else:
#                     r = replacement
#                 msg += f"; use {r.__name__} in {r.__module__} instead."
#             if message is not None:
#                 msg += "\n" + message
#             warnings.warn(msg, category=category, stacklevel=2)
#             return old(*args, **kwargs)
# 
#         return wrapped
# 
#     return wrap
# 
# Path: monty/fnmatch.py
# class WildCard:
#     """
#     This object provides an easy-to-use interface for filename matching with
#     shell patterns (fnmatch).
# 
#     >>> w = WildCard("*.nc|*.pdf")
#     >>> w.filter(["foo.nc", "bar.pdf", "hello.txt"])
#     ['foo.nc', 'bar.pdf']
# 
#     >>> w.filter("foo.nc")
#     ['foo.nc']
#     """
# 
#     def __init__(self, wildcard, sep="|"):
#         """
#         Initializes a WildCard.
# 
#         Args:
#             wildcard (str): String of tokens separated by sep. Each token
#                 represents a pattern.
#             sep (str): Separator for shell patterns.
#         """
#         self.pats = ["*"]
#         if wildcard:
#             self.pats = wildcard.split(sep)
# 
#     def __str__(self):
#         return f"<{self.__class__.__name__}, patterns = {self.pats}>"
# 
#     def filter(self, names):
#         """
#         Returns a list with the names matching the pattern.
#         """
#         names = list_strings(names)
# 
#         fnames = []
#         for f in names:
#             for pat in self.pats:
#                 if fnmatch.fnmatch(f, pat):
#                     fnames.append(f)
# 
#         return fnames
# 
#     def match(self, name):
#         """
#         Returns True if name matches one of the patterns.
#         """
#         for pat in self.pats:
#             if fnmatch.fnmatch(name, pat):
#                 return True
# 
#         return False
# 
# Path: monty/string.py
# def list_strings(arg):
#     """
#     Always return a list of strings, given a string or list of strings as
#     input.
# 
#     :Examples:
# 
#     >>> list_strings('A single string')
#     ['A single string']
# 
#     >>> list_strings(['A single string in a list'])
#     ['A single string in a list']
# 
#     >>> list_strings(['A','list','of','strings'])
#     ['A', 'list', 'of', 'strings']
#     """
#     if is_string(arg):
#         return [arg]
# 
#     return arg


# Path: monty/os/path.py
import os
import shutil
from monty.dev import deprecated
from monty.fnmatch import WildCard
from monty.string import list_strings

        match_mode (str): "basename" if  match should be done on the basename.
            "abspath" for absolute path.

    Returns:
        (list of str): Absolute paths of the files.

    Examples::

        # Find all pdf and ps files starting from the current directory.
        find_exts(".", ("pdf", "ps"))

        # Find all pdf files, exclude hidden directories and dirs whose name
        # starts with `_`
        find_exts(".", "pdf", exclude_dirs="_*|.*")

        # Find all ps files, in the directories whose basename starts with
        # output.
        find_exts(".", "ps", include_dirs="output*"))
    """
    exts = list_strings(exts)

    # Handle file!
    if os.path.isfile(top):
        return [os.path.abspath(top)] if any(top.endswith(ext) for ext in exts) else []

    # Build shell-style wildcards.
    if exclude_dirs is not None:
        exclude_dirs = WildCard(exclude_dirs)

    if include_dirs is not None:

        include_dirs = WildCard(include_dirs)