-
Notifications
You must be signed in to change notification settings - Fork 852
chore: add AGENTS.md and consolidate development scripts #1836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| CLAUDE.local.md | ||
| settings.local.json | ||
| worktrees/ | ||
| plans/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| @../AGENTS.md |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| { | ||
| "permissions": { | ||
| "allow": [ | ||
| "Bash(./scripts/build_pypi_package.sh:*)", | ||
| "Bash(./scripts/format.sh:*)", | ||
| "Bash(./scripts/generate_api_docs.sh:*)", | ||
| "Bash(./scripts/install.sh:*)", | ||
| "Bash(./scripts/lint.sh:*)", | ||
| "Bash(./scripts/run_mypy.sh:*)", | ||
| "Bash(./scripts/run_tests.sh:*)", | ||
| "Bash(./scripts/run_validation.sh:*)", | ||
| "Bash(./scripts/uninstall_all.sh:*)", | ||
| "Bash(python scripts/codegen.py:*)", | ||
| "Bash(echo $VIRTUAL_ENV)", | ||
| "Bash(gh issue view:*)", | ||
| "Bash(gh label list:*)", | ||
| "Bash(gh pr checks:*)", | ||
| "Bash(gh pr diff:*)", | ||
| "Bash(gh pr list:*)", | ||
| "Bash(gh pr status:*)", | ||
| "Bash(gh pr update-branch:*)", | ||
| "Bash(gh pr view:*)", | ||
| "Bash(gh search code:*)", | ||
| "Bash(git diff:*)", | ||
| "Bash(git grep:*)", | ||
| "Bash(git log:*)", | ||
| "Bash(git show:*)", | ||
| "Bash(git status:*)", | ||
| "Bash(grep:*)", | ||
| "Bash(ls:*)", | ||
| "Bash(tree:*)", | ||
| "WebFetch(domain:github.com)", | ||
| "WebFetch(domain:docs.slack.dev)" | ||
| ] | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,308 @@ | ||
| # AGENTS.md — Python Slack SDK | ||
|
|
||
| ## Project Overview | ||
|
|
||
| The Python Slack SDK (`slack_sdk`) is a modular Python library for interacting with the Slack platform APIs. It is published on PyPI as `slack-sdk`. The SDK provides independent packages for each Slack API surface: Web API, Webhooks, Socket Mode, OAuth, Audit Logs, SCIM, RTM, Block Kit models, and request signature verification. | ||
|
|
||
| - **Repository**: <https://github.com/slackapi/python-slack-sdk> | ||
| - **Documentation**: <https://docs.slack.dev/tools/python-slack-sdk/> | ||
| - **PyPI**: <https://pypi.org/project/slack-sdk/> | ||
| - **Current version**: defined in `slack_sdk/version.py` | ||
|
|
||
| ## Critical Rules | ||
|
|
||
| These are the most important constraints in this project. Violating any of them will break CI or corrupt auto-generated code: | ||
|
|
||
| 1. **Never edit auto-generated files.** The following files are produced by `scripts/codegen.py` and must not be modified directly: | ||
| - `slack_sdk/web/async_client.py` | ||
| - `slack_sdk/web/legacy_client.py` | ||
| - `slack_sdk/web/async_chat_stream.py` | ||
|
|
||
| Edit the source files (`client.py` or `chat_stream.py`) instead, then run codegen (see [Code Generation](#code-generation-critical-pattern)). | ||
|
|
||
| 2. **Zero runtime dependencies.** The core sync Web API client must have no required runtime dependencies. Do not add entries to `install_requires` / `dependencies` in `pyproject.toml`. | ||
|
|
||
| 3. **Do not modify the legacy `slack/` package.** It is in maintenance mode and only re-exports from `slack_sdk` with deprecation warnings. All new development goes in `slack_sdk/`. | ||
|
|
||
| 4. **Always run codegen + format after editing `client.py` or `chat_stream.py`:** | ||
|
|
||
| ```sh | ||
| python scripts/codegen.py --path . | ||
| ./scripts/format.sh | ||
| ``` | ||
|
|
||
| 5. **Use project scripts, not raw tool commands.** Run `./scripts/run_tests.sh`, not `pytest` directly. The scripts handle codegen and formatting. | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### Package Structure | ||
|
|
||
| The SDK is organized into independent sub-packages: | ||
|
|
||
| - **`slack_sdk/web/`** — Web API client (sync, async, legacy). Contains auto-generated files (see [Code Generation](#code-generation-critical-pattern)) | ||
| - **`slack_sdk/webhook/`** — Incoming Webhooks | ||
| - **`slack_sdk/socket_mode/`** — Socket Mode with pluggable backends | ||
| - **`slack_sdk/oauth/`** — OAuth flows and token storage | ||
| - **`slack_sdk/models/`** — Block Kit UI builders | ||
| - **`slack_sdk/audit_logs/`**, **`slack_sdk/scim/`** — Enterprise APIs | ||
| - **`slack_sdk/signature/`** — Request verification | ||
| - **`slack_sdk/http_retry/`** — Retry handlers | ||
| - **`slack/`** — Legacy package (maintenance mode, do not modify) | ||
|
|
||
| See the repository structure for the complete package layout. | ||
|
|
||
| ### Code Generation (Critical Pattern) | ||
|
|
||
| **NEVER edit these auto-generated files:** | ||
|
|
||
| - `slack_sdk/web/async_client.py` | ||
| - `slack_sdk/web/legacy_client.py` | ||
| - `slack_sdk/web/async_chat_stream.py` | ||
|
|
||
| Each contains a header warning: | ||
| ```text | ||
| # DO NOT EDIT THIS FILE | ||
| # 1) Modify slack_sdk/web/client.py | ||
| # 2) Run `python scripts/codegen.py` | ||
| # 3) Run `black slack_sdk/` | ||
| ``` | ||
|
|
||
| **How it works:** | ||
|
|
||
| 1. Edit `slack_sdk/web/client.py` (canonical source for Web API methods) | ||
| 2. Edit `slack_sdk/web/chat_stream.py` (canonical source for streaming chat) | ||
| 3. Run `python scripts/codegen.py --path .` to generate async/legacy variants | ||
| 4. Run `./scripts/format.sh` to format the generated code | ||
|
|
||
| The codegen script (`scripts/codegen.py`) automatically transforms sync code into async variants by adding `async def`, `await`, and replacing classes with async equivalents. | ||
|
|
||
| ### Web API Method Pattern | ||
|
|
||
| Every Web API method in `client.py` follows this pattern: | ||
|
|
||
| ```python | ||
| def method_name( | ||
| self, | ||
| *, # keyword-only arguments | ||
| required_param: str, | ||
| optional_param: Optional[str] = None, | ||
| **kwargs, | ||
| ) -> SlackResponse: | ||
| """Description of the API method | ||
| https://docs.slack.dev/reference/methods/method.name | ||
| """ | ||
| kwargs.update({"required_param": required_param}) | ||
| if optional_param is not None: | ||
| kwargs.update({"optional_param": optional_param}) | ||
| return self.api_call("method.name", params=kwargs) | ||
| ``` | ||
|
|
||
| Key conventions: | ||
|
|
||
| - All parameters are keyword-only (after `*`) | ||
| - Required params have no default; optional params default to `None` | ||
| - `**kwargs` captures additional/undocumented parameters | ||
| - Parameters are collected into `kwargs` dict and passed to `self.api_call()` | ||
| - The `api_call` method name uses Slack's dot-notation (e.g., `"chat.postMessage"`) | ||
| - Docstrings include a link to the Slack API reference | ||
|
|
||
| ### Error Types | ||
|
|
||
| All SDK exceptions are defined in `slack_sdk/errors/__init__.py` and inherit from `SlackClientError`. | ||
|
|
||
| Key exceptions to be aware of: | ||
|
|
||
| - **`SlackApiError`** — Raised when the API returns an error response (carries the `response` object) | ||
| - **`SlackRequestError`** — Raised when the HTTP request itself fails | ||
| - **`BotUserAccessError`** — Raised when using a bot token (`xoxb-*`) for a user-only method | ||
|
|
||
| See `slack_sdk/errors/__init__.py` for the complete list of exception types and their usage. | ||
|
|
||
| ### HTTP Retry Handlers | ||
|
|
||
| The `slack_sdk/http_retry/` module provides built-in retry strategies for connection errors, rate limiting (HTTP 429), and server errors (HTTP 500/503). | ||
|
|
||
| Key handlers: | ||
|
|
||
| - **`ConnectionErrorRetryHandler`** / **`AsyncConnectionErrorRetryHandler`** | ||
| - **`RateLimitErrorRetryHandler`** / **`AsyncRateLimitErrorRetryHandler`** (respects `Retry-After` header) | ||
| - **`ServerErrorRetryHandler`** / **`AsyncServerErrorRetryHandler`** | ||
|
|
||
| Retry intervals can be configured with `BackoffRetryIntervalCalculator` (exponential backoff) or `FixedValueRetryIntervalCalculator`. See `slack_sdk/http_retry/` for implementation details. | ||
|
|
||
| ### Test Patterns | ||
|
|
||
| Tests use `unittest.TestCase` with a mock web API server: | ||
|
|
||
| ```python | ||
| import unittest | ||
| from slack_sdk import WebClient | ||
| from tests.slack_sdk.web.mock_web_api_handler import MockHandler | ||
| from tests.mock_web_api_server import setup_mock_web_api_server, cleanup_mock_web_api_server | ||
|
|
||
| class TestFeature(unittest.TestCase): | ||
| def setUp(self): | ||
| setup_mock_web_api_server(self, MockHandler) | ||
| self.client = WebClient( | ||
| token="xoxb-api_test", | ||
| base_url="http://localhost:8888", | ||
| ) | ||
|
|
||
| def tearDown(self): | ||
| cleanup_mock_web_api_server(self) | ||
|
|
||
| def test_something(self): | ||
| resp = self.client.api_test() | ||
| self.assertTrue(resp["ok"]) | ||
| ``` | ||
|
|
||
| Each sub-package has its own `MockHandler` (e.g., `tests/slack_sdk/webhook/mock_web_api_handler.py`, `tests/slack_sdk/scim/mock_web_api_handler.py`). Use the handler from the matching sub-package. | ||
|
|
||
| Test directories: | ||
|
|
||
| - `tests/` — Unit tests (mirroring `slack_sdk/` structure) | ||
| - `tests/slack_sdk/` — Sync tests | ||
| - `tests/slack_sdk_async/` — Async variants | ||
| - `tests/slack_sdk_fixture/` — Pytest fixtures and test data | ||
| - `tests/data/` — JSON fixture files | ||
| - `tests/mock_web_api_server/` — Mock Slack API server | ||
| - `integration_tests/` — Tests against real Slack APIs (require env tokens) | ||
|
|
||
| ## Development Commands | ||
|
|
||
| ### Setup | ||
|
|
||
| **Prerequisites:** A Python virtual environment must be activated. See `.github/maintainers_guide.md` for detailed setup instructions using `pyenv` and `venv`. | ||
|
|
||
| **Quick check:** Verify venv is active with `echo $VIRTUAL_ENV` (should output a path). | ||
|
|
||
| Always use the project scripts instead of calling tools like `pytest` directly. | ||
|
|
||
| ### Install Dependencies | ||
|
|
||
| ```sh | ||
| ./scripts/install.sh | ||
| ``` | ||
|
|
||
| Installs all project dependencies (testing, optional, and tools) via pip. This script is called automatically by `run_validation.sh`, `run_integration_tests.sh`, and `run_mypy.sh`, so you typically don't need to run it separately. | ||
|
|
||
| ### Full Validation | ||
|
|
||
| ```sh | ||
| ./scripts/run_validation.sh | ||
| ``` | ||
|
|
||
| This is the canonical check — CI runs this and the PR template asks contributors to run it. It installs requirements, runs codegen, formats, lints, runs tests with coverage, and runs mypy type checking on the latest supported Python version (check the `LATEST_SUPPORTED_PY` environment variable in `.github/workflows/ci-build.yml`). | ||
|
|
||
| ### Individual Commands | ||
|
|
||
| Available scripts in the `scripts/` directory: | ||
|
|
||
| | Task | Command | | ||
| | --- | --- | | ||
| | Install dependencies | `./scripts/install.sh` | | ||
| | Uninstall all packages | `./scripts/uninstall_all.sh` | | ||
| | Format code | `./scripts/format.sh` | | ||
| | Lint (check formatting) | `./scripts/lint.sh` | | ||
| | Run all unit tests | `./scripts/run_tests.sh` | | ||
| | Run a specific test | `./scripts/run_tests.sh tests/slack_sdk/web/test_web_client.py` | | ||
| | Run type checking | `./scripts/run_mypy.sh` | | ||
| | Generate async/legacy code | `python scripts/codegen.py --path .` | | ||
| | Build PyPI package | `./scripts/build_pypi_package.sh` | | ||
| | Generate API docs | `./scripts/generate_api_docs.sh` | | ||
|
|
||
| ## Code Style & Tooling | ||
|
|
||
| All tooling configuration is defined in the following files: | ||
|
|
||
| - **Formatter**: `black` — see `[tool.black]` in `pyproject.toml` | ||
| - **Linter**: `flake8` — see `.flake8` | ||
| - **Type checker**: `mypy` — see `[tool.mypy]` in `pyproject.toml` | ||
| - **Test runner**: `pytest` — see `[tool.pytest.ini_options]` in `pyproject.toml` | ||
| - **Coverage**: `pytest-cov` reporting to Codecov | ||
| - **Build system**: see `[build-system]` and `[project]` in `pyproject.toml` | ||
|
|
||
| **Dependencies:** | ||
|
|
||
| - Testing: `requirements/testing.txt` | ||
| - Optional runtime: `requirements/optional.txt` | ||
| - Dev tools (black, flake8, mypy): `requirements/tools.txt` | ||
|
|
||
| ## CI Pipeline (GitHub Actions) | ||
|
|
||
| Defined in `.github/workflows/ci-build.yml`, runs on push to `main`, all PRs, and daily schedule. Check the workflow file for the current Python version matrix. | ||
|
|
||
| ## Key Files & Directories | ||
|
|
||
| **Source Code:** | ||
|
|
||
| - `slack_sdk/` — Main package (active development) | ||
| - `slack_sdk/web/client.py` — **CANONICAL SOURCE** for all Web API methods | ||
| - `slack_sdk/web/chat_stream.py` — Canonical streaming chat client | ||
| - `slack_sdk/version.py` — Single source of truth for version | ||
| - `slack/` — Legacy package (maintenance mode, DO NOT MODIFY) | ||
|
|
||
| **Configuration:** | ||
|
|
||
| - `pyproject.toml` — Project metadata, build config, tool settings (black, pytest, mypy) | ||
| - `.flake8` — Flake8 linter configuration | ||
| - `requirements/*.txt` — Dependency specifications | ||
|
|
||
| **Tooling:** | ||
|
|
||
| - `scripts/codegen.py` — Generates async/legacy client variants | ||
| - `scripts/*.sh` — Development and CI helper scripts | ||
|
|
||
| **GitHub & CI/CD:** | ||
|
|
||
| - `.github/` — GitHub-specific configuration and documentation | ||
| - `.github/workflows/` — Continuous integration pipeline definitions that run on GitHub Actions | ||
| - `.github/maintainers_guide.md` — Maintainer workflows and release process | ||
|
|
||
| **Documentation:** | ||
|
|
||
| - `README.md` — Project overview, installation, and usage examples | ||
| - `.github/maintainers_guide.md` — Maintainer workflows and release process | ||
|
|
||
| ## Common Contribution Workflows | ||
|
|
||
| ### Adding a New Web API Method | ||
|
|
||
| 1. Add the method to `slack_sdk/web/client.py` following the existing pattern | ||
| 2. Run code generation: `python scripts/codegen.py --path .` | ||
| 3. Run formatter: `./scripts/format.sh` | ||
| 4. Add tests in `tests/slack_sdk/web/` | ||
| 5. Validate: `./scripts/run_validation.sh` | ||
|
|
||
| ### Adding a New Feature to a Non-Web Module | ||
|
|
||
| 1. Implement the sync version in the appropriate `slack_sdk/` subpackage | ||
| 2. If the module has async variants, implement those as well (not auto-generated for non-web modules) | ||
| 3. Add tests mirroring the module structure | ||
| 4. Validate: `./scripts/run_validation.sh` | ||
|
|
||
| ### Fixing a Bug | ||
|
|
||
| 1. Write a test that reproduces the bug | ||
| 2. Fix the code (if in `client.py`, run codegen afterward) | ||
| 3. Validate: `./scripts/run_validation.sh` | ||
|
|
||
| ## Versioning & Releases | ||
|
|
||
| - Use the new version mentioned by the maintainer; if they do not provide it, prompt them for it. | ||
| - Ensure the new version follows [Semantic Versioning](http://semver.org/) via [PEP 440](https://peps.python.org/pep-0440/) | ||
| - Version lives in `slack_sdk/version.py` and is dynamically read by `pyproject.toml` | ||
| - Releases are triggered by publishing a GitHub Release, which triggers the PyPI deployment workflow; the maintainer will take care of this | ||
| - Commit message format for releases: `chore(release): version X.Y.Z` | ||
|
|
||
| ## Dependencies | ||
|
|
||
| The SDK has **zero required runtime dependencies** for the core sync Web API client and it is imperative it remains that way. Optional dependencies enable additional functionality: | ||
|
|
||
| - `aiohttp` — async HTTP client | ||
| - `websockets` / `websocket-client` — Socket Mode backends | ||
| - `SQLAlchemy` — OAuth token storage | ||
| - `boto3` — S3/DynamoDB token storage | ||
| - `aiodns` — faster DNS resolution for async | ||
|
|
||
| Version constraints for optional and dev dependencies are pinned in the `requirements/` directory. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| #!/bin/bash | ||
| # ./scripts/install.sh | ||
| # Installs all project dependencies (testing, optional, and tools) | ||
|
|
||
| set -e | ||
|
|
||
| script_dir=$(dirname $0) | ||
| cd ${script_dir}/.. | ||
|
|
||
| pip install -U pip | ||
|
|
||
| pip install -U -r requirements/testing.txt \ | ||
| -U -r requirements/optional.txt \ | ||
| -U -r requirements/tools.txt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐍 praise: Super nice command to have here!