|
1 | 1 | # AGENTS.md |
2 | 2 |
|
3 | | -## Project Overview |
| 3 | +Python client for the Crowdin API v2 and Crowdin Enterprise API v2 (PyPI: `crowdin-api-client`, import: `crowdin_api`). |
4 | 4 |
|
5 | | -Python client library for Crowdin API v2 and Crowdin Enterprise API v2. |
| 5 | +Supports Python 3.8+, so write 3.8-compatible code: no `X | Y` unions, no `match`, and import `TypedDict` from `crowdin_api.typing`. |
6 | 6 |
|
7 | | -Main structure: |
8 | | -- Source code: `crowdin_api/` |
9 | | -- Tests: `crowdin_api/tests/` and `crowdin_api/api_resources/**/tests/` |
| 7 | +## Layout |
10 | 8 |
|
11 | | -## Setup Commands |
| 9 | +- `crowdin_api/client.py` — `CrowdinClient`; one hand-written `@property` per resource |
| 10 | +- `crowdin_api/api_resources/<resource>/` — one package per API resource: `resource.py`, `types.py` (request TypedDicts), `enums.py`, `tests/test_<resource>_resources.py` |
| 11 | +- `crowdin_api/api_resources/abstract/resources.py` — `BaseResource` |
| 12 | +- `crowdin_api/requester.py` — `APIRequester` (session, retries, error mapping) |
12 | 13 |
|
13 | | -- Install dependencies: `python -m pip install --upgrade pip && pip install -r requirements/requirements-dev.txt` |
14 | | -- Run tests: `pytest` |
15 | | -- Run one test file: `pytest crowdin_api/api_resources/.../tests/test_*.py` |
16 | | -- Lint: `flake8 . --count --show-source --statistics` |
| 14 | +## Commands |
17 | 15 |
|
18 | | -## Code And Testing Expectations |
| 16 | +- Install: `pip install -r requirements/requirements-dev.txt` |
| 17 | +- Test (all): `pytest` — `setup.cfg` addopts enforce a 95% coverage gate |
| 18 | +- Test (one file): `pytest crowdin_api/api_resources/<resource>/tests/test_*.py --no-cov` — without `--no-cov` the coverage gate fails any partial run even when all tests pass |
| 19 | +- Lint (what CI runs): `flake8 . --count --show-source --statistics` |
| 20 | +- Format: `pre-commit run --all-files` (black `-l 100`, isort, flake8, xenon) |
19 | 21 |
|
20 | | -- Add or update unit tests for behavior changes. |
21 | | -- Keep public API and model changes backward compatible unless explicitly intended. |
22 | | -- Follow existing style and lint configuration (`setup.cfg`, `flake8`). |
23 | | -- Keep changes focused and consistent with existing resource patterns. |
| 22 | +`--doctest-modules` is active: pytest imports every module in `crowdin_api/`, and any `>>>` in a docstring runs as a test. |
24 | 23 |
|
25 | | -## Notes For API Details |
| 24 | +## Adding or changing an endpoint |
26 | 25 |
|
27 | | -Always use Crowdin/Crowdin Enterprise `llms.txt` index files for API method details. Choose the correct index by environment first, then project type. |
| 26 | +Fetch the endpoint spec first (see Crowdin API reference below). Then: |
28 | 27 |
|
29 | | -Use these URLs: |
| 28 | +1. Implement the method on the `*Resource` class in `crowdin_api/api_resources/<resource>/resource.py`: |
| 29 | + - List endpoints call `self._get_entire_data(method="get", path=..., params=...)` so `with_fetch_all()` pagination works; everything else calls `self.requester.request(...)`. |
| 30 | + - Project-scoped methods take `projectId: Optional[int] = None` and resolve it via `projectId or self.get_project_id()`. |
| 31 | + - Request body shapes go in `types.py` as TypedDicts; enum values in `enums.py`. Enums and `Sorting` objects can be passed straight into `params`/`request_data` — the custom JSON encoder serializes them, and `None` values are stripped before sending. |
| 32 | + - End the docstring with `Link to documentation:` and the developer.crowdin.com operation URL (pdoc publishes these). |
| 33 | +2. For a new resource, register it in three places: an import plus `__all__` entry in `crowdin_api/api_resources/__init__.py` (alphabetical), a `@property` on `CrowdinClient` in `client.py` (copy an existing property; use the enterprise-guard or per-platform variant when the API is Enterprise-only or differs by platform), and one tuple in each of the two parametrize lists in `crowdin_api/tests/test_client.py`. Some resource classes exist but were never registered (e.g. `BranchesResource`, `StringCorrectionsResource`) — "adding" one of those is exactly this registration work. |
| 34 | +3. Test in the resource's `tests/` dir: patch the requester with `@mock.patch("crowdin_api.requester.APIRequester.request")`, call the method, then `m_request.assert_called_once_with(method=..., path=..., ...)` with the exact kwargs. The `base_absolut_url` fixture (spelled without the second "e") provides the base URL. No test performs real HTTP. |
30 | 35 |
|
31 | | -- https://support.crowdin.com/_llms-txt/api/crowdin/file-based.txt - Crowdin API (file-based projects, preferred first) |
32 | | -- https://support.crowdin.com/_llms-txt/api/crowdin/string-based.txt - Crowdin API (string-based projects) |
33 | | -- https://support.crowdin.com/_llms-txt/api/enterprise/file-based.txt - Crowdin Enterprise API (file-based projects) |
34 | | -- https://support.crowdin.com/_llms-txt/api/enterprise/string-based.txt - Crowdin Enterprise API (string-based projects) |
| 36 | +A complete new resource touches ~8 files: the four package files (`__init__.py` is one line: `__pdoc__ = {'tests': False}`), the resource's test file, and the three registration files. |
35 | 37 |
|
36 | | -Each index contains links to method details (for example, `.../api.projects.strings.get.txt`). |
| 38 | +## Crowdin API reference |
37 | 39 |
|
38 | | -## Pull Requests And Commits |
| 40 | +Before implementing or changing any endpoint, fetch its spec from the llms.txt indexes (pick by environment, then project type): |
39 | 41 |
|
40 | | -- Use Conventional Commits for commit messages and PR titles. |
41 | | -- Before opening a PR, run lint and tests locally. |
| 42 | +- https://support.crowdin.com/_llms-txt/api/crowdin/file-based.txt — Crowdin API, file-based projects (start here) |
| 43 | +- https://support.crowdin.com/_llms-txt/api/crowdin/string-based.txt — Crowdin API, string-based projects |
| 44 | +- https://support.crowdin.com/_llms-txt/api/enterprise/file-based.txt — Crowdin Enterprise API, file-based projects |
| 45 | +- https://support.crowdin.com/_llms-txt/api/enterprise/string-based.txt — Crowdin Enterprise API, string-based projects |
| 46 | + |
| 47 | +Each index links one spec file per route (e.g. `.../api.projects.strings.get.txt`) with the exact request and response shapes. |
| 48 | + |
| 49 | +## Conventions |
| 50 | + |
| 51 | +- Conventional Commits for commit messages and PR titles; CI lints PR titles. |
| 52 | +- PRs target `main`. |
| 53 | +- Keep the public API backward compatible; mark removals with `@deprecated(...)` (from the `deprecated` package) instead of deleting. |
| 54 | +- Never edit `__version__` in `crowdin_api/__init__.py` — the Release workflow bumps it. |
| 55 | + |
| 56 | +## PR checklist |
| 57 | + |
| 58 | +A change is ready when: |
| 59 | + |
| 60 | +1. `pytest` passes, including the 95% coverage gate, |
| 61 | +2. `flake8 . --count --show-source --statistics` is clean, |
| 62 | +3. every new or changed endpoint method has a test asserting the exact requester call, and |
| 63 | +4. every new or changed public method's docstring ends with its documentation link. |
0 commit comments