docs: def generate(self, output_file=None):
          """
          Generates an HTML file based on data from the Parser object and Jinja2 templates
          :param output_file: If specified, output will be written to this file instead of stdout.
          """
  
          fd = output_file
  
          # Write to stdout if we do not have a file to write to
          if not fd:
              fd = stdout
          else:
              try:
                  fd = open(output_file, 'w')
              except IOError as e:
                  stderr.write('Unable to open outputfile %s: %s' % (output_file, e))
  
          with open(os.path.join(os.path.dirname(__file__), 'templates/base.html')) as template:
              html = Template(template.read())
  
              # Write potential build messages to stdout if we are writing to HTML file
              # If dest is stdout and supposed to be piped or redirected, build messages like TeamCity's will
              # have no effect, since they require to read from stdin.
              if output_file:
                  self.report_build_messages()
  
              # Write our rendered template to the file descriptor
              fd.write(
                  html.render(
                      files=sorted(self.files.values(), key=lambda x: x.path),
                      total_warnings=self.total_warnings,
                      total_errors=self.total_errors,
                      total_other=self.total_other,
                      violations=sorted(
                          ((code, count) for code, count in self.violations.items()),
                          key=lambda x: x[1],
                          reverse=True,
                      )
                  )
              )
  
              # If file descriptor is stdout
              if not output_file:
                  fd.flush()
              else:
                  fd.close()