Esempio n. 1
0
    def show(self):
        """
        This is where we go output the content of a block and any valid child
        block that it contains.

        """
        # Start by finalising the block.
        # Any active content is added to self.options
        if self.content:
            self.options.append(self.content)

        output = Composite()

        for index, option in enumerate(self.options):
            if index in self.valid_blocks:
                # A block may be valid but has a command that causes this to be
                # disregarded.
                if self.is_valid_by_command(index) is False:
                    continue
                # add the content of the block and any children
                # to the output
                for item in option:
                    if isinstance(item, Block):
                        output.append(item.show())
                    else:
                        output.append(item)
                break

        # Build up our output.
        self.process_composite_chunk_item(output.get_content())
        return output
Esempio n. 2
0
    def process_composite(self, response):
        """
        Process a composite response.
        composites do not have inter item separators as they appear joined.
        We need to respect the universal options too.
        """
        composite = response['composite']

        # if the composite is of not Composite make it one so we can simplify
        # it.
        if not isinstance(composite, Composite):
            composite = Composite(composite)

        # simplify and get underlying list.
        composite = composite.simplify().get_content()
        response['composite'] = composite

        if not isinstance(composite, list):
            raise Exception('expecting "composite" key in response')
        # if list is empty nothing to do
        if not len(composite):
            return
        if 'full_text' in response:
            err = 'conflicting "full_text" and "composite" in response'
            raise Exception(err)
        # set universal options on last component
        composite[-1].update(self.i3s_module_options)
        # update all components
        color = response.get('color')
        urgent = response.get('urgent')
        for index, item in enumerate(response['composite']):
            # validate the response
            if 'full_text' not in item:
                raise KeyError('missing "full_text" key in response')
            # make sure all components have a name
            if 'name' not in item:
                instance_index = item.get('index', index)
                item['instance'] = '{} {}'.format(
                    self.module_inst, instance_index
                )
                item['name'] = self.module_name
            # hide separator for all inner components unless existing
            if index != len(response['composite']) - 1:
                if 'separator' not in item:
                    item['separator'] = False
                    item['separator_block_width'] = 0
            # If a color was supplied for the composite and a composite
            # part does not supply a color, use the composite color.
            if color and 'color' not in item:
                item['color'] = color
            # Remove any none color from our output
            if hasattr(item.get('color'), 'none_setting'):
                del item['color']

            # remove urgent if not allowed
            if not self.allow_urgent:
                if 'urgent' in item:
                    del item['urgent']
            # if urgent we want to set this to all parts
            elif urgent and 'urgent' not in item:
                item['urgent'] = urgent

        # set min_width
        if 'min_width' in self.py3_module_options:
            min_width = self.py3_module_options['min_width']

            # get width, skip if width exceeds min_width
            width = sum([len(x['full_text']) for x in response['composite']])
            if width >= min_width:
                return

            # sometimes when we go under min_width to pad both side evenly,
            # we will add extra space on either side to honor min_width
            padding = int((min_width / 2.0) - (width / 2.0))
            offset = min_width - ((padding * 2) + width)

            # set align
            align = self.py3_module_options.get('align', 'center')
            if align == 'center':
                left = right = ' ' * padding
                if self.random_int:
                    left += ' ' * offset
                else:
                    right += ' ' * offset
            elif align == 'left':
                left, right = '', ' ' * (padding * 2 + offset)
            elif align == 'right':
                right, left = '', ' ' * (padding * 2 + offset)

            # padding
            if left:
                response['composite'][0]['full_text'] = (
                    left + response['composite'][0]['full_text']
                )
            if right:
                response['composite'][-1]['full_text'] += right
Esempio n. 3
0
def test_Composite_iadd_4():
    c = Composite('moo')
    c += (Composite('moo'))
    result = c.get_content()
    assert result == [{'full_text': 'moo'}, {'full_text': 'moo'}]
