3.12: Move code around
This commit is contained in:
parent
19aca9149a
commit
b42cd6aa15
@ -3,14 +3,14 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .core import Status
|
from .core import Status
|
||||||
from .core.modules import Module, AsyncModule, IntervalModule
|
from .core.modules import Module, IntervalModule
|
||||||
from .core.settings import SettingsBase
|
from .core.settings import SettingsBase
|
||||||
from .core.config import ConfigFinder
|
from .core.config import ConfigFinder
|
||||||
from .core.render import render_json
|
from .core.render import render_json
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"SettingsBase",
|
"SettingsBase",
|
||||||
"Module", "AsyncModule", "IntervalModule",
|
"Module", "IntervalModule",
|
||||||
"Status",
|
"Status",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -25,7 +25,6 @@ def test_config():
|
|||||||
def run(self):
|
def run(self):
|
||||||
self.call_start_hooks()
|
self.call_start_hooks()
|
||||||
for module in self.modules:
|
for module in self.modules:
|
||||||
|
|
||||||
sys.stdout.write("{module}: ".format(module=module.__name__))
|
sys.stdout.write("{module}: ".format(module=module.__name__))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
module.run()
|
module.run()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import threading
|
|
||||||
import os
|
import os
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
from . import io, util
|
from . import io, util
|
||||||
from .modules import Module, START_HOOKS
|
from .modules import Module, START_HOOKS
|
||||||
@ -11,7 +11,7 @@ class Status:
|
|||||||
self.standalone = standalone
|
self.standalone = standalone
|
||||||
if standalone:
|
if standalone:
|
||||||
self.io = io.StandaloneIO(interval)
|
self.io = io.StandaloneIO(interval)
|
||||||
self.ce_thread = threading.Thread(target=self.run_command_endpoint)
|
self.ce_thread = Thread(target=self.run_command_endpoint)
|
||||||
self.ce_thread.daemon = True
|
self.ce_thread.daemon = True
|
||||||
self.ce_thread.start()
|
self.ce_thread.start()
|
||||||
else:
|
else:
|
||||||
|
@ -51,7 +51,7 @@ class StandaloneIO(IOHandler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
n = -1
|
n = -1
|
||||||
proto = ('{"version":1,"bidirectional":true}', "[", "[]", ",[]", )
|
proto = ('{"version":1,"bidirectional":true}', "[", "[]", ",[]",)
|
||||||
|
|
||||||
def __init__(self, interval=1):
|
def __init__(self, interval=1):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from threading import Thread
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from .settings import SettingsBase
|
from .settings import SettingsBase
|
||||||
from .threads import AutomagicManager
|
from .threading import Manager
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Module", "AsyncModule", "IntervalModule",
|
"Module", "AsyncModule", "IntervalModule",
|
||||||
@ -36,15 +36,6 @@ class Module(SettingsBase):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
class AsyncModule(Module):
|
|
||||||
def registered(self, status_handler):
|
|
||||||
self.thread = Thread(target=self.mainloop)
|
|
||||||
self.thread.daemon = True
|
|
||||||
self.thread.start()
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
"""This is run in a separate daemon-thread"""
|
|
||||||
|
|
||||||
class IntervalModule(Module):
|
class IntervalModule(Module):
|
||||||
interval = 5 # seconds
|
interval = 5 # seconds
|
||||||
managers = {}
|
managers = {}
|
||||||
@ -53,7 +44,7 @@ class IntervalModule(Module):
|
|||||||
if self.interval in IntervalModule.managers:
|
if self.interval in IntervalModule.managers:
|
||||||
IntervalModule.managers[self.interval].append(self)
|
IntervalModule.managers[self.interval].append(self)
|
||||||
else:
|
else:
|
||||||
am = AutomagicManager(self.interval)
|
am = Manager(self.interval)
|
||||||
am.append(self)
|
am.append(self)
|
||||||
IntervalModule.managers[self.interval] = am
|
IntervalModule.managers[self.interval] = am
|
||||||
|
|
||||||
|
2
i3pystatus/core/threading/__init__.py
Normal file
2
i3pystatus/core/threading/__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
from .manager import Manager
|
49
i3pystatus/core/threading/manager.py
Normal file
49
i3pystatus/core/threading/manager.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
from ..util import partition
|
||||||
|
from . import threads, wrapper
|
||||||
|
|
||||||
|
class Manager:
|
||||||
|
def __init__(self, target_interval):
|
||||||
|
self.target_interval = target_interval
|
||||||
|
self.upper_bound = target_interval * 1.1
|
||||||
|
self.lower_bound = target_interval * 0.7
|
||||||
|
|
||||||
|
initial_thread = threads.Thread(target_interval, [self.wrap(self)])
|
||||||
|
self.threads = [initial_thread]
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
separate = []
|
||||||
|
for thread in self.threads:
|
||||||
|
separate.extend(self.branch(thread, thread.time))
|
||||||
|
self.create_threads(self.partition(separate))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Manager"
|
||||||
|
|
||||||
|
def wrap(self, workload):
|
||||||
|
return wrapper.WorkloadWrapper(wrapper.ExceptionWrapper(workload))
|
||||||
|
|
||||||
|
def branch(self, thread, vtime):
|
||||||
|
if len(thread) > 1 and vtime > self.upper_bound:
|
||||||
|
remove = thread.pop()
|
||||||
|
return [remove] + self.branch(thread, vtime - remove.time)
|
||||||
|
return []
|
||||||
|
|
||||||
|
def partition(self, workloads):
|
||||||
|
return partition(workloads, self.lower_bound, lambda workload: workload.time)
|
||||||
|
|
||||||
|
def create_threads(self, threads):
|
||||||
|
for workloads in threads:
|
||||||
|
self.create_thread(workloads)
|
||||||
|
|
||||||
|
def create_thread(self, workloads):
|
||||||
|
thread = threads.Thread(self.target_interval, workloads, start_barrier=0)
|
||||||
|
thread.start()
|
||||||
|
self.threads.append(thread)
|
||||||
|
|
||||||
|
def append(self, workload):
|
||||||
|
self.threads[0].append(self.wrap(workload))
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
for thread in self.threads:
|
||||||
|
thread.start()
|
53
i3pystatus/core/threading/threads.py
Normal file
53
i3pystatus/core/threading/threads.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
try:
|
||||||
|
from setproctitle import setproctitle
|
||||||
|
except ImportError:
|
||||||
|
def setproctitle(title):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Thread(threading.Thread):
|
||||||
|
def __init__(self, target_interval, workloads=None, start_barrier=1):
|
||||||
|
super().__init__()
|
||||||
|
self.workloads = workloads or []
|
||||||
|
self.target_interval = target_interval
|
||||||
|
self.start_barrier = start_barrier
|
||||||
|
self.daemon = True
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.workloads)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.workloads)
|
||||||
|
|
||||||
|
def pop(self):
|
||||||
|
return self.workloads.pop()
|
||||||
|
|
||||||
|
def append(self, workload):
|
||||||
|
self.workloads.append(workload)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def time(self):
|
||||||
|
return sum(map(lambda workload: workload.time, self))
|
||||||
|
|
||||||
|
def wait_for_start_barrier(self):
|
||||||
|
while len(self) <= self.start_barrier:
|
||||||
|
time.sleep(0.4)
|
||||||
|
|
||||||
|
def setproctitle(self):
|
||||||
|
setproctitle("i3pystatus {name}: {workloads}".format(name=self.name, workloads=list(map(repr, self.workloads))))
|
||||||
|
|
||||||
|
def execute_workloads(self):
|
||||||
|
for workload in self:
|
||||||
|
workload()
|
||||||
|
self.workloads.sort(key=lambda workload: workload.time)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.setproctitle()
|
||||||
|
while self:
|
||||||
|
self.execute_workloads()
|
||||||
|
filltime = self.target_interval - self.time
|
||||||
|
if filltime > 0:
|
||||||
|
time.sleep(filltime)
|
30
i3pystatus/core/threading/wrapper.py
Normal file
30
i3pystatus/core/threading/wrapper.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
timer = time.perf_counter if hasattr(time, "perf_counter") else time.clock
|
||||||
|
|
||||||
|
class Wrapper:
|
||||||
|
def __init__(self, workload):
|
||||||
|
self.workload = workload
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return repr(self.workload)
|
||||||
|
|
||||||
|
class ExceptionWrapper(Wrapper):
|
||||||
|
def __call__(self):
|
||||||
|
try:
|
||||||
|
self.workload()
|
||||||
|
except Exception as exc:
|
||||||
|
sys.stderr.write("Exception in {thread}".format(thread=threading.current_thread().name))
|
||||||
|
traceback.print_exception(*sys.exc_info(), file=sys.stderr)
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
class WorkloadWrapper(Wrapper):
|
||||||
|
time = 0.0
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
tp1 = timer()
|
||||||
|
self.workload()
|
||||||
|
self.time = timer() - tp1
|
@ -1,131 +0,0 @@
|
|||||||
import sys
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from .util import partition
|
|
||||||
|
|
||||||
try:
|
|
||||||
from setproctitle import setproctitle
|
|
||||||
except ImportError:
|
|
||||||
def setproctitle(title):
|
|
||||||
pass
|
|
||||||
|
|
||||||
timer = time.perf_counter if hasattr(time, "perf_counter") else time.clock
|
|
||||||
|
|
||||||
class Wrapper:
|
|
||||||
def __init__(self, workload):
|
|
||||||
self.workload = workload
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return repr(self.workload)
|
|
||||||
|
|
||||||
class ExceptionWrapper(Wrapper):
|
|
||||||
def __call__(self):
|
|
||||||
try:
|
|
||||||
self.workload()
|
|
||||||
except Exception as exc:
|
|
||||||
sys.stderr.write("Exception in {thread}".format(thread=threading.current_thread().name))
|
|
||||||
traceback.print_exception(*sys.exc_info(), file=sys.stderr)
|
|
||||||
sys.stderr.flush()
|
|
||||||
|
|
||||||
class WorkloadWrapper(Wrapper):
|
|
||||||
time = 0.0
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
tp1 = timer()
|
|
||||||
self.workload()
|
|
||||||
self.time = timer() - tp1
|
|
||||||
|
|
||||||
class Thread(threading.Thread):
|
|
||||||
def __init__(self, target_interval, workloads=None, start_barrier=1):
|
|
||||||
super().__init__()
|
|
||||||
self.workloads = workloads or []
|
|
||||||
self.target_interval = target_interval
|
|
||||||
self.start_barrier = start_barrier
|
|
||||||
self.daemon = True
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return iter(self.workloads)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.workloads)
|
|
||||||
|
|
||||||
def pop(self):
|
|
||||||
return self.workloads.pop()
|
|
||||||
|
|
||||||
def append(self, workload):
|
|
||||||
self.workloads.append(workload)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def time(self):
|
|
||||||
return sum(map(lambda workload: workload.time, self))
|
|
||||||
|
|
||||||
def wait_for_start_barrier(self):
|
|
||||||
while len(self) <= self.start_barrier:
|
|
||||||
time.sleep(0.4)
|
|
||||||
|
|
||||||
def setproctitle(self):
|
|
||||||
setproctitle("i3pystatus {name}: {workloads}".format(name=self.name, workloads=list(map(repr, self.workloads))))
|
|
||||||
|
|
||||||
def execute_workloads(self):
|
|
||||||
for workload in self:
|
|
||||||
workload()
|
|
||||||
self.workloads.sort(key=lambda workload: workload.time)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.setproctitle()
|
|
||||||
while self:
|
|
||||||
self.execute_workloads()
|
|
||||||
filltime = self.target_interval - self.time
|
|
||||||
if filltime > 0:
|
|
||||||
time.sleep(filltime)
|
|
||||||
|
|
||||||
class AutomagicManager:
|
|
||||||
def __init__(self, target_interval):
|
|
||||||
self.target_interval = target_interval
|
|
||||||
self.upper_bound = target_interval * 1.1
|
|
||||||
self.lower_bound = target_interval * 0.7
|
|
||||||
|
|
||||||
initial_thread = Thread(target_interval, [self.wrap(self)])
|
|
||||||
self.threads = [initial_thread]
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
separate = []
|
|
||||||
for thread in self.threads:
|
|
||||||
separate.extend(self.branch(thread, thread.time))
|
|
||||||
self.create_threads(self.partition(separate))
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Manager"
|
|
||||||
|
|
||||||
def wrap(self, workload):
|
|
||||||
return WorkloadWrapper(ExceptionWrapper(workload))
|
|
||||||
|
|
||||||
# def calculate_sparse_times():
|
|
||||||
# return ((self.lower_bound - thread.time, thread) for thread in self.threads)
|
|
||||||
|
|
||||||
def branch(self, thread, vtime):
|
|
||||||
if len(thread) > 1 and vtime > self.upper_bound:
|
|
||||||
remove = thread.pop()
|
|
||||||
return [remove] + self.branch(thread, vtime - remove.time)
|
|
||||||
return []
|
|
||||||
|
|
||||||
def partition(self, workloads):
|
|
||||||
return partition(workloads, self.lower_bound, lambda workload: workload.time)
|
|
||||||
|
|
||||||
def create_threads(self, threads):
|
|
||||||
for workloads in threads:
|
|
||||||
self.create_thread(workloads)
|
|
||||||
|
|
||||||
def create_thread(self, workloads):
|
|
||||||
thread = Thread(self.target_interval, workloads, start_barrier=0)
|
|
||||||
thread.start()
|
|
||||||
self.threads.append(thread)
|
|
||||||
|
|
||||||
def append(self, workload):
|
|
||||||
self.threads[0].append(self.wrap(workload))
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
for thread in self.threads:
|
|
||||||
thread.start()
|
|
@ -5,10 +5,6 @@ import itertools
|
|||||||
from .exceptions import *
|
from .exceptions import *
|
||||||
from .imputil import ClassFinder
|
from .imputil import ClassFinder
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"ModuleList", "KeyConstraintDict", "PrefixedKeyDict",
|
|
||||||
]
|
|
||||||
|
|
||||||
def lchop(string, prefix):
|
def lchop(string, prefix):
|
||||||
if string.startswith(prefix):
|
if string.startswith(prefix):
|
||||||
return string[len(prefix):]
|
return string[len(prefix):]
|
||||||
|
@ -5,9 +5,11 @@ from i3pystatus import IntervalModule
|
|||||||
|
|
||||||
class RunWatch(IntervalModule):
|
class RunWatch(IntervalModule):
|
||||||
"""
|
"""
|
||||||
Expands the given path using glob to a pidfile and checks if the process ID found inside is valid
|
Expands the given path using glob to a pidfile and checks
|
||||||
|
if the process ID found inside is valid
|
||||||
(that is, if the process is running).
|
(that is, if the process is running).
|
||||||
You can use this to check if a specific application, such as a VPN client or your DHCP client is running.
|
You can use this to check if a specific application,
|
||||||
|
such as a VPN client or your DHCP client is running.
|
||||||
|
|
||||||
Available formatters are {pid} and {name}.
|
Available formatters are {pid} and {name}.
|
||||||
"""
|
"""
|
||||||
|
7
setup.py
7
setup.py
@ -16,7 +16,12 @@ setup(name="i3pystatus",
|
|||||||
"Topic :: Desktop Environment :: Window Managers",
|
"Topic :: Desktop Environment :: Window Managers",
|
||||||
],
|
],
|
||||||
|
|
||||||
packages=["i3pystatus", "i3pystatus.core", "i3pystatus.mail"],
|
packages=[
|
||||||
|
"i3pystatus",
|
||||||
|
"i3pystatus.core",
|
||||||
|
"i3pystatus.core.threading",
|
||||||
|
"i3pystatus.mail"
|
||||||
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": ["i3pystatus = i3pystatus:main"],
|
"console_scripts": ["i3pystatus = i3pystatus:main"],
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user