Example #1
0
def test_text_flow():
    assert text_flow("") == ""

    assert text_flow("Testing") == "Testing"

    assert text_flow("One Two Three") == "One Two Three"

    assert text_flow("One Two Three", width=5) == ("One\n" "Two\n" "Three")

    assert text_flow("One Two Three", width=6,
                     space_padding=True) == ("One   \n"
                                             "Two   \n"
                                             "Three ")

    assert text_flow("One Two Three", width=7,
                     space_padding=True) == ("One Two\n"
                                             "Three  ")

    assert text_flow("One Two Three",
                     width=9,
                     left_margin=2,
                     space_padding=True) == ("  One Two\n"
                                             "  Three  ")

    assert text_flow("One Two Three",
                     width=7,
                     left_margin=1,
                     space_padding=True) == (" One   \n"
                                             " Two   \n"
                                             " Three ")
Example #2
0
    def render_rationale(self, check, checkid):
        if not "rationale" in check:
            return ""

        # Ideally we'll at some point invoke a proper markdown
        # parser here. But for now, let's simply fill the raw
        # content into an 80-column block of text and output it
        # enclosed in <pre></pre> tags...
        import html
        from fontbakery.utils import text_flow, unindent_rationale
        content = unindent_rationale(check['rationale'], checkid)
        rationale = html.escape(text_flow(content, 80))
        return f"<pre>--- Rationale ---\n{rationale}</pre>\n"
Example #3
0
    def _render_event_sync(self, print, event):
        status, message, (section, check, iterargs) = event

        if not status.weight >= self._structure_threshold \
           or status in self._skip_status_report:
            return

        if status == START:
            text = super()._render_event(event)
            if text:
                self.stdout.write(text)

        if status == STARTCHECK:
            if self.runner:
                formatted_iterargs = tuple(
                    ('{}[{}]'.format(*item), self.runner.get_iterarg(*item))
                    for item in iterargs)
            else:
                formatted_iterargs = iterargs

            if self.succinct:
                with_string = "All fonts"
                if formatted_iterargs != ():
                    with_string = os.path.basename(
                        f"{formatted_iterargs[0][1]}")

                print((" >> Check:   {}\n"
                       "    Desc:    {}\n"
                       "    Files:   {}").format(
                           self.theme["check-id"](check.id),
                           self.theme["description"](check.description),
                           with_string))

            else:
                # Omit printing of iterargs when there's none of them:
                with_string = ""
                if formatted_iterargs != ():
                    with_string = f"with {formatted_iterargs[0][1]}"

                print((' >> {}\n'
                       '    {}\n'
                       '    {}\n').format(
                           self.theme["check-id"](check.id),
                           self.theme["description"](check.description),
                           with_string))

                if check.rationale:
                    from fontbakery.utils import text_flow, unindent_rationale
                    content = unindent_rationale(check.rationale).strip()
                    print('    ' +
                          self.theme["rationale-title"]("  Rationale:" +
                                                        " " * 64) + '\n' +
                          text_flow(content,
                                    width=76,
                                    indent=4,
                                    left_margin=2,
                                    space_padding=True,
                                    text_color=self.theme["rationale-text"]))

        # Log statuses have weights >= 0
        # log_statuses = (INFO, WARN, PASS, SKIP, FAIL, ERROR, DEBUG)
        if status.weight >= self._log_threshold:
            print('    * {}: {}'.format(formatStatus(self.theme, status),
                                        message))
            if hasattr(message, 'traceback'):
                print('        ',
                      '\n         '.join(message.traceback.split('\n')))

        if status == ENDCHECK:
            if not self.succinct:
                print('\n')
            print('    Result: {}\n'.format(formatStatus(self.theme, message)))

        if status == SECTIONSUMMARY:
            order, counter = message
            print('')
            print('=' * 8, f'Section results: {section}', '=' * 8)
            print('{} {} in section'.format(
                len(order),
                len(order) == 1 and 'check' or 'checks'))
            print('')
            print(_render_results_counter(self.theme, counter))

        if status == END:
            print('')
            if self.results_by:
                print('Collected results by', self.results_by)
                for key in self._collected_results:
                    if self.results_by == '*check':
                        val = key
                    elif key is not None and self.runner:
                        val = self.runner.get_iterarg(self.results_by, key)
                    elif key is not None:
                        val = key
                    else:
                        val = f'(not using "{self.results_by}")'
                    print(f'{self.results_by}: {val}')
                    print(
                        _render_results_counter(self.theme,
                                                self._collected_results[key]))
                    print('')

            print('Total:')
            print('')
            print(_render_results_counter(self.theme, message))
            print('')

            # same end message as parent
            text = super()._render_event(event)
            if text:
                print(text)

            print(
                f"    {self.theme['header']('Meaning of check results:')}\n"
                f"\n"
                f"    An {formatStatus(self.theme, 'ERROR')} is something"
                f" wrong with FontBakery itself, possibly a bug.\n"
                f"    A {formatStatus(self.theme, 'FAIL')} is a problem"
                f" with the font that must be fixed.\n"
                f"    A {formatStatus(self.theme, 'WARN')} is something"
                f" that you should consider addressing.\n"
                f"    An {formatStatus(self.theme, 'INFO')} result simply"
                f" prints something useful. Typically stats.\n"
                f"    A {formatStatus(self.theme, 'PASS')} means the font looks good"
                f" for the given checking routine.\n"
                f"    And a {formatStatus(self.theme, 'SKIP')} happens when the check"
                f" does not apply to the given font.\n"
                f"\n"
                f"    If you get {formatStatus(self.theme, 'ERROR')}s,"
                f" please help us improve the tool by reporting them at\n"
                f"    {self.theme['url']('https://github.com/googlefonts/fontbakery/issues')}\n"
                f"\n"
                f"    (but other kinds of bug reports and/or\n"
                f"     feature requests are also always welcome, of course!)\n"
            )

        if status not in statuses:
            print('-' * 8, status, '-' * 8)
