clarify dependency groups vs optional dependencies

groups (PEP 735) stay local, optional deps go into package metadata

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+28 -12
languages
python
ecosystem
+28 -12
languages/python/ecosystem/project-setup.md
··· 59 60 key patterns: 61 - `dynamic = ["version"]` - version comes from git tags, not manual editing 62 - - `[dependency-groups]` - dev deps separate from runtime deps 63 - `[project.scripts]` - CLI entry points 64 65 ## versioning from git tags 66 ··· 108 myproject = "myproject.cli:main" 109 myproject-mcp = "myproject.mcp:main" 110 ``` 111 - 112 - ## optional dependencies 113 - 114 - for features that not everyone needs: 115 - 116 - ```toml 117 - [project.optional-dependencies] 118 - mcp = ["fastmcp>=2.0"] 119 - ``` 120 - 121 - install with `uv sync --extra mcp` or `uv add 'myproject[mcp]'`. 122 123 ## uv workspaces 124
··· 59 60 key patterns: 61 - `dynamic = ["version"]` - version comes from git tags, not manual editing 62 - `[project.scripts]` - CLI entry points 63 + 64 + ## dependency groups vs optional dependencies 65 + 66 + these look similar but serve different purposes. 67 + 68 + **dependency groups** (PEP 735) are local-only. they never appear in published package metadata. users who `pip install` your package won't see them: 69 + 70 + ```toml 71 + [dependency-groups] 72 + dev = ["pytest", "ruff"] 73 + docs = ["mkdocs", "mkdocs-material"] 74 + ``` 75 + 76 + install with `uv sync --group dev`. CI can install only what it needs. 77 + 78 + **optional dependencies** are published in package metadata. users can install them: 79 + 80 + ```toml 81 + [project.optional-dependencies] 82 + aws = ["prefect-aws"] 83 + mcp = ["fastmcp>=2.0"] 84 + ``` 85 + 86 + install with `pip install mypackage[aws]` or `uv add 'mypackage[mcp]'`. 87 + 88 + use groups for dev/test/CI. use optional deps for features consumers might want. 89 + 90 + from [switching a big python library from setup.py to pyproject.toml](https://blog.zzstoatzz.io/switching-a-big-python-library-from-setuppy-to-pyprojecttoml/) 91 92 ## versioning from git tags 93 ··· 135 myproject = "myproject.cli:main" 136 myproject-mcp = "myproject.mcp:main" 137 ``` 138 139 ## uv workspaces 140