|
| 1 | +# Copilot Instructions for Codesphere Python SDK |
| 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. |
| 8 | + |
| 9 | +## 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 | +``` |
0 commit comments