Example #4
0
  def _render_event_sync(self, print, event):
    status, message, (section, check, iterargs) = event

    if not status.weight >= self._structure_threshold \
                                      or status in self._skip_status_report:
      return

    if status == START:
      text = super(TerminalReporter, self)._render_event(event)
      if text:
        self.stdout.write(text)

    if status == STARTSECTION:
      order = message
      print('='*8, str(section),'='*8)
      print('{} {} in section'.format(len(order)
                          , len(order) == 1 and 'check' or 'checks' ))
      print('')

    if status == STARTCHECK:
      if self.runner:
        formatted_iterargs = tuple(
            ('{}[{}]'.format(*item), self.runner.get_iterarg(*item))
                                                    for item in iterargs)
      else:
        formatted_iterargs = iterargs

      # Omit printing of iterargs when there's none of them:
      with_string = ""
      if formatted_iterargs != ():
        with_string = f"with {formatted_iterargs[0][1]}"

      print((' >> {}\n'
             '    {}\n'
             '    {}\n').format(
        self.theme["check-id"](check.id),
        self.theme["description"](check.description),
        with_string))

      if check.rationale:
        from fontbakery.utils import text_flow, unindent_rationale
        content = unindent_rationale(check.rationale).strip()
        print('    ' + self.theme["rationale-title"]("  Rationale:" + " " * 64) + '\n'
              + text_flow(content,
                          width=76,
                          indent=4,
                          left_margin=2,
                          space_padding=True,
                          text_color=self.theme["rationale-text"]))

    # Log statuses have weights >= 0
    # log_statuses = (INFO, WARN, PASS, SKIP, FAIL, ERROR, DEBUG)
    if status.weight >= self._log_threshold:
      print('    * {}: {}'.format(formatStatus(self.theme, status),
                                  message))
      if hasattr(message, 'traceback'):
        print('        ','\n         '.join(message.traceback.split('\n')))

    if status == ENDCHECK:
      print('\n    Result: {}\n'.format(formatStatus(self.theme, message)))

    if status == ENDSECTION:
      print('')
      print('Section results:')
      print('')
      print(_render_results_counter(self.theme, message))
      print('')
      print ('='*8, f'END {section}','='*8)

    if status == END:
      print('')
      if self.results_by:
        print('Collected results by', self.results_by)
        for key in self._collected_results:
          if self.results_by == '*check':
            val = key
          elif key is not None and self.runner:
            val = self.runner.get_iterarg(self.results_by, key)
          elif key is not None:
            val = key
          else:
            val = f'(not using "{self.results_by}")'
          print(f'{self.results_by}: {val}')
          print(_render_results_counter(self.theme, self._collected_results[key]))
          print('')

      print('Total:')
      print('')
      print(_render_results_counter(self.theme, message))
      print('')

      # same end message as parent
      text = super(TerminalReporter, self)._render_event(event)
      if text:
        print(text)

    if status not in statuses:
      print('-'*8, status , '-'*8)