[project] name = "mealie" version = "3.6.1" description = "A Recipe Manager" authors = [{ name = "Hayden", email = "hay-kot@pm.me" }] license = "AGPL-3.0-only" requires-python = ">=3.12,<3.13" dependencies = [ "Jinja2==3.1.6", "Pillow==12.0.0", "PyYAML==6.0.3", "SQLAlchemy==2.0.44", "aiofiles==25.1.0", "alembic==1.17.2", "aniso8601==10.0.1", "appdirs==1.4.4", "apprise==1.9.5", "bcrypt==5.0.0", "extruct==0.18.0", "fastapi==0.123.1", "httpx==0.28.1", "lxml==6.0.2", "orjson==3.11.4", "pydantic==2.12.5", "pyhumps==3.8.0", "python-dateutil==2.9.0.post0", "python-dotenv==1.2.1", "python-ldap==3.4.5", "python-multipart==0.0.20", "python-slugify==8.0.4", "recipe-scrapers==15.10.0", "requests==2.32.5", "tzdata==2025.2", "uvicorn[standard]==0.38.0", "beautifulsoup4==4.14.3", "isodate==0.7.2", "text-unidecode==1.3", "rapidfuzz==3.14.3", "authlib==1.6.5", "html2text==2025.4.15", "paho-mqtt==1.6.1", "pydantic-settings==2.12.0", "pillow-heif==1.1.1", "pyjwt==2.10.1", "openai==2.8.1", "typing-extensions==4.15.0", "itsdangerous==2.2.0", "ingredient-parser-nlp==2.4.0", ] [project.scripts] mealie = "mealie.main:main" [project.optional-dependencies] pgsql = [ "psycopg2-binary==2.9.11" ] [dependency-groups] dev = [ "coverage==7.12.0", "coveragepy-lcov==0.1.2", "mkdocs-material==9.7.0", "mypy==1.19.0", "pre-commit==4.5.0", "pylint==4.0.4", "pytest==9.0.1", "pytest-asyncio==1.3.0", "rich==14.2.0", "ruff==0.14.7", "types-PyYAML==6.0.12.20250915", "types-python-dateutil==2.9.0.20251115", "types-python-slugify==8.0.2.20240310", "types-requests==2.32.4.20250913", "types-urllib3==1.26.25.14", "pydantic-to-typescript2==1.0.6", ] [build-system] requires = ["setuptools==80.9.0"] build-backend = "setuptools.build_meta" [tool.setuptools] include-package-data = true [tool.setuptools.packages.find] include = ["mealie*"] [tool.setuptools.package-data] "*" = ["*"] [tool.pytest.ini_options] addopts = "-ra -q" asyncio_default_fixture_loop_scope = "function" minversion = "6.0" python_classes = '*Tests' python_files = 'test_*' python_functions = 'test_*' testpaths = ["tests"] [tool.coverage.report] skip_empty = true [tool.mypy] follow_imports = "skip" ignore_missing_imports = true plugins = "pydantic.mypy" python_version = "3.12" strict_optional = true [tool.ruff] target-version = "py312" line-length = 120 output-format = "concise" # Exclude a variety of commonly ignored directories. exclude = [ ".bzr", ".direnv", ".eggs", ".git", ".hg", ".mypy_cache", ".nox", ".pants.d", ".ruff_cache", ".svn", ".tox", ".venv", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "venv", ] [tool.ruff.lint.isort] known-third-party = ["alembic"] [tool.ruff.lint] # Enable Pyflakes `E` and `F` codes by default. ignore = ["F403", "TID252", "B008"] select = [ "B", # flake8-bugbear "C4", # McCabe complexity "C90", # flake8-comprehensions "DTZ", # flake8-datetimez "E", # pycodestyles "F", # pyflakes "I", # isort "T", # flake8-print "UP", # pyupgrade # "ANN", # flake8-annotations # "BLE", # blind-except # "RUF", # Ruff specific ] [tool.ruff.lint.per-file-ignores] "__init__.py" = ["E402", "E501"] "mealie/alembic/versions/*" = ["E501", "I001"] "dev/scripts/all_recipes_stress_test.py" = ["E501"] "ldap_provider.py" = ["UP032"] "tests/conftest.py" = ["E402"] "tests/utils/routes/__init__.py" = ["F401"] [tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. max-complexity = 24 # Default is 10.