# Python

## Supported versions <a href="#suoported-versions" id="suoported-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.

Versions 3.0 to 3.14 are fully supported.

Version 2.7 is supported.

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

Discover and update the Python-specific [analysis-parameters](https://open-2v.gitbook.com/url/docs.sonarsource.com/sonarqube-community-build/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.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 Community Build Plugin and using Python analyzer APIs. Here are the steps to follow:

**Create a SonarQube Community Build plugin**

* Create a standard SonarQube Community Build plugin project.
* Attach this plugin to SonarQube Community Build’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. 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).

```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://open-2v.gitbook.com/url/docs.sonarsource.com/sonarqube-community-build/analyzing-source-code/analysis-parameters "mention") in **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 [understanding-quality-profiles](https://open-2v.gitbook.com/url/docs.sonarsource.com/sonarqube-community-build/quality-standards-administration/managing-quality-profiles/understanding-quality-profiles "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 direclty in VS Code. Note that [Connected mode](https://app.gitbook.com/s/6LPRABg3ubAJhpfR5K0Y/connect-your-ide/connected-mode "mention") 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://open-2v.gitbook.com/url/docs.sonarsource.com/sonarqube-community-build/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://open-2v.gitbook.com/url/docs.sonarsource.com/sonarqube-community-build/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://open-2v.gitbook.com/url/docs.sonarsource.com/sonarqube-community-build/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/))
