File: copilot-instructions.md

package info (click to toggle)
python-actron-neo-api 0.4.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 340 kB
  • sloc: python: 2,439; makefile: 3
file content (304 lines) | stat: -rw-r--r-- 9,695 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# GitHub Copilot Instructions for ActronAirAPI

## Project Overview
ActronAirAPI is a Python library providing a robust, type-safe interface to Actron Air HVAC systems. This library is designed for integration with Home Assistant and other automation platforms, emphasizing reliability, maintainability, and clean architecture.

## Core Development Principles

### 1. Code Quality Standards
- **Type Safety**: Use type hints everywhere (`typing` module, Pydantic models)
- **Error Handling**: Follow fail-fast for critical operations, graceful degradation for non-critical
- **Documentation**: All public APIs must have Google-style docstrings
- **Testing**: Write tests for new features and bug fixes

### 2. Pre-commit Compliance
**CRITICAL**: All code must pass pre-commit checks before committing. Run:
```bash
pre-commit run --all-files
```

Our pre-commit pipeline includes:
- **ruff**: Linting and auto-formatting (E, F, W, I rules)
- **mypy**: Type checking with strict mode
- **pydocstyle**: Google convention docstrings
- **File hygiene**: trailing whitespace, line endings, YAML/TOML validation

### 3. Exception Handling Philosophy

**Fail Fast (raise exceptions):**
- Authentication failures (`ActronAirAuthError`)
- API communication errors (`ActronAirAPIError`)
- Control command failures (turn on/off, mode changes)
- Missing required configuration
- Invalid API responses that break core functionality

