Ejemplo n.º 1
0
    def setup(self):
        """
        Setup py3status and spawn i3status/events/modules threads.
        """

        # SIGTSTP will be received from i3bar indicating that all output should
        # stop and we should consider py3status suspended.  It is however
        # important that any processes using i3 ipc should continue to receive
        # those events otherwise it can lead to a stall in i3.
        signal(SIGTSTP, self.i3bar_stop)
        # SIGCONT indicates output should be resumed.
        signal(SIGCONT, self.i3bar_start)

        # log py3status and python versions
        self.log("=" * 8)
        msg = "Starting py3status version {version} python {python_version}"
        self.log(msg.format(**self.config))

        try:
            # if running from git then log the branch and last commit
            # we do this by looking in the .git directory
            git_path = os.path.join(os.path.dirname(__file__), "..", ".git")
            # branch
            with open(os.path.join(git_path, "HEAD"), "r") as f:
                out = f.readline()
            branch = "/".join(out.strip().split("/")[2:])
            self.log("git branch: {}".format(branch))
            # last commit
            log_path = os.path.join(git_path, "logs", "refs", "heads", branch)
            with open(log_path, "r") as f:
                out = f.readlines()[-1]
            sha = out.split(" ")[1][:7]
            msg = ":".join(out.strip().split("\t")[-1].split(":")[1:])
            self.log("git commit: {}{}".format(sha, msg))
        except:  # noqa e722
            pass

        self.log("window manager: {}".format(self.config["wm_name"]))

        if self.config["debug"]:
            self.log("py3status started with config {}".format(self.config))

        if self.config["gevent"]:
            self.gevent_monkey_patch_report()

        # read i3status.conf
        config_path = self.config["i3status_config_path"]
        self.log("config file: {}".format(self.config["i3status_config_path"]))
        self.config["py3_config"] = process_config(config_path, self)

        # setup i3status thread
        self.i3status_thread = I3status(self)

        # If standalone or no i3status modules then use the mock i3status
        # else start i3status thread.
        i3s_modules = self.config["py3_config"]["i3s_modules"]
        if self.config["standalone"] or not i3s_modules:
            self.i3status_thread.mock()
            i3s_mode = "mocked"
        else:
            i3s_mode = "started"
            self.i3status_thread.start()
            while not self.i3status_thread.ready:
                if not self.i3status_thread.is_alive():
                    # i3status is having a bad day, so tell the user what went
                    # wrong and do the best we can with just py3status modules.
                    err = self.i3status_thread.error
                    self.notify_user(err)
                    self.i3status_thread.mock()
                    i3s_mode = "mocked"
                    break
                time.sleep(0.1)
        if self.config["debug"]:
            self.log("i3status thread {} with config {}".format(
                i3s_mode, self.config["py3_config"]))

        # add i3status thread monitoring task
        if i3s_mode == "started":
            task = CheckI3StatusThread(self.i3status_thread, self)
            self.timeout_queue_add(task)

        # setup input events thread
        self.events_thread = Events(self)
        self.events_thread.daemon = True
        self.events_thread.start()
        if self.config["debug"]:
            self.log("events thread started")

        # initialise the command server
        self.commands_thread = CommandServer(self)
        self.commands_thread.daemon = True
        self.commands_thread.start()
        if self.config["debug"]:
            self.log("commands thread started")

        # initialize the udev monitor (lazy)
        self.udev_monitor = UdevMonitor(self)

        # suppress modules' ouput wrt issue #20
        if not self.config["debug"]:
            sys.stdout = open("/dev/null", "w")
            sys.stderr = open("/dev/null", "w")

        # get the list of py3status configured modules
        self.py3_modules = self.config["py3_config"]["py3_modules"]

        # get a dict of all user provided modules
        self.log("modules include paths: {}".format(
            self.config["include_paths"]))
        user_modules = self.get_user_configured_modules()
        if self.config["debug"]:
            self.log("user_modules={}".format(user_modules))

        if self.py3_modules:
            # load and spawn i3status.conf configured modules threads
            self.load_modules(self.py3_modules, user_modules)
