Skip to content

Commit 1f7936e

Browse files
committed
add client portal file
1 parent 438f921 commit 1f7936e

3 files changed

Lines changed: 115 additions & 10 deletions

File tree

ibw/client.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from typing import Dict
1717

1818
from urllib3.exceptions import InsecureRequestWarning
19+
from ibw.clientportal import ClientPortal
1920

2021
urllib3.disable_warnings(category=InsecureRequestWarning)
2122
# http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
@@ -67,6 +68,7 @@ def __init__(self, username: str, account: str, client_gateway_path: str = None)
6768

6869
self.account = account
6970
self.username = username
71+
self.client_portal_client = ClientPortal()
7072

7173
self.api_version = 'v1/'
7274
self._operating_system = sys.platform
@@ -80,15 +82,17 @@ def __init__(self, username: str, account: str, client_gateway_path: str = None)
8082
self.backup_gateway_path = r"https://cdcdyn.interactivebrokers.com/portal.proxy"
8183

8284
if client_gateway_path is None:
83-
try:
84-
# Grab the Client Portal Path.
85-
self.client_portal_folder = pathlib.Path(__file__).parents[1].joinpath(
86-
'resources/clientportal.beta.gw'
87-
).resolve()
88-
except FileNotFoundError:
89-
raise FileNotFoundError(
90-
"The Client Portal Gateway doesn't exist. You need to download it before using the Library."
91-
)
85+
86+
# Grab the Client Portal Path.
87+
self.client_portal_folder: pathlib.Path = pathlib.Path(__file__).parents[1].joinpath(
88+
'resources/clientportal.beta.gw'
89+
).resolve()
90+
91+
# See if it exists.
92+
if not self.client_portal_folder.exists():
93+
print("The Client Portal Gateway doesn't exist. You need to download it before using the Library.")
94+
print("Downloading the Client Portal file...")
95+
self.client_portal_client.download_and_extract()
9296

9397
else:
9498
self.client_portal_folder = client_gateway_path

ibw/clientportal.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import io
2+
import pathlib
3+
import requests
4+
import zipfile
5+
6+
class ClientPortal():
7+
8+
def does_resources_directory_exist(self) -> bool:
9+
"""Used to determine if the resources folder exist.
10+
11+
Returns:
12+
bool: `True` if it exists, `False` otherwise.
13+
"""
14+
15+
# Grab the resources folder.
16+
resoruces_folder: pathlib.Path = pathlib.Path(__file__).parent.joinpath(
17+
'resources'
18+
).resolve
19+
20+
return resoruces_folder.exists()
21+
22+
def make_resources_directory(self) -> None:
23+
"""Makes the resource folder if it doesn't exist."""
24+
25+
if not self.does_resources_directory_exist:
26+
resoruces_folder: pathlib.Path = pathlib.Path(__file__).parent.joinpath(
27+
'resources'
28+
).resolve
29+
resoruces_folder.mkdir(parents=True)
30+
31+
def download_folder(self) -> str:
32+
"""Defines the folder to download the Client Portal to.
33+
34+
Returns:
35+
str: The path to the folder.
36+
"""
37+
38+
# Define the download folder.
39+
download_folder = pathlib.Path(__file__).parent.joinpath(
40+
'resources/clientportal.beta.gw'
41+
).resolve()
42+
43+
return download_folder
44+
45+
def download_client_portal(self) -> requests.Response:
46+
"""Downloads the Client Portal from Interactive Brokers.
47+
48+
Returns:
49+
requests.Response: A response object with clientportal content.
50+
"""
51+
52+
# Request the Client Portal
53+
response = requests.get(
54+
url='https://download2.interactivebrokers.com/portal/clientportal.beta.gw.zip'
55+
)
56+
57+
return response
58+
59+
def create_zip_file(self, response_content: requests.Response) -> zipfile.ZipFile:
60+
"""Creates a zip file to house the client portal content.
61+
62+
Arguments:
63+
----
64+
response_content (requests.Response): The response object with the
65+
client portal content.
66+
67+
Returns:
68+
----
69+
zipfile.ZipFile: A zip file object with the Client Portal.
70+
"""
71+
72+
# Download the Zip File.
73+
zip_file_content = zipfile.ZipFile(io.BytesIO(response_content.content))
74+
75+
return zip_file_content
76+
77+
def extract_zip_file(self, zip_file: zipfile.ZipFile) -> None:
78+
"""Extracts the Zip File.
79+
80+
Arguments:
81+
----
82+
zip_file (zipfile.ZipFile): The client portal zip file to be extracted.
83+
"""
84+
85+
# Extract the Content to the new folder.
86+
zip_file.extractall(path="resources/clientportal.beta.gw")
87+
88+
def download_and_extract(self) -> None:
89+
"""Downloads and extracts the client portal object."""
90+
91+
# Make the resource directory if needed.
92+
self.make_resources_directory()
93+
94+
# Download it.
95+
client_portal_response = self.download_client_portal()
96+
97+
# Create a zip file.
98+
client_portal_zip = self.create_zip_file(response_content=client_portal_response)
99+
100+
# Extract it.
101+
self.extract_zip_file(zip_file=client_portal_zip)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
# I'm in alpha development still, so a compliant version number is a1.
1919
# read this as MAJOR VERSION 0, MINOR VERSION 1, MAINTENANCE VERSION 0
20-
version='0.1.0',
20+
version='0.1.2',
2121
description='A python client library for the Interactive Broker Web API.',
2222

2323
# I have a long description but that will just be my README file.

0 commit comments

Comments
 (0)