Skip to content

Commit 113f376

Browse files
Improve test suite (#398)
1 parent cb80307 commit 113f376

18 files changed

Lines changed: 2877 additions & 2800 deletions

.github/.copilot-instructions.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Python Kraken SDK - Copilot Instructions
2+
3+
## Project Overview
4+
5+
This is the **python-kraken-sdk** - a high-performance REST and WebSocket API
6+
client for Kraken Crypto Asset Exchange supporting both Spot and Futures
7+
trading. The SDK prioritizes performance, maintainability, reliability,
8+
modularization, and code reuse.
9+
10+
## Core Principles
11+
12+
### Code Quality Standards
13+
14+
- **Performance First**: Optimize for speed and memory efficiency
15+
- **Maintainability**: Write clean, readable, self-documenting code
16+
- **Reliability**: Implement robust error handling and comprehensive testing
17+
- **Modularization**: Favor composition over inheritance, create reusable
18+
components
19+
- **DRY Principle**: Eliminate code duplication through shared utilities and
20+
base classes
21+
22+
### Comment Philosophy
23+
24+
- **Minimal Comments**: Code should be self-explanatory through clear naming and
25+
structure
26+
- **Only When Necessary**: Add comments only for non-obvious business logic,
27+
complex algorithms, or API-specific quirks
28+
- **No Obvious Comments**: Avoid stating what the code clearly does
29+
- **Focus on Why**: When commenting, explain the reasoning, not the mechanics
30+
31+
## Project Structure
32+
33+
```
34+
src/kraken/
35+
├── __init__.py # Main package exports
36+
├── cli.py # Command-line interface
37+
├── base_api/ # Core base classes and utilities
38+
│ └── __init__.py # SpotClient, FuturesClient, SpotAsyncClient, FuturesAsyncClient
39+
├── exceptions/ # Custom exception classes
40+
│ └── __init__.py # KrakenException hierarchy
41+
├── utils/ # Shared utilities and helpers
42+
├── spot/ # Spot trading API
43+
│ ├── __init__.py # Spot client exports
44+
│ ├── market.py # Market data client
45+
│ ├── trade.py # Trading operations client
46+
│ ├── user.py # User account client
47+
│ ├── funding.py # Funding operations client
48+
│ ├── earn.py # Earn/staking client
49+
│ ├── orderbook.py # Order book client
50+
│ ├── ws_client.py # WebSocket client implementation
51+
│ └── websocket/ # WebSocket infrastructure
52+
│ ├── __init__.py # SpotWSClientBase
53+
│ └── connectors.py # Connection management
54+
└── futures/ # Futures trading API
55+
├── __init__.py # Futures client exports
56+
├── market.py # Futures market data
57+
├── trade.py # Futures trading
58+
├── user.py # Futures user account
59+
├── funding.py # Futures funding
60+
├── ws_client.py # Futures WebSocket client
61+
└── websocket/ # Futures WebSocket infrastructure
62+
```
63+
64+
## Architecture Patterns
65+
66+
### Client Hierarchy
67+
68+
- **Base Classes**: `SpotClient`, `FuturesClient` (REST), `SpotAsyncClient`,
69+
`FuturesAsyncClient` (async REST)
70+
- **Specialized Clients**: Market, Trade, User, Funding, Earn (inherit from
71+
base)
72+
- **WebSocket Clients**: `SpotWSClient`, `FuturesWSClient` (extend async base
73+
classes)
74+
75+
### Key Design Patterns
76+
77+
- **Composition over Inheritance**: Favor utility functions and mixins
78+
- **Async/Await**: All WebSocket and async operations use proper async patterns
79+
- **Context Managers**: Support `async with` for resource management
80+
- **Type Hints**: Comprehensive typing with `typing` and `TYPE_CHECKING`
81+
- **Error Handling**: Custom exception hierarchy with specific error types
82+
83+
## Development Guidelines
84+
85+
### Code Style
86+
87+
- **Python 3.11+**: Use modern Python features and syntax
88+
- **Type Annotations**: All functions must have complete type hints
89+
- **Docstrings**: Use Google-style docstrings for public APIs
90+
- **Naming**: Clear, descriptive names that eliminate need for comments
91+
92+
### Performance Optimization
93+
94+
- **Async Operations**: Use async/await for I/O operations
95+
- **Connection Pooling**: Reuse HTTP connections where possible
96+
- **Memory Efficiency**: Avoid unnecessary object creation in hot paths
97+
- **Caching**: Use `@lru_cache` for expensive computations
98+
- **Lazy Loading**: Initialize resources only when needed
99+
100+
### Error Handling
101+
102+
- **Custom Exceptions**: Use specific exception types from `kraken.exceptions`
103+
- **Graceful Degradation**: Handle network failures and API errors robustly
104+
- **Retry Logic**: Implement exponential backoff for transient failures
105+
- **Logging**: Use structured logging with appropriate levels
106+
107+
### Testing Standards
108+
109+
- **Comprehensive Coverage**: Aim for high test coverage
110+
- **Unit Tests**: Test individual components in isolation
111+
- **Integration Tests**: Test API interactions (with mocking when needed)
112+
- **Class-Based Organization**: Use pytest classes with shared fixtures and
113+
constants
114+
- **Helper Methods**: Create reusable assertion helpers to eliminate duplication
115+
116+
### WebSocket Patterns
117+
118+
- **Connection Management**: Proper connection lifecycle handling
119+
- **Subscription Management**: Track active subscriptions
120+
- **Message Routing**: Efficient message dispatch to handlers
121+
- **Reconnection Logic**: Automatic reconnection with backoff
122+
123+
## Code Generation Guidelines
124+
125+
### When Creating New Features
126+
127+
1. **Extend Existing Patterns**: Follow established client patterns
128+
2. **Reuse Base Classes**: Inherit from appropriate base classes
129+
3. **Share Common Logic**: Extract reusable components
130+
4. **Maintain API Consistency**: Follow existing parameter and return patterns
131+
5. **Add Comprehensive Tests**: Include unit and integration tests
132+
133+
### When Refactoring
134+
135+
1. **Preserve Public APIs**: Maintain backward compatibility
136+
2. **Improve Performance**: Look for optimization opportunities
137+
3. **Reduce Complexity**: Simplify complex methods through decomposition
138+
4. **Enhance Type Safety**: Add or improve type annotations
139+
5. **Update Tests**: Ensure tests reflect changes
140+
141+
### Specific Preferences
142+
143+
- **Constants**: Use UPPER_CASE for module-level constants
144+
- **Private Methods**: Use single underscore prefix for internal methods
145+
- **Property Methods**: Use `@property` for computed attributes
146+
- **Context Managers**: Implement `__enter__`/`__exit__` or
147+
`__aenter__`/`__aexit__` when managing resources
148+
149+
## API Design Philosophy
150+
151+
- **Pythonic Interface**: Feel natural to Python developers
152+
- **Sensible Defaults**: Minimize required parameters
153+
- **Flexibility**: Support both high-level convenience and low-level control
154+
- **Performance**: Optimize for common use cases
155+
- **Documentation**: Self-documenting through clear parameter names and types
156+
157+
## Testing Philosophy
158+
159+
- **Fast Feedback**: Tests should run quickly
160+
- **Reliable**: Tests should not be flaky
161+
- **Isolated**: Each test should be independent
162+
- **Realistic**: Test real scenarios, not just edge cases
163+
- **Maintainable**: Tests should be easy to understand and modify
164+
165+
Remember: The goal is to create a professional, high-performance SDK that
166+
developers love to use. Prioritize clarity, performance, and reliability in all
167+
code contributions.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ task-tags = ["todo", "TODO", "fixme", "FIXME"]
291291
"S311", # pseudo-random-generator
292292
"SLF001", # private member access
293293
"TID252", # ban relative imports
294+
"PLR0904", # too many public methods
295+
"ANN401", # Use of typing.Any
294296
]
295297

