Skip to content

Commit f721614

Browse files
Fix flake8 and mypy issues in SDK
1 parent 0fa1f1f commit f721614

24 files changed

Lines changed: 101 additions & 91 deletions

examples/order_placement.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414

1515
def place_order():
16-
"""Example of placing and managing an order."""
16+
"""Place and manage an order using the ProjectX SDK."""
1717

1818
# Initialize the client
1919
client = ProjectXClient(username=USERNAME, api_key=API_KEY, environment=ENVIRONMENT)
@@ -41,7 +41,7 @@ def place_order():
4141
print("\nAvailable contracts:")
4242
for i, contract in enumerate(contracts[:5]): # Show first 5 matches
4343
print(
44-
f"{i+1}. {contract.name} - {contract.description} (Tick Size: {contract.tick_size}, Tick Value: {contract.tick_value})"
44+
f"{i+1}. {contract.name} - {contract.description} (Tick Size: {contract.tick_size}, Tick Value: {contract.tick_value})" # noqa: E501
4545
)
4646

4747
# Select a contract
@@ -126,7 +126,7 @@ def on_order_update(order_data):
126126
order_id = client.orders.place(
127127
account_id=account.id,
128128
contract_id=contract.id,
129-
type=order_type,
129+
order_type=order_type,
130130
side=side,
131131
size=size,
132132
limit_price=limit_price,

projectx_sdk/client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def __init__(
118118
self.trades = TradeService(self)
119119

120120
# Real-time client (lazy-initialized)
121-
self._realtime = None
121+
self._realtime: Optional[RealTimeClient] = None
122122

123123
@property
124124
def realtime(self) -> RealTimeClient:
@@ -223,13 +223,13 @@ def request(
223223

224224
# Check for API-level errors
225225
if not data.get("success", True):
226-
error_code = data.get("errorCode", 0)
227-
error_message = data.get("errorMessage", "Unknown error")
226+
error_code = data.get("errorCode", 0) if data else 0 # type: ignore
227+
error_message = data.get("errorMessage", "Unknown error") if data else "Unknown error" # type: ignore
228228
raise ProjectXError(
229229
f"API error {error_code}: {error_message}", error_code=error_code, response=data
230230
)
231231

232-
return data
232+
return data # type: ignore
233233

234234
except requests.RequestException as e:
235235
raise RequestError(f"Request failed: {str(e)}")

projectx_sdk/endpoints/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
from abc import ABC
44

5+
from projectx_sdk.endpoints.account import AccountService
6+
from projectx_sdk.endpoints.contract import ContractService
7+
from projectx_sdk.endpoints.history import HistoryService, TimeUnit
8+
from projectx_sdk.endpoints.order import OrderService
9+
from projectx_sdk.endpoints.position import PositionService
10+
from projectx_sdk.endpoints.trade import TradeService
11+
512

613
class BaseService(ABC):
714
"""
@@ -20,13 +27,6 @@ def __init__(self, client):
2027
self._client = client
2128

2229

23-
from projectx_sdk.endpoints.account import AccountService
24-
from projectx_sdk.endpoints.contract import ContractService
25-
from projectx_sdk.endpoints.history import HistoryService, TimeUnit
26-
from projectx_sdk.endpoints.order import OrderService
27-
from projectx_sdk.endpoints.position import PositionService
28-
from projectx_sdk.endpoints.trade import TradeService
29-
3030
__all__ = [
3131
"AccountService",
3232
"ContractService",

projectx_sdk/endpoints/contract.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Service module for contract-related API endpoints."""
2+
13
from typing import Any, Dict, List, Optional
24

35
from projectx_sdk.endpoints import BaseService
@@ -13,15 +15,16 @@ def search(self, search_text: str, live: bool = False) -> List[Contract]:
1315
1416
Args:
1517
search_text: The text to search for in contract names.
16-
live: Whether to search the live market contracts (True) or the simulation contracts (False).
18+
live: Whether to search the live market contracts (True) or
19+
the simulation contracts (False).
1720
1821
Returns:
1922
A list of matching contracts.
2023
"""
2124
data = {"searchText": search_text, "live": live}
22-
response = self._client.post("Contract/search", json=data)
25+
response: Dict[str, Any] = self._client.post("Contract/search", json=data)
2326
search_response = ContractSearchResponse.model_validate(response)
24-
return search_response.contracts
27+
return search_response.contracts # type: ignore
2528

2629
def search_by_id(self, contract_id: str) -> Optional[Contract]:
2730
"""
@@ -34,6 +37,6 @@ def search_by_id(self, contract_id: str) -> Optional[Contract]:
3437
The matching contract if found, None otherwise.
3538
"""
3639
data = {"contractId": contract_id}
37-
response = self._client.post("Contract/searchById", json=data)
40+
response: Dict[str, Any] = self._client.post("Contract/searchById", json=data)
3841
search_response = ContractSearchResponse.model_validate(response)
3942
return search_response.contracts[0] if search_response.contracts else None

projectx_sdk/endpoints/history.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
"""Service module for historical market data API endpoints."""
2+
13
from datetime import datetime
24
from enum import IntEnum
3-
from typing import Any, Dict, List, Optional
5+
from typing import Any, Dict, List
46

57
from projectx_sdk.endpoints import BaseService
68
from projectx_sdk.models.history import Bar, BarResponse
@@ -58,6 +60,6 @@ def retrieve_bars(
5860
"live": live,
5961
}
6062

61-
response = self._client.post("History/retrieveBars", json=data)
63+
response: Dict[str, Any] = self._client.post("History/retrieveBars", json=data)
6264
bar_response = BarResponse.model_validate(response)
63-
return bar_response.bars
65+
return bar_response.bars # type: ignore

projectx_sdk/endpoints/order.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Service module for order-related API endpoints."""
2+
13
from datetime import datetime
24
from typing import Any, Dict, List, Optional, Union
35

@@ -37,9 +39,9 @@ def search(
3739
if end_timestamp:
3840
data["endTimestamp"] = end_timestamp.isoformat()
3941

40-
response = self._client.post("Order/search", json=data)
42+
response: Dict[str, Any] = self._client.post("Order/search", json=data)
4143
search_response = OrderSearchResponse.model_validate(response)
42-
return search_response.orders
44+
return search_response.orders # type: ignore
4345

4446
def search_open(self, account_id: int) -> List[Order]:
4547
"""
@@ -53,9 +55,9 @@ def search_open(self, account_id: int) -> List[Order]:
5355
"""
5456
data = {"accountId": account_id}
5557

56-
response = self._client.post("Order/searchOpen", json=data)
58+
response: Dict[str, Any] = self._client.post("Order/searchOpen", json=data)
5759
search_response = OrderSearchResponse.model_validate(response)
58-
return search_response.orders
60+
return search_response.orders # type: ignore
5961

6062
def place(
6163
self,
@@ -107,9 +109,9 @@ def place(
107109
"linkedOrderId": linked_order_id,
108110
}
109111

110-
response = self._client.post("Order/place", json=data)
112+
response: Dict[str, Any] = self._client.post("Order/place", json=data)
111113
placement_response = OrderPlacementResponse.model_validate(response)
112-
return placement_response.order_id
114+
return placement_response.order_id # type: ignore
113115

114116
def cancel(self, account_id: int, order_id: int) -> bool:
115117
"""
@@ -124,9 +126,9 @@ def cancel(self, account_id: int, order_id: int) -> bool:
124126
"""
125127
data = {"accountId": account_id, "orderId": order_id}
126128

127-
response = self._client.post("Order/cancel", json=data)
129+
response: Dict[str, Any] = self._client.post("Order/cancel", json=data)
128130
cancellation_response = OrderCancellationResponse.model_validate(response)
129-
return cancellation_response.success
131+
return cancellation_response.success # type: ignore
130132

131133
def modify(
132134
self,
@@ -151,7 +153,7 @@ def modify(
151153
Returns:
152154
True if modification was successful, False otherwise
153155
"""
154-
data = {"accountId": account_id, "orderId": order_id}
156+
data: Dict[str, Any] = {"accountId": account_id, "orderId": order_id}
155157

156158
# Only include fields that are being modified
157159
if size is not None:
@@ -163,6 +165,6 @@ def modify(
163165
if trail_price is not None:
164166
data["trailPrice"] = trail_price
165167

166-
response = self._client.post("Order/modify", json=data)
168+
response: Dict[str, Any] = self._client.post("Order/modify", json=data)
167169
modification_response = OrderModificationResponse.model_validate(response)
168-
return modification_response.success
170+
return modification_response.success # type: ignore

projectx_sdk/endpoints/position.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from typing import Any, Dict, List, Optional
1+
"""Service module for position-related API endpoints."""
2+
3+
from typing import Any, Dict, List
24

35
from projectx_sdk.endpoints import BaseService
46
from projectx_sdk.models.position import Position, PositionSearchResponse
@@ -19,15 +21,15 @@ def search_open(self, account_id: int) -> List[Position]:
1921
"""
2022
data = {"accountId": account_id}
2123

22-
response = self._client.post("Position/searchOpen", json=data)
24+
response: Dict[str, Any] = self._client.post("Position/searchOpen", json=data)
2325
search_response = PositionSearchResponse.model_validate(response)
24-
return search_response.positions
26+
return search_response.positions # type: ignore
2527

2628
def close_contract(self, account_id: int, contract_id: str) -> bool:
2729
"""
2830
Close any open position in a specific contract.
2931
30-
This will send market orders to offset the entire open position
32+
Send market orders to offset the entire open position
3133
in the specified contract, closing it out completely.
3234
3335
Args:
@@ -39,8 +41,8 @@ def close_contract(self, account_id: int, contract_id: str) -> bool:
3941
"""
4042
data = {"accountId": account_id, "contractId": contract_id}
4143

42-
response = self._client.post("Position/closeContract", json=data)
43-
return response.get("success", False)
44+
response: Dict[str, Any] = self._client.post("Position/closeContract", json=data)
45+
return response.get("success", False) # type: ignore
4446

4547
def partial_close_contract(self, account_id: int, contract_id: str, size: int) -> bool:
4648
"""
@@ -59,5 +61,5 @@ def partial_close_contract(self, account_id: int, contract_id: str, size: int) -
5961
"""
6062
data = {"accountId": account_id, "contractId": contract_id, "size": size}
6163

62-
response = self._client.post("Position/partialCloseContract", json=data)
63-
return response.get("success", False)
64+
response: Dict[str, Any] = self._client.post("Position/partialCloseContract", json=data)
65+
return response.get("success", False) # type: ignore

projectx_sdk/endpoints/trade.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
"""Service module for trade-related API endpoints."""
2+
13
from datetime import datetime
2-
from typing import List, Optional
4+
from typing import Any, Dict, List, Optional
35

46
from projectx_sdk.endpoints import BaseService
57
from projectx_sdk.models.trade import Trade, TradeSearchResponse
@@ -27,6 +29,6 @@ def search(
2729
if end_timestamp:
2830
data["endTimestamp"] = end_timestamp.isoformat()
2931

30-
response = self._client.post("Trade/search", json=data)
32+
response: Dict[str, Any] = self._client.post("Trade/search", json=data)
3133
search_response = TradeSearchResponse.model_validate(response)
32-
return search_response.trades
34+
return search_response.trades # type: ignore

projectx_sdk/models/__init__.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
from abc import ABC, abstractmethod
44

5+
from projectx_sdk.models.account import Account, AccountSearchResponse
6+
from projectx_sdk.models.base import BaseResponse
7+
from projectx_sdk.models.contract import Contract, ContractSearchResponse
8+
from projectx_sdk.models.history import Bar, BarResponse
9+
from projectx_sdk.models.order import (
10+
Order,
11+
OrderCancellationResponse,
12+
OrderModificationResponse,
13+
OrderPlacementResponse,
14+
OrderSearchResponse,
15+
)
16+
from projectx_sdk.models.position import Position, PositionSearchResponse
17+
from projectx_sdk.models.trade import Trade, TradeSearchResponse
18+
519

620
class BaseModel(ABC):
721
"""
@@ -35,21 +49,6 @@ def to_dict(self):
3549
pass
3650

3751

38-
# Import model classes after defining BaseModel
39-
from projectx_sdk.models.account import Account, AccountSearchResponse
40-
from projectx_sdk.models.base import BaseResponse
41-
from projectx_sdk.models.contract import Contract, ContractSearchResponse
42-
from projectx_sdk.models.history import Bar, BarResponse
43-
from projectx_sdk.models.order import (
44-
Order,
45-
OrderCancellationResponse,
46-
OrderModificationResponse,
47-
OrderPlacementResponse,
48-
OrderSearchResponse,
49-
)
50-
from projectx_sdk.models.position import Position, PositionSearchResponse
51-
from projectx_sdk.models.trade import Trade, TradeSearchResponse
52-
5352
__all__ = [
5453
"BaseModel",
5554
"BaseResponse",

projectx_sdk/models/contract.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
from typing import List, Optional
1+
"""Data models for contract-related API responses."""
22

3-
from pydantic import BaseModel, Field
3+
from typing import List
4+
5+
from pydantic import BaseModel, Field, model_validator
46

57
from projectx_sdk.models.base import BaseResponse
68

0 commit comments

Comments
 (0)