Esempio n. 4
0
def test_Composite_append_3():
    c = Composite('moo')
    c.append([{'full_text': 'moo'}])
    result = c.get_content()
    assert result == [{'full_text': 'moo'}, {'full_text': 'moo'}]
Esempio n. 5
0
    'empty': '',
    'None': None,
    '?bad name': 'evil',
    u'☂ Very bad name ': u'☂ extremely evil',
    'long_str': 'I am a long string though not too long',
    'python2_unicode': u'Björk',
    'python2_str': 'Björk',
    'zero': 0,
    'zero_str': '0',
    'zero_float': 0.0,
    'str_int': '123',
    'str_float': '123.456',
    'str_nan': "I'm not a number",

    'composite_basic': Composite([{'full_text': 'red ', 'color': '#FF0000'},
                                  {'full_text': 'green ', 'color': '#00FF00'},
                                  {'full_text': 'blue', 'color': '#0000FF'}]),
    'complex': Composite([{'full_text': 'LA 09:34'},
                          {'full_text': 'NY 12:34'}]),
    'complex2': Composite([{'full_text': 'LA 09:34', 'color': '#FF0000'},
                           {'full_text': 'NY 12:34'}]),
    'simple': Composite({'full_text': 'NY 12:34'}),
    'empty_composite': Composite(),
    'comp_bad_color': Composite({'full_text': 'BAD', 'color': NoneColor()}),
}


class Module:
    module_param = 'something'
    module_true = True
    module_false = False
Esempio n. 6
0
    def format(
        self,
        format_string,
        module=None,
        param_dict=None,
        force_composite=False,
        attr_getter=None,
    ):
        """
        Format a string, substituting place holders which can be found in
        param_dict, attributes of the supplied module, or provided via calls to
        the attr_getter function.
        """
        # fix python 2 unicode issues
        if python2 and isinstance(format_string, str):
            format_string = format_string.decode("utf-8")

        if param_dict is None:
            param_dict = {}

        # if the processed format string is not in the cache then create it.
        if format_string not in self.block_cache:
            self.build_block(format_string)

        first_block = self.block_cache[format_string]

        def get_parameter(key):
            """
            function that finds and returns the value for a placeholder.
            """
            if key in param_dict:
                # was a supplied parameter
                param = param_dict.get(key)
            elif module and hasattr(module, key):
                param = getattr(module, key)
                if hasattr(param, "__call__"):
                    # we don't allow module methods
                    raise Exception()
            elif attr_getter:
                # get value from attr_getter function
                try:
                    param = attr_getter(key)
                except:  # noqa e722
                    raise Exception()
            else:
                raise Exception()
            if isinstance(param, Composite):
                if param.text():
                    param = param.copy()
                else:
                    param = u""
            elif python2 and isinstance(param, str):
                param = param.decode("utf-8")
            return param

        # render our processed format
        valid, output = first_block.render(get_parameter, module)

        # clean things up a little
        if isinstance(output, list):
            output = Composite(output)
        if not output:
            if force_composite:
                output = Composite()
            else:
                output = ""

        return output