296298
[tool.ruff.lint.flake8-copyright]

tests/futures/conftest.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@
1818
FUTURES_EXTENDED_TIMEOUT: int = 30
1919

2020

21-
@pytest.fixture
21+
@pytest.fixture(scope="session")
2222
def futures_api_key() -> str:
2323
"""Returns the Futures API key"""
2424
return FUTURES_API_KEY
2525

2626

27-
@pytest.fixture
27+
@pytest.fixture(scope="session")
2828
def futures_secret_key() -> str:
2929
"""Returns the Futures API secret key"""
3030
return FUTURES_SECRET_KEY
3131

3232

33-
@pytest.fixture
33+
@pytest.fixture(scope="session")
3434
def futures_market() -> Market:
3535
"""
3636
Fixture providing an unauthenticated Futures Market client
@@ -40,7 +40,7 @@ def futures_market() -> Market:
4040
return market
4141

4242

43-
@pytest.fixture
43+
@pytest.fixture(scope="session")
4444
def futures_auth_market() -> Market:
4545
"""
4646
Fixture providing an authenticated Futures Market client.
@@ -50,7 +50,7 @@ def futures_auth_market() -> Market:
5050
return market
5151

5252

53-
@pytest.fixture
53+
@pytest.fixture(scope="session")
5454
def futures_demo_market() -> Market:
5555
"""
5656
Fixture providing an authenticated Futures Market client that
@@ -65,7 +65,7 @@ def futures_demo_market() -> Market:
6565
return market
6666

6767

68-
@pytest.fixture
68+
@pytest.fixture(scope="session")
6969
def futures_user() -> User:
7070
"""
7171
Fixture providing an unauthenticated Futures User client.
@@ -75,7 +75,7 @@ def futures_user() -> User:
7575
return user
7676

