guide

DeepSource for Python: Static Analysis and Autofix Setup Guide

Set up DeepSource for Python projects. Covers .deepsource.toml config, Python rules, autofix, type checking, security analysis, and Django/Flask support.

Published:

DeepSource provides one of the most thorough Python static analysis experiences available in 2026. Its Python analyzer covers over 150 rules across bug detection, security scanning, performance optimization, and code style enforcement - with a sub-5% false positive rate that keeps findings actionable rather than noisy. Combined with Autofix, which generates ready-to-apply code changes for detected issues, DeepSource turns Python static analysis from a reporting exercise into an automated remediation workflow.

This guide covers everything you need to set up DeepSource for Python projects - from the initial .deepsource.toml configuration to advanced features like type checking integration, Django and Flask security rules, and coverage reporting with pytest. Whether you are adding DeepSource to a new Python project or migrating from another tool, this is a complete walkthrough of the Python analyzer in its current state.

DeepSource code quality platform homepage screenshot
DeepSource homepage

Why use DeepSource for Python static analysis

Python’s dynamic typing system creates entire categories of bugs that statically typed languages simply do not have. A function that expects a list[str] will happily accept a list[int] at runtime, mutable default arguments silently share state across function calls, and late-binding closures capture variables instead of values. These are not obscure edge cases - they are common patterns that ship to production in Python codebases of every size.

DeepSource’s Python analyzer is specifically designed to catch these Python-specific issues alongside the universal code quality concerns that apply to any language. Its advantage over general-purpose linters is the combination of depth and automation. When DeepSource finds a mutable default argument, it does not just flag it - it generates an Autofix that replaces def func(items=[]) with the correct def func(items=None) pattern, including the if items is None: items = [] guard inside the function body.

For teams already using tools like Ruff or Pylint, DeepSource does not replace those tools. Instead, it adds a layer of analysis that runs in CI/CD with PR integration, a unified dashboard for tracking code health over time, and automated fixes that eliminate manual remediation for routine issues. For a full overview of the platform beyond Python-specific features, see our DeepSource review.

DeepSource’s Python analyzer at a glance

The Python analyzer covers six issue categories, each with dozens of specific rules:

  • Anti-patterns - Mutable default arguments, bare except clauses, unnecessary pass statements, use of global variables, implicit string concatenation
  • Bug risks - Late-binding closures, incorrect __all__ definitions, unreachable code after return/raise, comparison to None using == instead of is
  • Performance - Membership testing on lists instead of sets, string concatenation in loops instead of join, unnecessary list creation for iteration
  • Security - SQL injection, command injection via subprocess, insecure deserialization, hardcoded credentials, weak cryptographic algorithms, SSRF patterns
  • Style - Line length violations, naming convention inconsistencies, missing docstrings, import ordering issues
  • Type checking - Integration with mypy or pytype for full type annotation validation

This breadth means a single DeepSource configuration catches issues that would otherwise require running three or four separate tools.

Setting up the Python analyzer

Getting DeepSource running on a Python project requires two steps: creating a .deepsource.toml configuration file and activating the repository in the DeepSource dashboard.

Step 1 - Create the .deepsource.toml file

The .deepsource.toml file lives in the root of your repository and defines which analyzers and transformers DeepSource runs. For a Python project, the minimal configuration is straightforward:

version = 1

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x"

This enables the Python analyzer with default settings. DeepSource will analyze all Python files in the repository using its full rule set.

Step 2 - Configure Python-specific settings

The [analyzers.meta] section accepts several Python-specific configuration options that control analysis behavior:

version = 1

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x"
  max_line_length = 120
  type_checker = "mypy"
  skip_doc_coverage = ["module", "magic", "init"]

Here is what each setting does:

runtime_version - Set this to "3.x" for Python 3 projects. DeepSource uses this to determine which language features and syntax patterns are valid. Setting it correctly prevents false positives from rules that check for Python 2 compatibility issues in a Python 3 codebase.

