text: # Copyright 2017-2020 Palantir Technologies, Inc.
  # Copyright 2021- Python Language Server Contributors.
  
  import logging
  import pycodestyle
  from pylsp import hookimpl, lsp
  
  try:
      from autopep8 import continued_indentation as autopep8_c_i
  except ImportError:
      pass
  else:
      # Check if autopep8's continued_indentation implementation
      # is overriding pycodestyle's and if so, re-register
      # the check using pycodestyle's implementation as expected
      if autopep8_c_i in pycodestyle._checks['logical_line']:
          del pycodestyle._checks['logical_line'][autopep8_c_i]
          pycodestyle.register_check(pycodestyle.continued_indentation)
  
  log = logging.getLogger(__name__)
  
  
  @hookimpl
  def pylsp_lint(workspace, document):
      config = workspace._config
      settings = config.plugin_settings('pycodestyle', document_path=document.path)
      log.debug("Got pycodestyle settings: %s", settings)
  
      opts = {
          'exclude': settings.get('exclude'),
          'filename': settings.get('filename'),
          'hang_closing': settings.get('hangClosing'),
          'ignore': settings.get('ignore'),
          'max_line_length': settings.get('maxLineLength'),
          'indent_size': settings.get('indentSize'),
          'select': settings.get('select'),
      }
      kwargs = {k: v for k, v in opts.items() if v}
      styleguide = pycodestyle.StyleGuide(kwargs)
  
      c = pycodestyle.Checker(
          filename=document.uri, lines=document.lines, options=styleguide.options,
          report=PyCodeStyleDiagnosticReport(styleguide.options)
      )
      c.check_all()
      diagnostics = c.report.diagnostics
  
      return diagnostics
  
  
  class PyCodeStyleDiagnosticReport(pycodestyle.BaseReport):
  
      def __init__(self, options):
          self.diagnostics = []
          super().__init__(options=options)
  
      def error(self, line_number, offset, text, check):
          code = text[:4]
          if self._ignore_code(code):
              return
  
          # Don't care about expected errors or warnings
          if code in self.expected:
              return
  
          # PyCodeStyle will sometimes give you an error the line after the end of the file
          #   e.g. no newline at end of file
          # In that case, the end offset should just be some number ~100
          # (because why not? There's nothing to underline anyways)
          err_range = {
              'start': {'line': line_number - 1, 'character': offset},
              'end': {
                  # FIXME: It's a little naiive to mark until the end of the line, can we not easily do better?
                  'line': line_number - 1,
                  'character': 100 if line_number > len(self.lines) else len(self.lines[line_number - 1])
              },
          }
          self.diagnostics.append({
              'source': 'pycodestyle',
              'range': err_range,
              'message': text,
              'code': code,
              # Are style errors really ever errors?
              'severity': _get_severity(code)
          })
  
  
  def _get_severity(code):
      # Are style errors ever really errors?
      if code[0] == 'E' or code[0] == 'W':
          return lsp.DiagnosticSeverity.Warning
      # If no severity is specified, why wouldn't this be informational only?
      return lsp.DiagnosticSeverity.Information
  