Esempio n. 7
0
    def process_composite(self, response):
        """
        Process a composite response.
        composites do not have inter item separators as they appear joined.
        We need to respect the universal options too.
        """
        composite = response['composite']

        # if the composite is of not Composite make it one so we can simplify
        # it.
        if not isinstance(composite, Composite):
            composite = Composite(composite)

        # simplify and get underlying list.
        composite = composite.simplify().get_content()
        response['composite'] = composite

        if not isinstance(composite, list):
            raise Exception('expecting "composite" key in response')
        # if list is empty nothing to do
        if not len(composite):
            return
        if 'full_text' in response:
            err = 'conflicting "full_text" and "composite" in response'
            raise Exception(err)
        # set universal options on last component
        composite[-1].update(self.module_options)
        # calculate any min width (we split this across components)
        min_width = None
        if 'min_width' in self.module_options:
            min_width = int(self.module_options['min_width'] / len(composite))
        # store alignment
        align = None
        if 'align' in self.module_options:
            align = self.module_options['align']

        # update all components
        color = response.get('color')
        urgent = response.get('urgent')
        for index, item in enumerate(response['composite']):
            # validate the response
            if 'full_text' not in item:
                raise KeyError('missing "full_text" key in response')
            # make sure all components have a name
            if 'name' not in item:
                instance_index = item.get('index', index)
                item['instance'] = '{} {}'.format(self.module_inst,
                                                  instance_index)
                item['name'] = self.module_name
            # hide separator for all inner components unless existing
            if index != len(response['composite']) - 1:
                if 'separator' not in item:
                    item['separator'] = False
                    item['separator_block_width'] = 0
            # set min width
            if min_width:
                item['min_width'] = min_width
            # set align
            if align:
                item['align'] = align
            # If a color was supplied for the composite and a composite
            # part does not supply a color, use the composite color.
            if color and 'color' not in item:
                item['color'] = color
            # Remove any none color from our output
            if hasattr(item.get('color'), 'none_setting'):
                del item['color']

            # remove urgent if not allowed
            if not self.allow_urgent:
                if 'urgent' in item:
                    del item['urgent']
            # if urgent we want to set this to all parts
            elif urgent and 'urgent' not in item:
                item['urgent'] = urgent
Esempio n. 8
0
    def process_composite(self, response):
        """
        Process a composite response.
        composites do not have inter item separators as they appear joined.
        We need to respect the universal options too.
        """
        composite = response["composite"]

        # if the composite is of not Composite make it one so we can simplify
        # it.
        if not isinstance(composite, Composite):
            composite = Composite(composite)

        # simplify and get underlying list.
        composite = composite.simplify().get_content()
        response["composite"] = composite

        if not isinstance(composite, list):
            raise Exception('expecting "composite" key in response')
        # if list is empty nothing to do
        if not len(composite):
            return
        if "full_text" in response:
            err = 'conflicting "full_text" and "composite" in response'
            raise Exception(err)

        # set markup
        if "markup" in self.py3status_module_options:
            markup = self.py3status_module_options["markup"]
            for item in composite:
                item["markup"] = markup

        # set universal options on last component
        composite[-1].update(self.i3bar_module_options)
        # update all components
        color = response.get("color")
        urgent = response.get("urgent")
        composite_length = len(response["composite"]) - 1
        for index, item in enumerate(response["composite"]):
            # validate the response
            if "full_text" not in item:
                raise KeyError('missing "full_text" key in response')
            # make sure all components have a name
            if "name" not in item:
                instance_index = item.get("index", index)
                item["instance"] = "{} {}".format(self.module_inst, instance_index)
                item["name"] = self.module_name
            # hide separator for all inner components unless existing
            if index != composite_length:
                if "separator" not in item:
                    item["separator"] = False
                    item["separator_block_width"] = 0
            # If a color was supplied for the composite and a composite
            # part does not supply a color, use the composite color.
            if color and "color" not in item:
                item["color"] = color
            # Remove any none color from our output
            if hasattr(item.get("color"), "none_setting"):
                del item["color"]

            # set background and border colors. set left/right border widths
            # only on first/last composites and no border width for inner
            # composites or we will see border lines between composites.
            for key, value in self.i3bar_gaps_module_options.items():
                if (key == "border_left" and index != 0) or (
                    key == "border_right" and index != composite_length
                ):
                    item[key] = 0
                else:
                    item[key] = value

            # set urgent based on available user-defined settings
            if not self.allow_urgent:
                if "urgent" in item:
                    del item["urgent"]
            elif urgent:
                if self.i3bar_gaps_urgent_options:
                    # set background and border colors. set left/right border widths
                    # only on first/last composites and no border width for inner
                    # composites or we will see border lines between composites.
                    for key, value in self.i3bar_gaps_urgent_options.items():
                        if (key == "border_left" and index != 0) or (
                            key == "border_right" and index != composite_length
                        ):
                            item[key] = 0
                        elif key == "foreground":
                            item["color"] = value
                        else:
                            item[key] = value
                    if "urgent" in item:
                        del item["urgent"]
                else:
                    item["urgent"] = urgent

        # set min_length
        if "min_length" in self.py3status_module_options:
            min_length = self.py3status_module_options["min_length"]

            # get length, skip if length exceeds min_length
            length = sum([len(x["full_text"]) for x in response["composite"]])
            if length >= min_length:
                return

            # sometimes we go under min_length to pad both side evenly,
            # we will add extra space on either side to honor min_length
            padding = int((min_length / 2.0) - (length / 2.0))
            offset = min_length - ((padding * 2) + length)

            # set position
            position = self.py3status_module_options.get("position", "left")
            if position == "center":
                left = right = " " * padding
                if self.random_int:
                    left += " " * offset
                else:
                    right += " " * offset
            elif position == "left":
                left, right = "", " " * (padding * 2 + offset)
            elif position == "right":
                right, left = "", " " * (padding * 2 + offset)

            # padding
            if left:
                response["composite"][0]["full_text"] = (
                    left + response["composite"][0]["full_text"]
                )
            if right:
                response["composite"][-1]["full_text"] += right