7777

78-
@pytest.fixture
78+
@pytest.fixture(scope="session")
7979
def futures_auth_user() -> User:
8080
"""
8181
Fixture providing an authenticated Futures User client.
@@ -85,7 +85,7 @@ def futures_auth_user() -> User:
8585
return user
8686

8787

88-
@pytest.fixture
88+
@pytest.fixture(scope="session")
8989
def futures_demo_user() -> User:
9090
"""
9191
Fixture providing an authenticated Futures User client that
@@ -100,7 +100,7 @@ def futures_demo_user() -> User:
100100
return user
101101

102102

103-
@pytest.fixture
103+
@pytest.fixture(scope="session")
104104
def futures_trade() -> Trade:
105105
"""
106106
Fixture providing an unauthenticated Futures Trade client.
@@ -110,7 +110,7 @@ def futures_trade() -> Trade:
110110
return trade
111111

112112

113-
@pytest.fixture
113+
@pytest.fixture(scope="session")
114114
def futures_auth_trade() -> Trade:
115115
"""
116116
Fixture providing an authenticated Futures Trade client.
@@ -120,7 +120,7 @@ def futures_auth_trade() -> Trade:
120120
return trade
121121

122122

123-
@pytest.fixture
123+
@pytest.fixture(scope="session")
124124
def futures_demo_trade() -> Trade:
125125
"""
126126
Fixture providing an authenticated Futures Trade client that
@@ -135,7 +135,7 @@ def futures_demo_trade() -> Trade:
135135
return trade
136136

137137

138-
@pytest.fixture
138+
@pytest.fixture(scope="session")
139139
def futures_funding() -> Funding:
140140
"""
141141
Fixture providing an unauthenticated Futures Funding client.
@@ -145,7 +145,7 @@ def futures_funding() -> Funding:
145145
return funding
146146

147147

148-
@pytest.fixture
148+
@pytest.fixture(scope="session")
149149
def futures_auth_funding() -> Funding:
150150
"""
151151
Fixture providing an authenticated Futures Funding client.
@@ -155,7 +155,7 @@ def futures_auth_funding() -> Funding:
155155
return funding
156156

157157

158-
@pytest.fixture
158+
@pytest.fixture(scope="session")
159159
def futures_demo_funding() -> Funding:
160160
"""
161161
Fixture providing an authenticated Futures Funding client that

0 commit comments

Comments
 (0)