**Graceful Degradation (log and continue):**
- Observer callback failures (don't break status updates)
- Peripheral sensor parsing errors (log warning, continue with None)
- Invalid sensor data (temperature/humidity out of range)
- Missing optional data fields
- Non-critical nested component parsing

**Example Pattern:**
```python
# Critical operation - fail fast (no try-except needed, let exceptions propagate)
async def send_command(self, command: Dict[str, Any]) -> Dict[str, Any]:
    """Send command - any error should fail fast and propagate to caller."""
    endpoint = self._get_system_link(serial_number, "commands")
    if not endpoint:
        raise ActronAirAPIError(f"No commands link found")
    return await self._make_request("post", endpoint, json_data=command)

# Non-critical operation - graceful degradation
def _process_peripherals(self) -> None:
    """Process peripherals - skip invalid ones but continue with others."""
    for peripheral_data in peripherals_data:
        try:
            peripheral = ActronAirPeripheral.from_peripheral_data(peripheral_data)
            self.peripherals.append(peripheral)
        except (ValidationError, ValueError, TypeError) as e:
            # Catch specific exceptions for data parsing issues
            _LOGGER.warning("Failed to parse peripheral: %s", e)
            # Continue processing other peripherals - one bad peripheral shouldn't break all
```

### 4. Code Architecture

**Project Structure:**
```
src/actron_neo_api/
├── __init__.py          # Public API exports
├── actron.py            # Main API client
├── oauth.py             # OAuth2 authentication
├── state.py             # State management
├── const.py             # Constants
├── exceptions.py        # Custom exceptions
└── models/
    ├── __init__.py      # Model exports
    ├── base.py          # Base model functionality
    ├── status.py        # Status models
    ├── system.py        # System models
    ├── settings.py      # Settings models
    ├── zone.py          # Zone models
    └── schemas.py       # API schemas
```

**Design Patterns:**
- **Pydantic Models**: All API data structures use Pydantic for validation
- **Type Safety**: Full type hints with mypy compliance
- **Async/Await**: All I/O operations are async
- **Object-Oriented API**: Models have methods for direct control
- **State Manager**: Centralized state tracking with observer pattern

### 5. Common Patterns and Best Practices

#### Pydantic Models
```python
from pydantic import BaseModel, Field
from typing import Optional

class ActronAirZone(BaseModel):
    """Zone with sensor data."""

    zone_id: int = Field(..., alias="ZoneNumber")
    temperature: Optional[float] = Field(None, alias="LiveTemp_oC")
    is_enabled: bool = Field(False, alias="EnabledZone")

    class Config:
        populate_by_name = True  # Allow both alias and field name
```

#### Logging
```python
import logging

_LOGGER = logging.getLogger(__name__)

# Use appropriate log levels:
_LOGGER.debug("Detailed debug info")      # Development/troubleshooting
_LOGGER.info("Normal operations")          # Key state changes
_LOGGER.warning("Recoverable issues")      # Missing optional data
_LOGGER.error("Serious problems", exc_info=True)  # Failures requiring attention
```

#### Async API Methods
```python
async def get_status(self, serial_number: str) -> Dict[str, Any]:
    """Get AC status.

    Args:
        serial_number: System serial number

    Returns:
        Status data dictionary

    Raises:
        ActronAirAuthError: Authentication failed
        ActronAirAPIError: API request failed
    """
    await self._ensure_initialized()
    return await self._make_request("get", f"systems/{serial_number}/status")
```

#### Property Accessors with Error Handling
```python
@property
def min_temp(self) -> float:
    """Minimum settable temperature."""
    try:
        return self.last_known_state["NV_Limits"]["UserSetpoint_oC"]["setCool_Min"]
    except (KeyError, TypeError):
        return 16.0  # Sensible default
```

### 6. Testing Requirements

When adding new features:
1. Write unit tests in `tests/`
2. Test both success and failure paths
3. Mock external API calls with `aiohttp`
4. Verify exception handling behavior

### 7. Documentation Standards

**Module Docstrings:**
```python
"""Brief module description.

Longer description explaining the module's purpose, key classes,
and how it fits into the overall architecture.
"""
```

**Function/Method Docstrings:**
```python
def method(self, param: str, optional: bool = False) -> Dict[str, Any]:
    """Brief description.

    Longer explanation if needed, describing behavior,
    side effects, and any important details.

    Args:
        param: Description of param
        optional: Description with default behavior

    Returns:
        Description of return value

    Raises:
        ValueError: When param is invalid
        ActronAirAPIError: When API call fails

    Example:
        >>> api.method("test", optional=True)
        {'result': 'success'}
    """
```

### 8. Common Gotchas and Anti-Patterns

**❌ DON'T:**
- Catch exceptions without re-raising or logging with `exc_info=True`
- Access dictionary keys without handling `KeyError`
- Use bare `except:` clauses
- Import modules after code execution (fails E402)
- Leave TODO comments without GitHub issues
- Commit code that fails pre-commit checks

**✅ DO:**
- Use `dict.get()` with defaults for optional data
- Provide sensible defaults for missing optional configuration
- Add type hints to all function signatures
- Write docstrings for all public APIs
- Log errors with context before re-raising
- Use `_LOGGER` instead of `print()` statements
- Run `pre-commit run --all-files` before committing

### 9. Version Compatibility

- **Python**: >= 3.8 (maintain backward compatibility)
- **Dependencies**:
  - `aiohttp >= 3.8.0`: Async HTTP client
  - `pydantic >= 2.0.0`: Data validation
- Test against multiple Python versions (3.8, 3.9, 3.10, 3.11, 3.12)

### 10. API Client Best Practices

**Session Management:**
```python
async def __aenter__(self):
    """Context manager entry."""
    return self

async def __aexit__(self, exc_type, exc_val, exc_tb):
    """Context manager exit - clean up resources."""
    await self.close()
```

**Token Management:**
- Proactively refresh tokens 15 minutes before expiry
- Handle 401 responses with automatic token refresh and retry
- Track which platform issued tokens (Neo vs Que)

**State Updates:**
- Use state manager for centralized state tracking
- Support observer pattern for state change notifications
- Parse nested components lazily to improve performance

### 11. Making Changes Checklist

Before proposing any code changes:
1. ✅ Understand the fail-fast vs graceful degradation philosophy
2. ✅ Check if similar patterns exist in the codebase
3. ✅ Add appropriate type hints
4. ✅ Write Google-style docstrings
5. ✅ Add error handling following project patterns
6. ✅ Run `pre-commit run --all-files`
7. ✅ Test with `pytest` if tests exist
8. ✅ Update documentation if changing public API

### 12. Contact and Resources

- **Repository**: https://github.com/kclif9/actronneoapi
- **Issues**: Report bugs and feature requests on GitHub
- **Home Assistant Integration**: Designed for HA compatibility

---

## Quick Reference Commands

```bash
# Install development dependencies
pip install -e ".[dev]"

# Run pre-commit checks
pre-commit run --all-files

# Install pre-commit hooks
pre-commit install

# Run tests (if available)
pytest

# Type checking
mypy src/

# Format code
ruff format .

# Lint and auto-fix
ruff check --fix .
```

---

## When Working on This Project

**Always consider:**
1. Will this change break existing integrations (Home Assistant)?
2. Does this follow the project's exception handling philosophy?
3. Will this pass all pre-commit checks?
4. Is the code type-safe and well-documented?
5. Does this maintain backward compatibility?

**Remember**: This library is used in production environments controlling real HVAC systems. Reliability and correctness are paramount. When in doubt, fail fast and provide clear error messages.