Skip to content

Patch for shell-command to add --no-parallel option #227

Description

@BernieSumption

Hi,

I have 'watchmedo shell-command' automatically run tests when I save files in my IDE. When I save several files simultaneously, I was getting multiple processes - one per file.

the --wait option prevents multiple processes from running in parallel, but my tests still run multiple times in series, which is also not what I want.

Here's a patch that adds a "--no-parallel" argument. This causes events that arrive while a process is still running to be silently ignored, which is the behaviour that I need.

Patch follows:

diff --git a/src/watchdog/tricks/__init__.py b/src/watchdog/tricks/__init__.py
index d129178..c15f672 100644
--- a/src/watchdog/tricks/__init__.py
+++ b/src/watchdog/tricks/__init__.py
@@ -78,14 +78,20 @@ class ShellCommandTrick(Trick):
     """Execeutes shell commands in response to matched events."""

     def __init__(self, shell_command=None, patterns=None, ignore_patterns=None,
-                 ignore_directories=False, wait_for_process=False):
+                 ignore_directories=False, wait_for_process=False,
+                 no_parallel_processes=False):
         super(ShellCommandTrick, self).__init__(patterns, ignore_patterns,
                                                 ignore_directories)
         self.shell_command = shell_command
         self.wait_for_process = wait_for_process
+        self.no_parallel_processes = no_parallel_processes
+        self.process = None

     def on_any_event(self, event):
         from string import Template
+        
+        if self.no_parallel_processes and self.process and self.process.poll() is None:
+            return

         if event.is_directory:
             object_type = 'directory'
@@ -111,9 +117,9 @@ class ShellCommandTrick(Trick):
             command = self.shell_command

         command = Template(command).safe_substitute(**context)
-        process = subprocess.Popen(command, shell=True)
+        self.process = subprocess.Popen(command, shell=True)
         if self.wait_for_process:
-            process.wait()
+            self.process.wait()


 class AutoRestartTrick(Trick):
diff --git a/src/watchdog/watchmedo.py b/src/watchdog/watchmedo.py
index 53ff21f..e798264 100755
--- a/src/watchdog/watchmedo.py
+++ b/src/watchdog/watchmedo.py
@@ -416,6 +416,11 @@ Example option usage::
      action='store_true',
      default=False,
      help="wait for process to finish to avoid multiple simultaneous instances")
+@arg('-n', '--no-parallel',
+     dest='no_parallel_processes',
+     action='store_true',
+     default=False,
+     help="Ignore events that happen while the previous process is still running")
 def shell_command(args):
     """
     Subcommand to execute shell commands in response to file system events.
@@ -435,7 +440,8 @@ def shell_command(args):
                                 patterns=patterns,
                                 ignore_patterns=ignore_patterns,
                                 ignore_directories=args.ignore_directories,
-                                wait_for_process=args.wait_for_process)
+                                wait_for_process=args.wait_for_process,
+                                no_parallel_processes=args.no_parallel_processes)
     observer = Observer(timeout=args.timeout)
     observe_with(observer, handler, args.directories, args.recursive)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions