This guide explains the modern development workflow for DiscordianAI using streamlined linting tools.
DiscordianAI targets Python 3.12 and newer (legacy support for 3.10/3.11 has been removed). The codebase uses modern Python features including:
- Generic Type Annotations (Python 3.9+):
list[dict[str, str]],dict[str, Any] - Union Types with | (Python 3.10+):
str | None,dict[str, Any] | None - Dataclasses (Python 3.7+):
@dataclassdecorators - Modern Type Hints: No legacy
typing.Unionortyping.Optionalneeded
We use tox to run the canonical CI/test suite. Run Python 3.12 locally (the canonical and supported interpreter):
# Primary suite (required)
tox -e py312- Canonical test/lint/audit suite (run in a terminal):
tox -e py312,black --check .,ruff check .,tox -e audit. tox -e auditrunspip-auditagainst runtime and dev dependencies.- Use Python 3.12 locally; do not downgrade targets or
target-versionsettings. - Maintain coverage at or above 84% (Codecov and tox gate); call out any drops and add tests when needed.
- Keep user-visible changes reflected in the changelog and preserve PR comment layout (including emojis/headings) with commands and results listed.
- See
.github/copilot-instructions.mdfor the assistant workflow loop and guardrails.
We've streamlined our development tools to use only two main tools instead of the previous four:
# Format code
black .
# Lint and fix (includes import sorting, style checks, etc.)
ruff check --fix .
# Run tests
pytestRuff is a fast Python linter written in Rust that replaces multiple tools:
- Import sorting (replaces
isort) - Style checking (replaces
flake8) - Code quality (replaces various flake8 plugins)
- Import organization (replaces
isort) - Unused imports/variables (replaces
pyflakes)
To run all checks and tests:
black --check .
ruff check .
pytest -qTo auto-fix formatting and linting:
black .
ruff check --fix .Previously, we used isort + black + ruff + flake8, which caused:
- Import sorting conflicts between
isortandruff - Endless loops where each tool "fixed" what the other tool "broke"
- Inconsistent results depending on which tool ran last
- Slower CI with multiple tool executions
Ruff handles everything that the other tools did, but:
- Faster (written in Rust)
- Consistent (single tool, single set of rules)
- Comprehensive (covers all our needs)
- No conflicts (single source of truth)
All ruff settings are in pyproject.toml:
[tool.ruff]
target-version = "py312"
line-length = 99
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort (import sorting)
"N", # pep8-naming
"D", # pydocstyle
# ... and many more
]
# AI-friendly rules - allows multiple return statements for readable routing logic
ignore = [
"S101", # Use of assert detected (OK in tests)
]
[tool.ruff.lint.isort]
combine-as-imports = true
force-sort-within-sections = true[tool.black]
line-length = 99| Old Tool | New Tool | Status |
|---|---|---|
isort |
ruff with "I" rule |
✅ Replaced |
flake8 |
ruff with comprehensive rules |
✅ Replaced |
black |
black |
✅ Kept |
pytest |
pytest |
✅ Kept |
- ❌ Don't run
isort- it conflicts with ruff - ❌ Don't run
flake8- ruff covers everything - ❌ Don't run multiple tools - use ruff for everything
- ✅ Use
ruff check --fixfor all linting and import sorting - ✅ Use
blackfor code formatting - ✅ Use
pytestfor testing
"Import sorting conflicts"
- Cause: Running both
isortandruff - Solution: Use only
ruff check --fix
"Different results each time"
- Cause: Multiple tools with different rules
- Solution: Use only
rufffor linting
"CI failing inconsistently"
- Cause: Tool order dependencies
- Solution: Use streamlined workflow
- Check ruff output:
ruff check . --verbose - Review configuration: Check
pyproject.tomlruff settings - Run auto-fix:
ruff check --fix . - Check specific rules:
ruff check . --select I(imports only)
- Always use
ruff check --fixbefore committing - Run
black .for consistent formatting - Use
pytestfor testing - Don't mix old and new tools
- Let ruff handle all linting (imports, style, quality)
- Faster development - single tool for all linting
- Consistent results - no more import sorting conflicts
- Better performance - Rust-based tooling
- Simplified CI - fewer steps, faster builds
- Modern standards - follows current Python best practices
- AI-friendly - configured for readable routing logic with multiple returns
- Centralized config - all patterns and constants in one place
- Single Source of Truth: All regex patterns, constants, and settings now centralized in
/src/config.py - Eliminated Duplication: Removed hardcoded patterns from individual modules
- Improved Maintainability: Changes to patterns only need to be made in one place
- Better Testing: Centralized configuration makes testing more reliable
- Improved Time-Sensitivity Detection: Better recognition of queries needing current information
- Optimized Entity Detection:
ENTITY_DETECTION_MIN_WORDS=10is parsed into config and available for routing; note that the current routing implementation does not yet consult this value at runtime. - Readable Logic: Restored clear, readable routing logic with early returns