max_line_length - Controls the threshold for line length style rules. The default is 79 characters (PEP 8 standard), but most modern Python projects use 88 (Black default), 100, or 120. Set this to match your team’s formatter configuration.

type_checker - Accepts "mypy" or "pytype". When enabled, DeepSource runs the specified type checker as part of its analysis pipeline and surfaces type errors alongside its own findings. This eliminates the need to configure a separate type checking step in your CI/CD pipeline.

skip_doc_coverage - Controls which Python constructs are excluded from documentation coverage metrics. Common values include "module" (module-level docstrings), "magic" (dunder methods like __init__, __str__), and "init" (__init__.py files). This prevents DeepSource from flagging missing docstrings on constructs where documentation is not valuable.

Step 3 - Add transformers for automated formatting

DeepSource transformers automatically format your code and commit the changes. For Python projects, the Ruff transformer handles both linting fixes and formatting:

version = 1

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x"
  max_line_length = 120
  type_checker = "mypy"

[[transformers]]
name = "ruff"
enabled = true

When the Ruff transformer is enabled, DeepSource runs Ruff’s auto-fix and formatting capabilities on every commit. This means import sorting, unused import removal, and code formatting happen automatically without developer intervention.

You can also use the black or autopep8 transformers if your team prefers those formatters:

# Alternative: use Black for formatting
[[transformers]]
name = "black"
enabled = true

Step 4 - Activate the repository

After pushing the .deepsource.toml file to your default branch, go to the DeepSource dashboard at app.deepsource.com and activate your repository. DeepSource will run its first analysis immediately, scanning every Python file in the repository and creating a baseline of existing issues.

The initial analysis on a medium-sized Python project (10,000-50,000 lines) typically completes in 2-5 minutes. After the baseline is established, subsequent analyses run incrementally on changed files and complete much faster.

For detailed instructions on connecting your GitHub repository, see our guide on DeepSource GitHub integration.

Python rules and issue categories

DeepSource’s Python rule set is where the analyzer distinguishes itself from simpler tools. Each rule is categorized by type and severity, and most rules include detailed explanations with code examples showing both the problematic pattern and the correct alternative.

Anti-pattern detection

Anti-pattern rules catch code that works but uses patterns that lead to bugs, confusion, or maintenance problems. These are among the most valuable rules for Python because the language’s flexibility allows many patterns that are technically valid but practically dangerous.

Mutable default arguments are the most commonly caught anti-pattern:

# DeepSource flags this - PYT-W0039
def add_item(item, items=[]):
    items.append(item)
    return items

# Correct pattern - DeepSource Autofix generates this
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

The mutable default argument bug is infamous in Python because it violates the principle of least surprise - calling add_item("a") multiple times accumulates items across calls because the default list is shared across all invocations.

Late-binding closures are another Python-specific trap:

# DeepSource flags this - closure captures variable, not value
functions = []
for i in range(5):
    functions.append(lambda: i)

# All functions return 4 (the final value of i), not 0-4
# Fix: use default argument to capture value
functions = []
for i in range(5):
    functions.append(lambda i=i: i)

Other anti-pattern rules include bare except: clauses that catch SystemExit and KeyboardInterrupt, use of eval() and exec() on untrusted input, unnecessary pass statements in non-empty blocks, and implicit string concatenation from missing commas in tuples.

Bug risk detection

Bug risk rules identify code that is likely to raise exceptions or produce incorrect results at runtime. For Python, these rules are particularly valuable because the interpreter does not catch many of these issues until the specific code path executes.

# DeepSource detects comparison to None with == instead of is
if user == None:  # Should be: if user is None:
    return default_user

# DeepSource detects unreachable code
def process(data):
    if not data:
        return None
        print("This never executes")  # Unreachable - flagged by DeepSource

# DeepSource detects incorrect __all__ exports
__all__ = ["process_data", "validate_input", "nonexistent_function"]
# nonexistent_function is not defined in this module

