Extending the Library¶
Extending the library is welcome, however it is best to open an issue first, to ensure that a PR would be accepted and makes sense in terms of features and design.
Extending the Linting Rules¶
Extending the rules is welcome, however it is best to open an issue first, to ensure that a PR would be accepted and makes sense in terms of coverage and design.
Adding New Rules¶
To add new rules, either add them to an existing category/checker (if it makes sense) or create a new one. Each checker is a class (e.g. class NautobotCodeLocationChangesChecker(BaseChecker)) which implements one or more pylint rules.
Before creating a Pylint-Nautobot checker, we recommend reviewing Pylint's How to Write a Checker. Pylint-Nautobot uses the BaseChecker class from pylint. Most checkers are AST checkers which use the astroid Python library. We recommend reading the Astroid Inference Introduction for a guide on AST.
Pylint also has two other kinds of checkers that can be found in the guide linked above.
Version Specifiers¶
Every check should have a class variable called version_specifier which is a string that follows the packaging.specifiers.SpecifierSet syntax. It is used as a filter for which versions of Nautobot a check applies to.
The following example is a checker that applies to all projects targeting any Nautobot 2.x.y version:
from pylint.checkers import BaseChecker
class NautobotSpecificExampleChecker(BaseChecker):
version_specifier = ">=2,<3"
...
Note
For a detailed overview of how you can specify versions take a look at PEP440. However, in general you should strive for as simple as possible version specifiers.
Writing the Rule¶
Rule Message¶
Each rule should have a unique message id. From the Pylint documentation:
The message-id should be a 4-digit number, prefixed with a message category. There are multiple message categories, these being
C,W,E,F,R, standing forConvention,Warning,Error,FatalandRefactoring. The 4 digits should not conflict with existing checkers and the first 2 digits should consistent across the checker (except shared messages).
You can run poetry run pylint --load-plugins=pylint_nautobot --list-msgs-enabled to see all the enabled messages in your environment and check if your desired message id is already in use. Pylint Nautobot does not have a strict convention for message ids, but it is recommended to use the 42xx range for new rules.
In addition to the unique message id, you must also provide a unique message symbol. This is an alias of the message id and it can be used wherever the message id can be used. The message symbol must start with "nb-". See the below example of a custom Pylint checker definition:
class NautobotCodeLocationChangesChecker(BaseChecker):
"""Visit 'import from' statements to find import locations that have moved in 2.0."""
version_specifier = ">=2,<3"
name = "nautobot-code-location-changes"
msgs = {
"E4251": ( # message id
"Import location has changed (%s -> %s).", # template of displayed message
"nb-code-location-changed", # message symbol
"Reference: https://docs.nautobot.com/projects/core/en/next/development/apps/migration/code-updates/", # message description
)
}
Testing Rules in a Specific Nautobot App¶
To test your new rules on another Nautobot project while developing, you can add your local pylint-nautobot environment in editable mode to it.
First, clone a repository containing a specific Nautobot App:
Install pylint-nautobot in editable mode from your cloned repo:
Enable the pylint-nautobot plugin in the target App's pyproject.toml:
Test whether the new rules are enabled, replacing the message codes with your own, by running the following in the nautobot-plugin-golden-config folder:
> poetry run pylint --list-msgs-enabled | grep nb-
nb-replaced-device-role (E4211)
nb-replaced-rack-role (E4212)
nb-replaced-ipam-role (E4213)
nb-replaced-region (E4214)
nb-replaced-site (E4215)
nb-replaced-aggregate (E4216)
nb-code-location-utilities (E4251)
While developing, you'll want to scope the linting only to your current set of rules - for example, here we're only testing for the nautobot-code-location-changes group of rules:
> poetry run pylint nautobot_golden_config --disable=all --enable=nautobot-code-location-changes
************* Module nautobot_golden_config.navigation
nautobot_golden_config/navigation.py:4:0: E4251: Import location has changed (nautobot.utilities.choices -> nautobot.core.choices). (nb-code-location-changed)
************* Module nautobot_golden_config.forms
nautobot_golden_config/forms.py:10:0: E4251: Import location has changed (nautobot.utilities.forms -> nautobot.core.forms). (nb-code-location-changed)
nautobot_golden_config/forms.py:12:0: E4252: Import location has changed for TreeModelSerializerMixin (nautobot.core.api.utils -> nautobot.core.api.serializers). (nb-code-location-changed-object)
nautobot_golden_config/forms.py:13:0: E4252: Import location has changed for deepmerge (nautobot.utilities.utils -> nautobot.core.utils.data). (nb-code-location-changed-object)
************* Module nautobot_golden_config.tables
nautobot_golden_config/tables.py:9:0: E4251: Import location has changed (nautobot.utilities.tables -> nautobot.core.tables). (nb-code-location-changed)
... output trimmed ...
Should you want to perform the full pylint suite of tests, follow the project's development setup (for Nautobot Apps typically invoke pylint).