# Python

## Supported versions <a href="#supported-versions" id="supported-versions"></a>

The level of support for a language is defined as follows:

* Fully supported: Analysis will complete. All the language features are understood and examined.
* Supported: Most language features are understood and examined but the version includes unsupported features. Analysis might break or provide incomplete results.

Python versions 3.0 to 3.14 are fully supported.

Python 2.7 is supported.

## Supported tools and frameworks <a href="#supported-tools-and-frameworks" id="supported-tools-and-frameworks"></a>

Django, FastAPI, Flask, Jupyter Notebooks, Numpy, Pandas, PySpark, PyTorch, Tensorflow and Scikit-learn.

## Language-specific properties <a href="#language-specific-properties" id="language-specific-properties"></a>

Discover and update the Python-specific [analysis-parameters](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/analysis-parameters "mention") by going to **Administration** > **Configuration** > **General Settings** > **Languages** > **Python**

## Handling project Python version <a href="#project-python-version" id="project-python-version"></a>

Python code is analyzed by default as compatible with python 2 and python 3. Some issues will be automatically silenced to avoid raising False Positives. In order to get a more precise analysis you can specify the Python versions your code supports via the `sonar.python.version` parameter.

The accepted format is a comma-separated list of versions having the format "X.Y". Here are some examples:

* `sonar.python.version=2.7`
* `sonar.python.version=3.8`
* `sonar.python.version=2.7, 3.7, 3.8, 3.9`

This parameter can be used in the *sonar-project.properties* file or the SonarScanner CLI command.

## Custom rules <a href="#custom-rules" id="custom-rules"></a>

## Overview <a href="#overview" id="overview"></a>

The Python analyzer parses the source code, creates an abstract syntax tree (AST), and then walks through the entire tree. A coding rule is a visitor that is able to visit nodes from this AST.

As soon as the coding rule visits a node, it can navigate its children and log issues if necessary.

### Writing a plugin <a href="#writing-a-plugin" id="writing-a-plugin"></a>

Custom rules for Python can be added by writing a SonarQube Server Plugin and using Python analyzer APIs. Here are the steps to follow:

**Create a SonarQube Server plugin**

* Create a standard SonarQube Server plugin project.
* Attach this plugin to SonarQube Server’s Python analyzer through the `pom.xml`:
  * Add the dependency to the Python analyzer.
  * Add the following line in the sonar-packaging-maven-plugin configuration. `<requirePlugins>python:2.0-SNAPSHOT</requirePlugins>`