The bug risk category also covers issues like using isinstance() with a non-class argument, modifying a dictionary while iterating over it, and accessing attributes on Optional types without a None check.

Security rules

DeepSource’s security rules are aligned with OWASP Top 10 and SANS Top 25 vulnerability categories. For Python web applications, these rules catch the most common attack vectors:

import subprocess
import hashlib
import pickle

# SQL injection - DeepSource flags string formatting in queries
query = f"SELECT * FROM users WHERE email = '{user_email}'"
cursor.execute(query)

# Command injection - DeepSource flags shell=True with variables
subprocess.call(f"convert {filename} output.png", shell=True)

# Insecure deserialization - DeepSource flags pickle.loads
data = pickle.loads(untrusted_bytes)

# Weak hashing - DeepSource flags MD5/SHA1 for passwords
password_hash = hashlib.md5(password.encode()).hexdigest()

# Hardcoded credentials - DeepSource detects secret patterns
DATABASE_PASSWORD = "production_secret_123"
AWS_SECRET_KEY = "AKIAIOSFODNN7EXAMPLE"

Each security finding includes the relevant CWE (Common Weakness Enumeration) identifier and OWASP category, which is useful for compliance reporting and security audit documentation.

Performance rules

Performance rules detect patterns where Python code works correctly but uses unnecessarily slow approaches:

# DeepSource flags membership testing on lists
# Lists use O(n) lookup; sets use O(1)
if user_id in [1, 2, 3, 4, 5]:  # Should use a set: {1, 2, 3, 4, 5}
    grant_access()

# DeepSource flags string concatenation in loops
result = ""
for item in items:
    result += str(item) + ", "  # Should use "".join()

# DeepSource flags unnecessary list creation for iteration
for item in list(some_generator()):  # list() is unnecessary here
    process(item)

These rules matter more than they might seem. In hot code paths processing thousands of items, the difference between a list membership test and a set membership test can be orders of magnitude in execution time.

Python Autofix in practice

DeepSource Autofix generates concrete code changes for detected Python issues. Unlike tools that only report problems, Autofix produces a reviewable diff that resolves the issue - and for Python, these fixes are almost always correct and idiomatic.

How Autofix works for Python

When DeepSource detects an issue with an available auto-fix, it generates the corrected code and presents it in two places: the DeepSource dashboard and the pull request comment thread. Developers can review the proposed change and apply it with a single click.

Here are examples of Python auto-fixes that DeepSource generates:

Mutable default argument fix:

# Before (detected issue)
def create_report(sections=[], title="Report"):
    sections.append("Summary")
    return {"title": title, "sections": sections}

# After (Autofix-generated)
def create_report(sections=None, title="Report"):
    if sections is None:
        sections = []
    sections.append("Summary")
    return {"title": title, "sections": sections}

String formatting modernization:

# Before (detected issue)
message = "User %s has %d items" % (username, count)

# After (Autofix-generated)
message = f"User {username} has {count} items"

Exception handling improvement:

# Before (detected issue)
try:
    process_data(raw_input)
except:
    log_error("Processing failed")

# After (Autofix-generated)
try:
    process_data(raw_input)
except Exception:
    log_error("Processing failed")

Autofix accuracy for Python

DeepSource reports a sub-5% false positive rate for its static analysis detections, and Autofix inherits that accuracy baseline. For deterministic fixes - unused import removal, formatting corrections, standard pattern replacements - accuracy is effectively 100%. The fix is mechanical and cannot introduce bugs.

For more complex fixes involving logic changes, the accuracy depends on the issue category. Mutable default argument fixes are safe because the pattern is well-defined. Exception handling fixes require developer review because narrowing an exception handler might miss legitimate exception types. Security fixes for SQL injection require verification that the parameterized query produces the same results.

The practical recommendation is to auto-apply deterministic fixes without review and manually review logic-changing fixes before merging. DeepSource presents all fixes as diffs rather than auto-merging them, so you always have the opportunity to inspect changes before they land.

