/datajoint_linter

Linting tools for DataJoint table classes. Catching issues in the IDE, before declaration

Primary LanguagePythonMIT LicenseMIT

DataJoint Linter

Linting tool for DataJoint table classes. Catching issues in the IDE, before declaration.

Installation

git clone https://github.com/CBroz1/datajoint_linter
pip install datajoint_linter # in your IDE's python environment

VSCode

  1. Install the PyLint Extension

  2. Test your installation on the example schema to see example errors.

    cd datajoint_linter
    pylint tests/schema_bad.py
  3. If the above finds errors, find your pylint path. If not, you may need to run pylint from another installed source. Try finding them with whereis and note the path that succeeds in finding errors.

    whereis pylint
  4. Add the following to your settings.json file:

    {
        "pylint.path": [
            "/your/path/pylint"
        ],
        "pylint.args": [
            "--load-plugins=datajoint_linter",
            "--permit-dj-filepaths=n",
            "--disable=E0401,W0401,W0611,W0621"
        ]
    }

permit-dj-filepath will quiet warnings about use of filepath datatypes. Setting it to y will enable filepath datatypes.

The above disable codes are recommended for any DataJoint project. They disable ...

  • E0401: Unable to import - installed packages vary by environment
  • E0102: Function redefined - for Merge tables
  • W0611: Unused import - for foreign key imports
  • W0621: Outer scope - false positives on key in make

Neovim

null-ls is now deprecated. Alternative configs (e.g, efm-langserver) may look similar.

local null_ls = require "null-ls"
local lint = null_ls.builtins.diagnostics
local sources = {
    lint.pylint.with({ extra_args = {
        "--load-plugins=datajoint_linter",
        "--permit-dj-filepaths=y", 
        "--disable=E0401,W0401,W0611,W0621"
    }})
}

How it works

This package is a static analysis tool of the definition for standard Tables (plus _Merge tables). It will catch ...

  • Bad data types
  • Definition syntax errors (e.g., nullable primary key)
  • Foreign key references to objects not in the namespace

Without running your code, it won't catch foreign type errors. For example,

  • -> m.NonexistentClass will only be checked before the . to test for the presence m in the namespace (e.g, import my_module as m)
  • -> imported_obj will only be checked for the presence of imported_obj in the namespace (e.g., from my_module import imported_obj). It will not check that DataJoint supports referencing this object type as foreign keys.
  • -> Table.proj(new='bad_key') will not be caught as the linter does not check the contents of projections

This linter also does not execute checks to see if filepath types have been enabled in the user's environment. To enable them, use the --permit-dj-filepaths flag. Definitions that are not string constants (e.g., those generated by functions) will be ignored.

Tests

Tests passing as of datajoint-python version 0.14.1.

pytest .

To do

Portions of the linter rely on extracted pieces from DataJoint's compile_foreign_key method syntax because the prepare_declare without any context, which prempively hits the first error in this method. This project could be significantly optimized by ...

  1. Running dynamic analysis, to fully process foreign key references in context.
  2. A PR to datajoint-python to extract pieces of declaration into private methods to be reused here.