Repository: ultrabug/py3status

Issue:
"killall -s USR1 py3status" does nothing
I am trying to include the send signal into my script that lowers and raises the volume. I am using the module volume_status.py. The change in volume works but sending the signal does not refresh the statusbar.

example  command:
`pactl set-sink-volume $(pactl list short sinks|grep RUNNING|awk '{print $1}') -5%`
`killall -s USR1 py3status`

i3config:
`order += "volume_status"`
`volume_status {`
`format = "Vol.: {percentage}%"`
`format_muted = "Vol: mute"`
`device = "pulse"`
`}`

The bar only refreshes after the default 10sec. It is like py3status is completely ignoring the signal. Unfortunately, I don't know how to trace this. Could you please help me out?

"killall -s USR1 py3status" does nothing
I am trying to include the send signal into my script that lowers and raises the volume. I am using the module volume_status.py. The change in volume works but sending the signal does not refresh the statusbar.

example  command:
`pactl set-sink-volume $(pactl list short sinks|grep RUNNING|awk '{print $1}') -5%`
`killall -s USR1 py3status`

i3config:
`order += "volume_status"`
`volume_status {`
`format = "Vol.: {percentage}%"`
`format_muted = "Vol: mute"`
`device = "pulse"`
`}`

The bar only refreshes after the default 10sec. It is like py3status is completely ignoring the signal. Unfortunately, I don't know how to trace this. Could you please help me out?



Discussion:
I think the reason is because run() needs calling on the module for it to update.

See if changing here https://github.com/ultrabug/py3status/blob/master/py3status/core.py#L329 fixes things

```
    def clear_modules_cache(self):
        """
        For every module, reset the 'cached_until' of all its methods.
        """
        for module in self.modules.values():
            module.clear_cache()
```

change to

```
    def clear_modules_cache(self):
        """
        For every module, reset the 'cached_until' of all its methods.
        """
        for module in self.modules.values():
            module.clear_cache()
            module.run()
```

It's not the best place to fix the issue but should  show what's needed

Thanks for reporting @neutronst4r 

@tobes : wouldn't run() here be blocking py3status until all modules refreshed ?

> wouldn't run() here be blocking py3status until all modules refreshed ?

Good question.

I think we need a method that just sets a timer for the modules run().  I'll have a think of a nice solution and do some testing.

I think the reason is because run() needs calling on the module for it to update.

See if changing here https://github.com/ultrabug/py3status/blob/master/py3status/core.py#L329 fixes things

```
    def clear_modules_cache(self):
        """
        For every module, reset the 'cached_until' of all its methods.
        """
        for module in self.modules.values():
            module.clear_cache()
```

change to

```
    def clear_modules_cache(self):
        """
        For every module, reset the 'cached_until' of all its methods.
        """
        for module in self.modules.values():
            module.clear_cache()
            module.run()
```

It's not the best place to fix the issue but should  show what's needed

Thanks for reporting @neutronst4r 

@tobes : wouldn't run() here be blocking py3status until all modules refreshed ?

> wouldn't run() here be blocking py3status until all modules refreshed ?

Good question.

I think we need a method that just sets a timer for the modules run().  I'll have a think of a nice solution and do some testing.


Resolving patch:
diff --git a/py3status/core.py b/py3status/core.py
--- a/py3status/core.py
+++ b/py3status/core.py
@@ -353,7 +353,7 @@ def clear_modules_cache(self):
         For every module, reset the 'cached_until' of all its methods.
         """
         for module in self.modules.values():
-            module.clear_cache()
+            module.force_update()
 
     def terminate(self, signum, frame):
         """
@@ -379,8 +379,7 @@ def notify_update(self, update):
         for group in groups_to_update:
             group_module = self.output_modules.get(group)
             if group_module:
-                group_module['module'].clear_cache()
-                group_module['module'].run()
+                group_module['module'].force_update()
 
     def create_output_modules(self):
         """
diff --git a/py3status/events.py b/py3status/events.py
--- a/py3status/events.py
+++ b/py3status/events.py
@@ -111,10 +111,7 @@ def refresh(self, module_name):
         if module is not None:
             if self.config['debug']:
                 syslog(LOG_INFO, 'refresh module {}'.format(module_name))
-            for obj in module.methods.values():
-                obj['cached_until'] = time()
-            # get module to update
-            module.run()
+            module.force_update()
         else:
             if time() > (self.last_refresh_ts + 0.1):
                 if self.config['debug']:
diff --git a/py3status/module.py b/py3status/module.py
--- a/py3status/module.py
+++ b/py3status/module.py
@@ -75,14 +75,21 @@ def load_from_namespace(module_name):
         class_inst = py_mod.Py3status()
         return class_inst
 
-    def clear_cache(self):
+    def force_update(self):
         """
-        Reset the cache for all methods of this module.
+        Forces an update of the module.
         """
+        # clear cached_until for each method to allow update
         for meth in self.methods:
             self.methods[meth]['cached_until'] = time()
             if self.config['debug']:
                 syslog(LOG_INFO, 'clearing cache for method {}'.format(meth))
+        # cancel any existing timer
+        if self.timer:
+            self.timer.cancel()
+        # get the thread to update itself
+        self.timer = Timer(0, self.run)
+        self.timer.start()
 
     def set_updated(self):
         """


Test patch: