Esempio n. 1
0
    def run(self):
        """
        Spawn i3status using a self generated config file and poll its output.
        """
        try:
            with NamedTemporaryFile(prefix='py3status_') as tmpfile:
                self.write_tmp_i3status_config(tmpfile)
                syslog(
                    LOG_INFO, 'i3status spawned using config file {}'.format(
                        tmpfile.name))

                i3status_pipe = Popen(
                    ['i3status', '-c', tmpfile.name],
                    stdout=PIPE,
                    stderr=PIPE,
                )
                self.poller_inp = IOPoller(i3status_pipe.stdout)
                self.poller_err = IOPoller(i3status_pipe.stderr)
                self.tmpfile_path = tmpfile.name

                try:
                    # loop on i3status output
                    while self.lock.is_set():
                        line = self.poller_inp.readline()
                        if line:
                            if line.startswith('[{'):
                                print_line(line)
                                with jsonify(line) as (prefix, json_list):
                                    self.last_output = json_list
                                    self.last_prefix = ','
                                    self.set_responses(json_list)
                                self.ready = True
                            elif not line.startswith(','):
                                if 'version' in line:
                                    header = loads(line)
                                    header.update({'click_events': True})
                                    line = dumps(header)
                                print_line(line)
                            else:
                                with jsonify(line) as (prefix, json_list):
                                    self.last_output = json_list
                                    self.last_prefix = prefix
                                    self.set_responses(json_list)
                        else:
                            err = self.poller_err.readline()
                            code = i3status_pipe.poll()
                            if code is not None:
                                msg = 'i3status died'
                                if err:
                                    msg += ' and said: {}'.format(err)
                                else:
                                    msg += ' with code {}'.format(code)
                                raise IOError(msg)
                except IOError:
                    err = sys.exc_info()[1]
                    self.error = err
        except OSError:
            # we cleanup the tmpfile ourselves so when the delete will occur
            # it will usually raise an OSError: No such file or directory
            pass
Esempio n. 2
0
    def run(self):
        """
        Spawn i3status using a self generated config file and poll its output.
        """
        try:
            with NamedTemporaryFile(prefix='py3status_') as tmpfile:
                self.write_tmp_i3status_config(tmpfile)
                syslog(LOG_INFO,
                       'i3status spawned using config file {}'.format(
                           tmpfile.name))

                i3status_pipe = Popen(
                    ['i3status', '-c', tmpfile.name],
                    stdout=PIPE,
                    stderr=PIPE, )
                self.poller_inp = IOPoller(i3status_pipe.stdout)
                self.poller_err = IOPoller(i3status_pipe.stderr)
                self.tmpfile_path = tmpfile.name

                try:
                    # loop on i3status output
                    while self.lock.is_set():
                        line = self.poller_inp.readline()
                        if line:
                            if line.startswith('[{'):
                                print_line(line)
                                with jsonify(line) as (prefix, json_list):
                                    self.last_output = json_list
                                    self.last_prefix = ','
                                    self.set_responses(json_list)
                                self.ready = True
                            elif not line.startswith(','):
                                if 'version' in line:
                                    header = loads(line)
                                    header.update({'click_events': True})
                                    line = dumps(header)
                                print_line(line)
                            else:
                                with jsonify(line) as (prefix, json_list):
                                    self.last_output = json_list
                                    self.last_prefix = prefix
                                    self.set_responses(json_list)
                        else:
                            err = self.poller_err.readline()
                            code = i3status_pipe.poll()
                            if code is not None:
                                msg = 'i3status died'
                                if err:
                                    msg += ' and said: {}'.format(err)
                                else:
                                    msg += ' with code {}'.format(code)
                                raise IOError(msg)
                except IOError:
                    err = sys.exc_info()[1]
                    self.error = err
        except OSError:
            # we cleanup the tmpfile ourselves so when the delete will occur
            # it will usually raise an OSError: No such file or directory
            pass
Esempio n. 3
0
    def mock(self):
        """
        Mock i3status behavior, used in standalone mode.
        """
        # mock thread is_alive() method
        self.is_alive = lambda: True

        # mock i3status base output
        init_output = ['{"click_events": true, "version": 1}', '[', '[]']
        for line in init_output:
            print_line(line)

        # mock i3status output parsing
        self.last_output = []
        self.last_prefix = ','
        self.update_json_list()
Esempio n. 4
0
    def mock(self):
        """
        Mock i3status behavior, used in standalone mode.
        """
        # mock thread is_alive() method
        self.is_alive = lambda: True

        # mock i3status base output
        init_output = ['{"click_events": true, "version": 1}', '[', '[]']
        for line in init_output:
            print_line(line)

        # mock i3status output parsing
        self.last_output = []
        self.last_prefix = ','
        self.update_json_list()
Esempio n. 5
0
    def run(self):
        """
        Main py3status loop, continuously read from i3status and modules
        and output it to i3bar for displaying.
        """
        # SIGUSR1 forces a refresh of the bar both for py3status and i3status,
        # this mimics the USR1 signal handling of i3status (see man i3status)
        signal(SIGUSR1, self.sig_handler)
        signal(SIGTERM, self.terminate)

        # initialize usage variables
        i3status_thread = self.i3status_thread
        py3_config = self.config['py3_config']

        # prepare the color mappings
        self.create_mappings(py3_config)

        # self.output_modules needs to have been created before modules are
        # started.  This is so that modules can do things like register their
        # content_function.
        self.create_output_modules()

        # Some modules need to be prepared before they can run
        # eg run their post_config_hook
        for module in self.modules.values():
            module.prepare_module()

        # modules can now receive updates
        self.py3_modules_initialized = True

        # start modules
        for module in self.modules.values():
            module.start_module()

        # this will be our output set to the correct length for the number of
        # items in the bar
        output = [None] * len(py3_config['order'])

        interval = self.config['interval']
        last_sec = 0

        # start our output
        header = {
            'version': 1,
            'click_events': True,
            'stop_signal': SIGTSTP
        }
        print_line(dumps(header))
        print_line('[[]')

        # main loop
        while True:
            # sleep a bit to avoid killing the CPU
            # by doing this at the begining rather than the end
            # of the loop we ensure a smoother first render of the i3bar
            time.sleep(0.1)

            while not self.i3bar_running:
                time.sleep(0.1)

            sec = int(time.time())

            # only check everything is good each second
            if sec > last_sec:
                last_sec = sec

                # check i3status thread
                if not i3status_thread.is_alive():
                    err = i3status_thread.error
                    if not err:
                        err = 'I3status died horribly.'
                    self.notify_user(err)

                # check events thread
                if not self.events_thread.is_alive():
                    # don't spam the user with i3-nagbar warnings
                    if not hasattr(self.events_thread, 'nagged'):
                        self.events_thread.nagged = True
                        err = 'Events thread died, click events are disabled.'
                        self.notify_user(err, level='warning')

                # update i3status time/tztime items
                if interval == 0 or sec % interval == 0:
                    i3status_thread.update_times()

            # check if an update is needed
            if self.queue:
                while (len(self.queue)):
                    module_name = self.queue.popleft()
                    module = self.output_modules[module_name]
                    for index in module['position']:
                        # store the output as json
                        out = module['module'].get_latest()
                        output[index] = self.process_module_output(out)

                # build output string
                out = ','.join([x for x in output if x])
                # dump the line to stdout
                print_line(',[{}]'.format(out))
Esempio n. 6
0
    def run(self):
        """
        Main py3status loop, continuously read from i3status and modules
        and output it to i3bar for displaying.
        """
        # SIGUSR1 forces a refresh of the bar both for py3status and i3status,
        # this mimics the USR1 signal handling of i3status (see man i3status)
        signal(SIGUSR1, self.sig_handler)
        signal(SIGTERM, self.terminate)

        # initialize usage variables
        i3status_thread = self.i3status_thread
        config = i3status_thread.config
        self.create_output_modules()

        # update queue populate with all py3modules
        self.queue.extend(self.modules)

        # this will be our output set to the correct length for the number of
        # items in the bar
        output = [None] * len(config['order'])

        interval = self.config['interval']
        last_sec = 0

        # start our output
        header = {
            'version': 1,
            'click_events': True,
            'stop_signal': SIGTSTP
        }
        print_line(dumps(header))
        print_line('[[]')

        # main loop
        while True:
            while not self.i3bar_running:
                time.sleep(0.1)

            sec = int(time.time())

            # only check everything is good each second
            if sec > last_sec:
                last_sec = sec

                # check i3status thread
                if not i3status_thread.is_alive():
                    err = i3status_thread.error
                    if not err:
                        err = 'I3status died horribly.'
                    self.notify_user(err)

                # check events thread
                if not self.events_thread.is_alive():
                    # don't spam the user with i3-nagbar warnings
                    if not hasattr(self.events_thread, 'nagged'):
                        self.events_thread.nagged = True
                        err = 'Events thread died, click events are disabled.'
                        self.notify_user(err, level='warning')

                # update i3status time/tztime items
                if interval == 0 or sec % interval == 0:
                    i3status_thread.update_times()

            # check if an update is needed
            if self.queue:
                while (len(self.queue)):
                    module_name = self.queue.popleft()
                    module = self.output_modules[module_name]
                    for index in module['position']:
                        # store the output as json
                        # modules can have more than one output
                        out = module['module'].get_latest()
                        output[index] = ', '.join([dumps(x) for x in out])

                # build output string
                out = ','.join([x for x in output if x])
                # dump the line to stdout
                print_line(',[{}]'.format(out))

            # sleep a bit before doing this again to avoid killing the CPU
            time.sleep(0.1)
Esempio n. 7
0
    def run(self):
        """
        Main py3status loop, continuously read from i3status and modules
        and output it to i3bar for displaying.
        """
        # SIGUSR1 forces a refresh of the bar both for py3status and i3status,
        # this mimics the USR1 signal handling of i3status (see man i3status)
        signal(SIGUSR1, self.sig_handler)
        signal(SIGTERM, self.terminate)

        # initialize usage variables
        i3status_thread = self.i3status_thread
        py3_config = self.config['py3_config']

        # prepare the color mappings
        self.create_mappings(py3_config)

        # self.output_modules needs to have been created before modules are
        # started.  This is so that modules can do things like register their
        # content_function.
        self.create_output_modules()

        # Some modules need to be prepared before they can run
        # eg run their post_config_hook
        for module in self.modules.values():
            module.prepare_module()

        # modules can now receive updates
        self.py3_modules_initialized = True

        # start modules
        for module in self.modules.values():
            module.start_module()

        # this will be our output set to the correct length for the number of
        # items in the bar
        output = [None] * len(py3_config['order'])

        interval = self.config['interval']
        last_sec = 0

        # start our output
        header = {'version': 1, 'click_events': True, 'stop_signal': SIGTSTP}
        print_line(dumps(header))
        print_line('[[]')

        # main loop
        while True:
            # sleep a bit to avoid killing the CPU
            # by doing this at the begining rather than the end
            # of the loop we ensure a smoother first render of the i3bar
            time.sleep(0.1)

            while not self.i3bar_running:
                time.sleep(0.1)

            sec = int(time.time())

            # only check everything is good each second
            if sec > last_sec:
                last_sec = sec

                # check i3status thread
                if not i3status_thread.is_alive():
                    err = i3status_thread.error
                    if not err:
                        err = 'I3status died horribly.'
                    self.notify_user(err)

                # check events thread
                if not self.events_thread.is_alive():
                    # don't spam the user with i3-nagbar warnings
                    if not hasattr(self.events_thread, 'nagged'):
                        self.events_thread.nagged = True
                        err = 'Events thread died, click events are disabled.'
                        self.notify_user(err, level='warning')

                # update i3status time/tztime items
                if interval == 0 or sec % interval == 0:
                    i3status_thread.update_times()

            # check if an update is needed
            if self.queue:
                while (len(self.queue)):
                    module_name = self.queue.popleft()
                    module = self.output_modules[module_name]
                    for index in module['position']:
                        # store the output as json
                        out = module['module'].get_latest()
                        output[index] = self.process_module_output(out)

                # build output string
                out = ','.join([x for x in output if x])
                # dump the line to stdout
                print_line(',[{}]'.format(out))
