maite.testing.pyright.pyright_analyze#
- maite.testing.pyright.pyright_analyze(*code_objs_and_or_paths, pyright_config=None, scan_docstring=False, path_to_pyright=None, preamble='', python_version=None, report_unnecessary_type_ignore_comment=None, type_checking_mode=None)[source]#
Scan a Python object, docstring, or file with pyright.
The following file formats are supported:
py
,rst
,md
, andipynb
.Some common pyright configuration options are exposed via this function for convenience; a full pyright JSON config can be specified to completely control the behavior of pyright.
This function requires that pyright is installed and can be run from the command line [1].
- Parameters:
- *code_objs_and_or_pathsAny
A function, module-object, class, or method to scan. Or, a path to a file to scan. Supported file formats are
py
,rst
,md, and `.ipynb
.Specifying a directory is permitted, but only
py
files in that directory will be scanned. All files will be copied to a temporary directory before being scanned.- pyright_configNone | dict[str, Any]
A JSON configuration for pyright’s settings [2].
- scan_docstringbool, optional (default=False), keyword-only
If
True
pyright will scan the docstring examples of the specified code object, rather than the code object itself.Example code blocks are expected to have the doctest format [3].
- path_to_pyrightPath, optional, keyword-only
Path to the pyright executable (see installation instructions: [4]). Defaults to
shutil.where('pyright')
if the executable can be found.- preamblestr, optional (default=’’), keyword-only
A “header” added to the source code that will be scanned. E.g., this can be useful for adding import statements.
- python_versionstr | None, keyword-only
The version of Python used for this execution environment as a string in the format “M.m”. E.g., “3.9” or “3.7”.
- report_unnecessary_type_ignore_commentbool | None, keyword-only
If
True
specifying# type: ignore
for an expression that would otherwise not result in an error will cause pyright to report an error.- type_checking_modeLiteral[“basic”, “strict”] | None, keyword-only
Modifies pyright’s default settings for what it marks as a warning verses an error. Defaults to ‘basic’.
- Returns:
- list[dict[str, Any]] (In one-to-one correspondence with
code_objs_and_or_paths
) - The JSON-decoded results of the scan [3].
version: str
time: str
generalDiagnostics: list[DiagnosticDict] (one entry per error/warning)
summary: SummaryDict
See Notes for more details.
- list[dict[str, Any]] (In one-to-one correspondence with
Notes
When supplying a single .rst file, code blocks demarcated by
code-block:: py[thon,con]
are parsed and used to populate a single temporary .py file that pyright will scan.SummaryDict
consists of:filesAnalyzed: int
errorCount: int
warningCount: int
informationCount: int
timeInSec: float
DiagnosticDict
consists of:file: str
severity: Literal[“error”, “warning”, “information”]
message: str
range: _Range
rule: NotRequired[str]
References
Examples
Here pyright will record an error when scan a function that attempts to add a string-annotated variable to an integer.
>>> from maite.testing.pyright import pyright_analyze >>> def f(x: str): ... return 1 + x >>> pyright_analyze(f)[0] {'version': ..., 'time': ..., 'generalDiagnostics': [{'file': ..., 'severity': ..., 'message': 'Operator "+" not supported for types "Literal[1]" and "str"', 'range': {'start': {'line': ..., 'character': ...}, 'end': {'line': ..., 'character': ...}}, 'rule': ...}], 'summary': {'filesAnalyzed': ..., 'errorCount': 1, 'warningCount': 0, 'informationCount': 0, 'timeInSec': ...}}
Whereas this function scans “clean”.
All imports must occur within the context of the scanned-object, or the imports can be specified in a preamble. For example, consider the following
>>> import math # import statement is not be in scope of `f` >>> def f(): ... math.acos(1) >>> pyright_analyze(f)[0]["summary"]["errorCount"] 1
We can add a ‘preamble’ do that the
math
module is imported.>>> pyright_analyze(f, preamble="import math")[0]["summary"]["errorCount"] 0
Scanning a function’s docstring.
>>> def plus_1(x: int): ... ''' ... Examples ... -------- ... >>> from mylib import plus_1 ... >>> plus_1('2') # <- pyright_analyze will catch typo (str instead of int) ... 3 ... ''' ... return x + 1 >>> pyright_analyze(plus_1, scan_docstring=True)[0]["summary"]["errorCount"] # nested notional example has fake import --> 1
Fixing the docstring issue
>>> def plus_1(x: int): ... ''' ... Examples ... -------- ... >>> from mylib import plus_1 ... >>> plus_1(2) ... 3 ... ''' ... return x + 1 >>> pyright_analyze(plus_1, scan_docstring=True)[0]["summary"]["errorCount"] # nested notional example has fake import --> 0