# All files / lib/detectors python-detector.js

81.81% Statements 18/22
76.66% Branches 23/30
100% Functions 1/1
88.23% Lines 15/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49

    4x
    4x

    4x
    1x

    3x

    3x
    3x
    1x

    3x

    3x
    3x
    2x

    3x
    3x

    3x

     import fs from 'fs-extra';
    import path from 'path';
    import { parseRequirements } from '../parsers/requirements-parser.js';

    export async function detectPythonStack(cwd) {
      const requirementsPath = path.join(cwd, 'requirements.txt');
      const pyprojectPath = path.join(cwd, 'pyproject.toml');

      if (!(await fs.pathExists(requirementsPath)) && !(await fs.pathExists(pyprojectPath))) {
        return { detected: false };
      }

      const deps = await parseRequirements(cwd);

      // Detect framework
      let framework = null;
      if (deps.fastapi || deps['starlette']) framework = 'fastapi';
      else if (deps.django || deps['Django']) framework = 'django';
      else Eif (deps.flask) framework = 'flask';

      Iif (!framework) {
        return { detected: false };
      }

      // Detect test runner
      let testRunner = null;
      if (deps.pytest) testRunner = 'pytest';
      else Iif (deps.unittest) testRunner = 'unittest';

      // Detect linter/formatter
      const linter = deps.ruff || deps['ruff'] ? 'ruff' : deps.pylint ? 'pylint' : null;
      const formatter = deps.black || deps['black'] ? 'black' : null;

      return {
        detected: true,
        stack: 'python-fastapi',
        confidence: 'high',
        language: 'python',
        framework,
        testRunner,
        linter,
        formatter,
        buildTool: 'pip',
        evidence: {
          files: [requirementsPath],
          dependencies: Object.keys(deps).slice(0, 5),
        },
      };
    }