Esempio n. 8
0
    def run(self):
        """
        Main py3status loop, continuously read from i3status and modules
        and output it to i3bar for displaying.
        """
        # SIGUSR1 forces a refresh of the bar both for py3status and i3status,
        # this mimics the USR1 signal handling of i3status (see man i3status)
        signal(SIGUSR1, self.sig_handler)
        signal(SIGTERM, self.terminate)

        # initialize usage variables
        i3status_thread = self.i3status_thread
        config = i3status_thread.config
        self.create_output_modules()

        # update queue populate with all py3modules
        self.queue.extend(self.modules)

        # this will be our output set to the correct length for the number of
        # items in the bar
        output = [None] * len(config['order'])

        interval = self.config['interval']
        last_sec = 0

        # start our output
        header = {
            'version': 1,
            'click_events': True,
            'stop_signal': SIGTSTP
        }
        print_line(dumps(header))
        print_line('[[]')

        # main loop
        while True:
            while not self.i3bar_running:
                time.sleep(0.1)

            sec = int(time.time())

            # only check everything is good each second
            if sec > last_sec:
                last_sec = sec

                # check i3status thread
                if not i3status_thread.is_alive():
                    err = i3status_thread.error
                    if not err:
                        err = 'I3status died horribly.'
                    self.notify_user(err)

                # check events thread
                if not self.events_thread.is_alive():
                    # don't spam the user with i3-nagbar warnings
                    if not hasattr(self.events_thread, 'nagged'):
                        self.events_thread.nagged = True
                        err = 'Events thread died, click events are disabled.'
                        self.notify_user(err, level='warning')

                # update i3status time/tztime items
                if interval == 0 or sec % interval == 0:
                    i3status_thread.update_times()

            # check if an update is needed
            if self.queue:
                while (len(self.queue)):
                    module_name = self.queue.popleft()
                    module = self.output_modules[module_name]
                    for index in module['position']:
                        # store the output as json
                        # modules can have more than one output
                        out = module['module'].get_latest()
                        output[index] = ', '.join([dumps(x) for x in out])

                # build output string
                out = ','.join([x for x in output if x])
                # dump the line to stdout
                print_line(',[{}]'.format(out))

            # sleep a bit before doing this again to avoid killing the CPU
            time.sleep(0.1)
Esempio n. 9
0
    def run(self):
        """
        Main py3status loop, continuously read from i3status and modules
        and output it to i3bar for displaying.
        """
        # SIGUSR1 forces a refresh of the bar both for py3status and i3status,
        # this mimics the USR1 signal handling of i3status (see man i3status)
        signal(SIGUSR1, self.sig_handler)
        signal(SIGTERM, self.terminate)

        # initialize usage variables
        delta = 0
        last_delta = -1
        previous_json_list = []

        # main loop
        while True:
            # check i3status thread
            if not self.i3status_thread.is_alive():
                err = self.i3status_thread.error
                if not err:
                    err = "i3status died horribly"
                self.i3_nagbar(err)
                break

            # check events thread
            if not self.events_thread.is_alive():
                # don't spam the user with i3-nagbar warnings
                if not hasattr(self.events_thread, "i3_nagbar"):
                    self.events_thread.i3_nagbar = True
                    err = "events thread died, click events are disabled"
                    self.i3_nagbar(err, level="warning")

            # get output from i3status
            prefix = self.i3status_thread.last_prefix
            json_list = deepcopy(self.i3status_thread.json_list)

            # transform time and tztime outputs from i3status
            # every configured interval seconds
            if (
                self.config["interval"] <= 1
                or int(delta) % self.config["interval"] == 0
                and int(last_delta) != int(delta)
            ):
                delta = 0
                last_delta = 0
                json_list = self.i3status_thread.tick_time_modules(json_list, force=True)
            else:
                json_list = self.i3status_thread.tick_time_modules(json_list, force=False)

            # construct the global output
            if self.modules and self.py3_modules:
                # new style i3status configured ordering
                json_list = self.i3status_thread.get_modules_output(json_list, self.modules)

            # dump the line to stdout only on change
            if json_list != previous_json_list:
                print_line("{}{}".format(prefix, dumps(json_list)))

            # remember the last json list output
            previous_json_list = deepcopy(json_list)

            # reset i3status json_list and json_list_ts
            self.i3status_thread.update_json_list()

            # sleep a bit before doing this again to avoid killing the CPU
            delta += 0.1
            sleep(0.1)