"""
 
 from argparse import ArgumentParser, ArgumentTypeError
-from os.path import isfile
+from os.path import isfile, isdir
 
 
 class ArgParserWantsExit(Exception):
 class NonExitingParser(ArgumentParser):
     """ArgumentParser that does not call sys.exit(2) on parse failure.
 
-    Calling sys.exit also just raises a SystemExit exception. But that is not
+    Calling `sys.exit` also just raises a SystemExit exception. But that is not
     a subclass of Exception and not as explicit and specific as this one.
 
     Convenient e.g. for global try-except blocks e.g. in a daemon::
     if not filename.strip():
         return ''
     return existing_file(filename)
+
+
+def existing_dir(path):
+    """
+    Function that raises ArgumentTypeError if argument is not an existing directory.
+
+    .. seealso:: :py:func:`existing_file`, :py:func:`existing_dir_or_empty`
+    """
+    if isdir(path):
+        return path
+    raise ArgumentTypeError('{} is not an existing directory'.format(path))
+
+
+def existing_dir_or_empty(path=''):
+    """
+    Like :py:func:`existing_dir` but accepts empty path (returns '' then).
+    """
+    if not path.strip():
+        return ''
+    return existing_dir(path)
 
 
 import unittest
 import os
-from os.path import isfile
-from tempfile import mkstemp
+from os.path import isfile, isdir
+from shutil import rmtree
+from tempfile import mkstemp, mkdtemp
 
 # relative import of tested module ensures we do not test installed version
 try:
             # test with existing file
             parser = argparse_helpers.NonExitingParser()
             parser.add_argument('--input', type=argparse_helpers.existing_file)
+            parser.add_argument('--input2', type=argparse_helpers.existing_file_or_empty)
+            parser.parse_args(['--input', temp_file, '--input2', temp_file])
         finally:
             if temp_handle:
                 os.close(temp_handle)
                                parser.parse_args,
                                ['--input', temp_file, ])
 
+    def test_existing_dir(self):
+        temp_dir = None
+        try:
+            # create a dir
+            temp_dir = mkdtemp()
+
+            # test with existing dir
+            parser = argparse_helpers.NonExitingParser()
+            parser.add_argument('--input', type=argparse_helpers.existing_dir)
+            parser.add_argument('--input2', type=argparse_helpers.existing_dir_or_empty)
+            parser.parse_args(['--input', temp_dir, '--input2', temp_dir])
+        finally:
+            if temp_dir and isdir(temp_dir):
+                rmtree(temp_dir)
+
+        # test with non-existing dir
+        self.assertRaisesRegex(argparse_helpers.ArgParserWantsExit,
+                               'is not an existing directory',
+                               parser.parse_args,
+                               ['--input', temp_dir, ])
+
+    def test_allow_empty(self):
+        parser = argparse_helpers.NonExitingParser()
+        parser.add_argument('--file', type=argparse_helpers.existing_file_or_empty)
+        parser.add_argument('--dir', type=argparse_helpers.existing_dir_or_empty)
+
+        # both emtpy: no problem
+        parser.parse_args(['--file', '', '--dir', ''])
+
+        # test with non-existing file/dir
+        self.assertRaisesRegex(argparse_helpers.ArgParserWantsExit,
+                               'is not an existing file',
+                               parser.parse_args,
+                               ['--dir', '', '--file', 'not-an-existing-file'])
+        self.assertRaisesRegex(argparse_helpers.ArgParserWantsExit,
+                               'is not an existing directory',
+                               parser.parse_args,
+                               ['--file', '', '--dir', 'not-an-existing-dir'])
+
+
 if __name__ == '__main__':
     unittest.main()