cit-pydata 0.0.1.dev0__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.
cit_pydata/__init__.py ADDED
@@ -0,0 +1,9 @@
1
+ import aws
2
+ import box
3
+ import joblog
4
+ import marketo
5
+ import salesforce
6
+ import sfsync
7
+ import sftp
8
+ import sql
9
+ import util
@@ -0,0 +1 @@
1
+ from .api import S3Client, SSMClient
cit_pydata/aws/api.py ADDED
@@ -0,0 +1,204 @@
1
+ import sys
2
+
3
+ from cit_pydata.util import api as util_api
4
+ from cit_pydata.util import ON_AWS
5
+
6
+ from typing import Literal
7
+ import boto3
8
+
9
+
10
+ def _get_boto_session(
11
+ service: str = None,
12
+ environment: str = None,
13
+ iam_user: str = None,
14
+ path_to_env_file: str = None,
15
+ region: str = None,
16
+ logger=util_api.get_logger(__name__, "info"),
17
+ ):
18
+ if ON_AWS:
19
+ return boto3.Session()
20
+
21
+ _environment_variable = environment + "_" + iam_user + "_" + "aws_access_key_id"
22
+ aws_access_key_id = util_api.get_environment_variable(
23
+ logger=logger,
24
+ path_to_env_file=path_to_env_file,
25
+ variable_name=_environment_variable,
26
+ )
27
+
28
+ if aws_access_key_id is None:
29
+ logger.error(f"Access Key Id does not exist for environment {environment}")
30
+ return
31
+
32
+ _environment_variable = environment + "_" + iam_user + "_" + "aws_secret_access_key"
33
+ aws_secret_access_key = util_api.get_environment_variable(
34
+ logger=logger,
35
+ path_to_env_file=path_to_env_file,
36
+ variable_name=_environment_variable,
37
+ )
38
+
39
+ if aws_secret_access_key is None:
40
+ logger.error(f"Secret Key not specified for environment {environment}")
41
+ return
42
+
43
+ _aws_region = region
44
+ if _aws_region is None:
45
+ _environment_variable = environment + "_" + iam_user + "_" + "aws_region"
46
+ _aws_region = util_api.get_environment_variable(
47
+ logger=logger,
48
+ path_to_env_file=path_to_env_file,
49
+ variable_name=_environment_variable,
50
+ )
51
+
52
+ if _aws_region is None:
53
+ logger.error(f"AWS Region not specified for environment {environment}")
54
+ return
55
+
56
+ _session = boto3.Session(
57
+ aws_access_key_id=aws_access_key_id,
58
+ aws_secret_access_key=aws_secret_access_key,
59
+ region_name=_aws_region,
60
+ )
61
+
62
+ return _session
63
+
64
+
65
+ class S3Client:
66
+ def __init__(
67
+ self,
68
+ environment: str = None,
69
+ iam_user: str = None,
70
+ path_to_env_file: str = None,
71
+ log_level: Literal["info", "debug"] = "info",
72
+ ):
73
+ self.logger = util_api.get_logger(__name__, log_level)
74
+ environment = environment.lower()
75
+
76
+ self.session = _get_boto_session(
77
+ service="s3",
78
+ environment=environment,
79
+ iam_user=iam_user,
80
+ path_to_env_file=path_to_env_file,
81
+ logger=self.logger,
82
+ )
83
+ self.client = self.session.client("s3")
84
+
85
+ def get_object_metadata(self, **kwargs):
86
+ """
87
+ Returns pandas dataframe with S3 Objects
88
+
89
+ kwargs for method client.list_objects_v2
90
+ https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.list_objects_v2
91
+ """
92
+
93
+ # self.logger.info(f'Getting S3 objects: {**kwargs}')
94
+ object_list = []
95
+ next_page_token = "init"
96
+
97
+ # Object metadata is retrieved in batches of 1000
98
+ while next_page_token:
99
+ response: dict = None
100
+ if next_page_token == "init":
101
+ response = self.client.list_objects_v2(**kwargs)
102
+ else:
103
+ response = self.client.list_objects_v2(
104
+ ContinuationToken=next_page_token, **kwargs
105
+ )
106
+
107
+ next_page_token = response.get("NextContinuationToken", None)
108
+ # self.logger.debug(next_page_token)
109
+ for object_item in response["Contents"]:
110
+ object_list.append(object_item)
111
+ response.pop("Contents")
112
+
113
+ if not pandas in sys.modules:
114
+ import pandas
115
+ df_s3_objects = pandas.DataFrame(object_list)
116
+ # self.logger.debug(response)
117
+ # self.logger.debug(df_s3_objects.info())
118
+
119
+ return response, df_s3_objects
120
+
121
+ def metadata_to_sql(self, sql_client, table_name: str, dataframe):
122
+ if "sqlalchemy" not in sys.modules:
123
+ import sqlalchemy
124
+
125
+ try:
126
+ sql_client.insert_df(
127
+ table_name=table_name,
128
+ df=dataframe,
129
+ index=False,
130
+ dtype={"LastModified": sqlalchemy.DateTime},
131
+ )
132
+ # dataframe.to_sql(name = table_name, con = sql_client.sql_engine, if_exists='replace', index=False, dtype={'LastModified':sqlalchemy.DateTime})
133
+ except Exception as e:
134
+ self.logger.error(f"Failed to send S3 Object metadata to SQL")
135
+ self.logger.exception(str(e))
136
+
137
+
138
+ class SSMClient:
139
+ def __init__(
140
+ self,
141
+ environment: str = None,
142
+ iam_user: str = None,
143
+ path_to_env_file: str = None,
144
+ log_level: Literal["info", "debug"] = "info",
145
+ logger=None,
146
+ ):
147
+ self.logger = util_api.get_logger(__name__, log_level) if not logger else logger
148
+ self.session = _get_boto_session(
149
+ service="ssm",
150
+ environment=environment,
151
+ iam_user=iam_user,
152
+ path_to_env_file=path_to_env_file,
153
+ logger=self.logger,
154
+ )
155
+ self.client = self.session.client("ssm")
156
+
157
+ def get_parameter(
158
+ self, name: str, with_decryption: bool = False, is_verbose: bool = False
159
+ ):
160
+ value = None
161
+ try:
162
+ value = self.client.get_parameter(Name=name, WithDecryption=with_decryption)
163
+ except Exception as ce:
164
+ self.logger.error(ce)
165
+ return None
166
+
167
+ if value is None:
168
+ self.logger.error(f'SSM Parameter not found "{name}"')
169
+ return
170
+
171
+ if is_verbose:
172
+ return value
173
+ else:
174
+ return value["Parameter"]["Value"]
175
+
176
+ # for parameter in response['Parameters']:
177
+ # return parameter['Value']
178
+
179
+ def describe_parameters(
180
+ self, filter_parameters: list[dict], is_verbose: bool = False
181
+ ):
182
+ """
183
+ filter_parameters=[
184
+ {
185
+ 'Key': 'string',
186
+ 'Option': 'string',
187
+ 'Values': [
188
+ 'string',
189
+ ]
190
+ },
191
+ """
192
+ max_results = 50
193
+ describe_param_dict: dict = self.client.describe_parameters(
194
+ ParameterFilters=filter_parameters, MaxResults=max_results
195
+ )
196
+
197
+ param_list = describe_param_dict.get("Parameters", None)
198
+ # return_list = []
199
+ # for parameter in param_list
200
+ # param_keys_to_return_list = ['Name']
201
+ # param_dict = parameter.get()
202
+ # return_list.append()
203
+
204
+ return param_list
@@ -0,0 +1 @@
1
+ from .api import BoxClient
cit_pydata/box/api.py ADDED
@@ -0,0 +1,107 @@
1
+ import os
2
+ import sys
3
+
4
+ from cit_pydata.util import api as util_api
5
+
6
+
7
+ class BoxClient:
8
+ def __init__(self, box_jwt_auth_file_path, logger=None):
9
+ self.logger = util_api.get_logger(__name__, "INFO") if not logger else logger
10
+
11
+ self.box_jwt_auth_file_path = box_jwt_auth_file_path
12
+
13
+ # client is the boxsdk Client object
14
+ self.client = None
15
+
16
+ def _get_client(self):
17
+ if "boxsdk" not in sys.modules:
18
+ from boxsdk import Client, JWTAuth, OAuth2
19
+ # JWT Auth
20
+ auth = JWTAuth.from_settings_file(self.box_jwt_auth_file_path)
21
+
22
+ try:
23
+ self.client = Client(auth)
24
+ except Client.BoxAPIException as err:
25
+ self.logger.error("Failed to Authenticate to Box API:", err)
26
+
27
+ def get_folder(self, folder_id: str):
28
+ if not self.client:
29
+ self._get_client()
30
+
31
+ return self.client.folder(folder_id=folder_id)
32
+
33
+ def get_file(self):
34
+ pass
35
+
36
+ def get_folder_items(self, folder_id: str, filter_type: str = None):
37
+ if not self.client:
38
+ self._get_client()
39
+
40
+ item_id_dict = {}
41
+ items = self.client.folder(folder_id=folder_id).get_items()
42
+
43
+ assert filter_type in ["file", "folder", None]
44
+ if filter_type == "file":
45
+ for item in items:
46
+ if item.type == filter_type:
47
+ item_id_dict[item.id] = item
48
+ elif filter_type == "folder":
49
+ for item in items:
50
+ if item.type == filter_type:
51
+ item_id_dict[item.id] = item
52
+ else:
53
+ for item in items:
54
+ item_id_dict[item.id] = item
55
+
56
+ for item in items:
57
+ if item.type == filter_type:
58
+ item_id_dict[item.id] = {"name": item.name, "type": item.type}
59
+ else:
60
+ item_id_dict[item.id] = {"name": item.name, "type": item.type}
61
+
62
+ return item_id_dict
63
+
64
+ def get_shared_link(self, folder_id):
65
+ if not self.client:
66
+ self._get_client()
67
+
68
+ folder = self.get_folder(folder_id)
69
+ shared_link = folder.get().shared_link
70
+ return shared_link
71
+
72
+ def copy_file(self, source_file_id, target_folder_id):
73
+ """
74
+ Copies Box fild to another folder
75
+ source_file_id - Box file id of the file to copy
76
+ target_folder_id - Box folder id of where to copy the file too
77
+ """
78
+ if not self.client:
79
+ self._get_client()
80
+
81
+ file_to_copy = self.client.file(source_file_id)
82
+ target_folder = self.client.folder(target_folder_id)
83
+ try:
84
+ file_copy = file_to_copy.copy(target_folder)
85
+ self.logger.info(
86
+ 'File "{0}" has been copied into folder "{1}"'.format(
87
+ file_copy.name, file_copy.parent.name
88
+ )
89
+ )
90
+ except Exception as e:
91
+ self.logger.error(f"Failed to copy Box item {e}")
92
+
93
+ def upload_file(self, file_path, box_folder_id):
94
+ if not self.client:
95
+ self._get_client()
96
+
97
+ if os.path.exists(file_path):
98
+ new_file = self.client.folder(box_folder_id).upload(file_path)
99
+ self.logger.info(
100
+ 'File "{0}" uploaded to Box with file ID {1}'.format(
101
+ new_file.name, new_file.id
102
+ )
103
+ )
104
+ return True
105
+ else:
106
+ self.logger.error(f"File does not exist {file_path}")
107
+ return False
@@ -0,0 +1 @@
1
+ from .api import JobLogClient
@@ -0,0 +1,93 @@
1
+ import sys
2
+
3
+ from cit_pydata.util import api as util_api
4
+
5
+
6
+ class JobLogClient:
7
+ def __init__(self, sql_client, job_name, logger=None):
8
+ self.logger = util_api.get_logger(__name__, "INFO") if not logger else logger
9
+
10
+ self.sql_client = sql_client
11
+
12
+ self.job_name = job_name
13
+ self.log_guid = None
14
+
15
+ def start(self):
16
+ if "uuid" not in sys.modules:
17
+ import uuid
18
+ if not self.log_guid:
19
+ self.log_guid = str(uuid.uuid4())
20
+ param_list = [self.job_name, "initializing", self.log_guid]
21
+ self.sql_client.execute_stored_procedure("usp_Start_JobLog", param_list)
22
+ self.logger.info(
23
+ f"JOBLOG - Started Job {self.job_name} with GUID {self.log_guid}"
24
+ )
25
+ return self.log_guid
26
+ else:
27
+ self.logger.error(f"JOBLOG - Failed to start. Logging already started")
28
+
29
+ def finish(self, is_success: bool = True, message: str = None):
30
+ if is_success:
31
+ result = "Success"
32
+ self.logger.info(
33
+ f'JOBLOG - SUCCESS - "{self.job_name}" with GUID {self.log_guid}'
34
+ )
35
+ else:
36
+ result = "Failure"
37
+ self.logger.info(
38
+ f'JOBLOG - FAILED - "{self.job_name}" with GUID {self.log_guid}'
39
+ )
40
+
41
+ param_list = [self.log_guid, message, result]
42
+
43
+ # Update JobLog with result
44
+ self.sql_client.execute_stored_procedure("usp_Update_JobLog", param_list)
45
+
46
+ def update_status(self, message):
47
+ param_list = [self.log_guid, message, None]
48
+ self.sql_client.execute_stored_procedure("usp_Update_JobLog", param_list)
49
+
50
+ def update_joblog(sql_client, method, guid, status, logger=None):
51
+ # If no sql_client supplied quietly ignore
52
+ if sql_client:
53
+ assert method in ["Success", "Failure", "Status"]
54
+
55
+ if method in ["Success", "Failure"]:
56
+ result = method
57
+ param_list = [guid, status, result]
58
+ elif method == "Status":
59
+ param_list = [guid, status]
60
+
61
+ stored_procedure_name = "usp_Update_JobLog"
62
+ sql_client.execute_stored_procedure(stored_procedure_name, param_list)
63
+
64
+ def insert_message(
65
+ self,
66
+ message_name,
67
+ message_type,
68
+ value_string: str = None,
69
+ value_bit: bool = None,
70
+ value_int: int = None,
71
+ value_date=None,
72
+ ):
73
+ """
74
+ INSERT INTO tbl_JobLogAttribute
75
+ (JobLogGUID,AttributeName,AttributeType,AttributeLogType,ValueType,ValueString,ValueBit,ValueInteger,ValueDate)
76
+
77
+ sample usage:
78
+ job_log.insert_message('Job Parameter', 'Input Parameter', 'getActiveMembershipMainContact')
79
+ """
80
+ param_list = [
81
+ self.log_guid,
82
+ message_name,
83
+ message_type,
84
+ None,
85
+ None,
86
+ value_string,
87
+ value_bit,
88
+ value_int,
89
+ value_date,
90
+ ]
91
+ self.logger.debug(f"JOBLOG - insert attribute param_list: {param_list}")
92
+ # Update JobLog with result
93
+ self.sql_client.execute_stored_procedure("usp_LogJobAttribute", param_list)
@@ -0,0 +1 @@
1
+ from .api import MarketoClient