11from typing import Any , Dict , Optional
22
3- import httpx
3+ import requests
44from fake_useragent import UserAgent # type: ignore
5- from httpx import Client , Response
65
76from tastytrade import API_URL , CERT_URL
87from tastytrade .utils import (TastytradeError , TastytradeJsonDataclass ,
@@ -34,14 +33,6 @@ class Session:
3433 :param dxfeed_tos_compliant:
3534 whether to use the dxfeed TOS-compliant API endpoint for the streamer
3635 """
37- client : Client
38- is_test : bool
39- remember_token : Optional [str ]
40- session_token : str
41- streamer_token : str
42- dxlink_url : str
43- user : Dict [str , str ]
44-
4536 def __init__ (
4637 self ,
4738 login : str ,
@@ -50,8 +41,7 @@ def __init__(
5041 remember_token : Optional [str ] = None ,
5142 is_test : bool = False ,
5243 two_factor_authentication : Optional [str ] = None ,
53- dxfeed_tos_compliant : bool = False ,
54- proxy : Optional [str ] = None
44+ dxfeed_tos_compliant : bool = False
5545 ):
5646 body = {
5747 'login' : login ,
@@ -65,7 +55,7 @@ def __init__(
6555 raise TastytradeError ('You must provide a password or remember '
6656 'token to log in.' )
6757 # The base url to use for API requests
68- base_url = CERT_URL if is_test else API_URL
58+ self . base_url = CERT_URL if is_test else API_URL
6959 #: Whether this is a cert or real session
7060 self .is_test = is_test
7161 # The headers to use for API requests
@@ -74,21 +64,19 @@ def __init__(
7464 'Content-Type' : 'application/json' ,
7565 'User-Agent' : UserAgent ().random
7666 }
67+ # Set client for requests
68+ self .client = requests .Session ()
69+ self .client .headers .update (headers )
7770 if two_factor_authentication is not None :
78- response = httpx .post (
79- f'{ base_url } /sessions' ,
71+ response = self . client .post (
72+ f'{ self . base_url } /sessions' ,
8073 json = body ,
81- headers = {
82- ** headers ,
83- 'X-Tastyworks-OTP' : two_factor_authentication
84- },
85- proxy = proxy
74+ headers = {'X-Tastyworks-OTP' : two_factor_authentication }
8675 )
8776 else :
88- response = httpx .post (
89- f'{ base_url } /sessions' ,
90- json = body ,
91- proxy = proxy
77+ response = self .client .post (
78+ f'{ self .base_url } /sessions' ,
79+ json = body
9280 )
9381 validate_response (response ) # throws exception if not 200
9482
@@ -97,47 +85,41 @@ def __init__(
9785 self .user = json ['data' ]['user' ]
9886 #: The session token used to authenticate requests
9987 self .session_token = json ['data' ]['session-token' ]
100- headers ['Authorization' ] = self .session_token
10188 #: A single-use token which can be used to login without a password
10289 self .remember_token = json ['data' ].get ('remember-token' )
103- # Set clients for sync and async requests
104- self .client = Client (
105- base_url = base_url ,
106- headers = headers ,
107- proxy = proxy ,
108- timeout = 30 # many requests can take a while
109- )
90+ self .client .headers .update ({'Authorization' : self .session_token })
11091 self .validate ()
11192
11293 # Pull streamer tokens and urls
113- url = ('api-quote-tokens'
94+ url = ('/ api-quote-tokens'
11495 if dxfeed_tos_compliant or is_test
115- else 'quote-streamer-tokens' )
116- response = self .client .get (f'/{ url } ' )
117- validate_response (response )
118- data = response .json ()['data' ]
96+ else '/quote-streamer-tokens' )
97+ data = self .get (url )
11998 #: Auth token for dxfeed websocket
12099 self .streamer_token = data ['token' ]
121100 #: URL for dxfeed websocket
122101 self .dxlink_url = data ['dxlink-url' ]
123102
124103 def get (self , url , ** kwargs ) -> Dict [str , Any ]:
125- response = self .client .get (url , ** kwargs )
104+ response = self .client .get (self . base_url + url , timeout = 30 , ** kwargs )
126105 return self ._validate_and_parse (response )
127106
128107 def delete (self , url , ** kwargs ) -> None :
129- response = self .client .delete (url , ** kwargs )
108+ response = self .client .delete (self . base_url + url , ** kwargs )
130109 validate_response (response )
131110
132111 def post (self , url , ** kwargs ) -> Dict [str , Any ]:
133- response = self .client .post (url , ** kwargs )
112+ response = self .client .post (self . base_url + url , ** kwargs )
134113 return self ._validate_and_parse (response )
135114
136115 def put (self , url , ** kwargs ) -> Dict [str , Any ]:
137- response = self .client .put (url , ** kwargs )
116+ response = self .client .put (self . base_url + url , ** kwargs )
138117 return self ._validate_and_parse (response )
139118
140- def _validate_and_parse (self , response : Response ) -> Dict [str , Any ]:
119+ def _validate_and_parse (
120+ self ,
121+ response : requests .Response
122+ ) -> Dict [str , Any ]:
141123 validate_response (response )
142124 return response .json ()['data' ]
143125
@@ -147,7 +129,7 @@ def validate(self) -> bool:
147129
148130 :return: True if the session is valid and False otherwise.
149131 """
150- response = self .client .post (' /sessions/validate' )
132+ response = self .client .post (f' { self . base_url } /sessions/validate' )
151133 return (response .status_code // 100 == 2 )
152134
153135 def destroy (self ) -> None :
0 commit comments