berryworld 1.0.0.185313__py3-none-any.whl → 1.0.0.188349__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.
- berryworld/__init__.py +1 -2
- berryworld/credentials.py +0 -34
- {berryworld-1.0.0.185313.dist-info → berryworld-1.0.0.188349.dist-info}/METADATA +3 -3
- {berryworld-1.0.0.185313.dist-info → berryworld-1.0.0.188349.dist-info}/RECORD +7 -8
- {berryworld-1.0.0.185313.dist-info → berryworld-1.0.0.188349.dist-info}/WHEEL +1 -1
- berryworld/postgres_connection.py +0 -205
- {berryworld-1.0.0.185313.dist-info → berryworld-1.0.0.188349.dist-info/licenses}/LICENSE +0 -0
- {berryworld-1.0.0.185313.dist-info → berryworld-1.0.0.188349.dist-info}/top_level.txt +0 -0
berryworld/__init__.py
CHANGED
|
@@ -3,10 +3,9 @@ from .handy_mix import HandyMix, URLResolver
|
|
|
3
3
|
from .transportation_solver import TransportationAlgorithm
|
|
4
4
|
from .allocation_solver import AllocationSolver
|
|
5
5
|
from .pickle_management import PickleManagement
|
|
6
|
-
from .postgres_connection import Postgresql
|
|
7
6
|
from .email_logging import EmailLogging
|
|
8
7
|
from .verify_keys import Verify
|
|
9
|
-
from .credentials import
|
|
8
|
+
from .credentials import SnowflakeCredentials, SQLCredentials, BCCredentials, CDSCredentials, SharePointCredentials, \
|
|
10
9
|
WebServiceCredentials, MicrosoftTeamsCredentials
|
|
11
10
|
from .persistent_storage import PersistentStorage
|
|
12
11
|
from .generate_env import EnvVariables
|
berryworld/credentials.py
CHANGED
|
@@ -71,40 +71,6 @@ class SQLCredentials:
|
|
|
71
71
|
raise ValueError("Variable %s not found" % str(e))
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
class PostgresCredentials:
|
|
75
|
-
def __init__(self, db_name, server_type=None):
|
|
76
|
-
if db_name is None:
|
|
77
|
-
raise ValueError("Please provide a value for db_name")
|
|
78
|
-
self.db_name = db_name
|
|
79
|
-
self.server_type = server_type
|
|
80
|
-
|
|
81
|
-
def simple_creds(self):
|
|
82
|
-
if self.server_type is None:
|
|
83
|
-
raise ValueError("Please provide a value for server_type")
|
|
84
|
-
|
|
85
|
-
try:
|
|
86
|
-
if os.name == 'nt':
|
|
87
|
-
server_name = os.environ.get(
|
|
88
|
-
"POSTGRESQL_" + self.db_name.upper() + '_' + self.server_type.upper() + '_LOCAL_SERVER_NAME')
|
|
89
|
-
else:
|
|
90
|
-
server_name = os.environ.get(
|
|
91
|
-
"POSTGRESQL_" + self.db_name.upper() + '_' + self.server_type.upper() + '_SERVER_NAME')
|
|
92
|
-
|
|
93
|
-
db_name = os.environ.get(
|
|
94
|
-
"POSTGRESQL_" + self.db_name.upper() + '_' + self.server_type.upper() + '_DB_NAME')
|
|
95
|
-
user_name = os.environ.get(
|
|
96
|
-
"POSTGRESQL_" + self.db_name.upper() + '_' + self.server_type.upper() + '_USER_NAME')
|
|
97
|
-
password = os.environ.get(
|
|
98
|
-
"POSTGRESQL_" + self.db_name.upper() + '_' + self.server_type.upper() + '_PASSWORD')
|
|
99
|
-
|
|
100
|
-
return {'server_name': re.sub(r'(\\)\1*', r'\1', server_name),
|
|
101
|
-
'db_name': db_name,
|
|
102
|
-
'user_name': user_name,
|
|
103
|
-
'password': password}
|
|
104
|
-
except ValueError as e:
|
|
105
|
-
raise ValueError("Variable %s not found" % str(e))
|
|
106
|
-
|
|
107
|
-
|
|
108
74
|
class BCCredentials:
|
|
109
75
|
def __init__(self, db_name=None, auth=False):
|
|
110
76
|
self.db_name = db_name
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: berryworld
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.188349
|
|
4
4
|
Summary: Handy classes to improve ETL processes
|
|
5
5
|
Home-page: https://www.berryworld.com
|
|
6
6
|
Author: BerryWorld ltd
|
|
@@ -17,7 +17,6 @@ Requires-Dist: numpy>=1.25.2
|
|
|
17
17
|
Requires-Dist: opencensus>=0.11.0
|
|
18
18
|
Requires-Dist: opencensus_ext_azure>=1.1.7
|
|
19
19
|
Requires-Dist: pandas>=1.4.2
|
|
20
|
-
Requires-Dist: psycopg2>=2.8.6
|
|
21
20
|
Requires-Dist: pyodbc>=4.0.39
|
|
22
21
|
Requires-Dist: python-dotenv>=1.0.0
|
|
23
22
|
Requires-Dist: PyYAML>=6.0
|
|
@@ -35,6 +34,7 @@ Dynamic: classifier
|
|
|
35
34
|
Dynamic: description
|
|
36
35
|
Dynamic: description-content-type
|
|
37
36
|
Dynamic: home-page
|
|
37
|
+
Dynamic: license-file
|
|
38
38
|
Dynamic: requires-dist
|
|
39
39
|
Dynamic: requires-python
|
|
40
40
|
Dynamic: summary
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
berryworld/__init__.py,sha256=
|
|
1
|
+
berryworld/__init__.py,sha256=WJKsOTkpDuQqBU-MppW2YNdRLnEZ8Q7giOvNI4orCi0,1120
|
|
2
2
|
berryworld/aks_logs.py,sha256=Gb2_cokiZbEX01Yoptd0MxpDociaug-GrXdwliyxFBo,2293
|
|
3
3
|
berryworld/allocation_solver.py,sha256=asFtaCAze6-eHUGWXA0kAp67UBS-Upj1KKdrVLj_ttQ,8513
|
|
4
4
|
berryworld/app_logs.py,sha256=MKzKPYd3JuPfOQNAapIgaeZeFHw1z_w2mbn9I6QCADE,4180
|
|
5
5
|
berryworld/app_logs_query.py,sha256=U94b-z3X9cuY_KFozupUcfaYciXWBn7p_RHkoRsfROU,4376
|
|
6
6
|
berryworld/cache_data.py,sha256=AWAhV4PPkilZ4Xb1pUXuuu6UdHICAx8QqDtb9rVnjDM,2254
|
|
7
|
-
berryworld/credentials.py,sha256=
|
|
7
|
+
berryworld/credentials.py,sha256=jJENjLE-qxR0yBtZPMPEOJ6H83bZeo4hI265AerwcUI,9540
|
|
8
8
|
berryworld/devops.py,sha256=7mRbyZPGzk5ox-6J2etv3NxCcfP4cprG0_Xelh7prn8,9776
|
|
9
9
|
berryworld/email_con.py,sha256=uSBzs_Ijz9pUPWt9e7U3TCB7i6q7hU1bB5vhsTB_tmw,14448
|
|
10
10
|
berryworld/email_logging.py,sha256=LeSrTExhQhar49gJR2wGC1dS0lqsNpFl9pS3eYWqnuo,4936
|
|
@@ -15,7 +15,6 @@ berryworld/logic_apps.py,sha256=a0uU4tNO3v2w7grdBv-OOx4hUf7VBIerJpwZ9U-29dQ,1459
|
|
|
15
15
|
berryworld/microsoft_teams.py,sha256=8uPo0yku-euBj2VdzBoZCeX3IcsCCOqISLqaVZUVxfA,16030
|
|
16
16
|
berryworld/persistent_storage.py,sha256=KQA57ez8eVTUCtudYkHPg_S5lcOEa_E7xXcaN1DYMMc,8601
|
|
17
17
|
berryworld/pickle_management.py,sha256=5o6UuXBpTj23Jgpz6sj9V-vdcdWBK1xMEckWxT-Whj4,2436
|
|
18
|
-
berryworld/postgres_connection.py,sha256=whKDnchd5Feqpmxpoh2vlyn36EKHR-dVEULYq0N_4wA,8287
|
|
19
18
|
berryworld/power_automate.py,sha256=Y11GoeDEwd3Y2RdvtPPhBSFK65APEceAQKtNo4gVLK4,26464
|
|
20
19
|
berryworld/sharepoint_con.py,sha256=TuH-Vxk1VxjTi7x80KFssf_J8YPLRXpV27RBaFZi37U,22254
|
|
21
20
|
berryworld/snowflake_conn.py,sha256=52ugfkyVCbR_Xr8YiZtNwPrwe93_1uE9uRy_VNPT6Gs,2428
|
|
@@ -26,12 +25,12 @@ berryworld/verify_keys.py,sha256=X4Nuz3o0XbRDYofbJGvxIDeN5gfWj19PN7lhO6T3hR8,435
|
|
|
26
25
|
berryworld/vivantio.py,sha256=QfZo0UKqkzVRg_LyiwivNd3aEup4TH57x4KxLZkCJwc,10627
|
|
27
26
|
berryworld/vivantio_logging.py,sha256=ciy7gA4u3FrgUIpEBnMgocbNPp6jcu9TPoy-kLcrTZU,5736
|
|
28
27
|
berryworld/xml_parser.py,sha256=HWD71NaTN3DaIOGT6Wzxs4CEsroFhGQwe9iPLIL80Co,957
|
|
28
|
+
berryworld-1.0.0.188349.dist-info/licenses/LICENSE,sha256=vtkVCJM6E2af2gnsi2XxKPr4WY-uIbvzVLXieFND0UU,1074
|
|
29
29
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
30
|
tests/test_allocation_config.py,sha256=e12l6fE9U57eSPS35g6ekJ_hol7-RHg89JV60_m1BlE,4633
|
|
31
31
|
tests/test_handy_mix_config.py,sha256=Un56mz9KJmdn4K4OwzHAHLSRzDU1Xv2nFrONNuzOG04,2594
|
|
32
32
|
tests/test_xml_parser.py,sha256=3QTlhFEd6KbK6nRFKZnc35tad6wqukTbe4QrFi8mr_8,859
|
|
33
|
-
berryworld-1.0.0.
|
|
34
|
-
berryworld-1.0.0.
|
|
35
|
-
berryworld-1.0.0.
|
|
36
|
-
berryworld-1.0.0.
|
|
37
|
-
berryworld-1.0.0.185313.dist-info/RECORD,,
|
|
33
|
+
berryworld-1.0.0.188349.dist-info/METADATA,sha256=IQNILK3na6R8NKy5LsS7k4mRTciBjh9mJjsdlVI-Sv0,1362
|
|
34
|
+
berryworld-1.0.0.188349.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
35
|
+
berryworld-1.0.0.188349.dist-info/top_level.txt,sha256=GIZ5qy-P5oxfEH755vA1IMFeTVdX3-40JxMe6nOe5I8,17
|
|
36
|
+
berryworld-1.0.0.188349.dist-info/RECORD,,
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import pandas as pd
|
|
3
|
-
import psycopg2
|
|
4
|
-
from .credentials import PostgresCredentials
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class Postgresql:
|
|
8
|
-
def __init__(self, server_creds=None, elastic_pool=False, sslrootcert=None, **kwargs):
|
|
9
|
-
""" Initialize the class
|
|
10
|
-
-----------------------------
|
|
11
|
-
server_creds = {
|
|
12
|
-
"server_name": "",
|
|
13
|
-
"db_name": "",
|
|
14
|
-
"user_name": "",
|
|
15
|
-
"password": ""
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
con_ = SQLConnection(server_creds)
|
|
19
|
-
-----------------------------
|
|
20
|
-
:param server_creds: Dictionary containing the info to connect to the Postgres Server
|
|
21
|
-
:param elastic_pool: Connection to the Elastic Pool in the service or local connection
|
|
22
|
-
:param sslrootcert: Path to local ssl root certificate
|
|
23
|
-
:param kwargs: Additional parameters to be passed to the connection
|
|
24
|
-
"""
|
|
25
|
-
if (kwargs == {}) & (server_creds is None):
|
|
26
|
-
raise ValueError('Please provide a valid server_creds or kwargs')
|
|
27
|
-
|
|
28
|
-
if elastic_pool:
|
|
29
|
-
self.sslmode = None
|
|
30
|
-
else:
|
|
31
|
-
self.sslmode = 'require'
|
|
32
|
-
|
|
33
|
-
self.sslrootcert = sslrootcert
|
|
34
|
-
self.conn_str = None
|
|
35
|
-
self.conn = None
|
|
36
|
-
self.cur = None
|
|
37
|
-
|
|
38
|
-
if kwargs != {}:
|
|
39
|
-
try:
|
|
40
|
-
db = kwargs['db_name']
|
|
41
|
-
server = kwargs['server_type']
|
|
42
|
-
server_creds = PostgresCredentials(db, server_type=server).simple_creds()
|
|
43
|
-
except KeyError:
|
|
44
|
-
raise KeyError('Please provide a valid db_name and server_type')
|
|
45
|
-
|
|
46
|
-
self.server = server_creds['server_name']
|
|
47
|
-
self.db = server_creds['db_name']
|
|
48
|
-
self.user = server_creds['user_name']
|
|
49
|
-
self.pw = server_creds['password']
|
|
50
|
-
|
|
51
|
-
def connect(self):
|
|
52
|
-
""" Open the connection to Postgresql """
|
|
53
|
-
"""
|
|
54
|
-
If sslmode is required connect direct to the server with ssl certificate, else connect to Postgres Elasticpool
|
|
55
|
-
without specifying sslmode as the certificate is defined within the kubernetes env with server_tls_sslmode
|
|
56
|
-
"""
|
|
57
|
-
if self.sslmode:
|
|
58
|
-
if self.sslrootcert:
|
|
59
|
-
self.conn_str = "dbname='%s' user='%s' host='%s' password='%s' port='5432' " \
|
|
60
|
-
"sslmode='%s' sslrootcert='%s' " % (
|
|
61
|
-
self.db, self.user, self.server, self.pw, self.sslmode, self.sslrootcert)
|
|
62
|
-
|
|
63
|
-
else:
|
|
64
|
-
self.conn_str = "dbname='%s' user='%s' host='%s' password='%s' port='5432' sslmode='%s' " % (
|
|
65
|
-
self.db, self.user, self.server, self.pw, self.sslmode)
|
|
66
|
-
|
|
67
|
-
else:
|
|
68
|
-
self.conn_str = "dbname='%s' user='%s' host='%s' password='%s' port='5432' " % (
|
|
69
|
-
self.db, self.user, self.server, self.pw)
|
|
70
|
-
|
|
71
|
-
self.conn = psycopg2.connect(self.conn_str)
|
|
72
|
-
|
|
73
|
-
def close(self):
|
|
74
|
-
""" Close the connection to Postgresql """
|
|
75
|
-
self.conn.close()
|
|
76
|
-
|
|
77
|
-
@staticmethod
|
|
78
|
-
def _chunker(seq, size):
|
|
79
|
-
""" Split the data set in chunks to be sent to SQL
|
|
80
|
-
:param seq: Sequence of records to be split
|
|
81
|
-
:param size: Size of any of the chunks to split the data
|
|
82
|
-
:return: The DataFrame divided in chunks
|
|
83
|
-
"""
|
|
84
|
-
return (seq[pos:pos + size] for pos in range(0, len(seq), size))
|
|
85
|
-
|
|
86
|
-
@staticmethod
|
|
87
|
-
def convert_decimal_str(string):
|
|
88
|
-
""" Method to parse the Decimal type in python
|
|
89
|
-
:param string: String variable to parse
|
|
90
|
-
"""
|
|
91
|
-
string = re.sub("'\)(?!(,[ ]+\())(?=([^$]))", "", string)
|
|
92
|
-
return re.sub("Decimal\('", "", string)
|
|
93
|
-
|
|
94
|
-
def query(self, sql_query):
|
|
95
|
-
""" Read data from Postgres SQL according to the sql_query
|
|
96
|
-
-----------------------------
|
|
97
|
-
query_str = "SELECT * FROM %s" & table
|
|
98
|
-
con_.query(query_str)
|
|
99
|
-
-----------------------------
|
|
100
|
-
:param sql_query: Query to be sent to SQL
|
|
101
|
-
:return: DataFrame gathering the requested data
|
|
102
|
-
"""
|
|
103
|
-
cursor = None
|
|
104
|
-
self.connect()
|
|
105
|
-
try:
|
|
106
|
-
cursor = self.conn.cursor()
|
|
107
|
-
cursor.execute(sql_query)
|
|
108
|
-
rows = cursor.fetchall()
|
|
109
|
-
col_names = [desc[0] for desc in cursor.description]
|
|
110
|
-
result = pd.DataFrame(rows, columns=col_names)
|
|
111
|
-
return result
|
|
112
|
-
except Exception as e:
|
|
113
|
-
raise Exception(e)
|
|
114
|
-
finally:
|
|
115
|
-
if cursor:
|
|
116
|
-
cursor.close()
|
|
117
|
-
self.close()
|
|
118
|
-
|
|
119
|
-
def run_statement(self, statement):
|
|
120
|
-
""" Execute SQL statement
|
|
121
|
-
-----------------------------
|
|
122
|
-
query_str = "DELETE FROM %s WHERE Id > 100" & table
|
|
123
|
-
con_.run_statement(query_str)
|
|
124
|
-
-----------------------------
|
|
125
|
-
:param statement: Statement as string to be run in Postgres SQL
|
|
126
|
-
:return: Print the number of rows affected
|
|
127
|
-
"""
|
|
128
|
-
cursor = None
|
|
129
|
-
self.connect()
|
|
130
|
-
try:
|
|
131
|
-
cursor = self.conn.cursor()
|
|
132
|
-
cursor.execute(statement)
|
|
133
|
-
self.conn.commit()
|
|
134
|
-
except Exception as e:
|
|
135
|
-
raise Exception(e)
|
|
136
|
-
finally:
|
|
137
|
-
if cursor:
|
|
138
|
-
cursor.close()
|
|
139
|
-
self.close()
|
|
140
|
-
|
|
141
|
-
def insert(self, data, schema, table, truncate=False, output=None, print_sql=False, chunk=1000):
|
|
142
|
-
""" Insert data in a table in SQL truncating the table if needed
|
|
143
|
-
-----------------------------
|
|
144
|
-
df = pd.DataFrame({'col1': ['a', 'b'], 'col2': [1, 2]})
|
|
145
|
-
con_.insert(df, table_schema, table_name)
|
|
146
|
-
-----------------------------
|
|
147
|
-
:param data: DataFrame containing the data to upload
|
|
148
|
-
:param schema: Schema of the table in which the data will be uploaded
|
|
149
|
-
:param table: Table in which the data will be uploaded
|
|
150
|
-
:param truncate: Indicate whether the table has to be truncated before the data is sent or not
|
|
151
|
-
:param output: Outputs the columns indicated in this list
|
|
152
|
-
:param chunk: Indicate how many rows will be uploaded at once
|
|
153
|
-
:param print_sql: boolean to indicate that you want the sql_statement to be printed on the console
|
|
154
|
-
:return: A DataFrame with the output columns requested if output is not None, else None
|
|
155
|
-
"""
|
|
156
|
-
if output is None:
|
|
157
|
-
output = []
|
|
158
|
-
if data is None:
|
|
159
|
-
# no data to upload
|
|
160
|
-
return ValueError("The data provided is invalid!")
|
|
161
|
-
|
|
162
|
-
cursor = None
|
|
163
|
-
self.connect()
|
|
164
|
-
try:
|
|
165
|
-
cursor = self.conn.cursor()
|
|
166
|
-
# Truncate table if needed
|
|
167
|
-
if truncate:
|
|
168
|
-
cursor.execute("TRUNCATE TABLE %s.%s" % (schema, table))
|
|
169
|
-
|
|
170
|
-
# Convert category columns to string
|
|
171
|
-
cat_cols = data.columns[(data.dtypes == 'category').values].to_list()
|
|
172
|
-
data[cat_cols] = data[cat_cols].astype(str)
|
|
173
|
-
# Deal with bull values and apostrophes (')
|
|
174
|
-
data = data.replace("'NULL'", "NULL")
|
|
175
|
-
data = data.replace("'", "~~", regex=True)
|
|
176
|
-
data = data.fillna("null")
|
|
177
|
-
# Insert data into the table destination
|
|
178
|
-
records = [tuple(x) for x in data.values]
|
|
179
|
-
insert_ = """INSERT INTO %s.%s """ % (schema, table)
|
|
180
|
-
insert_ += str(tuple(data.columns.values)).replace("\'", "") + """ VALUES """
|
|
181
|
-
results = pd.DataFrame()
|
|
182
|
-
for batch in self._chunker(records, chunk):
|
|
183
|
-
rows = str(batch).strip('[]').replace("~~", "''")
|
|
184
|
-
rows = rows.replace("'NULL'", "NULL").replace("'null'", 'null')
|
|
185
|
-
insert_rows = insert_ + rows
|
|
186
|
-
insert_rows = self.convert_decimal_str(insert_rows)
|
|
187
|
-
insert_rows = re.sub(r"\';", "'')", insert_rows)
|
|
188
|
-
if len(output) > 0:
|
|
189
|
-
insert_rows += " RETURNING " + ','.join(output)
|
|
190
|
-
|
|
191
|
-
if print_sql:
|
|
192
|
-
print(insert_rows)
|
|
193
|
-
cursor.execute(insert_rows)
|
|
194
|
-
if len(output) > 0:
|
|
195
|
-
results = pd.concat([results, pd.DataFrame.from_records(cursor.fetchall(), columns=output)])
|
|
196
|
-
self.conn.commit()
|
|
197
|
-
|
|
198
|
-
if len(output) > 0:
|
|
199
|
-
return results
|
|
200
|
-
except Exception as e:
|
|
201
|
-
raise Exception(e)
|
|
202
|
-
finally:
|
|
203
|
-
if cursor:
|
|
204
|
-
cursor.close()
|
|
205
|
-
self.close()
|
|
File without changes
|
|
File without changes
|