[tool.poetry]
name = "mcp-souschef"
version = "7.2.0"
description = "AI-powered MCP server for Chef, SaltStack, Puppet, PowerShell, and Bash to Ansible migration, plus Ansible upgrade planning"
readme = "README.md"
homepage = "https://github.com/kpeacocke/souschef"
repository = "https://github.com/kpeacocke/souschef"
documentation = "https://kpeacocke.github.io/souschef/"
keywords = ["chef", "ansible", "migration", "infrastructure", "automation", "mcp", "ai", "conversion"]
authors = ["SousChef Contributors"]
license = "MIT"
packages = [{include = "souschef"}]
classifiers = ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Systems Administration", "Topic :: Utilities"]

[tool.poetry.urls]

[tool.poetry.dependencies]
python = ">=3.10,<4.0"
tomli = {version = ">=2.0.0", python = "<3.11"}
click = ">=8.1.0"
mcp = ">=1.25.0"
python-dotenv = ">=1.2.1"
pyyaml = ">=6.0.0"
pydantic = ">=2.0.0"
requests = ">=2.31.0"
cryptography = ">=43.0.0"
packaging = ">=23.0"
# Optional dependencies for different features
anthropic = {version = ">=0.75.0", optional = true}
openai = {version = ">=1.0.0", optional = true}
pandas = {version = ">=2.0.0", optional = true}
streamlit = {version = ">=1.28.0", optional = true}
plotly = {version = ">=5.17.0,<7.0", optional = true}
boto3 = {version = ">=1.26.0", optional = true}
psycopg = {version = ">=3.1.19", extras = ["binary"], optional = true}
pyjwt = ">=2.12.0"

[tool.poetry.extras]
ai = ["anthropic", "openai"]
ui = ["pandas", "streamlit", "plotly"]
storage = ["boto3", "psycopg"]
all = ["anthropic", "openai", "pandas", "streamlit", "plotly", "boto3", "psycopg"]
[tool.poetry.group.dev.dependencies]
pytest = ">=9.0.2"
pytest-cov = ">=7.0.0"
pytest-benchmark = ">=5.1.0"
hypothesis = ">=6.125.0"
ruff = ">=0.14.10"
mypy = ">=1.14.0"
pip-audit = ">=2.7.0"
twine = ">=6.0.0"
pre-commit = ">=4.5.1"
mutmut = ">=3.4.0"
syrupy = "^5.0.0"
ansible-lint = ">=25.12.2,<27.0.0"
pytest-timeout = "^2.4.0"
types-pyyaml = "^6.0.12.20250915"
mkdocs = "^1.6.0"
mkdocs-material = "^9.5.0"
mkdocstrings = {extras = ["python"], version = ">=0.26,<1.1"}
mkdocs-git-revision-date-localized-plugin = "^1.2.0"
networkx = "^3.2.0"
matplotlib = "^3.8.0"
types-networkx = "^3.6.1.20251220"
types-requests = "^2.32.4.20260107"
types-urllib3 = "^1.26.25.14"
pandas-stubs = "^2.0.0"
responses = ">=0.25,<0.27"
gitpython = ">=3.1.47"
pygments = ">=2.20.0"
python-semantic-release = ">=9.8.0,<10.0.0"

[tool.poetry.scripts]
souschef = "souschef.cli:main"
souschef-mcp = "souschef.server:main"

[build-system]
requires = ["poetry-core>=2.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.semantic_release]
version_toml = ["pyproject.toml:tool.poetry.version"]
tag_format = "v{version}"
build_command = "poetry build"
log_level = "INFO"

[tool.semantic_release.changelog]
changelog_file = "CHANGELOG.md"
commit_message = "chore(release): v{version}"

[tool.semantic_release.branches.main]
match = "main"
prerelease = false

[tool.ruff]
line-length = 88
exclude = ["tools/", "test-output/", "htmlcov/", "site/"]

[tool.ruff.lint]
select = ["E", "F", "W", "C90", "I", "N", "UP", "B", "A", "C4", "T20", "SIM", "PTH", "ISC"]
# Docstring rules - use categories for maintainability; ignore specific exceptions
extend-select = ["D2", "D3", "D4"]
ignore = ["D100", "D104", "D105", "D107", "D203", "D212"]

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/*" = ["S101", "E501"]  # Allow assert statements, long lines in test data
"examples/*" = ["T201", "E501", "D"]  # Allow print statements, long lines, and skip docstrings in demos
"souschef/server.py" = ["T201", "E501", "ISC003"]  # Allow print in main entry, long lines, explicit string concatenation
"souschef/assessment.py" = ["E501"]  # Long lines in migration report templates
"souschef/parsers/validation.py" = ["E501"]  # Long lines in validation messages
"souschef/converters/resource.py" = ["C901"]  # Allow complex function for resource conversion logic
"souschef/deployment.py" = ["ISC003"]  # Allow explicit string concatenation
"souschef/ui/app.py" = ["E402", "C901"]  # Allow imports after path manipulation, complex UI functions
"souschef/ui/pages/cookbook_analysis.py" = ["C901"]  # Allow complex functions in UI code
"souschef/parsers/salt.py" = ["C901", "E501"]  # Allow complex state parsing logic and long lines
"souschef/converters/salt.py" = ["C901", "E501"]  # Allow complex conversion logic and long lines
"souschef/ui/pages/salt_migration.py" = ["C901", "E501"]  # Allow complex UI sections and long lines

[tool.pytest.ini_options]
minversion = "6.0"
addopts = "-ra -q"
filterwarnings = [
    "ignore::ResourceWarning",
]
testpaths = [
    "tests/unit",
    "tests/integration",
    "tests/e2e",
]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]

[tool.coverage.run]
source = ["souschef"]
relative_files = true
omit = ["tests/*", "examples/*"]

[tool.coverage.report]
exclude_lines = [
    "pragma: no cover",
    "def __repr__",
    "raise AssertionError",
    "raise NotImplementedError",
    "if __name__ == .__main__.:",
    "if TYPE_CHECKING:",
    "if typing.TYPE_CHECKING:",
]

[tool.coverage.xml]
output = "coverage.xml"

[tool.coverage.paths]
source = [
    "souschef/",
    "*/souschef/",
]

[tool.mutmut]
backup = false
paths_to_mutate = ["souschef/core/validation.py"]
also_copy = [
    "souschef/",
]
pytest_add_cli_args_test_selection = [
    "tests/unit/test_server.py::TestValidationFramework",
    "tests/unit/test_validation_comprehensive.py",
]

[tool.mypy]
python_version = "3.13"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
check_untyped_defs = true
warn_redundant_casts = true
warn_unused_ignores = true
strict_optional = true
no_implicit_optional = true

[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
check_untyped_defs = false

[[tool.mypy.overrides]]
module = [
    "plotly.*",
    "streamlit.*",
    "mcp.*",
]
ignore_missing_imports = true
