> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/rtk-ai/rtk/llms.txt
> Use this file to discover all available pages before exploring further.

# Python Development Tools

> Token-optimized Python linting, testing, and package management

## Overview

RTK provides comprehensive Python development tool support with **70-90% token savings** through:

* **JSON parsing**: Structured output from Ruff and pip
* **State machine parsing**: Text-based pytest output
* **Error grouping**: Group by file, rule, or error code
* **Auto-detection**: Detects `uv` for faster pip operations

## Supported Tools

> **Ruff**
>
> Fast linter/formatter (80% savings)

> **Pytest**
>
> Test runner with failures only (90% savings)

> **pip/uv**
>
> Package manager with JSON parsing (70-85% savings)

> **Mypy**
>
> Type checker with error grouping (80% savings)

## rtk ruff

Ruff linter and formatter with JSON parsing.

### Usage

```bash theme={null}
rtk ruff check [options] [path]
rtk ruff format [options] [path]
```

### Examples

```bash Standard ruff check theme={null}
$ ruff check .
src/utils.py:12:5: F401 [*] `os` imported but unused
src/utils.py:18:1: E302 [*] Expected 2 blank lines, found 1
src/api/client.py:42:80: E501 Line too long (95 > 88 characters)
src/api/client.py:55:10: F841 [*] Local variable `result` is assigned to but never used
src/models/user.py:23:5: D103 Missing docstring in public function
Found 5 errors (4 fixable with --fix)
# 7+ lines, ~300 tokens
```

```bash RTK ruff check theme={null}
$ rtk ruff check .
✗ 5 errors (4 fixable) in 3 files

By rule:
  F401: 1 error (fixable)
    src/utils.py:12 `os` imported but unused

  F841: 1 error (fixable)
    src/api/client.py:55 Local variable `result` assigned but never used

  E302: 1 error (fixable)
    src/utils.py:18 Expected 2 blank lines, found 1

  E501: 1 error
    src/api/client.py:42 Line too long (95 > 88)

  D103: 1 error
    src/models/user.py:23 Missing docstring in public function
# 18 lines, ~60 tokens (80% savings)
```

### Features

* **JSON parsing**: Uses `--output-format=json` automatically
* **Rule grouping**: Groups violations by rule code
* **Fix hints**: Shows which errors are auto-fixable
* **Exit code preservation**: Safe for CI/CD

### Implementation

From `src/ruff_cmd.rs`:

```rust theme={null}
// Force JSON output for check command
if is_check {
    cmd.arg("check").arg("--output-format=json");
}

// Parse JSON diagnostics
#[derive(Deserialize)]
struct RuffDiagnostic {
    code: String,
    message: String,
    location: RuffLocation,
    filename: String,
    fix: Option<RuffFix>,
}

let diagnostics: Vec<RuffDiagnostic> = serde_json::from_str(&stdout)?;

// Group by rule code
let mut by_rule: HashMap<String, Vec<_>> = HashMap::new();
for diag in diagnostics {
    by_rule.entry(diag.code).or_default().push(diag);
}
```

### rtk ruff format

Ruff formatter with compact output.

```bash Standard ruff format theme={null}
$ ruff format .
3 files reformatted, 12 files left unchanged
```

```bash RTK ruff format theme={null}
$ rtk ruff format .
✓ 3 files reformatted
```

## rtk pytest

Pytest test runner showing failures only.

### Usage

```bash theme={null}
rtk pytest [options] [file::test]
```

### Examples

```bash Standard pytest theme={null}
$ pytest
============================= test session starts ==============================
platform linux -- Python 3.11.0, pytest-7.4.0, pluggy-1.0.0
rootdir: /path/to/project
collected 25 items

tests/test_utils.py ........                                             [ 32%]
tests/test_api.py .F...F.                                                [ 60%]
tests/test_models.py ..........                                          [100%]

=================================== FAILURES ===================================
________________________________ test_fetch_data _______________________________

    def test_fetch_data():
>       assert response.status_code == 200
E       AssertionError: assert 404 == 200

tests/test_api.py:42: AssertionError

_______________________________ test_validate_user _____________________________

    def test_validate_user():
>       assert user.is_valid()
E       AssertionError: assert False
E        +  where False = <bound method User.is_valid of <User id=123>>()

tests/test_api.py:68: AssertionError
=========================== short test summary info ============================
FAILED tests/test_api.py::test_fetch_data - AssertionError: assert 404 == 200
FAILED tests/test_api.py::test_validate_user - AssertionError: assert False
========================= 2 failed, 23 passed in 1.52s =========================
# 35+ lines, ~800 tokens
```

```bash RTK pytest theme={null}
$ rtk pytest
✗ 2 failed, 23 passed (1.52s)

tests/test_api.py::test_fetch_data
  AssertionError: assert 404 == 200
  at tests/test_api.py:42

tests/test_api.py::test_validate_user
  AssertionError: assert False
  at tests/test_api.py:68

[full output: ~/.local/share/rtk/tee/1707753600_pytest.log]
# 11 lines, ~80 tokens (90% savings)
```

### Features

* **State machine parser**: Parses text output (no JSON mode needed)
* **Auto-flags**: Forces `--tb=short -q` for compact output
* **Failure details**: Preserves assertion messages and tracebacks
* **Tee recovery**: Full output saved to file on failure

### Implementation

From `src/pytest_cmd.rs`:

```rust theme={null}
#[derive(Debug, PartialEq)]
enum ParseState {
    Header,       // Session start info
    TestProgress, // Running tests (dots)
    Failures,     // Failure details
    Summary,      // Final counts
}

fn filter_pytest_output(output: &str) -> String {
    let mut state = ParseState::Header;
    let mut failures = Vec::new();
    
    for line in output.lines() {
        match state {
            ParseState::TestProgress if line.starts_with("====== FAILURES") => {
                state = ParseState::Failures;
            }
            ParseState::Failures => {
                // Extract failure sections
                failures.push(line);
            }
            // ...
        }
    }
}
```

### Supported Options

* `-v`: Verbose mode (passthrough)
* `-k <pattern>`: Run tests matching pattern
* `-x`: Stop on first failure
* `--tb=<style>`: Traceback style (short/long/no)

## rtk pip

Package manager with auto-detection of `uv`.

### Usage

```bash theme={null}
rtk pip list [options]
rtk pip outdated [options]
rtk pip install <package>
rtk pip show <package>
```

### Auto-detection

RTK automatically detects and uses `uv` if available:

```bash theme={null}
# Checks for `uv` in PATH
which uv  # If found, uses "uv pip"
          # Otherwise, uses "pip"
```

### Examples

```bash Standard pip list theme={null}
$ pip list
Package           Version
----------------- ---------
requests          2.31.0
django            4.2.7
celery            5.3.4
numpy             1.24.3
pandas            2.0.3
pytest            7.4.3
...
# 20+ lines, ~400 tokens
```

```bash RTK pip list theme={null}
$ rtk pip list
📦 127 packages:

Core:
  requests 2.31.0
  django 4.2.7
  celery 5.3.4

Data:
  numpy 1.24.3
  pandas 2.0.3

Testing:
  pytest 7.4.3
  coverage 7.3.2
...
# 15 lines, ~120 tokens (70% savings)
```

### rtk pip outdated

Show outdated packages with upgrade suggestions.

```bash Standard pip outdated theme={null}
$ pip list --outdated
Package    Version   Latest    Type
---------- --------- --------- -----
requests   2.28.0    2.31.0    wheel
django     4.1.7     4.2.7     wheel
celery     5.2.7     5.3.4     wheel
# 5+ lines, ~200 tokens
```

```bash RTK pip outdated theme={null}
$ rtk pip outdated
⚠️ 3 packages need updates:
  requests: 2.28.0 → 2.31.0
  django: 4.1.7 → 4.2.7
  celery: 5.2.7 → 5.3.4

Upgrade all: pip install -U requests django celery
# 6 lines, ~30 tokens (85% savings)
```

### Features

* **JSON parsing**: Uses `--format=json` for structured output
* **Grouping**: Groups packages by category (Core, Data, Testing, etc.)
* **Upgrade hints**: Generates upgrade commands
* **uv support**: Seamlessly uses `uv pip` when available

### Implementation

From `src/pip_cmd.rs`:

```rust theme={null}
// Auto-detect uv
let use_uv = which_command("uv").is_some();
let base_cmd = if use_uv { "uv" } else { "pip" };

// Force JSON output
cmd.arg("list").arg("--format=json");

// Parse JSON
#[derive(Deserialize)]
struct Package {
    name: String,
    version: String,
    latest_version: Option<String>,
}

let packages: Vec<Package> = serde_json::from_str(&stdout)?;
```

## rtk mypy

Mypy type checker with error grouping.

### Usage

```bash theme={null}
rtk mypy [options] [files]
```

### Examples

```bash Standard mypy theme={null}
$ mypy .
src/utils.py:12: error: Incompatible return value type (got "int", expected "str")
src/utils.py:24: error: Argument 1 to "process" has incompatible type "str"; expected "int"
src/api/client.py:42: error: "Response" has no attribute "json_data"
src/api/client.py:55: error: Cannot call function of unknown type
src/models/user.py:18: error: Need type annotation for "data" (hint: "data: Dict[<type>, <type>] = ...")
Found 5 errors in 3 files (checked 12 source files)
# 7+ lines, ~350 tokens
```

```bash RTK mypy theme={null}
$ rtk mypy .
✗ 5 errors in 3 files

src/utils.py (2 errors)
  :12 Incompatible return value type (got "int", expected "str")
  :24 Argument 1 to "process" has incompatible type

src/api/client.py (2 errors)
  :42 "Response" has no attribute "json_data"
  :55 Cannot call function of unknown type

src/models/user.py (1 error)
  :18 Need type annotation for "data"
# 12 lines, ~70 tokens (80% savings)
```

### Features

* **File grouping**: Group errors by file
* **Line numbers**: Compact `:line` format
* **Error messages**: Preserve full error text
* **Exit codes**: Safe for CI/CD

## CI/CD Integration

All Python tools preserve exit codes:

```yaml theme={null}
# .github/workflows/ci.yml
name: Python CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install dependencies
        run: pip install -r requirements.txt
      - name: Lint
        run: rtk ruff check .
      - name: Type check
        run: rtk mypy .
      - name: Test
        run: rtk pytest
```

## Token Savings Summary

| Command | Standard Tokens | RTK Tokens | Savings |
| - | - | - | - |
| `ruff check` (5 errors) | 300 | 60 | **-80%** |
| `pytest` (2 fail, 23 pass) | 800 | 80 | **-90%** |
| `pip list` (127 packages) | 400 | 120 | **-70%** |
| `pip outdated` (3 packages) | 200 | 30 | **-85%** |
| `mypy` (5 errors) | 350 | 70 | **-80%** |

## Next Steps

> **[Go](/commands/go)**
>
> Go development tools

> **[Testing](/commands/testing)**
>
> Cross-language test runners


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.