Skip to content

SCR900: pylint

Message reported by pylint

Code SCR900
Name pylint
Category Scripts (SCR)
Default severity warning
Enabled by default no
Fix available sometimes
Fix safety safe or unsafe, depending on the finding (see below)
ign-lint equivalent PylintScriptRule, PerspectiveScriptPylintRule

Runs the real pylint over every script and reports its messages at their exact place in the file: library modules, gateway, session and WebDev event files, and every script embedded in a view, session properties or tags (with the def header Ignition compiles it under). This is the equivalent of ign-lint's PylintScriptRule.

pylint runs once per lint run, in one process, over all scripts. Each script is linted as its own module, so module-wide checks (such as inconsistent-quotes) never mix scripts. pylint must be installed (pip install pylint); when it cannot be started, the run prints one warning and every other rule still runs.

The rule severity (severity in [rules.SCR900]) applies only to message categories that category-mapping does not map: for a mapped category the mapping wins, for every kind of script (library modules, event scripts, WebDev, views, tags). With severity = "error" and category-mapping = { C = "warning" }, C0103 is a warning everywhere.

Messages that pylint gets wrong for Ignition are not reported:

  • undefined-variable and import-error for names every script sees (system, fpmi, sys, the project's top-level library packages) and for Jython 2.7 builtins (xrange, basestring, unicode, ...). When the project's library is not known (scripts outside a project), undefined-variable is not reported at all, like SCR101.
  • syntax-error for scripts that are valid Jython 2.7 (pylint parses Python 3, so print "x" or except E, e: fail there). Real syntax errors are SCR001's; syntax-error is reported only when the script does not parse and SCR001 is disabled.
  • Naming, docstring, argument and signature messages about the generated header (def runAction(self, event):), which Ignition writes and the user cannot change. Other messages located in the header (such as too-many-branches) are reported at the script's property. Custom method headers are the user's, so all of their messages are reported.

pylint has hundreds of checks beyond iglint's native SCR rules (conventions, refactoring hints, many more error classes). Teams that used ign-lint's pylint integration keep the same checks, without its combined-file artefacts (wrong line numbers, one Python 2 statement hiding every finding of a view, messages leaking between scripts).

def runAction(self, event):
if self.props.text == None:
self.props.text = "empty"
Comparison 'self.props.text == None' should be 'self.props.text is None' (singleton-comparison, C0121)
  • pylint (default "pylint"): the command that runs pylint, with arguments, split on whitespace (for example "python3 -m pylint --enable=C0303"). Single and double quotes group a word that contains spaces ("'/opt/my tools/pylint' --jobs=1"); inside double quotes \" and \\ escape, other backslashes are literal (Windows paths). Every argument is passed to pylint, before iglint's own. A relative path with a directory part is relative to the project root.
  • pylintrc (unset by default): pylint configuration file, relative to the project root. By default iglint uses its bundled configuration: ign-lint's .ignition-pylintrc (MIT License), which also disables unused-argument, missing-docstring, redefined-outer-name and function-redefined as ign-lint's combined file did. A missing file falls back to the bundled configuration with a warning.
  • jobs (default 0): number of pylint processes that run at the same time, each on a share of the scripts (with pylint's --jobs=1); 0 (the default) starts one per CPU, 1 lints in a single process. Fewer processes are started when there are few scripts (at least 8 per process). Scripts are independent modules, so the findings do not depend on jobs. Where possible (POSIX, and a pylint script or python -m pylint as the command), one Python process imports pylint once and forks the others.
  • disable (default []): pylint messages to disable in addition to the configuration file (passed as --disable). Empty by default. ign-lint's combined file starts with #pylint: disable=unused-argument,missing-docstring,redefined-outer-name,function-redefined, which applies whatever rcfile is used; a configuration read from an ign-lint rule_config.json (and iglint ign-lint) therefore sets disable to those four messages, so equal configurations give equal findings. The bundled configuration disables them already; with your own pylintrc in iglint.toml they are reported unless the rcfile or disable turns them off.
  • category-mapping (default { F = "error", E = "error", W = "warning", C = "warning", R = "warning" }): severity per pylint message category letter (F, E, W, C, R, I). It replaces the default (F and E errors, W, C and R warnings); categories it leaves out get the rule severity.

When pylint reports trailing-whitespace (C0303, disabled by the bundled configuration), the script's first such finding carries ign-lint's fix: every line of the script is rstrip()ed. Safe, except when whitespace inside a multi-line string literal (or after a backslash in a string Jython drops) would be removed, the script does not parse, or the edit changes a token of the script (whitespace after a stray backslash, which Jython's lexer reads): then unsafe. SCR124 is the native equivalent. Like every fix, it is unsafe while code in the workspace may read the files a fix edits (any file access, read, write, rename or delete, whose path is not a literal outside the workspace, or code that is not vetted); the project setting [fix] assume-scripts-do-not-read-workspace-files = true declares that no script does (see docs/internal/fix-safety.md, "File reads").

A message that a native rule also reports at the same place (and about the same name), for example undefined-variable and SCR101, is shown only as the native finding.

Results are cached with the rest of the run. The cache key includes the command, jobs and the content of the pylint configuration, but not pylint's version: run with --no-cache after upgrading pylint.

Set in [rules.SCR900] of iglint.toml (or [tool.iglint.rules.SCR900] in pyproject.toml).

Option Type Default Description
pylint string "pylint" Command that runs pylint, split on whitespace.
pylintrc string none pylint configuration file relative to the project root; the bundled one by default.
jobs integer 0 Number of parallel pylint processes: 0 is one per CPU.
disable array of strings [] pylint messages disabled in addition to the configuration file.
category-mapping table { F = "error", E = "error", W = "warning", C = "warning", R = "warning" } Severity per pylint category letter; replaces the default.

ign-lint kwargs in a rule_config.json: pylintrc -> pylintrc, category_mapping -> category-mapping.


Generated from the rule metadata by iglint generate-docs; iglint rule SCR900 prints the same page in the terminal. Source: docs/rules/SCR900.md.