Permalink
Fetching contributors…
Cannot retrieve contributors at this time
151 lines (86 sloc) 5.82 KB

PythonLinter class

If your linter plugin interfaces with a linter that is written in python, you should subclass from SublimeLinter.lint.PythonLinter.

Note

This is done for you if you use the :ref:`Create Linter Plugin <create-linter-plugin-command>` command and select Python as the linter language.

By doing so, you get the following features:

SublimeLinter-flake8, SublimeLinter-pep8, and SublimeLinter-pyflakes are good examples of python-based linters.

check (method)

check(self, code, filename)

If your PythonLinter subclass sets the :ref:`module <module>` attribute, you must implement this method.

This method is called if:

This method should perform linting and return a string with one more lines per error, an array of strings, or an array of objects that can be converted to strings. Here is the check method from the Flake8 class, which is a good template for your own check implementations:

def check(self, code, filename):
    """Run flake8 on code and return the output."""

    options = {
        'reporter': Report
    }

    type_map = {
        'select': [],
        'ignore': [],
        'max-line-length': 0,
        'max-complexity': 0
    }

    self.build_options(options, type_map, transform=lambda s: s.replace('-', '_'))

    if persist.settings.get('debug'):
        persist.printf('{} options: {}'.format(self.name, options))

    checker = self.module.get_style_guide(**options)

    return checker.input_file(
        filename=os.path.basename(filename),
        lines=code.splitlines(keepends=True)
    )

A few things to note:

  • We use the :ref:`build_options` method to build the options expected by the get_style_guide method.
  • We print the options to the console if we are in debug mode.

check_version (class attribute)

Some python-based linters are version-sensitive; the python version they are run with has to match the version of the code they lint. If you define the :ref:`module <module>` attribute, this attribute should be set to True if the linter is version-sensitive.

cmd (class attribute)

When using a python-based linter, there is a special form that should be used for the cmd attribute:

script@python[version]

script is the name of the linter script, and version is the optional version of python required by the script.

For example, the SublimeLinter-pyflakes linter plugin defines cmd as:

cmd = 'pyflakes@python'

This tells |sl| to locate the pyflakes script and run it on the system python or the version of python configured in settings.

When using the script@python form, |sl| does the following:

  • Locates script in a cross-platform way. Python scripts are installed differently on Windows than they are on Mac OS X and Linux.
  • Does version matching between the version specified in the cmd attribute and the version specified by settings.
  • Defers to using the built-in python if possible.

module (class attribute)

If you want to import a python module and run a method directly in order to lint, this attribute should be set to the module name, suitable for passing to importlib.import_module. During class construction, the named module will be imported, and if successful, the attribute will be replaced with the imported module.

Note

Because the module is going to run within |st|, it must be compatible with python 3.3 or later. If not, do not define this attribute.

For example, the Flake8 linter class defines:

module = 'flake8.engine'

Later, when it wants to use the method flake8.engine.get_style_guide, it does so like this:

checker = self.module.get_style_guide(**options)

If the module attribute is defined and is successfully imported, whether it is used depends on the following algorithm:

If you set the module attribute, you must implement the :ref:`check <check-method>` in your PythonLinter subclass in order to use the module to do the linting.