Esempio n. 9
0
    def process_composite(self, response):
        """
        Process a composite response.
        composites do not have inter item separators as they appear joined.
        We need to respect the universal options too.
        """
        composite = response['composite']

        # if the composite is of not Composite make it one so we can simplify
        # it.
        if not isinstance(composite, Composite):
            composite = Composite(composite)

        # simplify and get underlying list.
        composite = composite.simplify().get_content()
        response['composite'] = composite

        if not isinstance(composite, list):
            raise Exception('expecting "composite" key in response')
        # if list is empty nothing to do
        if not len(composite):
            return
        if 'full_text' in response:
            err = 'conflicting "full_text" and "composite" in response'
            raise Exception(err)
        # set universal options on last component
        composite[-1].update(self.module_options)
        # calculate any min width (we split this across components)
        min_width = None
        if 'min_width' in self.module_options:
            min_width = int(self.module_options['min_width'] / len(composite))
        # store alignment
        align = None
        if 'align' in self.module_options:
            align = self.module_options['align']

        # update all components
        color = response.get('color')
        urgent = response.get('urgent')
        for index, item in enumerate(response['composite']):
            # validate the response
            if 'full_text' not in item:
                raise KeyError('missing "full_text" key in response')
            # make sure all components have a name
            if 'name' not in item:
                instance_index = item.get('index', index)
                item['instance'] = '{} {}'.format(
                    self.module_inst, instance_index
                )
                item['name'] = self.module_name
            # hide separator for all inner components unless existing
            if index != len(response['composite']) - 1:
                if 'separator' not in item:
                    item['separator'] = False
                    item['separator_block_width'] = 0
            # set min width
            if min_width:
                item['min_width'] = min_width
            # set align
            if align:
                item['align'] = align
            # If a color was supplied for the composite and a composite
            # part does not supply a color, use the composite color.
            if color and 'color' not in item:
                item['color'] = color
            # Remove any none color from our output
            if hasattr(item.get('color'), 'none_setting'):
                del item['color']

            # remove urgent if not allowed
            if not self.allow_urgent:
                if 'urgent' in item:
                    del item['urgent']
            # if urgent we want to set this to all parts
            elif urgent and 'urgent' not in item:
                item['urgent'] = urgent
