[project] name = "wizarr" version = "2026.7.1" description = "Add your description here" readme = "README.md" requires-python = ">=3.13" dependencies = [ "apprise>=1.9.3", "cachetools>=5.5.2", "cryptography>=48.0.1", "email-validator>=2.2.0", "flask>=3.1.1", "flask-apscheduler>=1.13.1", "flask-babel>=4.0.0", "flask-htmx>=0.4.0", "flask-limiter>=3.8.0", "flask-login>=0.6.3", "flask-migrate>=4.1.0", "flask-restx>=1.3.0", "flask-session>=0.8.0", "flask-sqlalchemy>=3.1.1", "flask-wtf>=1.2.2", "gunicorn>=26.0.0", "ldap3>=2.9.1", "markdown>=3.8", "packaging>=25.0", "plexapi>=4.17.0", "python-dotenv>=1.1.0", "python-frontmatter>=1.1.0", "pyyaml>=6.0.2", "requests>=2.34.2", "setuptools>=65.5.1", "sqlalchemy>=2.0.41", "structlog>=25.4.0", "webauthn>=2.0.0", "websocket-client>=1.8.0", "wtforms>=3.2.1", ] [dependency-groups] dev = [ "pytest>=9.1.1", "pytest-flask>=1.3.0", "pytest-mock>=3.14.1", "pytest-playwright>=0.8.0", "pyright>=1.1.411", "pre-commit>=4.0.1", "playwright>=1.60.0", "commitizen>=4.16.3", "ruff>=0.15.20", "ty>=0.0.1a20", "djlint>=1.36.4", "wlc>=1.16.1", ] [tool.uv] # Disable dev extras when running plain `uv run` inside production containers. default-groups = [] [tool.ruff] target-version = "py313" line-length = 88 lint.select = [ # Original rules "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "T20", # flake8-print (debug statements) "RET", # flake8-return "SIM", # flake8-simplify # Phase 1 additions - Security & Safety "S", # flake8-bandit - security issues "A", # flake8-builtins - shadowing builtins "T10", # flake8-debugger - no debugger statements # Phase 1 additions - Code Quality "ARG", # flake8-unused-arguments "ERA", # eradicate - commented-out code "PIE", # flake8-pie - misc improvements "PTH", # flake8-use-pathlib "RUF", # Ruff-specific rules # Phase 1 additions - Best Practices "DTZ", # flake8-datetimez - timezone awareness "ASYNC", # flake8-async "INP", # flake8-no-pep420 - require __init__.py "PERF", # perflint - performance # Phase 2 cherry-picks - Code complexity & design "C901", # mccabe - function complexity "PLR0911", # too-many-return-statements "PLR0912", # too-many-branches "PLR0913", # too-many-arguments "PLR0915", # too-many-statements "PLR1714", # repeated-equality-comparison "PLR1730", # if-stmt-min-max "PLR5501", # collapsible-else-if ] lint.ignore = [ "E501", # line too long, handled by formatter "T201", # print statements allowed # Security exceptions for development context "S101", # assert allowed in tests "S104", # binding to all interfaces ok in dev "S311", # pseudo-random ok for non-crypto use # Unicode in translations (false positives) "RUF001", # ambiguous unicode in strings "RUF002", # ambiguous unicode in docstrings "RUF003", # ambiguous unicode in comments # Fix separately - don't block on this "INP001", # implicit namespace packages - will create __init__.py files separately # Phase 2 ignores - Too noisy or opinionated "PLR2004", # magic-value-comparison - too noisy # Complexity rules - too strict for media server integrations "PLR0911", # too-many-return-statements "PLR0912", # too-many-branches "PLR0913", # too-many-arguments "PLR0915", # too-many-statements "C901", # complex-structure ] [tool.ruff.lint.mccabe] max-complexity = 15 # Aligns with CLAUDE.md "15 logical lines" guideline [tool.ruff.lint.per-file-ignores] "tests/**/*.py" = ["S106", "S105", "S113", "S110", "S701", "RUF015", "RUF059", "ARG001", "ARG002", "ARG005", "PERF401", "RUF005", "DTZ005", "PTH110", "PTH108", "PTH118", "PTH120", "PTH207", "PTH119", "PTH107"] # Allow test patterns "plus/tests/**/*.py" = ["S106", "S105", "S701"] # Allow Plus test patterns "dev.py" = ["S603", "S607"] # Allow subprocess in dev script "migrations/**/*.py" = ["ERA001", "ARG001", "S608", "S110"] # Allow migration patterns "plus/**/*.py" = ["RUF012", "S110", "PERF403", "ARG001", "ARG002", "ARG004", "F841", "RUF022", "RUF059", "ERA001", "SIM102"] # Allow Plus feature patterns "scripts/**/*.py" = ["S603", "RUF005", "PTH100", "PTH120"] # Allow script patterns "setup_plus.py" = ["S603", "RUF005"] # Allow subprocess in setup script [tool.ruff.lint.isort] known-first-party = ["app"] known-third-party = ["flask_session"] [tool.ty.rules] # Flask-SQLAlchemy db.Model is dynamic and unresolvable by ty unsupported-base = "ignore" [tool.pyright] include = ["app", "tests"] exclude = ["migrations"] venvPath = "." venv = ".venv" pythonVersion = "3.13" typeCheckingMode = "basic" reportMissingImports = true reportMissingTypeStubs = false reportUnusedImport = true reportUnusedVariable = true [tool.commitizen] name = "cz_conventional_commits" version = "2026.7.1" version_files = [ "pyproject.toml:version" ] style = [ ["qmark", "fg:#ff9d00 bold"], ["question", "bold"], ["answer", "fg:#ff9d00 bold"], ["pointer", "fg:#ff9d00 bold"], ["highlighted", "fg:#ff9d00 bold"], ["selected", "fg:#cc5454"], ["separator", "fg:#cc5454"], ["instruction", ""], ["text", ""], ["disabled", "fg:#858585 italic"] ]