wcp-library 1.1.0__py3-none-any.whl → 1.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wcp_library/async_sql/oracle.py +4 -4
- wcp_library/async_sql/postgres.py +4 -4
- wcp_library/credentials/ftp.py +124 -0
- wcp_library/credentials/oracle.py +1 -1
- wcp_library/credentials/postgres.py +1 -1
- wcp_library/emailing.py +3 -3
- wcp_library/ftp/ftp.py +122 -0
- wcp_library/ftp/sftp.py +122 -0
- wcp_library/logging.py +6 -5
- wcp_library/sql/oracle.py +4 -4
- wcp_library/sql/postgres.py +3 -3
- {wcp_library-1.1.0.dist-info → wcp_library-1.1.3.dist-info}/METADATA +4 -2
- wcp_library-1.1.3.dist-info/RECORD +24 -0
- wcp_library-1.1.0.dist-info/RECORD +0 -21
- /wcp_library/{credentials/api.py → ftp/__init__.py} +0 -0
- {wcp_library-1.1.0.dist-info → wcp_library-1.1.3.dist-info}/WHEEL +0 -0
wcp_library/async_sql/oracle.py
CHANGED
@@ -10,8 +10,8 @@ from wcp_library.async_sql import retry
|
|
10
10
|
logger = logging.getLogger(__name__)
|
11
11
|
|
12
12
|
|
13
|
-
async def
|
14
|
-
|
13
|
+
async def _connect_warehouse(username: str, password: str, hostname: str, port: int, database: str, min_connections: int,
|
14
|
+
max_connections: int) -> AsyncConnectionPool:
|
15
15
|
"""
|
16
16
|
Create Warehouse Connection
|
17
17
|
|
@@ -71,8 +71,8 @@ class AsyncOracleConnection(object):
|
|
71
71
|
|
72
72
|
sid_or_service = self._database if self._database else self._sid
|
73
73
|
|
74
|
-
self._session_pool = await
|
75
|
-
|
74
|
+
self._session_pool = await _connect_warehouse(self._username, self._password, self._hostname, self._port,
|
75
|
+
sid_or_service, self.min_connections, self.max_connections)
|
76
76
|
|
77
77
|
async def set_user(self, credentials_dict: dict) -> None:
|
78
78
|
"""
|
@@ -10,8 +10,8 @@ from wcp_library.async_sql import retry
|
|
10
10
|
logger = logging.getLogger(__name__)
|
11
11
|
|
12
12
|
|
13
|
-
async def
|
14
|
-
|
13
|
+
async def _connect_warehouse(username: str, password: str, hostname: str, port: int, database: str, min_connections: int,
|
14
|
+
max_connections: int) -> AsyncConnectionPool:
|
15
15
|
"""
|
16
16
|
Create Warehouse Connection
|
17
17
|
|
@@ -66,8 +66,8 @@ class AsyncPostgresConnection(object):
|
|
66
66
|
:return: None
|
67
67
|
"""
|
68
68
|
|
69
|
-
self._session_pool = await
|
70
|
-
|
69
|
+
self._session_pool = await _connect_warehouse(self._username, self._password, self._hostname, self._port,
|
70
|
+
self._database, self.min_connections, self.max_connections)
|
71
71
|
|
72
72
|
async def set_user(self, credentials_dict: dict) -> None:
|
73
73
|
"""
|
@@ -0,0 +1,124 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
import requests
|
4
|
+
from yarl import URL
|
5
|
+
|
6
|
+
from wcp_library.credentials import MissingCredentialsError
|
7
|
+
|
8
|
+
logger = logging.getLogger(__name__)
|
9
|
+
|
10
|
+
|
11
|
+
class FTPCredentialManager:
|
12
|
+
def __init__(self, passwordState_api_key: str):
|
13
|
+
self.password_url = URL("https://vault.wcap.ca/api/passwords/")
|
14
|
+
self.api_key = passwordState_api_key
|
15
|
+
self.headers = {"APIKey": self.api_key, 'Reason': 'Python Script Access'}
|
16
|
+
self._password_list_id = 208
|
17
|
+
|
18
|
+
def _get_credentials(self) -> dict:
|
19
|
+
"""
|
20
|
+
Get all credentials from the password list
|
21
|
+
|
22
|
+
:return: Dictionary of credentials
|
23
|
+
"""
|
24
|
+
|
25
|
+
logger.debug("Getting credentials from PasswordState")
|
26
|
+
url = (self.password_url / str(self._password_list_id)).with_query("QueryAll")
|
27
|
+
passwords = requests.get(str(url), headers=self.headers).json()
|
28
|
+
|
29
|
+
if not passwords:
|
30
|
+
raise MissingCredentialsError("No credentials found in this Password List")
|
31
|
+
|
32
|
+
password_dict = {}
|
33
|
+
for password in passwords:
|
34
|
+
password_info = {'PasswordID': password['PasswordID'], 'UserName': password['UserName'], 'Password': password['Password']}
|
35
|
+
for field in password['GenericFieldInfo']:
|
36
|
+
password_info[field['DisplayName']] = field['Value'].lower() if field['DisplayName'].lower() == 'username' else field['Value']
|
37
|
+
password_dict[password['UserName'].lower()] = password_info
|
38
|
+
logger.debug("Credentials retrieved")
|
39
|
+
return password_dict
|
40
|
+
|
41
|
+
def get_credentials(self, username: str) -> dict:
|
42
|
+
"""
|
43
|
+
Get the credentials for a specific username
|
44
|
+
|
45
|
+
:param username:
|
46
|
+
:return: Dictionary of credentials
|
47
|
+
"""
|
48
|
+
|
49
|
+
logger.debug(f"Getting credentials for {username}")
|
50
|
+
credentials = self._get_credentials()
|
51
|
+
|
52
|
+
try:
|
53
|
+
return_credential = credentials[username.lower()]
|
54
|
+
except KeyError:
|
55
|
+
raise MissingCredentialsError(f"Credentials for {username} not found in this Password List")
|
56
|
+
logger.debug(f"Credentials for {username} retrieved")
|
57
|
+
return return_credential
|
58
|
+
|
59
|
+
def update_credential(self, credentials_dict: dict) -> bool:
|
60
|
+
"""
|
61
|
+
Update the credentials for a specific username
|
62
|
+
|
63
|
+
Credentials dictionary must have the following keys:
|
64
|
+
- PasswordID
|
65
|
+
- UserName
|
66
|
+
- Password
|
67
|
+
|
68
|
+
The dictionary should be obtained from the get_credentials method and modified accordingly
|
69
|
+
|
70
|
+
:param credentials_dict:
|
71
|
+
:return: True if successful, False otherwise
|
72
|
+
"""
|
73
|
+
|
74
|
+
logger.debug(f"Updating credentials for {credentials_dict['UserName']}")
|
75
|
+
url = (self.password_url / str(self._password_list_id)).with_query("QueryAll")
|
76
|
+
passwords = requests.get(str(url), headers=self.headers).json()
|
77
|
+
|
78
|
+
relevant_credential_entry = [x for x in passwords if x['UserName'] == credentials_dict['UserName']][0]
|
79
|
+
for field in relevant_credential_entry['GenericFieldInfo']:
|
80
|
+
if field['DisplayName'] in credentials_dict:
|
81
|
+
credentials_dict[field['GenericFieldID']] = credentials_dict[field['DisplayName']]
|
82
|
+
credentials_dict.pop(field['DisplayName'])
|
83
|
+
|
84
|
+
response = requests.put(str(self.password_url), json=credentials_dict, headers=self.headers)
|
85
|
+
if response.status_code == 200:
|
86
|
+
logger.debug(f"Credentials for {credentials_dict['UserName']} updated")
|
87
|
+
return True
|
88
|
+
else:
|
89
|
+
logger.error(f"Failed to update credentials for {credentials_dict['UserName']}")
|
90
|
+
return False
|
91
|
+
|
92
|
+
def new_credentials(self, credentials_dict: dict) -> bool:
|
93
|
+
"""
|
94
|
+
Create a new credential entry
|
95
|
+
|
96
|
+
Credentials dictionary must have the following keys:
|
97
|
+
- UserName
|
98
|
+
- Password
|
99
|
+
- Host
|
100
|
+
- Port
|
101
|
+
- FTP/SFTP (FTP or SFTP)
|
102
|
+
|
103
|
+
:param credentials_dict:
|
104
|
+
:return: True if successful, False otherwise
|
105
|
+
"""
|
106
|
+
|
107
|
+
data = {
|
108
|
+
"PasswordListID": self._password_list_id,
|
109
|
+
"Title": credentials_dict['UserName'].upper() if "Title" not in credentials_dict else credentials_dict['Title'].upper(),
|
110
|
+
"Notes": credentials_dict['Notes'] if 'Notes' in credentials_dict else None,
|
111
|
+
"UserName": credentials_dict['UserName'].lower(),
|
112
|
+
"Password": credentials_dict['Password'],
|
113
|
+
"GenericField1": credentials_dict['Host'],
|
114
|
+
"GenericField2": credentials_dict['Port'],
|
115
|
+
"GenericField3": credentials_dict['FTP/SFTP']
|
116
|
+
}
|
117
|
+
|
118
|
+
response = requests.post(str(self.password_url), json=data, headers=self.headers)
|
119
|
+
if response.status_code == 201:
|
120
|
+
logger.debug(f"New credentials for {credentials_dict['UserName']} created")
|
121
|
+
return True
|
122
|
+
else:
|
123
|
+
logger.error(f"Failed to create new credentials for {credentials_dict['UserName']}")
|
124
|
+
return False
|
wcp_library/emailing.py
CHANGED
@@ -7,7 +7,7 @@ from email.utils import formatdate
|
|
7
7
|
from pathlib import Path
|
8
8
|
|
9
9
|
|
10
|
-
def send_email(sender: str, recipients: list, subject: str, message=None):
|
10
|
+
def send_email(sender: str, recipients: list, subject: str, message: str=None) -> None:
|
11
11
|
"""
|
12
12
|
Function to send an email
|
13
13
|
|
@@ -32,7 +32,7 @@ def send_email(sender: str, recipients: list, subject: str, message=None):
|
|
32
32
|
server.quit()
|
33
33
|
|
34
34
|
|
35
|
-
def email_reporting(subject: str, message: str):
|
35
|
+
def email_reporting(subject: str, message: str) -> None:
|
36
36
|
"""
|
37
37
|
Function to email the reporting team from the Python email
|
38
38
|
|
@@ -55,7 +55,7 @@ def email_reporting(subject: str, message: str):
|
|
55
55
|
server.quit()
|
56
56
|
|
57
57
|
|
58
|
-
def email_with_attachments(sender: str, recipients: list, subject: str, message=None, attachments: list[Path]=None):
|
58
|
+
def email_with_attachments(sender: str, recipients: list, subject: str, message: str=None, attachments: list[Path]=None) -> None:
|
59
59
|
"""
|
60
60
|
Function to send an email with attachments
|
61
61
|
|
wcp_library/ftp/ftp.py
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
import ftplib
|
2
|
+
import logging
|
3
|
+
import re
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Optional
|
6
|
+
|
7
|
+
import ftputil
|
8
|
+
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
class FTP:
|
13
|
+
def __init__(self, host: Optional[str]=None, port: Optional[int]=21, password_vault_dict: Optional[dict]=None):
|
14
|
+
self.host: str = host if not password_vault_dict else password_vault_dict['Host']
|
15
|
+
self.port: int = port if not password_vault_dict else password_vault_dict['Port']
|
16
|
+
self._username: Optional[str] = None if not password_vault_dict else password_vault_dict['UserName']
|
17
|
+
self._password: Optional[str] = None if not password_vault_dict else password_vault_dict['Password']
|
18
|
+
|
19
|
+
self._ftp_factory: ftputil.session.session_factory = ftputil.session.session_factory(base_class=ftplib.FTP_TLS,
|
20
|
+
port=self.port,
|
21
|
+
encrypt_data_channel=True,
|
22
|
+
encoding="UTF-8")
|
23
|
+
self.ftp_connection: Optional[ftputil.FTPHost] = None if not (self._username and self._password) \
|
24
|
+
else ftputil.FTPHost(self.host, self._username, self._password, session_factory=self._ftp_factory)
|
25
|
+
|
26
|
+
def login(self, username: str, password: str) -> None:
|
27
|
+
"""
|
28
|
+
Login to the FTP server
|
29
|
+
|
30
|
+
:param username:
|
31
|
+
:param password:
|
32
|
+
:return:
|
33
|
+
"""
|
34
|
+
|
35
|
+
logger.debug(f"Logging into {self.host} with username {username}")
|
36
|
+
self.host = ftputil.FTPHost(self.host, username, password, session_factory=self._ftp_factory)
|
37
|
+
|
38
|
+
def download(self, remote_file: Path, local_file: Path) -> None:
|
39
|
+
"""
|
40
|
+
Download a file from the FTP server
|
41
|
+
|
42
|
+
:param remote_file:
|
43
|
+
:param local_file:
|
44
|
+
:return:
|
45
|
+
"""
|
46
|
+
|
47
|
+
logger.debug(f"Downloading {remote_file} to {local_file}")
|
48
|
+
self.ftp_connection.download(remote_file, local_file)
|
49
|
+
|
50
|
+
def download_files(self, local_dir: Path, regex_pattern: str='*') -> None:
|
51
|
+
"""
|
52
|
+
Download files from the FTP server matching the regex pattern
|
53
|
+
|
54
|
+
:param local_dir:
|
55
|
+
:param regex_pattern:
|
56
|
+
:return:
|
57
|
+
"""
|
58
|
+
|
59
|
+
logger.debug(f"Downloading files from FTP server matching {regex_pattern} to {local_dir}")
|
60
|
+
files = self.list_files()
|
61
|
+
for file in files:
|
62
|
+
if re.match(regex_pattern, file.name):
|
63
|
+
logger.debug(f"Downloading {file} to {local_dir / file.name}")
|
64
|
+
self.ftp_connection.download(file, local_dir / file.name)
|
65
|
+
|
66
|
+
def list_files(self) -> list[Path]:
|
67
|
+
"""
|
68
|
+
List files on the FTP server
|
69
|
+
|
70
|
+
Returns a list of file paths
|
71
|
+
|
72
|
+
:return:
|
73
|
+
"""
|
74
|
+
|
75
|
+
logger.debug(f"Listing files on {self.ftp_connection.curdir}")
|
76
|
+
return [Path(x) for x in self.ftp_connection.listdir(self.ftp_connection.curdir) if self.ftp_connection.path.isfile(x)]
|
77
|
+
|
78
|
+
def list_dirs(self) -> list[Path]:
|
79
|
+
"""
|
80
|
+
List directories on the FTP server
|
81
|
+
|
82
|
+
Returns a list of directory paths
|
83
|
+
|
84
|
+
:return:
|
85
|
+
"""
|
86
|
+
|
87
|
+
logger.debug(f"Listing directories on {self.ftp_connection.curdir}")
|
88
|
+
return [Path(x) for x in self.ftp_connection.listdir(self.ftp_connection.curdir) if self.ftp_connection.path.isdir(x)]
|
89
|
+
|
90
|
+
def change_dir(self, remote_dir: Path) -> None:
|
91
|
+
"""
|
92
|
+
Change the directory on the FTP server
|
93
|
+
|
94
|
+
:param remote_dir:
|
95
|
+
:return:
|
96
|
+
"""
|
97
|
+
|
98
|
+
logger.debug(f"Changing FTP directory to {remote_dir}")
|
99
|
+
self.ftp_connection.chdir(remote_dir)
|
100
|
+
|
101
|
+
def upload(self, local_file: Path, remote_file: Path) -> None:
|
102
|
+
"""
|
103
|
+
Upload a file to the FTP server
|
104
|
+
|
105
|
+
:param local_file:
|
106
|
+
:param remote_file:
|
107
|
+
:return:
|
108
|
+
"""
|
109
|
+
|
110
|
+
logger.debug(f"Uploading {local_file} to {remote_file}")
|
111
|
+
self.ftp_connection.upload(local_file, remote_file)
|
112
|
+
|
113
|
+
def close(self) -> None:
|
114
|
+
"""
|
115
|
+
Close the FTP connection
|
116
|
+
|
117
|
+
:return:
|
118
|
+
"""
|
119
|
+
|
120
|
+
logger.debug(f"Closing FTP connection")
|
121
|
+
self.ftp_connection.close()
|
122
|
+
self.ftp_connection = None
|
wcp_library/ftp/sftp.py
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
import logging
|
2
|
+
import re
|
3
|
+
import stat
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Optional
|
6
|
+
|
7
|
+
import paramiko
|
8
|
+
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
class SFTP:
|
13
|
+
def __init__(self, host: str, port: int=22):
|
14
|
+
self.host: str = host
|
15
|
+
self.port: int = port
|
16
|
+
self._username: Optional[str] = None
|
17
|
+
self._password: Optional[str] = None
|
18
|
+
|
19
|
+
self.ssh = paramiko.SSHClient()
|
20
|
+
# AutoAddPolicy automatically adds the hostname and new host key to the local HostKeys object
|
21
|
+
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
22
|
+
|
23
|
+
self.sftp_connection: Optional[paramiko.SFTP] = None
|
24
|
+
|
25
|
+
def login(self, username: str, password: str) -> None:
|
26
|
+
"""
|
27
|
+
Login to the SFTP server
|
28
|
+
|
29
|
+
:param username:
|
30
|
+
:param password:
|
31
|
+
:return:
|
32
|
+
"""
|
33
|
+
|
34
|
+
logger.debug(f"Logging into {self.host} with username {username}")
|
35
|
+
self.ssh.connect(self.host, self.port, username, password)
|
36
|
+
self.sftp_connection = self.ssh.open_sftp()
|
37
|
+
|
38
|
+
def download(self, remote_file: Path, local_file: Path) -> None:
|
39
|
+
"""
|
40
|
+
Download a file from the SFTP server
|
41
|
+
|
42
|
+
:param remote_file:
|
43
|
+
:param local_file:
|
44
|
+
:return:
|
45
|
+
"""
|
46
|
+
|
47
|
+
logger.debug(f"Downloading {remote_file} to {local_file}")
|
48
|
+
self.sftp_connection.get(str(remote_file), local_file)
|
49
|
+
|
50
|
+
def download_files(self, local_dir: Path, regex_pattern: str='*') -> None:
|
51
|
+
"""
|
52
|
+
Download files from the SFTP server matching the regex pattern
|
53
|
+
|
54
|
+
:param local_dir:
|
55
|
+
:param regex_pattern:
|
56
|
+
:return:
|
57
|
+
"""
|
58
|
+
|
59
|
+
logger.debug(f"Downloading files from FTP server matching {regex_pattern} to {local_dir}")
|
60
|
+
files = self.list_files()
|
61
|
+
for file in files:
|
62
|
+
if re.match(regex_pattern, file.name):
|
63
|
+
logger.debug(f"Downloading {file} to {local_dir / file.name}")
|
64
|
+
self.sftp_connection.get(str(file), local_dir / file.name)
|
65
|
+
|
66
|
+
def list_files(self) -> list[Path]:
|
67
|
+
"""
|
68
|
+
List files on the SFTP server
|
69
|
+
|
70
|
+
Returns a list of file paths
|
71
|
+
|
72
|
+
:return:
|
73
|
+
"""
|
74
|
+
|
75
|
+
logger.debug(f"Listing files on {self.sftp_connection.getcwd()}")
|
76
|
+
return [Path(x) for x in self.sftp_connection.listdir() if stat.S_ISREG(self.sftp_connection.lstat(x).st_mode)]
|
77
|
+
|
78
|
+
def list_dirs(self) -> list[Path]:
|
79
|
+
"""
|
80
|
+
List directories on the SFTP server
|
81
|
+
|
82
|
+
Returns a list of directory paths
|
83
|
+
|
84
|
+
:return:
|
85
|
+
"""
|
86
|
+
|
87
|
+
logger.debug(f"Listing directories on {self.sftp_connection.getcwd()}")
|
88
|
+
return [Path(x) for x in self.sftp_connection.listdir() if stat.S_ISDIR(self.sftp_connection.lstat(x).st_mode)]
|
89
|
+
|
90
|
+
def change_dir(self, remote_dir: Path) -> None:
|
91
|
+
"""
|
92
|
+
Change the directory on the SFTP server
|
93
|
+
|
94
|
+
:param remote_dir:
|
95
|
+
:return:
|
96
|
+
"""
|
97
|
+
|
98
|
+
logger.debug(f"Changing FTP directory to {remote_dir}")
|
99
|
+
self.sftp_connection.chdir(str(remote_dir))
|
100
|
+
|
101
|
+
def upload(self, local_file: Path, remote_file: Path) -> None:
|
102
|
+
"""
|
103
|
+
Upload a file to the SFTP server
|
104
|
+
|
105
|
+
:param local_file:
|
106
|
+
:param remote_file:
|
107
|
+
:return:
|
108
|
+
"""
|
109
|
+
|
110
|
+
logger.debug(f"Uploading {local_file} to {remote_file}")
|
111
|
+
self.sftp_connection.put(local_file, str(remote_file))
|
112
|
+
|
113
|
+
def close(self):
|
114
|
+
"""
|
115
|
+
Close the SFTP connection
|
116
|
+
|
117
|
+
:return:
|
118
|
+
"""
|
119
|
+
|
120
|
+
logger.debug("Closing FTP connection")
|
121
|
+
self.sftp_connection.close()
|
122
|
+
self.sftp_connection = None
|
wcp_library/logging.py
CHANGED
@@ -4,7 +4,7 @@ import sys
|
|
4
4
|
from wcp_library import application_path
|
5
5
|
|
6
6
|
|
7
|
-
def create_log(
|
7
|
+
def create_log(file_level: int, console_level: int, iterations: int, project_name: str, mode: str = "w",
|
8
8
|
format: str = "%(asctime)s:%(levelname)s:%(module)s:%(filename)s:%(lineno)d:%(message)s"):
|
9
9
|
"""
|
10
10
|
Create log file.
|
@@ -13,7 +13,8 @@ def create_log(level: int, iterations: int, project_name: str, mode: str = "w",
|
|
13
13
|
|
14
14
|
format help: https://docs.python.org/3/library/logging.html#logrecord-attributes
|
15
15
|
|
16
|
-
:param
|
16
|
+
:param file_level: Logging level to output to log file.
|
17
|
+
:param console_level: Logging level to output to console.
|
17
18
|
:param iterations: Number of log files to keep.
|
18
19
|
:param project_name: Name of the project. (Used as the log file name)
|
19
20
|
:param mode: Mode to open the log file. (Default: "w")
|
@@ -33,12 +34,12 @@ def create_log(level: int, iterations: int, project_name: str, mode: str = "w",
|
|
33
34
|
|
34
35
|
logging.basicConfig(
|
35
36
|
filename=(application_path / (project_name + ".log")),
|
36
|
-
level=
|
37
|
+
level=file_level,
|
37
38
|
format=format,
|
38
39
|
filemode=mode
|
39
40
|
)
|
40
41
|
|
41
|
-
MIN_LEVEL =
|
42
|
+
MIN_LEVEL = console_level
|
42
43
|
stdout_hdlr = logging.StreamHandler(sys.stdout)
|
43
44
|
stderr_hdlr = logging.StreamHandler(sys.stderr)
|
44
45
|
stdout_hdlr.setLevel(MIN_LEVEL)
|
@@ -48,4 +49,4 @@ def create_log(level: int, iterations: int, project_name: str, mode: str = "w",
|
|
48
49
|
rootLogger.addHandler(stdout_hdlr)
|
49
50
|
rootLogger.addHandler(stderr_hdlr)
|
50
51
|
logger = logging.getLogger(__name__)
|
51
|
-
logger.setLevel(
|
52
|
+
logger.setLevel(console_level)
|
wcp_library/sql/oracle.py
CHANGED
@@ -10,8 +10,8 @@ from wcp_library.sql import retry
|
|
10
10
|
logger = logging.getLogger(__name__)
|
11
11
|
|
12
12
|
|
13
|
-
def
|
14
|
-
|
13
|
+
def _connect_warehouse(username: str, password: str, hostname: str, port: int, database: str, min_connections: int,
|
14
|
+
max_connections: int) -> ConnectionPool:
|
15
15
|
"""
|
16
16
|
Create Warehouse Connection
|
17
17
|
|
@@ -72,8 +72,8 @@ class OracleConnection(object):
|
|
72
72
|
|
73
73
|
sid_or_service = self._database if self._database else self._sid
|
74
74
|
|
75
|
-
self._session_pool =
|
76
|
-
|
75
|
+
self._session_pool = _connect_warehouse(self._username, self._password, self._hostname, self._port,
|
76
|
+
sid_or_service, self.min_connections, self.max_connections)
|
77
77
|
|
78
78
|
def set_user(self, credentials_dict: dict) -> None:
|
79
79
|
"""
|
wcp_library/sql/postgres.py
CHANGED
@@ -10,8 +10,8 @@ from wcp_library.sql import retry
|
|
10
10
|
logger = logging.getLogger(__name__)
|
11
11
|
|
12
12
|
|
13
|
-
def
|
14
|
-
|
13
|
+
def _connect_warehouse(username: str, password: str, hostname: str, port: int, database: str, min_connections: int,
|
14
|
+
max_connections: int) -> ConnectionPool:
|
15
15
|
"""
|
16
16
|
Create Warehouse Connection
|
17
17
|
|
@@ -66,7 +66,7 @@ class PostgresConnection(object):
|
|
66
66
|
:return: None
|
67
67
|
"""
|
68
68
|
|
69
|
-
self._session_pool =
|
69
|
+
self._session_pool = _connect_warehouse(self._username, self._password, self._hostname, self._port,
|
70
70
|
self._database, self.min_connections, self.max_connections)
|
71
71
|
|
72
72
|
def set_user(self, credentials_dict: dict) -> None:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: wcp-library
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.3
|
4
4
|
Summary: Common utilites for internal development at WCP
|
5
5
|
Home-page: https://github.com/Whitecap-DNA/WCP-Library
|
6
6
|
Author: Mitch-Petersen
|
@@ -10,8 +10,10 @@ Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
12
12
|
Requires-Dist: aiohttp (>=3.10.10,<4.0.0)
|
13
|
+
Requires-Dist: ftputil (>=5.1.0,<6.0.0)
|
13
14
|
Requires-Dist: oracledb (>=2.5.0,<3.0.0)
|
14
15
|
Requires-Dist: pandas (>=2.2.3,<3.0.0)
|
16
|
+
Requires-Dist: paramiko (>=3.5.0,<4.0.0)
|
15
17
|
Requires-Dist: pip-system-certs (>=4.0,<5.0)
|
16
18
|
Requires-Dist: psycopg (>=3.2.3,<4.0.0)
|
17
19
|
Requires-Dist: psycopg-binary (>=3.2.3,<4.0.0)
|
@@ -32,7 +34,7 @@ Commonly used functions for the D&A team.
|
|
32
34
|
`pip install WCP-Library`
|
33
35
|
|
34
36
|
## Usage
|
35
|
-
See Wiki for more information.
|
37
|
+
See [Wiki](https://github.com/Whitecap-DNA/WCP-Library/wiki/) for more information.
|
36
38
|
|
37
39
|
## Authors and acknowledgment
|
38
40
|
Mitch Petersen
|
@@ -0,0 +1,24 @@
|
|
1
|
+
wcp_library/__init__.py,sha256=vgWnSAz9S7evUpt8lfZVBg2NWAn-wenaAaPcBnfJxxc,327
|
2
|
+
wcp_library/async_credentials/__init__.py,sha256=ny6UitVV_xIecVzaWuHrJO9LpywBPke6u4C0F2wiM7o,1881
|
3
|
+
wcp_library/async_credentials/api.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
wcp_library/async_credentials/oracle.py,sha256=MvC7wsHnSyAyPGnRVlH0dvvW2xk5ap_IAByoHX4rUWY,5436
|
5
|
+
wcp_library/async_credentials/postgres.py,sha256=3wjqtLH0Nc-U80iscYnz5DV-9M2X4IjPW51C5MI2_tI,5297
|
6
|
+
wcp_library/async_sql/__init__.py,sha256=m4eWmUGYUEDomhhOp1ScB2uSIXFsNUNO589o5RwWdyM,1035
|
7
|
+
wcp_library/async_sql/oracle.py,sha256=T4wLdX3sHQQOfDNqb35GM4wHFP5Vs5veB7iQtdCxPVM,7402
|
8
|
+
wcp_library/async_sql/postgres.py,sha256=MGPv1ffUDn7oJX1ojviVD3N7jk8dtQERnbDateuwZJo,6597
|
9
|
+
wcp_library/credentials/__init__.py,sha256=HRmg7mqcATeclIz3lZQjSR4nmK6aY6MK9-QXEYZoFrw,1857
|
10
|
+
wcp_library/credentials/ftp.py,sha256=FRxKVWifz7olQIrSjDgkTqk7rmc7Zdwmkfq7b62DQY8,4965
|
11
|
+
wcp_library/credentials/oracle.py,sha256=IJVGd10LH5LUNKUSFAbApi0sjR1AbloMJRHTuR9zFrQ,5095
|
12
|
+
wcp_library/credentials/postgres.py,sha256=psOPIAr6rBxce47hIHBJxgBAdsAEufjsUKZD0JRnZwI,4956
|
13
|
+
wcp_library/emailing.py,sha256=xqNly6Tmj-pvwl5bdys3gauZFDd4SuWCQYzGFNemv2Q,2496
|
14
|
+
wcp_library/ftp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
+
wcp_library/ftp/ftp.py,sha256=0Cv_7iKMrYfqMnax9_8rJ12yiGN117ktwsi1HUNqLd8,4234
|
16
|
+
wcp_library/ftp/sftp.py,sha256=zUL2IJSJ4FAk-OI1SeGVd3njbBfbiP7ZsBWBt8irou4,3536
|
17
|
+
wcp_library/informatica.py,sha256=IXZtk_9X1XLbOEwFrsyOwTgajQKvtXgANBHmuTOP3Kk,4064
|
18
|
+
wcp_library/logging.py,sha256=cFaY7kHEV1DukNiIVIsckrS046vBQ3W9sbFDfP1tcPk,2056
|
19
|
+
wcp_library/sql/__init__.py,sha256=CLlBEBrWVAwE79bUxuQiwikSrYH8m9QRYSJ2l0-ofsY,1003
|
20
|
+
wcp_library/sql/oracle.py,sha256=FeMvqLte26vNQlR1esdZAUICy9IqOuE0zTTrx245bhY,7283
|
21
|
+
wcp_library/sql/postgres.py,sha256=I2iDQ13z_hbEfpFBliozLfsg8xUdSzEVqr12yyPSdh4,6489
|
22
|
+
wcp_library-1.1.3.dist-info/METADATA,sha256=zajA-dJ586d2R7DYhH7Ams4EFUkDpkYJYLSbdR2JBdU,1421
|
23
|
+
wcp_library-1.1.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
24
|
+
wcp_library-1.1.3.dist-info/RECORD,,
|
@@ -1,21 +0,0 @@
|
|
1
|
-
wcp_library/__init__.py,sha256=vgWnSAz9S7evUpt8lfZVBg2NWAn-wenaAaPcBnfJxxc,327
|
2
|
-
wcp_library/async_credentials/__init__.py,sha256=ny6UitVV_xIecVzaWuHrJO9LpywBPke6u4C0F2wiM7o,1881
|
3
|
-
wcp_library/async_credentials/api.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
wcp_library/async_credentials/oracle.py,sha256=MvC7wsHnSyAyPGnRVlH0dvvW2xk5ap_IAByoHX4rUWY,5436
|
5
|
-
wcp_library/async_credentials/postgres.py,sha256=3wjqtLH0Nc-U80iscYnz5DV-9M2X4IjPW51C5MI2_tI,5297
|
6
|
-
wcp_library/async_sql/__init__.py,sha256=m4eWmUGYUEDomhhOp1ScB2uSIXFsNUNO589o5RwWdyM,1035
|
7
|
-
wcp_library/async_sql/oracle.py,sha256=QHadNMWhJlCw27bWBIqtoDpfmm8GDMtAUYri_HbVMoc,7398
|
8
|
-
wcp_library/async_sql/postgres.py,sha256=7ehET1l42gKnsOcqeWLcXBEdYfvvA1qVfdG0QJv57Vk,6593
|
9
|
-
wcp_library/credentials/__init__.py,sha256=HRmg7mqcATeclIz3lZQjSR4nmK6aY6MK9-QXEYZoFrw,1857
|
10
|
-
wcp_library/credentials/api.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
wcp_library/credentials/oracle.py,sha256=tinrog9TLW6jw7j8S-Ese_VHnhFcAoOPJpHsE0Xwx6M,5094
|
12
|
-
wcp_library/credentials/postgres.py,sha256=Li-4nDMMxKGYh-hKhhL1r9M4wIc_TRgEgP1_UkEf-90,4955
|
13
|
-
wcp_library/emailing.py,sha256=T8WXvMRA6cC0uRvyCw9yZcI-pAnCn0Gbn5B_ftRzEqA,2462
|
14
|
-
wcp_library/informatica.py,sha256=IXZtk_9X1XLbOEwFrsyOwTgajQKvtXgANBHmuTOP3Kk,4064
|
15
|
-
wcp_library/logging.py,sha256=h8p_Ezo_QPSIKrPxzIlNVXddU4IXHyp1_2NqVDirfuk,1958
|
16
|
-
wcp_library/sql/__init__.py,sha256=CLlBEBrWVAwE79bUxuQiwikSrYH8m9QRYSJ2l0-ofsY,1003
|
17
|
-
wcp_library/sql/oracle.py,sha256=ur91kgds11M7xiGlDNkodxu2P7M-crqK0toYJcOHgdo,7285
|
18
|
-
wcp_library/sql/postgres.py,sha256=hIw9ckxV_iRqZA0rSCMmbG82iil8mY4g-ajtHYVIq3I,6492
|
19
|
-
wcp_library-1.1.0.dist-info/METADATA,sha256=VgYJYmhdV99qaKoErB1yzbr7oUAwPQy-LUwFgz9eR4Q,1287
|
20
|
-
wcp_library-1.1.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
21
|
-
wcp_library-1.1.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|