Esempio n. 10
0
    def process_composite(self, response):
        """
        Process a composite response.
        composites do not have inter item separators as they appear joined.
        We need to respect the universal options too.
        """
        composite = response["composite"]

        # if the composite is of not Composite make it one so we can simplify
        # it.
        if not isinstance(composite, Composite):
            composite = Composite(composite)

        # simplify and get underlying list.
        composite = composite.simplify().get_content()
        response["composite"] = composite

        if not isinstance(composite, list):
            raise Exception('expecting "composite" key in response')
        # if list is empty nothing to do
        if not len(composite):
            return
        if "full_text" in response:
            err = 'conflicting "full_text" and "composite" in response'
            raise Exception(err)
        # set universal options on last component
        composite[-1].update(self.i3s_module_options)
        # update all components
        color = response.get("color")
        urgent = response.get("urgent")
        for index, item in enumerate(response["composite"]):
            # validate the response
            if "full_text" not in item:
                raise KeyError('missing "full_text" key in response')
            # make sure all components have a name
            if "name" not in item:
                instance_index = item.get("index", index)
                item["instance"] = "{} {}".format(self.module_inst,
                                                  instance_index)
                item["name"] = self.module_name
            # hide separator for all inner components unless existing
            if index != len(response["composite"]) - 1:
                if "separator" not in item:
                    item["separator"] = False
                    item["separator_block_width"] = 0
            # If a color was supplied for the composite and a composite
            # part does not supply a color, use the composite color.
            if color and "color" not in item:
                item["color"] = color
            # Remove any none color from our output
            if hasattr(item.get("color"), "none_setting"):
                del item["color"]

            # remove urgent if not allowed
            if not self.allow_urgent:
                if "urgent" in item:
                    del item["urgent"]
            # if urgent we want to set this to all parts
            elif urgent and "urgent" not in item:
                item["urgent"] = urgent

        # set min_length
        if "min_length" in self.py3_module_options:
            min_length = self.py3_module_options["min_length"]

            # get length, skip if length exceeds min_length
            length = sum([len(x["full_text"]) for x in response["composite"]])
            if length >= min_length:
                return

            # sometimes we go under min_length to pad both side evenly,
            # we will add extra space on either side to honor min_length
            padding = int((min_length / 2.0) - (length / 2.0))
            offset = min_length - ((padding * 2) + length)

            # set position
            position = self.py3_module_options.get("position", "left")
            if position == "center":
                left = right = " " * padding
                if self.random_int:
                    left += " " * offset
                else:
                    right += " " * offset
            elif position == "left":
                left, right = "", " " * (padding * 2 + offset)
            elif position == "right":
                right, left = "", " " * (padding * 2 + offset)

            # padding
            if left:
                response["composite"][0]["full_text"] = (
                    left + response["composite"][0]["full_text"])
            if right:
                response["composite"][-1]["full_text"] += right