Ejemplo n.º 2
0
    def setup(self):
        """
        Setup py3status and spawn i3status/events/modules threads.
        """

        # log py3status and python versions
        self.log("=" * 8)
        msg = "Starting py3status version {version} python {python_version}"
        self.log(msg.format(**self.config))

        try:
            # if running from git then log the branch and last commit
            # we do this by looking in the .git directory
            git_path = Path(__file__).resolve().parent.parent / ".git"
            # branch
            with (git_path / "HEAD").open() as f:
                out = f.readline()
            branch = "/".join(out.strip().split("/")[2:])
            self.log(f"git branch: {branch}")
            # last commit
            log_path = git_path / "logs" / "refs" / "heads" / branch
            with log_path.open() as f:
                out = f.readlines()[-1]
            sha = out.split(" ")[1][:7]
            msg = ":".join(out.strip().split("\t")[-1].split(":")[1:])
            self.log(f"git commit: {sha}{msg}")
        except:  # noqa e722
            pass

        self.log("window manager: {}".format(self.config["wm_name"]))

        if self.config["debug"]:
            self.log(f"py3status started with config {self.config}")

        if self.config["gevent"]:
            self.is_gevent = self.gevent_monkey_patch_report()
        else:
            self.is_gevent = False

        # read i3status.conf
        config_path = self.config["i3status_config_path"]
        self.log("config file: {}".format(self.config["i3status_config_path"]))
        self.config["py3_config"] = process_config(config_path, self)

        # read resources
        if "resources" in str(self.config["py3_config"].values()):
            from subprocess import check_output

            resources = check_output(["xrdb", "-query"]).decode().splitlines()
            self.config["resources"] = {
                k: v.strip()
                for k, v in (x.split(":", 1) for x in resources)
            }

        # setup i3status thread
        self.i3status_thread = I3status(self)

        # If standalone or no i3status modules then use the mock i3status
        # else start i3status thread.
        i3s_modules = self.config["py3_config"]["i3s_modules"]
        if self.config["standalone"] or not i3s_modules:
            self.i3status_thread.mock()
            i3s_mode = "mocked"
        else:
            for module in i3s_modules:
                self.log(f"adding module {module}")
            i3s_mode = "started"
            self.i3status_thread.start()
            while not self.i3status_thread.ready:
                if not self.i3status_thread.is_alive():
                    # i3status is having a bad day, so tell the user what went
                    # wrong and do the best we can with just py3status modules.
                    err = self.i3status_thread.error
                    self.notify_user(err)
                    self.i3status_thread.mock()
                    i3s_mode = "mocked"
                    break
                time.sleep(0.1)
        if self.config["debug"]:
            self.log("i3status thread {} with config {}".format(
                i3s_mode, self.config["py3_config"]))

        # add i3status thread monitoring task
        if i3s_mode == "started":
            task = CheckI3StatusThread(self.i3status_thread, self)
            self.timeout_queue_add(task)

        # setup input events thread
        self.events_thread = Events(self)
        self.events_thread.daemon = True
        self.events_thread.start()
        if self.config["debug"]:
            self.log("events thread started")

        # initialise the command server
        self.commands_thread = CommandServer(self)
        self.commands_thread.daemon = True
        self.commands_thread.start()
        if self.config["debug"]:
            self.log("commands thread started")

        # initialize the udev monitor (lazy)
        self.udev_monitor = UdevMonitor(self)

        # suppress modules' output wrt issue #20
        if not self.config["debug"]:
            sys.stdout = Path("/dev/null").open("w")
            sys.stderr = Path("/dev/null").open("w")

        # make sure we honor custom i3bar protocol stop/resume signals
        # while providing users a way to opt out from that feature
        # using the 0 value as specified by the i3bar protocol
        custom_stop_signal = (self.config["py3_config"].get(
            "py3status", {}).get("stop_signal"))
        if custom_stop_signal is not None:
            try:
                # 0 is a special value for i3bar protocol, use it as-is
                if custom_stop_signal == 0:
                    self.stop_signal = custom_stop_signal
                else:
                    self.stop_signal = Signals(custom_stop_signal)
            except ValueError:
                error = (
                    f"py3status.stop_signal '{custom_stop_signal}' is invalid "
                    f"and should be a number between 0 (disable) and 31")
                self.log(error, level="error")
                raise Exception(error)

        # SIGTSTP can be received and indicates that all output should
        # stop and we should consider py3status suspended.  It is however
        # important that any processes using i3 ipc should continue to receive
        # those events otherwise it can lead to a stall in i3.
        signal(SIGTSTP, self.i3bar_stop)
        # SIGCONT indicates output should be resumed.
        signal(SIGCONT, self.i3bar_start)

        # get the list of py3status configured modules
        self.py3_modules = self.config["py3_config"]["py3_modules"]

        # get a dict of all user provided modules
        self.log("modules include paths: {}".format(
            self.config["include_paths"]))
        user_modules = self.get_user_configured_modules()
        if self.config["debug"]:
            self.log(f"user_modules={user_modules}")

        if self.py3_modules:
            # load and spawn i3status.conf configured modules threads
            self.load_modules(self.py3_modules, user_modules)