[project] name = "mealie" version = "3.5.0" 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.2,<4.0.0", "Pillow>=12.0.0,<13.0.0", "PyYAML>=6.0.1,<7.0.0", "SQLAlchemy>=2.0.0,<3.0.0", "aiofiles>=25.0.0,<26.0.0", "alembic>=1.11.3,<2.0.0", "aniso8601==10.0.1", "appdirs==1.4.4", "apprise>=1.4.5,<2.0.0", "bcrypt>=5.0.0,<6.0.0", "extruct>=0.18.0,<1.0.0", "fastapi>=0.120.0,<1.0.0", "httpx>=0.28.0,<1.0.0", "lxml>=6.0.0,<7.0.0", "orjson>=3.8.0,<4.0.0", "pydantic>=2.6.1,<3.0.0", "pyhumps>=3.5.3,<4.0.0", "python-dateutil>=2.8.2,<3.0.0", "python-dotenv>=1.0.0,<2.0.0", "python-ldap>=3.3.1,<4.0.0", "python-multipart>=0.0.20,<1.0.0", "python-slugify>=8.0.0,<9.0.0", "recipe-scrapers>=15.0.0,<16.0.0", "requests>=2.31.0,<3.0.0", "tzdata>=2025.2,<2025.3", "uvicorn[standard]>=0.38.0,<1.0.0", "beautifulsoup4>=4.11.2,<5.0.0", "isodate>=0.7.0,<1.0.0", "text-unidecode>=1.3,<2.0", "rapidfuzz>=3.2.0,<4.0.0", "authlib>=1.3.0,<2.0.0", "html2text>=2025.0.0,<2026.0.0", "paho-mqtt>=1.6.1,<2.0.0", "pydantic-settings>=2.1.0,<3.0.0", "pillow-heif>=1.0.0,<2.0.0", "pyjwt>=2.8.0,<3.0.0", "openai>=2.0.0,<3.0.0", "typing-extensions>=4.12.2,<5.0.0", "itsdangerous>=2.2.0,<3.0.0", "ingredient-parser-nlp>=2.0.0,<3.0.0", ] [project.scripts] mealie = "mealie.main:main" [project.optional-dependencies] pgsql = [ "psycopg2-binary>=2.9.1,<3.0.0" ] [dependency-groups] dev = [ "coverage>=7.0,<8.0", "coveragepy-lcov>=0.1.1,<1.0.0", "mkdocs-material>=9.0.0,<10.0.0", "mypy>=1.5.1,<2.0.0", "pre-commit>=4.0.0,<5.0.0", "pylint>=4.0.0,<5.0.0", "pytest>=9.0.1,<9.1.0", "pytest-asyncio>=1.0.0,<2.0.0", "rich>=14.0.0,<15.0.0", "ruff>=0.14.0,<1.0.0", "types-PyYAML>=6.0.4,<7.0.0", "types-python-dateutil>=2.8.18,<3.0.0", "types-python-slugify>=8.0.2.0,<8.1.0", "types-requests>=2.27.12,<3.0.0", "types-urllib3>=1.26.11,<2.0.0", "pydantic-to-typescript2>=1.0.4,<2.0.0", ] [build-system] requires = ["setuptools>=77.0.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.