# Python

## 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/10.7/analyzing-source-code/analysis-parameters "mention") in **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.py.version` parameter.

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

* `sonar.py.version=2.7`
* `sonar.py.version=3.8`
* `sonar.py.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 Plugin and using Python analyzer APIs. Here are the steps to follow:

**Create a SonarQube plugin**

* Create a standard SonarQube plugin project.
* Attach this plugin to the SonarQube 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. with Java annotations.
* 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](https://github.com/SonarSource/sonar-custom-rules-examples/tree/master/python-custom-rules) 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://docs.sonarsource.com/sonarqube-server/10.7/server-upgrade-and-maintenance/maintenance/improving-performance "mention")), SonarQube 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 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/10.7/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 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/10.7/analyzing-source-code/analysis-parameters "mention") in **Administration** > **Configuration** > **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-profiles](https://docs.sonarsource.com/sonarqube-server/10.7/instance-administration/analysis-functions/quality-profiles "mention").

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

You can analyze your Jupyter Notebooks projects [Scan my project](https://app.gitbook.com/s/6LPRABg3ubAJhpfR5K0Y/using/scan-my-project "mention"). Note that [Connected mode](https://docs.sonarsource.com/sonarqube-for-vs-code/connect-your-ide/connected-mode) will be ignored when working with Jupyter Notebooks (if this feature is important to you, you can [submit the idea on SonarQube’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 [introduction](https://docs.sonarsource.com/sonarqube-server/10.7/user-guide/issues/introduction "mention") to learn more about primary vs. secondary locations).
* Analysis does not measure code duplication at this time.

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

* [external-analyzer-reports](https://docs.sonarsource.com/sonarqube-server/10.7/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/10.7/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/))