* Implement the following extension points:
  * [Plugin](https://javadocs.sonarsource.org/10.3.0.1951/org/sonar/api/Plugin.html)
  * [RulesDefinition](https://javadocs.sonarsource.org/10.3.0.1951/org/sonar/api/server/rule/RulesDefinition.html) and [PythonCustomRuleRepository](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/PythonCustomRuleRepository.java), which can be implemented by a single class, to declare your custom rules.
* Declare the RulesDefinition as an extension in the Plugin extension point.

**Implement a rule**

* Create a class that will hold the implementation of the rule, it should:
  * extend `PythonVisitorCheck` or `PythonSubscriptionCheck`.
  * Define the rule name, key, tags, etc. This can be done either by adding Java annotations or by adding them directly in the corresponding JSON file, like [this one](https://github.com/SonarSource/sonar-python/blob/master/docs/python-custom-rules-example/src/main/resources/org/sonar/l10n/python/rules/python/subscription.json).
* declare this class in the `RulesDefinition`.

### Example plugin <a href="#example-plugin" id="example-plugin"></a>

A sample plugin can be found here: [python-custom-rules-example](https://github.com/SonarSource/sonar-python/tree/master/docs/python-custom-rules-example) to help you get started.

### Implementation details <a href="#implementation-details" id="implementation-details"></a>

**Using PythonVisitorCheck**

To explore a part of the AST, override a method from `PythonVisitorCheck`. For example, if you want to explore "if statement" nodes, override the `visitIfStatement` method that will be called each time an [ifStatement](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/tree/IfStatement.java) node is encountered in the AST.

{% hint style="warning" %}
When overriding a visit method, you must call the super method in order to allow the visitor to visit the children of the node.
{% endhint %}

**Using PythonSubscriptionCheck**

To explore a part of the AST, override [`PythonSubscriptionCheck#initialize`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/SubscriptionCheck.java#L26) and call [`SubscriptionCheck.Context#registerSyntaxNodeConsumer`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/SubscriptionCheck.java#L30) with the [`Tree#Kind`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/tree/Tree.java#L42) of node you want to visit. For example, if you want to explore "if statement", you should register to the kind [`Tree#Kind#IF_STATEMENT`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/tree/Tree.java#L115) and then provide a lambda that will consume a [`SubscriptionContext`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/SubscriptionContext.java#L33) to act on such nodes.

**Create issues**

From the check, an issue can be created by calling the [`SubscriptionContext#addIssue`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/SubscriptionContext.java#L36) method or a `PythonVisitorCheck` [`#addIssue`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-frontend/src/main/java/org/sonar/plugins/python/api/PythonVisitorCheck.java#L35) method.

**Testing checks**

You can use the [`PythonCheckVerifier#verify`](https://github.com/SonarSource/sonar-python/blob/c957e33/python-checks-testkit/src/main/java/org/sonar/python/checks/utils/PythonCheckVerifier.java) method to test custom checks. Don’t forget to add the testkit dependency to access this class from your project:

```css-79elbk
  <dependency>
      <groupId>org.sonarsource.python</groupId>
      <artifactId>python-checks-testkit</artifactId>
      <version>${project.version}</version>
      <scope>test</scope>
  </dependency>
```

You should end each line having an issue with a comment in the following form:

```css-79elbk
# Noncompliant {{Message}}
```

Comment syntax is described [here](https://github.com/SonarSource/sonar-analyzer-commons/blob/38db754/test-commons/README.md).

### Configuring plugins for analyzer loading optimization <a href="#configuring-plugins-for-analyzer-loading-optimization" id="configuring-plugins-for-analyzer-loading-optimization"></a>

By default, the loading of analyzers is optimized (see [Improving performance](https://app.gitbook.com/s/iJj3TXBdWssTGGg8qK5I/server-upgrade-and-maintenance/maintenance/improving-performance "mention")), SonarQube Server will only download analyzers and third-party plugins for the detected languages before running an analysis.

When creating custom plugins, to prevent errors when projects are analyzed, "you must use the `requiredForLanguages` property in your plugin’s `pom.xml` file (Gradle: `Plugin-RequiredForLanguages` in the MANIFEST directly) to specify the languages your plugin supports. Without this property, your plugin will be executed unconditionally during analysis, even when its language-specific dependencies are unavailable. See [plugin-basics](https://docs.sonarsource.com/sonarqube-server/extension-guide/developing-a-plugin/plugin-basics "mention") for details on this behavior and the `requiredForLanguages` property.

```css-79elbk
<configuration>
   [...]
   <requiredForLanguages>python</requiredForLanguages>
</configuration>
```

## Jupyter Notebooks <a href="#jupyter-notebooks" id="jupyter-notebooks"></a>

Jupyter Notebooks are an open document format based on JSON. They are used for all sorts of data science tasks: data cleaning and transformation, data visualization, statistical modeling, machine learning, deep learning, etc.

### Supported versions <a href="#supported-versions" id="supported-versions"></a>

SonarQube Server can analyze Jupyter Notebooks nbformat.v4 and later.

### Specific properties <a href="#specific-properties" id="specific-properties"></a>

Discover and update the Jupyter Notebooks-specific [analysis-parameters](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/analysis-parameters "mention") by going to **Administration** > **General Settings** > **Languages** > **Python** > **Jupyter Notebooks**.

### Managing rules <a href="#managing-rules" id="managing-rules"></a>

Jupyter Notebook rules can be enabled and disabled in your quality profile. See [editing-a-custom-quality-profile](https://docs.sonarsource.com/sonarqube-server/quality-standards-administration/managing-quality-profiles/editing-a-custom-quality-profile "mention").

### Jupyter Notebooks in SonarQube for VSCode <a href="#jupyter-notebooks-in-sonarqube-for-vscode" id="jupyter-notebooks-in-sonarqube-for-vscode"></a>

You can analyze your Jupyter Notebooks projects directly in VS Code. Note that [connected mode](https://docs.sonarsource.com/sonarqube-server/user-guide/connected-mode) will be ignored when working with Jupyter Notebooks (if this feature is important to you, you can [submit the idea on SonarQube Server’s portal](https://portal.productboard.com/sonarsource/3-sonarqube/tabs/5-under-consideration)).

### Important notes <a href="#important-notes" id="important-notes"></a>

* Only Python code is analyzed in Jupyter Notebooks.
* Only primary locations are shown (see the [Issues](https://docs.sonarsource.com/sonarqube-server/user-guide/issues/introduction) page to learn more about primary vs. secondary locations).
* Analysis does not measure code duplication at this time.

## Parallel code scan

By default, the Python analyzer tries to parallelize the analysis of files; it uses 90% of the cores available, up until 6.

If required, it is possible to customize the number of scheduled parallel jobs by configuring the property `sonar.python.analysis.threads n` at the scanner level, where `n` is an integer indicating the number of threads allocated for the analysis.

You should consider setting the `sonar.python.analysis.threads` property only when the automatic detection of the number of logical CPUs cannot detect the desired number.

A typical example is when the analysis should not consume all the available computing resources to leave room for other tasks running in parallel on the same machine.

When setting the `sonar.python.analysis.threads` property, you should set it to a value less or equal to the number of logical CPUs available. Over-committing does not accelerate the analysis and can even slow it down.

You can disable parallel code scan for Python by setting the property `sonar.python.analysis.parallel` to `false`. This can be useful when debugging an analysis.

## Related Pages <a href="#related-pages" id="related-pages"></a>

* [external-analyzer-reports](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/importing-external-issues/external-analyzer-reports "mention") ([Pylint](https://pylint.pycqa.org/), [Bandit](https://github.com/PyCQA/bandit/blob/master/README.rst), [Flake8](https://flake8.pycqa.org/en/latest/))
* [overview](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/test-coverage/overview "mention") (the [Coverage tool](http://nedbatchelder.com/code/coverage/) provided by [Ned Batchelder](http://nedbatchelder.com/), [Nose](https://nose.readthedocs.org/en/latest/), [pytest](https://docs.pytest.org/en/latest/))
