# Python

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

* Python 3.x
* Python 2.x

## 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.0/analyzing-source-code/analysis-parameters "mention") in **Administration > 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"

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</requirePlugin>`
* 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).

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

* [importing-third-party-issues](https://docs.sonarsource.com/sonarqube-server/10.0/analyzing-source-code/importing-external-issues/importing-third-party-issues "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.0/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/))


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sonarsource.com/sonarqube-server/10.0/analyzing-source-code/languages/python.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
