From b632d5aa7957fa96a62ac3ef7be9b4cf2b601469 Mon Sep 17 00:00:00 2001 From: Graeme Holliday Date: Mon, 20 May 2024 18:09:23 -0500 Subject: [PATCH] prepare v7.3 release --- docs/conf.py | 2 +- requirements.txt | 24 ++++++++++++------------ setup.py | 2 +- tastytrade/__init__.py | 2 +- tastytrade/streamer.py | 33 +++++++++++++++++++++++---------- 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index b37dde7..f6d0be0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -9,7 +9,7 @@ project = 'tastytrade' copyright = '2024, Graeme Holliday' author = 'Graeme Holliday' -release = '7.2' +release = '7.3' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/requirements.txt b/requirements.txt index b7608c9..9a7560b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,13 @@ -requests==2.31.0 -mypy==1.4.1 -flake8==5.0.4 -isort==5.11.5 -types-requests==2.31.0.1 -types-pytz==2024.1.0.20240203 -websockets==11.0.3 -pandas_market_calendars==4.3.3 -pydantic==2.6.3 -pytest==7.4.0 -pytest_cov==4.1.0 -pytest-asyncio==0.21.1 +requests==2.32.1 +mypy==1.10.0 +flake8==7.0.0 +isort==5.13.2 +types-requests==2.31.0.20240406 +types-pytz==2024.1.0.20240417 +websockets==12.0 +pandas_market_calendars==4.4.0 +pydantic==2.7.1 +pytest==8.2.1 +pytest_cov==5.0.0 +pytest-asyncio==0.23.7 fake-useragent==1.5.1 \ No newline at end of file diff --git a/setup.py b/setup.py index 4e12514..d942084 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name='tastytrade', - version='7.2', + version='7.3', description='An unofficial SDK for Tastytrade!', long_description=LONG_DESCRIPTION, long_description_content_type='text/x-rst', diff --git a/tastytrade/__init__.py b/tastytrade/__init__.py index 778d478..92de668 100644 --- a/tastytrade/__init__.py +++ b/tastytrade/__init__.py @@ -2,7 +2,7 @@ API_URL = 'https://api.tastyworks.com' CERT_URL = 'https://api.cert.tastyworks.com' -VERSION = '7.2' +VERSION = '7.3' logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) diff --git a/tastytrade/streamer.py b/tastytrade/streamer.py index 16dde45..bd6f2f4 100644 --- a/tastytrade/streamer.py +++ b/tastytrade/streamer.py @@ -5,9 +5,11 @@ from datetime import datetime from decimal import Decimal from enum import Enum +from ssl import SSLContext, create_default_context from typing import Any, AsyncIterator, Dict, List, Optional, Union import websockets +from websockets import WebSocketClientProtocol from tastytrade import logger from tastytrade.account import (Account, AccountBalance, CurrentPosition, @@ -110,7 +112,7 @@ def __init__(self, session: Session): CERT_STREAMER_URL if is_certification else STREAMER_URL self._queue: Queue = Queue() - self._websocket = None + self._websocket: Optional[WebSocketClientProtocol] = None self._connect_task = asyncio.create_task(self._connect()) async def __aenter__(self): @@ -144,10 +146,10 @@ async def _connect(self) -> None: token provided during initialization. """ headers = {'Authorization': f'Bearer {self.token}'} - async with websockets.connect( # type: ignore + async with websockets.connect( self.base_url, extra_headers=headers - ) as websocket: + ) as websocket: # type: ignore self._websocket = websocket self._heartbeat_task = asyncio.create_task(self._heartbeat()) @@ -274,7 +276,11 @@ class DXLinkStreamer: print(quote) """ - def __init__(self, session: ProductionSession, ssl_context=None): + def __init__( + self, + session: ProductionSession, + ssl_context: SSLContext = create_default_context() + ): self._counter = 0 self._lock: Lock = Lock() self._queues: Dict[EventType, Queue] = defaultdict(Queue) @@ -297,7 +303,7 @@ def __init__(self, session: ProductionSession, ssl_context=None): self._authenticated = False self._wss_url = session.dxlink_url self._auth_token = session.streamer_token - self.ssl_context = ssl_context + self._ssl_context = ssl_context self._connect_task = asyncio.create_task(self._connect()) @@ -312,8 +318,12 @@ async def __aenter__(self): return self @classmethod - async def create(cls, session: ProductionSession) -> 'DXLinkStreamer': - self = cls(session) + async def create( + cls, + session: ProductionSession, + ssl_context: SSLContext = create_default_context() + ) -> 'DXLinkStreamer': + self = cls(session, ssl_context=ssl_context) return await self.__aenter__() async def __aexit__(self, exc_type, exc, tb): @@ -332,7 +342,10 @@ async def _connect(self) -> None: authorization token provided during initialization. """ - async with websockets.connect(self._wss_url, ssl=self.ssl_context) as websocket: + async with websockets.connect( + self._wss_url, + ssl=self._ssl_context + ) as websocket: self._websocket = websocket await self._setup_connection() @@ -588,9 +601,9 @@ async def unsubscribe_candle( 'type': 'FEED_SUBSCRIPTION', 'channel': self._channels[EventType.CANDLE], 'remove': [{ - 'symbol': f'{ticker}{{={interval},tho=true}}' + f'{ticker}{{={interval}}}' if extended_trading_hours - else f'{ticker}{{={interval}}}', + else 'symbol': f'{ticker}{{={interval},tho=true}}', 'type': 'Candle', }] }