datablender 0.0.1__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.
- datablender/__init__.py +68 -0
- datablender/base/__init__.py +283 -0
- datablender/base/connection.py +370 -0
- datablender/base/data.py +1856 -0
- datablender/base/dataConfiguration.py +701 -0
- datablender/base/dataElement.py +584 -0
- datablender/base/dataLogging.py +702 -0
- datablender/base/dataSets.py +233 -0
- datablender/base/directory.py +225 -0
- datablender/base/file.py +496 -0
- datablender/base/queryBuilder.py +1498 -0
- datablender/base/request.py +182 -0
- datablender/base/text.py +79 -0
- datablender/base/web.py +602 -0
- datablender/data/__init__.py +124 -0
- datablender/data/asyncDataProcess.py +1047 -0
- datablender/data/asyncDataServer.py +538 -0
- datablender/data/asyncDataSourceCore.py +1971 -0
- datablender/data/dataDirectory.py +1540 -0
- datablender/data/dataFile.py +635 -0
- datablender/data/dataProcess.py +639 -0
- datablender/data/dataServer.py +488 -0
- datablender/data/dataSource.py +647 -0
- datablender/data/dataSourceCore.py +1318 -0
- datablender/data/dataVersion.py +1526 -0
- datablender/data/directoryElementController.py +172 -0
- datablender/data/filesTable.py +219 -0
- datablender/database/__init__.py +26 -0
- datablender/database/database.py +1151 -0
- datablender/database/elementSQL.py +1093 -0
- datablender/database/extension.py +265 -0
- datablender/database/function.py +324 -0
- datablender/database/partition.py +26 -0
- datablender/database/role.py +385 -0
- datablender/database/schema.py +1009 -0
- datablender/database/table.py +2274 -0
- datablender/database/view.py +848 -0
- datablender/tests/__init__.py +8 -0
- datablender/tests/test_base.py +1604 -0
- datablender/tests/test_data.py +3346 -0
- datablender/tests/test_database.py +799 -0
- datablender-0.0.1.dist-info/METADATA +68 -0
- datablender-0.0.1.dist-info/RECORD +45 -0
- datablender-0.0.1.dist-info/WHEEL +5 -0
- datablender-0.0.1.dist-info/top_level.txt +1 -0
datablender/__init__.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datablender.base import (
|
|
6
|
+
File,
|
|
7
|
+
Connection,
|
|
8
|
+
readFile,
|
|
9
|
+
getNextID,
|
|
10
|
+
normalize_user_name,
|
|
11
|
+
Directory,
|
|
12
|
+
DirectoryElement,
|
|
13
|
+
ZipFile_,
|
|
14
|
+
Text,
|
|
15
|
+
formatText,
|
|
16
|
+
Request,
|
|
17
|
+
Bot,
|
|
18
|
+
BotAction,
|
|
19
|
+
WebElement,
|
|
20
|
+
QueryBuilder,
|
|
21
|
+
DataConfiguration,
|
|
22
|
+
DataLogging,
|
|
23
|
+
DataEventsTable,
|
|
24
|
+
DataElement,
|
|
25
|
+
Data,
|
|
26
|
+
AsyncConnection,
|
|
27
|
+
AsyncDataConfiguration,
|
|
28
|
+
AsyncRequest,
|
|
29
|
+
DataSets
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
from datablender.database import (
|
|
33
|
+
DatabaseElement,
|
|
34
|
+
SchemaElement,
|
|
35
|
+
Database,
|
|
36
|
+
Extension,
|
|
37
|
+
Role,
|
|
38
|
+
Schema,
|
|
39
|
+
Table,
|
|
40
|
+
View,
|
|
41
|
+
Function,
|
|
42
|
+
AsyncView,
|
|
43
|
+
AsyncTable,
|
|
44
|
+
AsyncDatabase
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
from datablender.data import (
|
|
48
|
+
DataVersion,
|
|
49
|
+
DataVersionColumn,
|
|
50
|
+
DataVersionTable,
|
|
51
|
+
DataVersionValue,
|
|
52
|
+
DataSource,
|
|
53
|
+
DataFetcher,
|
|
54
|
+
RawDataFile,
|
|
55
|
+
DirectoryElementController,
|
|
56
|
+
DataProcess,
|
|
57
|
+
FilesTable,
|
|
58
|
+
DataFile,
|
|
59
|
+
DataDirectory,
|
|
60
|
+
DataDirectoryElement,
|
|
61
|
+
DataZipFile,
|
|
62
|
+
DataSourceCore,
|
|
63
|
+
DataServer,
|
|
64
|
+
importData,
|
|
65
|
+
AsyncDataServer,
|
|
66
|
+
AsyncDataSource,
|
|
67
|
+
AsyncDataProcess
|
|
68
|
+
)
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
from typing import Callable,Tuple
|
|
5
|
+
import types
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import numpy
|
|
10
|
+
import pandas
|
|
11
|
+
|
|
12
|
+
import importlib
|
|
13
|
+
import importlib.util
|
|
14
|
+
|
|
15
|
+
def getDirectoryElementName(
|
|
16
|
+
path:str=None,
|
|
17
|
+
directory_name:str=None,
|
|
18
|
+
element_name:str=None
|
|
19
|
+
) -> Tuple[str,str]:
|
|
20
|
+
"""Get directory name and data directory element name from path.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
path (str, optional): Path. Defaults to None.
|
|
24
|
+
directory_name (str, optional): Directory name. Defaults to None.
|
|
25
|
+
element_name (str, optional): Directory element name. Defaults to None.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Tuple[str,str]: Directory name and directory element name.
|
|
29
|
+
"""
|
|
30
|
+
if path:
|
|
31
|
+
return os.path.dirname(
|
|
32
|
+
os.path.normpath(path)
|
|
33
|
+
),os.path.basename(
|
|
34
|
+
os.path.normpath(path)
|
|
35
|
+
)
|
|
36
|
+
elif directory_name and element_name:
|
|
37
|
+
return directory_name,element_name
|
|
38
|
+
|
|
39
|
+
from datablender.base.file import File,ZipFile_
|
|
40
|
+
from datablender.base.directory import Directory,DirectoryElement
|
|
41
|
+
from datablender.base.text import Text,formatText
|
|
42
|
+
from datablender.base.request import Request, AsyncRequest
|
|
43
|
+
|
|
44
|
+
def normalize_user_name(user_name:str):
|
|
45
|
+
return user_name.split(' ')[0]
|
|
46
|
+
|
|
47
|
+
def getNextID(elements:list,id_attribute_name:str='id') -> int:
|
|
48
|
+
"""Get next id in a list of dictionnary.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
elements (list): List of dictionnary.
|
|
52
|
+
id_attribute_name (str, optional): Id attribute name. Defaults to 'id'.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
int: Next id.
|
|
56
|
+
"""
|
|
57
|
+
ids = numpy.append(
|
|
58
|
+
numpy.array([element[id_attribute_name] for element in elements]),
|
|
59
|
+
numpy.nan
|
|
60
|
+
)
|
|
61
|
+
df = pandas.DataFrame({
|
|
62
|
+
'column':numpy.sort(ids),
|
|
63
|
+
'ids':numpy.arange(1,ids.size+1,1)
|
|
64
|
+
})
|
|
65
|
+
return df.loc[df['column']!=df['ids'],'ids'].min()
|
|
66
|
+
|
|
67
|
+
def readFile(
|
|
68
|
+
path:str=None,
|
|
69
|
+
directory_name:str=None,
|
|
70
|
+
file_name:str=None,
|
|
71
|
+
**kwargs
|
|
72
|
+
) -> pandas.DataFrame:
|
|
73
|
+
return File(
|
|
74
|
+
directory_name,
|
|
75
|
+
file_name,
|
|
76
|
+
path
|
|
77
|
+
).read(
|
|
78
|
+
**kwargs
|
|
79
|
+
).content
|
|
80
|
+
|
|
81
|
+
def getFunction(
|
|
82
|
+
function_name:str,
|
|
83
|
+
directory_name:str,
|
|
84
|
+
module:str='__init__',
|
|
85
|
+
code:str = None,
|
|
86
|
+
schema_name:str = None,
|
|
87
|
+
schema_type:str = None
|
|
88
|
+
) -> Callable:
|
|
89
|
+
|
|
90
|
+
if module is None:
|
|
91
|
+
module = '__init__'
|
|
92
|
+
|
|
93
|
+
if directory_name is None:
|
|
94
|
+
directory_name = os.path.join(
|
|
95
|
+
os.getenv(
|
|
96
|
+
'code_directory',
|
|
97
|
+
os.getcwd()
|
|
98
|
+
),
|
|
99
|
+
schema_type,
|
|
100
|
+
schema_name
|
|
101
|
+
)
|
|
102
|
+
os.makedirs(
|
|
103
|
+
directory_name,
|
|
104
|
+
exist_ok=True
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if code is not None:
|
|
108
|
+
File(
|
|
109
|
+
directory_name,
|
|
110
|
+
os.path.join(directory_name,'{}.py'.format(module))
|
|
111
|
+
).write(code)
|
|
112
|
+
|
|
113
|
+
spec = importlib.util.spec_from_file_location(
|
|
114
|
+
module,
|
|
115
|
+
os.path.join(directory_name,'{}.py'.format(module))
|
|
116
|
+
)
|
|
117
|
+
module = importlib.util.module_from_spec(spec)
|
|
118
|
+
spec.loader.exec_module(module)
|
|
119
|
+
return getattr(module, function_name)
|
|
120
|
+
|
|
121
|
+
def getModule(
|
|
122
|
+
directory_name:str,
|
|
123
|
+
module:str='__init__',
|
|
124
|
+
package_name:str = None,
|
|
125
|
+
schema_name:str = None,
|
|
126
|
+
schema_type:str = None
|
|
127
|
+
) -> types.ModuleType:
|
|
128
|
+
|
|
129
|
+
original_path = os.getcwd()
|
|
130
|
+
|
|
131
|
+
if package_name:
|
|
132
|
+
module = package_name
|
|
133
|
+
else:
|
|
134
|
+
if module is None:
|
|
135
|
+
module = '__init__'
|
|
136
|
+
|
|
137
|
+
if directory_name is None:
|
|
138
|
+
directory_name = os.path.join(
|
|
139
|
+
os.getenv(
|
|
140
|
+
'CODE_DIRECTORY',
|
|
141
|
+
os.getcwd()
|
|
142
|
+
),
|
|
143
|
+
schema_type,
|
|
144
|
+
schema_name
|
|
145
|
+
)
|
|
146
|
+
os.makedirs(
|
|
147
|
+
directory_name,
|
|
148
|
+
exist_ok=True
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# os.chdir(directory_name)
|
|
152
|
+
sys.path.append(directory_name)
|
|
153
|
+
|
|
154
|
+
module = importlib.import_module(module)
|
|
155
|
+
|
|
156
|
+
# spec = importlib.util.spec_from_file_location(
|
|
157
|
+
# module,
|
|
158
|
+
# os.path.join(directory_name,'{}.py'.format(module))
|
|
159
|
+
# )
|
|
160
|
+
# module = importlib.util.module_from_spec(spec)
|
|
161
|
+
# spec.loader.exec_module(module)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
sys.path.append(original_path)
|
|
165
|
+
|
|
166
|
+
return module
|
|
167
|
+
|
|
168
|
+
def manageQuery(
|
|
169
|
+
name:str=None,
|
|
170
|
+
query:str=None,
|
|
171
|
+
file_name:str=None,
|
|
172
|
+
directory_name:str=None,
|
|
173
|
+
schema_name:str=None,
|
|
174
|
+
schema_type:str= None,
|
|
175
|
+
data_config_is_active:bool=None
|
|
176
|
+
) -> Tuple[str,str,str]:
|
|
177
|
+
|
|
178
|
+
if query is not None:
|
|
179
|
+
if data_config_is_active:
|
|
180
|
+
if file_name is None and directory_name is None and name is not None:
|
|
181
|
+
file_name = name+'.sql'
|
|
182
|
+
directory_name = os.path.join(
|
|
183
|
+
os.getenv(
|
|
184
|
+
'CODE_DIRECTORY',
|
|
185
|
+
os.getcwd()
|
|
186
|
+
),
|
|
187
|
+
schema_type,
|
|
188
|
+
schema_name,
|
|
189
|
+
'queries'
|
|
190
|
+
)
|
|
191
|
+
os.makedirs(
|
|
192
|
+
directory_name,
|
|
193
|
+
exist_ok=True
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
File(
|
|
197
|
+
directory_name,
|
|
198
|
+
file_name
|
|
199
|
+
).write(query)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
# if os.path.isfile(os.path.join(os.path.abspath(directory_name),file_name)):
|
|
203
|
+
# query = File(
|
|
204
|
+
# directory_name,
|
|
205
|
+
# file_name
|
|
206
|
+
# ).read().content
|
|
207
|
+
|
|
208
|
+
# if directory_name is None:
|
|
209
|
+
|
|
210
|
+
# directory_name = os.getenv(
|
|
211
|
+
# 'CODE_DIRECTORY',
|
|
212
|
+
# os.getcwd()
|
|
213
|
+
# )
|
|
214
|
+
|
|
215
|
+
# if schema_name:
|
|
216
|
+
# new_directory_name = os.path.join(
|
|
217
|
+
# directory_name,
|
|
218
|
+
# schema_type,
|
|
219
|
+
# schema_name,
|
|
220
|
+
# 'queries'
|
|
221
|
+
# )
|
|
222
|
+
# if os.path.isdir(new_directory_name):
|
|
223
|
+
# directory_name = new_directory_name
|
|
224
|
+
|
|
225
|
+
# elif not os.path.isdir(directory_name):
|
|
226
|
+
# new_directory_name = os.path.join(
|
|
227
|
+
# os.getenv('CODE_DIRECTORY',os.getcwd()),
|
|
228
|
+
# directory_name
|
|
229
|
+
# )
|
|
230
|
+
# if os.path.isdir(new_directory_name):
|
|
231
|
+
# directory_name = new_directory_name
|
|
232
|
+
|
|
233
|
+
# if file_name is None:
|
|
234
|
+
# pass
|
|
235
|
+
|
|
236
|
+
# query = File(
|
|
237
|
+
# directory_name,
|
|
238
|
+
# file_name+'.sql' if '.' not in file_name else file_name
|
|
239
|
+
# ).read().content
|
|
240
|
+
|
|
241
|
+
elif file_name is not None:
|
|
242
|
+
pass
|
|
243
|
+
|
|
244
|
+
elif name is not None:
|
|
245
|
+
if directory_name is None:
|
|
246
|
+
directory_name=os.getenv(
|
|
247
|
+
'CODE_DIRECTORY',
|
|
248
|
+
os.getcwd()
|
|
249
|
+
)
|
|
250
|
+
if schema_type:
|
|
251
|
+
directory_name = os.path.join(
|
|
252
|
+
directory_name,
|
|
253
|
+
schema_type
|
|
254
|
+
)
|
|
255
|
+
if schema_name:
|
|
256
|
+
directory_name = os.path.join(
|
|
257
|
+
directory_name,
|
|
258
|
+
schema_name
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
query = File(
|
|
262
|
+
os.path.join(
|
|
263
|
+
directory_name,
|
|
264
|
+
'queries'
|
|
265
|
+
),
|
|
266
|
+
name+'.sql'
|
|
267
|
+
).read(encoding = 'utf-8').content
|
|
268
|
+
|
|
269
|
+
return query,file_name,directory_name
|
|
270
|
+
|
|
271
|
+
from datablender.base.web import Bot,BotAction,WebElement
|
|
272
|
+
from datablender.base.connection import Connection, AsyncConnection
|
|
273
|
+
from datablender.base.queryBuilder import QueryBuilder
|
|
274
|
+
from datablender.base.dataLogging import (
|
|
275
|
+
DataEventsTable,
|
|
276
|
+
DataLogging,
|
|
277
|
+
AsyncDataEventsTable,
|
|
278
|
+
AsyncDataLogging
|
|
279
|
+
)
|
|
280
|
+
from datablender.base.dataConfiguration import DataConfiguration,AsyncDataConfiguration
|
|
281
|
+
from datablender.base.dataElement import DataElement, AsyncDataElement
|
|
282
|
+
from datablender.base.data import Data
|
|
283
|
+
from datablender.base.dataSets import DataSets
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import psycopg2
|
|
8
|
+
import postgis
|
|
9
|
+
import sqlalchemy
|
|
10
|
+
import aiohttp
|
|
11
|
+
import asyncio
|
|
12
|
+
import asyncpg
|
|
13
|
+
from sqlalchemy.ext.asyncio import (
|
|
14
|
+
create_async_engine,
|
|
15
|
+
async_sessionmaker,
|
|
16
|
+
AsyncSession
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT,ISOLATION_LEVEL_DEFAULT
|
|
20
|
+
|
|
21
|
+
from datablender.base import normalize_user_name
|
|
22
|
+
|
|
23
|
+
class Connection:
|
|
24
|
+
"""Connection to a database.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
----------
|
|
28
|
+
host (str): Server's host.
|
|
29
|
+
port (str): Server's port.
|
|
30
|
+
database_name (str): Database name.
|
|
31
|
+
user_name (str): User name.
|
|
32
|
+
password (str): Password.
|
|
33
|
+
dialect (str): Dialect.
|
|
34
|
+
connection_string (str) : Connection string.
|
|
35
|
+
engine (object) : SQLAlchemy engine.
|
|
36
|
+
connection (object) : Connection.
|
|
37
|
+
cursor (object) : Connection's cursor.
|
|
38
|
+
|
|
39
|
+
Methods:
|
|
40
|
+
----------
|
|
41
|
+
getConnection (self) -> None: Get the connection.
|
|
42
|
+
getCursor (self) -> None: Get the connection's cursor.
|
|
43
|
+
getEngine (self) -> None: Get SQLAlchemy engine.
|
|
44
|
+
connectActions (self) -> None: Get the connection, cursor and engine.
|
|
45
|
+
connect (self) -> None: Connect to the database.
|
|
46
|
+
close (self) -> None: a .
|
|
47
|
+
registerToPostgis (self) -> None: .
|
|
48
|
+
setIsolationLevel (self) -> None: .
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
host:str = 'localhost',
|
|
55
|
+
port:str = '5432',
|
|
56
|
+
database_name:str = 'postgres',
|
|
57
|
+
user_name:str = 'postgres',
|
|
58
|
+
password:str = None,
|
|
59
|
+
default_database:int = 'postgres',
|
|
60
|
+
**kwargs
|
|
61
|
+
):
|
|
62
|
+
"""Initiate the connection.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
host (str, optional): Server's host. Defaults to 'localhost'.
|
|
66
|
+
port (str, optional): Server's port. Defaults to '5432'.
|
|
67
|
+
database_name (str, optional): Database name. Defaults to 'postgres'.
|
|
68
|
+
user_name (str, optional): User name. Defaults to 'postgres'.
|
|
69
|
+
password (str, optional): Password. Defaults to None.
|
|
70
|
+
dialect (str, optional): Dialect. Defaults to 'PostgreSQL'.
|
|
71
|
+
"""
|
|
72
|
+
self.database_name = database_name
|
|
73
|
+
self.default_database = default_database
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
self.host = os.getenv('host',host)
|
|
77
|
+
self.port = os.getenv('port',port)
|
|
78
|
+
self.password = os.getenv('PASSWORD',password)
|
|
79
|
+
|
|
80
|
+
self.user_name = user_name if user_name != 'postgres' else normalize_user_name(
|
|
81
|
+
os.getenv(
|
|
82
|
+
'username',
|
|
83
|
+
user_name
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
self.connect(**kwargs)
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def connection_string(self) -> str:
|
|
91
|
+
"""Get connection string.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
str: Connection string.
|
|
95
|
+
"""
|
|
96
|
+
return "postgresql+psycopg2://{}:{}@{}:{}/{}".format(
|
|
97
|
+
self.user_name,
|
|
98
|
+
self.password,
|
|
99
|
+
self.host,
|
|
100
|
+
self.port,
|
|
101
|
+
self.database_name
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def getConnection(self) -> None:
|
|
105
|
+
"""Get connection.
|
|
106
|
+
"""
|
|
107
|
+
self.connection = psycopg2.connect(
|
|
108
|
+
database = self.database_name,
|
|
109
|
+
user = self.user_name,
|
|
110
|
+
host = self.host,
|
|
111
|
+
password = self.password,
|
|
112
|
+
port = self.port
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def getCursor(self,**kwargs) -> None:
|
|
116
|
+
"""Get connection's cursor.
|
|
117
|
+
"""
|
|
118
|
+
self.cursor = self.connection.cursor(**kwargs)
|
|
119
|
+
|
|
120
|
+
def getEngine(self) -> None:
|
|
121
|
+
"""Get SQLAlchemy engine.
|
|
122
|
+
"""
|
|
123
|
+
self.engine = sqlalchemy.create_engine(
|
|
124
|
+
self.connection_string
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def connect(self,**kwargs) -> None:
|
|
128
|
+
"""Connect to the database.
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
TypeError: _description_
|
|
132
|
+
TypeError: _description_
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
object: self
|
|
136
|
+
"""
|
|
137
|
+
self.getConnection()
|
|
138
|
+
self.getCursor(**kwargs)
|
|
139
|
+
self.getEngine()
|
|
140
|
+
|
|
141
|
+
def close(self) -> None:
|
|
142
|
+
"""Close the connected object.
|
|
143
|
+
"""
|
|
144
|
+
if self.cursor:
|
|
145
|
+
self.cursor.close()
|
|
146
|
+
if self.connection:
|
|
147
|
+
self.connection.close()
|
|
148
|
+
if self.engine:
|
|
149
|
+
self.engine.dispose()
|
|
150
|
+
|
|
151
|
+
def registerToPostgis(self) -> None:
|
|
152
|
+
"""Register to Postgis.
|
|
153
|
+
"""
|
|
154
|
+
postgis.register(self.cursor)
|
|
155
|
+
|
|
156
|
+
def setIsolationLevel(
|
|
157
|
+
self,
|
|
158
|
+
level:str = 'default'
|
|
159
|
+
) -> None:
|
|
160
|
+
"""Set the isolation level.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
level (str, optional): Level to set. Defaults to auto.
|
|
164
|
+
"""
|
|
165
|
+
self.connection.set_isolation_level(
|
|
166
|
+
{
|
|
167
|
+
'auto':ISOLATION_LEVEL_AUTOCOMMIT,
|
|
168
|
+
'default':ISOLATION_LEVEL_DEFAULT
|
|
169
|
+
}[level]
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
def setSchema(
|
|
173
|
+
self,
|
|
174
|
+
schema:str='public'
|
|
175
|
+
) -> None:
|
|
176
|
+
"""Set default schema.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
schema (str, optional): Schema to set to default. Defaults to 'public'.
|
|
180
|
+
"""
|
|
181
|
+
self.cursor.execute(
|
|
182
|
+
"SET search_path TO "+schema
|
|
183
|
+
)
|
|
184
|
+
self.connection.commit()
|
|
185
|
+
|
|
186
|
+
def setDatabase(
|
|
187
|
+
self,
|
|
188
|
+
database_name:str
|
|
189
|
+
) -> None:
|
|
190
|
+
"""Change the connection's database.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
database_name (str): Database name.
|
|
194
|
+
"""
|
|
195
|
+
self.close()
|
|
196
|
+
self.database_name = database_name
|
|
197
|
+
self.connect()
|
|
198
|
+
|
|
199
|
+
def getDefaultConnection(
|
|
200
|
+
self,
|
|
201
|
+
default_database_name:str=None
|
|
202
|
+
) -> None:
|
|
203
|
+
"""Change the database connection to the default one
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
default_database_name (str, optional): Name of the default database. Defaults to None.
|
|
207
|
+
"""
|
|
208
|
+
if default_database_name:
|
|
209
|
+
self.default_database = default_database_name
|
|
210
|
+
|
|
211
|
+
self.setDatabase(
|
|
212
|
+
self.default_database
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
class AsyncConnection:
|
|
216
|
+
"""Connection to a database.
|
|
217
|
+
|
|
218
|
+
Attributes:
|
|
219
|
+
----------
|
|
220
|
+
host (str): Server's host.
|
|
221
|
+
port (str): Server's port.
|
|
222
|
+
database_name (str): Database name.
|
|
223
|
+
user_name (str): User name.
|
|
224
|
+
password (str): Password.
|
|
225
|
+
dialect (str): Dialect.
|
|
226
|
+
connection_string (str) : Connection string.
|
|
227
|
+
engine (object) : SQLAlchemy engine.
|
|
228
|
+
connection (object) : Connection.
|
|
229
|
+
cursor (object) : Connection's cursor.
|
|
230
|
+
|
|
231
|
+
Methods:
|
|
232
|
+
----------
|
|
233
|
+
getConnection (self) -> None: Get the connection.
|
|
234
|
+
getCursor (self) -> None: Get the connection's cursor.
|
|
235
|
+
getEngine (self) -> None: Get SQLAlchemy engine.
|
|
236
|
+
connectActions (self) -> None: Get the connection, cursor and engine.
|
|
237
|
+
connect (self) -> None: Connect to the database.
|
|
238
|
+
close (self) -> None: a .
|
|
239
|
+
registerToPostgis (self) -> None: .
|
|
240
|
+
setIsolationLevel (self) -> None: .
|
|
241
|
+
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
def __init__(
|
|
245
|
+
self,
|
|
246
|
+
host:str = 'localhost',
|
|
247
|
+
port:str = '5432',
|
|
248
|
+
database_name:str = 'postgres',
|
|
249
|
+
user_name:str = 'postgres',
|
|
250
|
+
password:str = None,
|
|
251
|
+
default_database:int = 'postgres',
|
|
252
|
+
**kwargs
|
|
253
|
+
):
|
|
254
|
+
"""Initiate the connection.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
host (str, optional): Server's host. Defaults to 'localhost'.
|
|
258
|
+
port (str, optional): Server's port. Defaults to '5432'.
|
|
259
|
+
database_name (str, optional): Database name. Defaults to 'postgres'.
|
|
260
|
+
user_name (str, optional): User name. Defaults to 'postgres'.
|
|
261
|
+
password (str, optional): Password. Defaults to None.
|
|
262
|
+
dialect (str, optional): Dialect. Defaults to 'PostgreSQL'.
|
|
263
|
+
"""
|
|
264
|
+
self.database_name = database_name
|
|
265
|
+
self.default_database = default_database
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
self.host = os.getenv('host',host)
|
|
269
|
+
self.port = os.getenv('port',port)
|
|
270
|
+
self.password = os.getenv('PASSWORD',password)
|
|
271
|
+
|
|
272
|
+
self.user_name = user_name if user_name != 'postgres' else normalize_user_name(
|
|
273
|
+
os.getenv(
|
|
274
|
+
'username',
|
|
275
|
+
user_name
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def connection_string(self) -> str:
|
|
281
|
+
"""Get connection string.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
str: Connection string.
|
|
285
|
+
"""
|
|
286
|
+
return "postgresql+asyncpg://{}:{}@{}:{}/{}".format(
|
|
287
|
+
self.user_name,
|
|
288
|
+
self.password,
|
|
289
|
+
self.host,
|
|
290
|
+
self.port,
|
|
291
|
+
self.database_name
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
async def connect(self,**kwargs) -> None:
|
|
295
|
+
"""Connect to the database.
|
|
296
|
+
|
|
297
|
+
Raises:
|
|
298
|
+
TypeError: _description_
|
|
299
|
+
TypeError: _description_
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
object: self
|
|
303
|
+
"""
|
|
304
|
+
await self.getConnection()
|
|
305
|
+
self.getEngine()
|
|
306
|
+
|
|
307
|
+
async def getConnection(self) -> None:
|
|
308
|
+
"""Get connection.
|
|
309
|
+
"""
|
|
310
|
+
self.connection:asyncpg.connection.Connection = await asyncpg.connect(
|
|
311
|
+
database = self.database_name,
|
|
312
|
+
user = self.user_name,
|
|
313
|
+
host = self.host,
|
|
314
|
+
password = self.password,
|
|
315
|
+
port = self.port
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
def getEngine(self) -> None:
|
|
319
|
+
"""Get SQLAlchemy engine.
|
|
320
|
+
"""
|
|
321
|
+
self.engine = create_async_engine(
|
|
322
|
+
self.connection_string
|
|
323
|
+
)
|
|
324
|
+
self.async_session = async_sessionmaker(self.engine, expire_on_commit=False)
|
|
325
|
+
|
|
326
|
+
async def close(self) -> None:
|
|
327
|
+
await self.connection.close()
|
|
328
|
+
await self.engine.dispose()
|
|
329
|
+
|
|
330
|
+
async def setSchema(
|
|
331
|
+
self,
|
|
332
|
+
schema:str='public'
|
|
333
|
+
) -> None:
|
|
334
|
+
"""Set default schema.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
schema (str, optional): Schema to set to default. Defaults to 'public'.
|
|
338
|
+
"""
|
|
339
|
+
await self.connection.execute(
|
|
340
|
+
"SET search_path TO "+schema
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
async def setDatabase(
|
|
344
|
+
self,
|
|
345
|
+
database_name:str
|
|
346
|
+
) -> None:
|
|
347
|
+
"""Change the connection's database.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
database_name (str): Database name.
|
|
351
|
+
"""
|
|
352
|
+
await self.close()
|
|
353
|
+
self.database_name = database_name
|
|
354
|
+
await self.connect()
|
|
355
|
+
|
|
356
|
+
async def getDefaultConnection(
|
|
357
|
+
self,
|
|
358
|
+
default_database_name:str=None
|
|
359
|
+
) -> None:
|
|
360
|
+
"""Change the database connection to the default one
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
default_database_name (str, optional): Name of the default database. Defaults to None.
|
|
364
|
+
"""
|
|
365
|
+
if default_database_name:
|
|
366
|
+
self.default_database = default_database_name
|
|
367
|
+
|
|
368
|
+
await self.setDatabase(
|
|
369
|
+
self.default_database
|
|
370
|
+
)
|