Type checking integration

Python’s type annotation system has matured significantly, and most production Python codebases in 2026 use type hints extensively. DeepSource integrates with mypy and pytype to surface type errors alongside its own static analysis findings.

Configuring mypy with DeepSource

To enable mypy type checking in DeepSource, set the type_checker field in your .deepsource.toml:

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x"
  type_checker = "mypy"

When enabled, DeepSource runs mypy as part of its analysis pipeline. Type errors appear in the DeepSource dashboard with the same severity classification and category structure as other findings. This means you can track type safety metrics over time, enforce type checking through quality gates, and see type errors in PR comments alongside code quality and security findings.

If your project uses a mypy.ini or pyproject.toml with mypy configuration, DeepSource respects those settings. This ensures consistency between local mypy runs and the DeepSource analysis.

Configuring pytype with DeepSource

pytype is Google’s Python type checker and takes a different approach than mypy. While mypy requires explicit type annotations, pytype can infer types from code without annotations and check for consistency. To use pytype:

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x"
  type_checker = "pytype"

pytype is particularly useful for legacy Python codebases that do not have type annotations yet. It infers types from usage patterns and catches inconsistencies without requiring the upfront investment of annotating the entire codebase.

What type checking catches

With a type checker enabled, DeepSource catches an additional layer of Python bugs:

from typing import Optional

# Type error: operand could be None
def calculate_discount(price: float, discount: Optional[float]) -> float:
    return price * (1 - discount)  # mypy: Unsupported operand types

# Type error: missing return in branch
def get_status(code: int) -> str:
    if code == 200:
        return "ok"
    # mypy: Missing return statement (implicit None is not str)

# Type error: incompatible assignment
config: dict[str, int] = {}
config["timeout"] = "30"  # mypy: Incompatible types (str vs int)

These errors are invisible to linters and to DeepSource’s own static analysis rules. The type checker integration fills a gap that would otherwise require a separate CI/CD step.

Security analysis for Python web applications

DeepSource’s security analysis capabilities are particularly relevant for Python because of the language’s dominance in web application development. Django, Flask, and FastAPI applications handle user input, interact with databases, and manage authentication - all areas where security vulnerabilities have the highest impact.

Django-specific security detection

DeepSource’s Python analyzer includes rules that understand Django’s ORM, template engine, and middleware system. These are not generic security rules applied to Python code - they are rules that understand the Django framework and detect misuse of its specific APIs.

Raw SQL detection:

# DeepSource flags raw SQL with string formatting
def search_users(request):
    query = request.GET.get("q", "")
    # Security: SQL injection via raw query
    users = User.objects.raw(
        f"SELECT * FROM auth_user WHERE username LIKE '%{query}%'"
    )
    return render(request, "results.html", {"users": users})

# Correct: use parameterized queries
def search_users(request):
    query = request.GET.get("q", "")
    users = User.objects.raw(
        "SELECT * FROM auth_user WHERE username LIKE %s",
        [f"%{query}%"]
    )
    return render(request, "results.html", {"users": users})

Insecure Django settings:

DeepSource checks your Django settings files for security misconfigurations:

  • DEBUG = True in production settings
  • ALLOWED_HOSTS = ['*'] accepting any host
  • Missing security middleware (SecurityMiddleware, XFrameOptionsMiddleware)
  • Weak or hardcoded SECRET_KEY values
  • Missing SECURE_SSL_REDIRECT, SECURE_HSTS_SECONDS, and other HTTPS enforcement settings
  • CSRF_COOKIE_SECURE = False on production deployments

Template injection:

from django.utils.safestring import mark_safe

# DeepSource flags mark_safe with user input
def render_comment(request):
    comment = request.POST.get("comment", "")
    # Security: XSS via mark_safe on user input
    safe_comment = mark_safe(comment)
    return render(request, "comment.html", {"comment": safe_comment})