Esempio n. 11
0
 'zero_str':
 '0',
 'zero_float':
 0.0,
 'str_int':
 '123',
 'str_float':
 '123.456',
 'str_nan':
 "I'm not a number",
 'composite_basic':
 Composite([{
     'full_text': 'red ',
     'color': '#FF0000'
 }, {
     'full_text': 'green ',
     'color': '#00FF00'
 }, {
     'full_text': 'blue',
     'color': '#0000FF'
 }]),
 'complex':
 Composite([{
     'full_text': 'LA 09:34'
 }, {
     'full_text': 'NY 12:34'
 }]),
 'complex2':
 Composite([{
     'full_text': 'LA 09:34',
     'color': '#FF0000'
 }, {
Esempio n. 12
0
    def process_composite(self, response):
        """
        Process a composite response.
        composites do not have inter item separators as they appear joined.
        We need to respect the universal options too.
        """
        composite = response['composite']

        # if the composite is of not Composite make it one so we can simplify
        # it.
        if not isinstance(composite, Composite):
            composite = Composite(composite)

        # simplify and get underlying list.
        composite = composite.simplify().get_content()
        response['composite'] = composite

        if not isinstance(composite, list):
            raise Exception('expecting "composite" key in response')
        # if list is empty nothing to do
        if not len(composite):
            return
        if 'full_text' in response:
            err = 'conflicting "full_text" and "composite" in response'
            raise Exception(err)
        # set universal options on last component
        composite[-1].update(self.i3s_module_options)
        # update all components
        color = response.get('color')
        urgent = response.get('urgent')
        for index, item in enumerate(response['composite']):
            # validate the response
            if 'full_text' not in item:
                raise KeyError('missing "full_text" key in response')
            # make sure all components have a name
            if 'name' not in item:
                instance_index = item.get('index', index)
                item['instance'] = '{} {}'.format(self.module_inst,
                                                  instance_index)
                item['name'] = self.module_name
            # hide separator for all inner components unless existing
            if index != len(response['composite']) - 1:
                if 'separator' not in item:
                    item['separator'] = False
                    item['separator_block_width'] = 0
            # If a color was supplied for the composite and a composite
            # part does not supply a color, use the composite color.
            if color and 'color' not in item:
                item['color'] = color
            # Remove any none color from our output
            if hasattr(item.get('color'), 'none_setting'):
                del item['color']

            # remove urgent if not allowed
            if not self.allow_urgent:
                if 'urgent' in item:
                    del item['urgent']
            # if urgent we want to set this to all parts
            elif urgent and 'urgent' not in item:
                item['urgent'] = urgent

        # set min_width
        if 'min_width' in self.py3_module_options:
            min_width = self.py3_module_options['min_width']

            # get width, skip if width exceeds min_width
            width = sum([len(x['full_text']) for x in response['composite']])
            if width >= min_width:
                return

            # sometimes when we go under min_width to pad both side evenly,
            # we will add extra space on either side to honor min_width
            padding = int((min_width / 2.0) - (width / 2.0))
            offset = min_width - ((padding * 2) + width)

            # set align
            align = self.py3_module_options.get('align', 'center')
            if align == 'center':
                left = right = ' ' * padding
                if self.random_int:
                    left += ' ' * offset
                else:
                    right += ' ' * offset
            elif align == 'left':
                left, right = '', ' ' * (padding * 2 + offset)
            elif align == 'right':
                right, left = '', ' ' * (padding * 2 + offset)

            # padding
            if left:
                response['composite'][0]['full_text'] = (
                    left + response['composite'][0]['full_text'])
            if right:
                response['composite'][-1]['full_text'] += right
Esempio n. 13
0
    def format(self, format_string, module=None, param_dict=None,
               force_composite=False, attr_getter=None):
        """
        Format a string, substituting place holders which can be found in
        param_dict, attributes of the supplied module, or provided via calls to
        the attr_getter function.
        """

        def set_param(param, value, key, block, format=''):
            """
            Converts a placeholder to a string value.
            We fix python 2 unicode issues and use string.format()
            to ensure that formatting is applied correctly
            """
            if self.python2 and isinstance(param, str):
                param = param.decode('utf-8')
            # '', None, and False are ignored
            # numbers like 0 and 0.0 are not.
            if not (param in ['', None] or param is False):
                if format.startswith(':'):
                    # if a parameter has been set to be formatted as a numeric
                    # type then we see if we can coerce it to be.  This allows
                    # the user to format types that normally would not be
                    # allowed eg '123' it also allows {:d} to be used as a
                    # shorthand for {:.0f}.  If the parameter cannot be
                    # successfully converted then the format is removed.
                    try:
                        if 'f' in format:
                            param = float(param)
                        if 'd' in format:
                            param = int(float(param))
                    except ValueError:
                        value = u'{%s}' % key
                value = value.format(**{key: param})
                block.add(value)
                # If not_zero block command is used we do not want to mark this
                # block as valid if the parameter is zero.
                # we do of course want to et the parameter in case the block is
                # valid via another route, eg second parameter
                try:
                    if block.block_config.not_zero and float(param) == 0:
                        return
                except ValueError:
                    pass
                block.mark_valid()

        # fix python 2 unicode issues
        if self.python2 and isinstance(format_string, str):
            format_string = format_string.decode('utf-8')

        if param_dict is None:
            param_dict = {}

        block = Block(param_dict, module)

        # Tokenize the format string and process them
        for token in self.tokens(format_string):
            value = token.group(0)
            if token.group('block_start'):
                # Create new block
                new_block = Block(param_dict, module, block)
                block.add(new_block)
                block = new_block
            elif token.group('block_end'):
                # Close block setting any valid state as needed
                # and return to parent block to continue
                block.set_valid_state()
                if not block.parent:
                    raise Exception('Too many `]`')
                block = block.parent
            elif token.group('switch'):
                # a new option has been created
                block.set_valid_state()
                block.switch()
            elif token.group('placeholder'):
                # Found a {placeholder}
                key = token.group('key')
                if key in param_dict:
                    # was a supplied parameter
                    param = param_dict.get(key)
                    if isinstance(param, Composite):
                        # supplied parameter is a composite
                        if param.get_content():
                            block.add(param.copy())
                            block.mark_valid()
                    else:
                        format = token.group('format')
                        set_param(param, value, key, block, format)
                elif module and hasattr(module, key):
                    # attribute of the module
                    param = getattr(module, key)
                    if not hasattr(param, '__call__'):
                        set_param(param, value, key, block)
                    else:
                        block.add(value)
                elif attr_getter:
                    # get value from attr_getter function
                    param = attr_getter(key)
                    set_param(param, value, key, block)
                else:
                    # substitution not found so add as a literal
                    block.add(value)
            elif token.group('literal'):
                block.add(value)
            elif token.group('lost_brace'):
                # due to how parsing happens we can get a lonesome }
                # eg in format_string '{{something}' this fixes that issue
                block.add(value)
            elif token.group('command'):
                # a block command has been found
                block.set_commands(token.group('command'))
            elif token.group('escaped'):
                # escaped characters add unescaped values
                if value[0] in ['\\', '{', '}']:
                    value = value[1:]
                block.add(value)

        if block.parent:
            raise Exception('Block not closed')

        # This is the main block if none of the sections are valid use the last
        # one for situations like '{placeholder}|Nothing'
        if not block.valid_blocks:
            block.mark_valid()
        output = block.show()

        # post format
        # swap color names to values
        for item in output:
            # ignore empty items
            if not item.get('full_text') and not item.get('separator'):
                continue
            # colors
            color_this = item.get('color')
            if color_this and color_this[0] != '#':
                color_name = 'color_%s' % color_this
                threshold_color_name = 'color_threshold_%s' % color_this
                # substitute color
                color_this = (
                    getattr(module, color_name, None) or
                    getattr(module, threshold_color_name, None) or
                    getattr(module.py3, color_name.upper(), None)
                )
                if color_this:
                        item['color'] = color_this
                else:
                    del item['color']
        output = Composite(output).simplify()
        # if only text then we can become a string
        if not force_composite:
            if len(output) == 0:
                return ''
            elif (len(output) == 1 and list(output[0].keys()) == ['full_text']):
                output = output[0]['full_text']

        return output
Esempio n. 14
0
 "str_float":
 "123.456",
 "str_nan":
 "I'm not a number",
 "trailing_zeroes_1":
 "50.000",
 "trailing_zeroes_2":
 "5.500",
 "composite_basic":
 Composite([
     {
         "full_text": "red ",
         "color": "#FF0000"
     },
     {
         "full_text": "green ",
         "color": "#00FF00"
     },
     {
         "full_text": "blue",
         "color": "#0000FF"
     },
 ]),
 "complex":
 Composite([{
     "full_text": "LA 09:34"
 }, {
     "full_text": "NY 12:34"
 }]),
 "complex2":
 Composite([{
     "full_text": "LA 09:34",
Esempio n. 15
0
    def process_composite(self, response):
        """
        Process a composite response.
        composites do not have inter item separators as they appear joined.
        We need to respect the universal options too.
        """
        composite = response["composite"]

        # if the composite is of not Composite make it one so we can simplify
        # it.
        if not isinstance(composite, Composite):
            composite = Composite(composite)

        # simplify and get underlying list.
        composite = composite.simplify().get_content()
        response["composite"] = composite

        if not isinstance(composite, list):
            raise Exception('expecting "composite" key in response')
        # if list is empty nothing to do
        if not len(composite):
            return
        if "full_text" in response:
            err = 'conflicting "full_text" and "composite" in response'
            raise Exception(err)

        # set markup
        if "markup" in self.py3status_module_options:
            markup = self.py3status_module_options["markup"]
            line = ""
            for item in composite:
                # validate the response
                if "full_text" not in item:
                    raise KeyError('missing "full_text" key in response')
                color = item.get("color")
                if color:
                    span = u"<span fgcolor='{}'>{}</span>"
                    line += span.format(color, item["full_text"])
                else:
                    line += item["full_text"]

            composite = [{"full_text": line, "markup": markup}]
            response["composite"] = composite

        # set universal options on last component
        composite[-1].update(self.i3bar_module_options)
        # update all components
        color = response.get("color")
        urgent = response.get("urgent")
        composite_length = len(response["composite"]) - 1
        for index, item in enumerate(response["composite"]):
            # validate the response
            if "full_text" not in item:
                raise KeyError('missing "full_text" key in response')
            # make sure all components have a name
            if "name" not in item:
                instance_index = item.get("index", index)
                item["instance"] = "{} {}".format(self.module_inst,
                                                  instance_index)
                item["name"] = self.module_name
            # hide separator for all inner components unless existing
            if index != composite_length:
                if "separator" not in item:
                    item["separator"] = False
                    item["separator_block_width"] = 0
            # If a color was supplied for the composite and a composite
            # part does not supply a color, use the composite color.
            if color and "color" not in item:
                item["color"] = color
            # Remove any none color from our output
            if hasattr(item.get("color"), "none_setting"):
                del item["color"]

            # set background and border colors. set left/right border widths
            # only on first/last composites and no border width for inner
            # composites or we will see border lines between composites.
            for key, value in self.i3bar_gaps_module_options.items():
                if (key == "border_left"
                        and index != 0) or (key == "border_right"
                                            and index != composite_length):
                    item[key] = 0
                else:
                    item[key] = value

            # set urgent based on available user-defined settings
            if not self.allow_urgent:
                if "urgent" in item:
                    del item["urgent"]
            elif urgent:
                if self.i3bar_gaps_urgent_options:
                    # set background and border colors. set left/right border widths
                    # only on first/last composites and no border width for inner
                    # composites or we will see border lines between composites.
                    for key, value in self.i3bar_gaps_urgent_options.items():
                        if (key == "border_left"
                                and index != 0) or (key == "border_right" and
                                                    index != composite_length):
                            item[key] = 0
                        elif key == "foreground":
                            item["color"] = value
                        else:
                            item[key] = value
                    if "urgent" in item:
                        del item["urgent"]
                else:
                    item["urgent"] = urgent

        # set min_length
        if "min_length" in self.py3status_module_options:
            min_length = self.py3status_module_options["min_length"]

            # get length, skip if length exceeds min_length
            length = sum([len(x["full_text"]) for x in response["composite"]])
            if length >= min_length:
                return

            # sometimes we go under min_length to pad both side evenly,
            # we will add extra space on either side to honor min_length
            padding = int((min_length / 2.0) - (length / 2.0))
            offset = min_length - ((padding * 2) + length)

            # set position
            position = self.py3status_module_options.get("position", "left")
            if position == "center":
                left = right = " " * padding
                if self.random_int:
                    left += " " * offset
                else:
                    right += " " * offset
            elif position == "left":
                left, right = "", " " * (padding * 2 + offset)
            elif position == "right":
                right, left = "", " " * (padding * 2 + offset)

            # padding
            if left:
                response["composite"][0]["full_text"] = (
                    left + response["composite"][0]["full_text"])
            if right:
                response["composite"][-1]["full_text"] += right