|
1 | | -# Copilot Instructions for Codesphere Python SDK |
| 1 | +# Codesphere SDK - AI Instructions |
2 | 2 |
|
3 | | -## Project Context |
4 | | - |
5 | | -This repository contains the **Codesphere Python SDK**, an official asynchronous Python client for the [Codesphere Public API](https://codesphere.com/api/swagger-ui/). It provides a high-level, type-safe interface for managing Codesphere resources including Teams, Workspaces, Domains, Environment Variables, and Metadata. |
6 | | - |
7 | | -The SDK follows a resource-based architecture where API operations are defined declaratively and executed through a centralized handler system. |
| 3 | +## Architecture & Core |
| 4 | +- **Async-First:** All I/O operations MUST be `async/await`. |
| 5 | +- **Base Classes:** |
| 6 | + - Models: Use `core.base.CamelModel` (handles camelCase API conversion). |
| 7 | + - Resources: Inherit from `ResourceBase` + `_APIOperationExecutor`. |
| 8 | +- **HTTP:** Use `APIHttpClient` (wraps httpx). Raise `httpx.HTTPStatusError` for API errors. |
8 | 9 |
|
9 | 10 | ## Project Structure |
10 | | - |
11 | | -``` |
12 | | -src/codesphere/ |
13 | | -├── __init__.py # Public API exports |
14 | | -├── client.py # Main SDK entry point (CodesphereSDK) |
15 | | -├── config.py # Settings via pydantic-settings |
16 | | -├── exceptions.py # Custom exception classes |
17 | | -├── http_client.py # Async HTTP client wrapper (APIHttpClient) |
18 | | -├── utils.py # Utility functions |
19 | | -├── core/ # Core SDK infrastructure |
20 | | -│ ├── base.py # Base classes (ResourceBase, CamelModel, ResourceList) |
21 | | -│ ├── handler.py # API operation executor (_APIOperationExecutor, APIRequestHandler) |
22 | | -│ └── operations.py # APIOperation definition and AsyncCallable type |
23 | | -└── resources/ # API resource implementations |
24 | | - ├── metadata/ # Datacenters, Plans, Images |
25 | | - ├── team/ # Teams and nested Domains |
26 | | - │ └── domain/ # Domain management (schemas, operations, manager) |
27 | | - └── workspace/ # Workspaces and nested resources |
28 | | - ├── envVars/ # Environment variables management |
29 | | - ├── landscape/ # (Placeholder) |
30 | | - └── pipeline/ # (Placeholder) |
31 | | -
|
32 | | -tests/ # Test files mirroring src structure |
33 | | -examples/ # Usage examples organized by resource type |
34 | | -``` |
35 | | - |
36 | | -## Coding Guidelines |
37 | | - |
38 | | -### General Principles |
39 | | - |
40 | | -- **Async-First**: All API operations MUST be async. Use `async/await` syntax consistently. |
41 | | -- **Type Hints**: Always provide complete type annotations for function parameters, return values, and class attributes. |
42 | | -- **Pydantic Models**: Use Pydantic `BaseModel` for all data structures. Prefer `CamelModel` for API payloads to handle camelCase conversion. |
43 | | - |
44 | | -### Naming Conventions |
45 | | - |
46 | | -- **Variables/Functions**: Use `snake_case` (e.g., `workspace_id`, `list_datacenters`) |
47 | | -- **Classes**: Use `PascalCase` (e.g., `WorkspaceCreate`, `APIHttpClient`) |
48 | | -- **Constants/Operations**: Use `UPPER_SNAKE_CASE` with leading underscore for internal operations (e.g., `_LIST_BY_TEAM_OP`) |
49 | | -- **Private Attributes**: Prefix with underscore (e.g., `_http_client`, `_token`) |
50 | | - |
51 | | -### Resource Pattern |
52 | | - |
53 | | -When adding new API resources, follow this structure: |
54 | | - |
55 | | -1. **schemas.py**: Define Pydantic models for Create, Base, Update, and the main resource class |
56 | | -2. **operations.py**: Define `APIOperation` instances for each endpoint |
57 | | -3. **resources.py**: Create the resource class extending `ResourceBase` with operation fields |
58 | | -4. **__init__.py**: Export public classes |
59 | | - |
60 | | -```python |
61 | | -# Example operation definition |
62 | | -_GET_OP = APIOperation( |
63 | | - method="GET", |
64 | | - endpoint_template="/resources/{resource_id}", |
65 | | - response_model=ResourceModel, |
66 | | -) |
67 | | - |
68 | | -# Example resource method |
69 | | -async def get(self, resource_id: int) -> ResourceModel: |
70 | | - return await self.get_op(data=resource_id) |
71 | | -``` |
72 | | - |
73 | | -### Model Guidelines |
74 | | - |
75 | | -- Extend `CamelModel` for API request/response models (automatic camelCase aliasing) |
76 | | -- Extend `_APIOperationExecutor` for models that can perform operations on themselves |
77 | | -- Use `Field(default=..., exclude=True)` for operation callables |
78 | | -- Use `@cached_property` for lazy-loaded sub-managers (e.g., `workspace.env_vars`) |
79 | | - |
80 | | -```python |
81 | | -class Workspace(WorkspaceBase, _APIOperationExecutor): |
82 | | - delete_op: AsyncCallable[None] = Field(default=_DELETE_OP, exclude=True) |
83 | | - |
84 | | - async def delete(self) -> None: |
85 | | - await self.delete_op() |
86 | | -``` |
87 | | - |
88 | | -### Error Handling |
89 | | - |
90 | | -- Raise `httpx.HTTPStatusError` for HTTP errors (handled by `APIHttpClient`) |
91 | | -- Raise `RuntimeError` for SDK misuse (e.g., accessing resources without context manager) |
92 | | -- Use custom exceptions from `exceptions.py` for SDK-specific errors |
93 | | - |
94 | | -### Testing |
95 | | - |
96 | | -- Use `pytest.mark.asyncio` for async tests |
97 | | -- Use `@dataclass` for test case definitions with parametrization |
98 | | -- Mock `httpx.AsyncClient` for HTTP request testing |
99 | | -- Test files should mirror the source structure in `tests/` |
100 | | - |
101 | | -### Code Style |
102 | | - |
103 | | -- Line length: 88 characters (Ruff/Black standard) |
104 | | -- Indentation: 4 spaces |
105 | | -- Quotes: Double quotes for strings |
106 | | -- Imports: Group stdlib, third-party, and local imports |
107 | | - |
108 | | -### Development Commands |
109 | | - |
110 | | -```bash |
111 | | -make install # Set up development environment |
112 | | -make lint # Run Ruff linter |
113 | | -make format # Format code with Ruff |
114 | | -make test # Run pytest |
115 | | -make commit # Guided commit with Commitizen |
116 | | -``` |
| 11 | +- `src/codesphere/core/`: Base classes & handlers. |
| 12 | +- `src/codesphere/resources/`: Resource implementations (follow `schemas.py`, `operations.py`, `resources.py` pattern). |
| 13 | +- `tests/integration/`: Real API tests (require `CS_TOKEN`). |
| 14 | +- `tests/unit/`: Mocked logic tests. |
| 15 | + |
| 16 | +## Resource Implementation Pattern |
| 17 | +When adding resources, strictly follow this pattern: |
| 18 | + |
| 19 | +1. **`schemas.py`**: Define Pydantic models (inherit `CamelModel`). |
| 20 | +2. **`operations.py`**: Define `APIOperation` constants. |
| 21 | + ```python |
| 22 | + _GET_OP = APIOperation(method="GET", endpoint_template="/res/{id}", response_model=ResModel) |
| 23 | + ``` |
| 24 | +3. **`resources.py`**: Implementation logic. |
| 25 | + ```python |
| 26 | + class MyResource(ResourceBase, _APIOperationExecutor): |
| 27 | + # Operation callable (exclude from model dump) |
| 28 | + delete_op: AsyncCallable[None] = Field(default=_DELETE_OP, exclude=True) |
| 29 | + |
| 30 | + async def delete(self) -> None: |
| 31 | + await self.delete_op() |
| 32 | + ``` |
| 33 | + |
| 34 | +## Testing Rules |
| 35 | +- **Unit Tests (`tests/`):** MUST mock all HTTP calls (`unittest.mock.AsyncMock`). |
| 36 | +- **Integration Tests (`tests/integration/`):** |
| 37 | + - Use `pytest.mark.integration`. |
| 38 | + - Use provided fixtures: `sdk_client` (fresh client), `test_team_id`, `test_workspace`. |
| 39 | + - **Cleanup:** Always delete created resources in a `try...finally` block. |
| 40 | + |
| 41 | +## Key Fixtures & Env Vars |
| 42 | +| Fixture | Scope | Description | |
| 43 | +|---|---|---| |
| 44 | +| `sdk_client` | func | Fresh `CodesphereSDK` instance. | |
| 45 | +| `test_team_id` | session | ID from `CS_TEST_TEAM_ID` (or default). | |
| 46 | +| `integration_token` | session | Token from `CS_TOKEN`. | |
| 47 | + |
| 48 | +## Style & Naming |
| 49 | +- **Classes:** PascalCase (`WorkspaceCreate`). |
| 50 | +- **Vars:** snake_case. |
| 51 | +- **Internal Ops:** UPPER_SNAKE (`_LIST_OP`). |
| 52 | +- **Private:** Leading underscore (`_http_client`). |
| 53 | +- **Typing:** Strict type hints required. |
0 commit comments