Flask-specific security detection

Flask’s minimal approach means security features that Django provides by default must be explicitly added. DeepSource’s Python analyzer knows which Flask security patterns are missing:

from flask import Flask, request

app = Flask(__name__)

# DeepSource flags debug mode
app.debug = True  # Security: debug mode exposes interactive debugger

# DeepSource flags hardcoded secret key
app.secret_key = "development-secret"  # Security: hardcoded secret

# DeepSource flags missing input validation
@app.route("/api/execute", methods=["POST"])
def execute():
    command = request.form.get("cmd")
    # Security: command injection
    os.system(command)
    return "Done"

DeepSource detects Flask applications that lack CSRF protection (no Flask-WTF), use app.run(debug=True) in production-reachable code, set overly permissive CORS headers, or handle file uploads without size and type validation.

FastAPI security considerations

For FastAPI applications, DeepSource catches patterns like endpoints that bypass Pydantic validation, overly permissive CORS configuration, and missing authentication dependencies:

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# DeepSource flags wildcard CORS origins
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Security: overly permissive CORS
    allow_methods=["*"],
    allow_headers=["*"],
)

# DeepSource flags raw request access bypassing Pydantic
@app.post("/data")
async def process_data(request: Request):
    body = await request.json()  # No Pydantic validation
    # Should use a Pydantic model as parameter instead

Integrating DeepSource with pytest

DeepSource does not run your test suite directly. Its relationship with pytest operates on two levels: static analysis of test code and coverage data ingestion.

Static analysis of test files

DeepSource analyzes your pytest test files using the same rules it applies to production code, with adjustments for test-specific patterns. It catches issues like:

# DeepSource flags assertions that always pass
def test_user_creation():
    user = create_user("[email protected]")
    assert True  # This assertion proves nothing

# DeepSource flags overly broad exception handling in tests
def test_data_processing():
    try:
        result = process(invalid_data)
    except:
        pass  # Swallowing all exceptions defeats the test purpose

# DeepSource detects unused fixtures
@pytest.fixture
def database_connection():
    conn = create_connection()
    yield conn
    conn.close()

def test_query():
    # database_connection fixture defined but not used in this test
    result = run_query("SELECT 1")
    assert result == 1

Sending coverage data to DeepSource

To integrate pytest coverage reporting with DeepSource, generate a coverage report and upload it using the DeepSource CLI:

# Step 1: Run pytest with coverage
pytest --cov=src --cov-report=xml

# Step 2: Install the DeepSource CLI
curl https://deepsource.io/cli | sh

# Step 3: Upload coverage data
DEEPSOURCE_DSN=https://[email protected] \
  ./bin/deepsource report \
    --analyzer python \
    --key python \
    --value-file coverage.xml

The DSN (Data Source Name) is available in your DeepSource project settings under the “Reporting” section.

In a CI/CD pipeline, the coverage upload integrates naturally with your existing pytest workflow:

# .github/workflows/test.yml
name: Tests
on: [pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install -r requirements.txt
      - run: pytest --cov=src --cov-report=xml
      - name: Report coverage to DeepSource
        run: |
          curl https://deepsource.io/cli | sh
          ./bin/deepsource report \
            --analyzer python \
            --key python \
            --value-file coverage.xml
        env:
          DEEPSOURCE_DSN: ${{ secrets.DEEPSOURCE_DSN }}

Once coverage data flows into DeepSource, you can track coverage trends over time, set coverage thresholds as quality gates, and see which files and functions lack test coverage directly in the DeepSource dashboard.

Advanced .deepsource.toml configuration

Beyond the basic Python analyzer setup, the .deepsource.toml file supports several advanced configurations that are useful for larger Python projects.

Excluding files and directories

For Python projects with generated code, database migrations, or vendored dependencies, you may want to exclude certain paths from analysis:

version = 1

exclude_patterns = [
  "migrations/**",
  "*/migrations/**",
  "vendor/**",
  "docs/**",
  "*.pb2.py",
  "*.pb2_grpc.py",
  "*_generated.py",
]

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x"
  max_line_length = 120
  type_checker = "mypy"

The exclude_patterns field accepts glob patterns. This is particularly important for Django projects where migration files are auto-generated and would trigger numerous style and complexity findings that are not actionable.

Monorepo configuration

For monorepos containing multiple Python services, DeepSource analyzes all Python files in the repository by default. You can use exclude_patterns to scope the analysis to specific services or use multiple analyzer configurations:

version = 1

exclude_patterns = [
  "infrastructure/**",
  "scripts/**",
  "*.ipynb",
]

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x"
  max_line_length = 120
  type_checker = "mypy"

[[analyzers]]
name = "javascript"
enabled = true

  [analyzers.meta]
  environment = ["nodejs"]

[[transformers]]
name = "ruff"
enabled = true

This configuration analyzes both Python and JavaScript code in the same repository while excluding infrastructure scripts and Jupyter notebooks.

Combining multiple transformers

You can enable multiple transformers to handle different aspects of code formatting:

[[transformers]]
name = "ruff"
enabled = true

[[transformers]]
name = "isort"
enabled = true

However, be careful about conflicts. If you enable Ruff as a transformer, it already handles import sorting - adding isort separately would be redundant and could cause conflicting changes.

DeepSource vs. other Python analysis tools

Understanding where DeepSource fits relative to other Python analysis tools helps you build the right stack for your team.

DeepSource vs. Ruff

Ruff is a lightning-fast Python linter with 800+ rules that runs in pre-commit hooks and provides instant feedback. DeepSource is a platform that runs deeper analysis in CI/CD with PR integration, Autofix, and a dashboard. They are complementary rather than competitive. The recommended setup is Ruff locally for fast linting and DeepSource in CI for deeper analysis, security scanning, and automated fixes. In fact, DeepSource supports Ruff as a transformer, meaning you can run Ruff formatting through DeepSource’s pipeline.

DeepSource vs. SonarQube

SonarQube has 500+ Python rules compared to DeepSource’s 150+, making it the deeper rule-based analyzer. However, SonarQube requires self-hosting (or SonarQube Cloud with LOC-based pricing), while DeepSource is fully managed. DeepSource’s Autofix generates ready-to-apply code changes that SonarQube does not offer. For teams that want deep rule coverage without hosting overhead, DeepSource is the simpler choice. For enterprise teams with compliance requirements and existing SonarQube infrastructure, SonarQube’s rule depth and quality gate system may justify the operational overhead.

DeepSource vs. Codacy

Codacy ($15/user/month) aggregates multiple Python tools including Pylint and Bandit into a unified dashboard. DeepSource ($24/user/month) runs its own analyzer with a sub-5% false positive rate. Codacy supports 40+ languages compared to DeepSource’s 12+, making Codacy better for polyglot teams. DeepSource’s Autofix and lower false positive rate make it better for Python-focused teams that want automated remediation.

For a comprehensive comparison of DeepSource against competing platforms, see our DeepSource alternatives guide.

CodeAnt AI as an alternative

CodeAnt AI is worth evaluating as an alternative to DeepSource for Python static analysis. Priced at $24-40/user/month, CodeAnt AI provides AI-powered code quality analysis with Python support, including detection of code smells, security vulnerabilities, and performance issues.

CodeAnt AI differentiates itself with its AI-driven approach to issue detection, which can catch context-dependent problems that rule-based analyzers miss. For Python projects, it provides analysis of code patterns, duplication detection, and automated suggestions for improvement.

The key differences from DeepSource are in approach rather than coverage. DeepSource uses a primarily rule-based analyzer augmented with AI for code review, while CodeAnt AI leans more heavily on AI for issue detection. Teams should evaluate both against their specific Python codebase to determine which produces more actionable findings with fewer false positives.

Pricing for Python teams

DeepSource’s pricing is not language-specific - the same plans apply regardless of which analyzers you enable. For Python teams, here is what each tier offers.

The Open Source plan is free for public repositories. It includes unlimited team members, unlimited public repos, 1,000 PR reviews per month, and the full Python analyzer. This is sufficient for open-source Python projects.

The Team plan costs $24/user/month with annual billing. It includes everything in the Open Source plan plus private repository support, unlimited Autofix, monorepo support, audit logs, and $120/user/year in AI Review credits. This is the plan most Python teams will use.

The Enterprise plan has custom pricing and adds self-hosted deployment, SSO/SCIM, dedicated account management, and SLA-backed support.

DeepSource uses committer-based billing, meaning only users who push code to analyzed repositories count toward the billing total. Non-committing team members (managers, reviewers who only view the dashboard) are not charged.

For full pricing details including cost comparisons at different team sizes, see our DeepSource pricing breakdown.

Getting started checklist

Here is a practical checklist for setting up DeepSource on a Python project:

  1. Create a .deepsource.toml file in your repository root with the Python analyzer enabled
  2. Set runtime_version to "3.x" and max_line_length to match your formatter
  3. Enable a type_checker (mypy or pytype) if your codebase uses type annotations
  4. Add the Ruff transformer for automated formatting
  5. Add exclude_patterns for migrations, generated code, and vendor directories
  6. Push the config file to your default branch
  7. Activate the repository in the DeepSource dashboard
  8. Review the initial analysis results and suppress any false positives
  9. Configure pytest coverage reporting in your CI pipeline
  10. Set up GitHub integration for PR comments

After the initial setup, DeepSource runs automatically on every push and pull request. New issues are reported as PR comments with Autofix suggestions where available. The dashboard tracks code health metrics over time, giving you visibility into whether your Python codebase is improving or accumulating technical debt.

For teams evaluating multiple tools, DeepSource offers a 14-day free trial of the Team plan with no credit card required. This gives you enough time to run the analyzer on your actual codebase and evaluate the findings against your current tooling before committing to a subscription.

Frequently Asked Questions

How do I set up DeepSource for a Python project?

Create a .deepsource.toml file in the root of your repository with the Python analyzer enabled. Set the runtime_version to your Python version (e.g., 3.x), configure max_line_length if needed, and optionally enable a type_checker like mypy or pytype. Push the config file to your default branch, then activate the repository in the DeepSource dashboard. DeepSource will run its first analysis automatically and flag any existing issues.

What Python rules does DeepSource support?

DeepSource's Python analyzer covers over 150 rules across six categories: anti-patterns (PYT), bug risks (PYT), performance (PYT), security (PYT), style (PYT), and type checking (PYT). Rules detect issues like mutable default arguments, late-binding closures, missing type annotations, SQL injection patterns, Django ORM anti-patterns, insecure hash algorithms, unused imports, and unreachable code. The rule set is continuously updated as new Python versions introduce features.

Does DeepSource support Django and Flask?

Yes. DeepSource's Python analyzer includes rules specific to Django and Flask applications. For Django, it detects raw SQL queries that bypass the ORM, missing CSRF middleware, insecure settings like DEBUG=True in production, unoptimized query patterns such as N+1 queries, and improper use of mark_safe. For Flask, it flags debug mode in production, hardcoded secret keys, missing input validation, and insecure deserialization patterns. These framework-specific rules activate automatically when DeepSource detects Django or Flask imports.

How does DeepSource Autofix work for Python?

When DeepSource detects a Python issue that has an available auto-fix, it generates a concrete code change presented as a reviewable diff. For Python, Autofix handles issues like removing unused imports, replacing mutable default arguments with None patterns, converting string formatting to f-strings, fixing incorrect exception handling patterns, and applying Pythonic idioms. You can apply fixes individually with a single click or apply multiple fixes in bulk from the DeepSource dashboard or directly in pull request comments.

Can DeepSource replace Pylint or Ruff for Python?

DeepSource is not a direct replacement for Pylint or Ruff - it serves a different role. Ruff is a fast linter designed for pre-commit hooks and instant IDE feedback with 800+ rules. Pylint performs deep semantic analysis with type inference. DeepSource is a platform that runs its own analyzer alongside optional integrations with tools like Ruff, providing a dashboard, PR integration, Autofix, and trend tracking. Many teams use Ruff locally for fast linting and DeepSource in CI/CD for deeper analysis, security scanning, and automated fixes.

Does DeepSource support Python type checking?

Yes. DeepSource integrates with mypy and pytype for Python type checking. You enable a type checker in the .deepsource.toml config under analyzers.meta by setting type_checker to either mypy or pytype. When enabled, DeepSource runs the type checker as part of its analysis pipeline and surfaces type errors alongside its own static analysis findings in a unified dashboard. This means you can see type checking results, code quality issues, and security findings all in one place.

How does DeepSource detect Python security vulnerabilities?

DeepSource's Python analyzer includes security rules aligned with OWASP and SANS categories. It detects SQL injection through string formatting in database queries, command injection via subprocess calls with shell=True, insecure deserialization using pickle.loads on untrusted data, hardcoded credentials and secret keys, use of weak cryptographic algorithms like MD5 and SHA1 for password hashing, SSRF vulnerabilities, path traversal attacks, and XML External Entity injection. These rules apply to both standalone Python code and web framework code.

What is the .deepsource.toml configuration for Python?

The .deepsource.toml file defines which analyzers and transformers DeepSource runs on your repository. For Python, you need a [[analyzers]] block with name set to python and enabled set to true. Under [analyzers.meta], set runtime_version to your Python version (3.x for Python 3), max_line_length for style rules, and optionally type_checker to mypy or pytype. You can also add a [[transformers]] block for Ruff or other formatters. The version field at the top should be set to 1.

How does DeepSource integrate with pytest?

DeepSource does not run pytest directly. Instead, it analyzes your test code using its static analysis rules and can detect test-related anti-patterns such as assertions that always pass, overly broad exception catching in tests, missing assertion messages, and unused test fixtures. For code coverage integration, you can send pytest coverage data to DeepSource using the deepsource CLI tool, which lets DeepSource track coverage trends and flag uncovered code paths in its dashboard.

How much does DeepSource cost for Python projects?

DeepSource's pricing is not language-specific - the same plans apply regardless of which analyzers you use. The Open Source plan is free for public repositories with unlimited team members. The Team plan costs $24/user/month with annual billing and includes unlimited Autofix, monorepo support, and bundled AI Review credits. Enterprise pricing is custom and includes self-hosted deployment options. DeepSource counts active committers for billing, so non-committing team members are not charged.

What are alternatives to DeepSource for Python static analysis?

Key alternatives include CodeAnt AI ($24-40/user/month) which provides AI-powered code quality with Python support, SonarQube with 500+ Python rules and quality gates, Codacy ($15/user/month) which aggregates multiple Python tools, Semgrep with dedicated Django and Flask security rulesets, and Snyk Code for cross-file Python dataflow analysis. Free open-source options include Ruff for linting, Pylint for deep analysis, mypy for type checking, and Bandit for security scanning.

Does DeepSource support Python monorepos?

Yes. DeepSource supports monorepo configurations where multiple Python projects or services live in a single repository. You configure analyzer paths in the .deepsource.toml file using the skip_doc_coverage and exclude_patterns settings to control which directories DeepSource analyzes. The Team plan includes monorepo support. DeepSource can analyze different subdirectories with different runtime versions and configurations within the same repository.

Explore More

Free Newsletter

Stay ahead with AI dev tools

Weekly insights on AI code review, static analysis, and developer productivity. No spam, unsubscribe anytime.

Join developers getting weekly AI tool insights.

Related Articles