module-typica 0.2.2__tar.gz → 0.2.3__tar.gz
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.
- {module_typica-0.2.2 → module_typica-0.2.3}/PKG-INFO +5 -5
- {module_typica-0.2.2 → module_typica-0.2.3}/Readme.md +4 -3
- {module_typica-0.2.2 → module_typica-0.2.3}/pyproject.toml +18 -2
- {module_typica-0.2.2 → module_typica-0.2.3}/typica/connection.py +12 -9
- {module_typica-0.2.2 → module_typica-0.2.3}/typica/metadata.py +17 -6
- module_typica-0.2.3/typica/modules/cclickhouse.py +67 -0
- module_typica-0.2.3/typica/modules/pmongo.py +70 -0
- module_typica-0.2.3/typica/modules/psycopg.py +76 -0
- module_typica-0.2.3/typica/modules/psycopg_alchemy.py +83 -0
- module_typica-0.2.3/typica/modules/redis.py +165 -0
- {module_typica-0.2.2 → module_typica-0.2.3}/typica/utils/enums.py +9 -8
- {module_typica-0.2.2 → module_typica-0.2.3}/typica/__init__.py +0 -0
- {module_typica-0.2.2 → module_typica-0.2.3}/typica/base.py +0 -0
- {module_typica-0.2.2 → module_typica-0.2.3}/typica/response.py +0 -0
- {module_typica-0.2.2 → module_typica-0.2.3}/typica/utils/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: module-typica
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Standard Pydantic usages & utilities
|
|
5
5
|
Author: Oktapian
|
|
6
6
|
Author-email: oktapian@jkt1.ebdesk.com
|
|
@@ -12,15 +12,15 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
12
12
|
Requires-Dist: deprecated (>=1.2.14,<2.0.0)
|
|
13
13
|
Requires-Dist: pydantic (>=2.9.2,<3.0.0)
|
|
14
14
|
Requires-Dist: pydantic-settings (>=2.6.1,<3.0.0)
|
|
15
|
-
Requires-Dist: tomli (>=2.1.0,<3.0.0)
|
|
16
15
|
Description-Content-Type: text/markdown
|
|
17
16
|
|
|
18
17
|
# Description
|
|
19
|
-
[](https://www.python.org/downloads/release/python-3100/)
|
|
20
|
-
[](https://pydantic.dev)
|
|
21
|
-
|
|
22
18
|
This is a standardized model library that uses the pydantic library, which is often used in work, especially in database connection, parameter, or response in service, and other utilities. This repository provides a standardized model that can be used in various scenarios. It aims to simplify the process of defining and validating models in Python applications.
|
|
23
19
|
|
|
20
|
+
## Usages
|
|
21
|
+
there are several use cases that can be implemented using this library, such as some of the examples below
|
|
22
|
+
|
|
23
|
+
|
|
24
24
|
|
|
25
25
|
## Contributors
|
|
26
26
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Description
|
|
2
|
-
[](https://www.python.org/downloads/release/python-3100/)
|
|
3
|
-
[](https://pydantic.dev)
|
|
4
|
-
|
|
5
2
|
This is a standardized model library that uses the pydantic library, which is often used in work, especially in database connection, parameter, or response in service, and other utilities. This repository provides a standardized model that can be used in various scenarios. It aims to simplify the process of defining and validating models in Python applications.
|
|
6
3
|
|
|
4
|
+
## Usages
|
|
5
|
+
there are several use cases that can be implemented using this library, such as some of the examples below
|
|
6
|
+
|
|
7
|
+
|
|
7
8
|
|
|
8
9
|
## Contributors
|
|
9
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "module-typica"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.3"
|
|
4
4
|
description = "Standard Pydantic usages & utilities"
|
|
5
5
|
authors = ["Oktapian <oktapian@jkt1.ebdesk.com>"]
|
|
6
6
|
readme = "Readme.md"
|
|
@@ -14,12 +14,28 @@ venv = ".venv"
|
|
|
14
14
|
python = "^3.10"
|
|
15
15
|
pydantic = "^2.9.2"
|
|
16
16
|
pydantic-settings = "^2.6.1"
|
|
17
|
-
tomli = "^2.1.0"
|
|
18
17
|
deprecated = "^1.2.14"
|
|
19
18
|
|
|
20
19
|
[tool.poetry.group.dev.dependencies]
|
|
21
20
|
faker = "^25.3.0"
|
|
22
21
|
|
|
22
|
+
|
|
23
|
+
[tool.poetry.group.postgresql.dependencies]
|
|
24
|
+
psycopg2-binary = "^2.9.10"
|
|
25
|
+
sqlalchemy = "^2.0.36"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
[tool.poetry.group.mongo.dependencies]
|
|
29
|
+
pymongo = "^4.10.1"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
[tool.poetry.group.clickhouse.dependencies]
|
|
33
|
+
clickhouse-connect = "^0.8.7"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
[tool.poetry.group.redis.dependencies]
|
|
37
|
+
redis = "^5.2.0"
|
|
38
|
+
|
|
23
39
|
[build-system]
|
|
24
40
|
requires = ["poetry-core"]
|
|
25
41
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -4,13 +4,11 @@ from typing import Optional
|
|
|
4
4
|
from pydantic import BaseModel, Field, model_validator
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
class EndpointMeta(BaseModel):
|
|
9
8
|
host: Optional[str] = Field("localhost", description="Connection host")
|
|
10
9
|
port: Optional[str | int] = Field(8000, description="Connection port")
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
|
|
14
12
|
class AuthMeta(BaseModel):
|
|
15
13
|
username: Optional[str] = Field(None, description="Database username")
|
|
16
14
|
password: Optional[str] = Field(None, description="Database password")
|
|
@@ -23,7 +21,6 @@ class URIConnectionMeta(BaseModel):
|
|
|
23
21
|
class DBConnectionMeta(EndpointMeta, AuthMeta, URIConnectionMeta):
|
|
24
22
|
database: Optional[str] = Field(None, description="Database name")
|
|
25
23
|
|
|
26
|
-
|
|
27
24
|
def uri_string(self, base: str = "http", with_db: bool = True) -> str:
|
|
28
25
|
"""
|
|
29
26
|
Return a URI string for the database connection.
|
|
@@ -39,7 +36,6 @@ class DBConnectionMeta(EndpointMeta, AuthMeta, URIConnectionMeta):
|
|
|
39
36
|
return f"{base}://{meta}/{self.database if with_db else ''}"
|
|
40
37
|
return ""
|
|
41
38
|
|
|
42
|
-
|
|
43
39
|
@model_validator(mode="after")
|
|
44
40
|
def extract_uri(self):
|
|
45
41
|
if self.uri:
|
|
@@ -63,8 +59,11 @@ class DBConnectionMeta(EndpointMeta, AuthMeta, URIConnectionMeta):
|
|
|
63
59
|
self.port = int(self.port)
|
|
64
60
|
return self
|
|
65
61
|
|
|
62
|
+
|
|
66
63
|
class ClusterConnectionMeta(AuthMeta, URIConnectionMeta):
|
|
67
|
-
cluster_uri: Optional[list[EndpointMeta]]
|
|
64
|
+
cluster_uri: Optional[list[EndpointMeta]] = Field(
|
|
65
|
+
[], description="List of clusters endpoint"
|
|
66
|
+
)
|
|
68
67
|
database: Optional[str] = Field(None, description="Database name")
|
|
69
68
|
|
|
70
69
|
def uri_string(self, base: str = "http", with_db: bool = True) -> str:
|
|
@@ -81,7 +80,6 @@ class ClusterConnectionMeta(AuthMeta, URIConnectionMeta):
|
|
|
81
80
|
return f"{base}://{self.username}:{self.password}@{meta}/{self.database if with_db else ''}"
|
|
82
81
|
return f"{base}://{meta}/{self.database if with_db else ''}"
|
|
83
82
|
return ""
|
|
84
|
-
|
|
85
83
|
|
|
86
84
|
@model_validator(mode="after")
|
|
87
85
|
def extract_uri(self):
|
|
@@ -103,7 +101,9 @@ class ClusterConnectionMeta(AuthMeta, URIConnectionMeta):
|
|
|
103
101
|
cluster_uri = []
|
|
104
102
|
for cluster in raw_clusters.split(","):
|
|
105
103
|
hostData = re.split(r"\:", cluster)
|
|
106
|
-
cluster_uri.append(
|
|
104
|
+
cluster_uri.append(
|
|
105
|
+
EndpointMeta(host=hostData[0], port=int(hostData[1]))
|
|
106
|
+
)
|
|
107
107
|
self.cluster_uri = cluster_uri
|
|
108
108
|
else:
|
|
109
109
|
self.username, self.password, self.host, self.port = re.split(
|
|
@@ -122,7 +122,6 @@ class S3ConnectionMeta(EndpointMeta):
|
|
|
122
122
|
bucket: str = Field(..., description="S3 bucket name")
|
|
123
123
|
base_path: Optional[str] = Field("/", description="S3 base path")
|
|
124
124
|
|
|
125
|
-
|
|
126
125
|
@property
|
|
127
126
|
def json_meta(self) -> dict:
|
|
128
127
|
"""
|
|
@@ -134,4 +133,8 @@ class S3ConnectionMeta(EndpointMeta):
|
|
|
134
133
|
"endpoint_url": f"http://{self.host}:{self.port}",
|
|
135
134
|
"key": self.access_key,
|
|
136
135
|
"secret": self.secret_key,
|
|
137
|
-
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class RedisConnectionMeta(EndpointMeta, AuthMeta):
|
|
140
|
+
database: int = Field(..., description="Database name")
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from pydantic import BaseModel, Field
|
|
@@ -16,6 +15,17 @@ class SchemaMeta(BaseModel):
|
|
|
16
15
|
field_hide: Optional[bool] = Field(False, description="Hide field")
|
|
17
16
|
|
|
18
17
|
|
|
18
|
+
class SchemaRawMeta(SchemaMeta):
|
|
19
|
+
regional_field: Optional[str] = Field(None, description="Regional field")
|
|
20
|
+
none_percentage: Optional[float] = Field(
|
|
21
|
+
0.0, description="Percentage of null / none values"
|
|
22
|
+
)
|
|
23
|
+
unique_value: Optional[list[str]] = Field(
|
|
24
|
+
None, description="Unique values in field"
|
|
25
|
+
)
|
|
26
|
+
describe_field: Optional[str] = Field(None, description="Describe field")
|
|
27
|
+
|
|
28
|
+
|
|
19
29
|
class SimplifieMetadata(BaseModel):
|
|
20
30
|
id: str = Field(..., description="Identifier for the metadata")
|
|
21
31
|
|
|
@@ -32,7 +42,9 @@ class SimplifieMetadata(BaseModel):
|
|
|
32
42
|
sub_category: Optional[str] = Field(None)
|
|
33
43
|
|
|
34
44
|
# ? Schemas
|
|
35
|
-
schemas: list[SchemaMeta] = Field(
|
|
45
|
+
schemas: list[SchemaMeta] = Field(
|
|
46
|
+
..., description="Description of all fields in data"
|
|
47
|
+
)
|
|
36
48
|
|
|
37
49
|
# ? Database
|
|
38
50
|
database_access: DBConnectionMeta | ClusterConnectionMeta
|
|
@@ -65,10 +77,9 @@ class FullMetadata(SimplifieMetadata):
|
|
|
65
77
|
|
|
66
78
|
# ? Data lake
|
|
67
79
|
# * Use case: bronze
|
|
68
|
-
lake_access: Optional[
|
|
69
|
-
|
|
70
|
-
)
|
|
80
|
+
lake_access: Optional[
|
|
81
|
+
S3ConnectionMeta | DBConnectionMeta | ClusterConnectionMeta
|
|
82
|
+
] = Field(None, description="Data lake access")
|
|
71
83
|
lake_meta_path: Optional[str] = Field(None, description="Data lake metadata path")
|
|
72
84
|
lake_data_path: Optional[str] = Field(None, description="Data lake data path")
|
|
73
85
|
lake_data_format: Optional[str] = Field(None, description="Data lake data format")
|
|
74
|
-
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from clickhouse_connect import get_client
|
|
2
|
+
from clickhouse_connect.driver.client import Client
|
|
3
|
+
|
|
4
|
+
from typica.connection import DBConnectionMeta
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CHConnector:
|
|
8
|
+
|
|
9
|
+
_meta: DBConnectionMeta
|
|
10
|
+
_client: Client
|
|
11
|
+
|
|
12
|
+
def __init__(self, meta: DBConnectionMeta) -> None:
|
|
13
|
+
"""
|
|
14
|
+
Initialize the ClickHouse connector with the given connection metadata.
|
|
15
|
+
|
|
16
|
+
:param meta: The metadata of the database connection.
|
|
17
|
+
:type meta: DBConnectionMeta
|
|
18
|
+
"""
|
|
19
|
+
self._meta = meta
|
|
20
|
+
|
|
21
|
+
def __enter__(self) -> "CHConnector":
|
|
22
|
+
"""
|
|
23
|
+
Connect to the ClickHouse server and return the connection object.
|
|
24
|
+
|
|
25
|
+
:return: The connection object.
|
|
26
|
+
:rtype: CHConnector
|
|
27
|
+
:raises ValueError: If the connection to the ClickHouse server fails.
|
|
28
|
+
"""
|
|
29
|
+
self.connect()
|
|
30
|
+
return self
|
|
31
|
+
|
|
32
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Close the connection to the ClickHouse server.
|
|
35
|
+
|
|
36
|
+
This method is called when the context manager exits its scope.
|
|
37
|
+
"""
|
|
38
|
+
self.close()
|
|
39
|
+
|
|
40
|
+
def connect(self) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Establish a connection to the ClickHouse server.
|
|
43
|
+
|
|
44
|
+
:raises ValueError: If the connection to the ClickHouse server fails.
|
|
45
|
+
:raises Exception: If any other error occurs during the connection.
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
self._client = get_client(
|
|
49
|
+
host=str(self._meta.host),
|
|
50
|
+
port=int(self._meta.port), # type: ignore
|
|
51
|
+
user=self._meta.username,
|
|
52
|
+
password=self._meta.password
|
|
53
|
+
or "", # cause get_client doesn't support empty password
|
|
54
|
+
database=str(self._meta.database),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
except Exception as e:
|
|
58
|
+
raise e
|
|
59
|
+
|
|
60
|
+
def close(self) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Close the connection to the ClickHouse server.
|
|
63
|
+
|
|
64
|
+
This method is a no-op if the connection is already closed.
|
|
65
|
+
"""
|
|
66
|
+
if self._client:
|
|
67
|
+
self._client.close()
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from pymongo import MongoClient
|
|
2
|
+
from pymongo.database import Database
|
|
3
|
+
from pymongo.errors import NetworkTimeout, ExecutionTimeout
|
|
4
|
+
|
|
5
|
+
from typica.connection import DBConnectionMeta
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MongoConnector:
|
|
9
|
+
|
|
10
|
+
_meta: DBConnectionMeta
|
|
11
|
+
_client: MongoClient
|
|
12
|
+
_db: Database
|
|
13
|
+
|
|
14
|
+
def __init__(self, meta: DBConnectionMeta) -> None:
|
|
15
|
+
"""
|
|
16
|
+
Initialize the Mongo connector with the given connection metadata.
|
|
17
|
+
|
|
18
|
+
:param meta: The metadata of the database connection.
|
|
19
|
+
:type meta: DBConnectionMeta
|
|
20
|
+
"""
|
|
21
|
+
self._meta = meta
|
|
22
|
+
if not self._meta.uri:
|
|
23
|
+
self._meta.uri = self._meta.uri_string(base="mongodb", with_db=False)
|
|
24
|
+
|
|
25
|
+
def __enter__(self):
|
|
26
|
+
"""
|
|
27
|
+
Connect to the MongoDB server and return the connection object.
|
|
28
|
+
|
|
29
|
+
:return: The connection object.
|
|
30
|
+
:rtype: MongoConnector
|
|
31
|
+
:raises ValueError: If the connection to the MongoDB server fails.
|
|
32
|
+
"""
|
|
33
|
+
self.connect()
|
|
34
|
+
if self._client is None:
|
|
35
|
+
raise ValueError("Mongo not connected.")
|
|
36
|
+
return self
|
|
37
|
+
|
|
38
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Close the connection to the MongoDB server.
|
|
41
|
+
|
|
42
|
+
This method is called when the context manager exits its scope.
|
|
43
|
+
"""
|
|
44
|
+
self.close()
|
|
45
|
+
|
|
46
|
+
def connect(self, **kwargs) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Establish a connection to the MongoDB server.
|
|
49
|
+
|
|
50
|
+
:param kwargs: Additional keyword arguments for MongoClient.
|
|
51
|
+
:raises ValueError: If the connection to the MongoDB server fails.
|
|
52
|
+
:raises Exception: If any other error occurs during the connection.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
self._client = MongoClient(self._meta.uri, **kwargs)
|
|
57
|
+
self._db = self._client[str(self._meta.database)]
|
|
58
|
+
except (NetworkTimeout, ExecutionTimeout):
|
|
59
|
+
raise ValueError("Mongo connection timed out.")
|
|
60
|
+
except Exception as e:
|
|
61
|
+
raise e
|
|
62
|
+
|
|
63
|
+
def close(self) -> None:
|
|
64
|
+
"""
|
|
65
|
+
Close the connection to the MongoDB server.
|
|
66
|
+
|
|
67
|
+
This method is a no-op if the connection is already closed.
|
|
68
|
+
"""
|
|
69
|
+
if self._client:
|
|
70
|
+
self._client.close()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import psycopg2
|
|
2
|
+
|
|
3
|
+
from psycopg2.extensions import connection, cursor
|
|
4
|
+
from psycopg2.errors import (
|
|
5
|
+
IdleSessionTimeout,
|
|
6
|
+
IdleInTransactionSessionTimeout,
|
|
7
|
+
ConnectionFailure,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from typica.connection import DBConnectionMeta
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PostgreConnector:
|
|
14
|
+
|
|
15
|
+
_meta: DBConnectionMeta
|
|
16
|
+
_conn: connection
|
|
17
|
+
_cursor: cursor
|
|
18
|
+
|
|
19
|
+
def __init__(self, meta: DBConnectionMeta) -> None:
|
|
20
|
+
"""
|
|
21
|
+
Initialize the Postgre connector with the given connection metadata.
|
|
22
|
+
|
|
23
|
+
:param meta: The metadata of the database connection.
|
|
24
|
+
:type meta: DBConnectionMeta
|
|
25
|
+
"""
|
|
26
|
+
self._meta = meta
|
|
27
|
+
|
|
28
|
+
def __enter__(self) -> "PostgreConnector":
|
|
29
|
+
"""
|
|
30
|
+
Connect to the PostgreSQL server and return the connection object.
|
|
31
|
+
|
|
32
|
+
:return: The connection object.
|
|
33
|
+
:rtype: PostgreConnector
|
|
34
|
+
:raises ValueError: If the connection to the PostgreSQL server fails.
|
|
35
|
+
"""
|
|
36
|
+
self.connect()
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
def __exit__(self, exc_type, exc_value, exc_traceback) -> None:
|
|
40
|
+
self.close()
|
|
41
|
+
|
|
42
|
+
def connect(self, **kwargs) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Establish a connection to the PostgreSQL server.
|
|
45
|
+
|
|
46
|
+
:param kwargs: Additional keyword arguments for psycopg2.connect.
|
|
47
|
+
:raises ValueError: If the connection to the PostgreSQL server fails.
|
|
48
|
+
:raises Exception: If any other error occurs during the connection.
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
self._conn = psycopg2.connect(
|
|
52
|
+
dbname=self._meta.database,
|
|
53
|
+
user=self._meta.username,
|
|
54
|
+
password=self._meta.password,
|
|
55
|
+
host=self._meta.host,
|
|
56
|
+
port=self._meta.port,
|
|
57
|
+
**kwargs
|
|
58
|
+
)
|
|
59
|
+
self._cursor = self._conn.cursor()
|
|
60
|
+
except ConnectionFailure:
|
|
61
|
+
raise ValueError("PostgreSQL connection failed.")
|
|
62
|
+
except (IdleInTransactionSessionTimeout, IdleSessionTimeout):
|
|
63
|
+
raise ValueError("Session timed out.")
|
|
64
|
+
except Exception as e:
|
|
65
|
+
raise e
|
|
66
|
+
|
|
67
|
+
def close(self) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Close the connection to the PostgreSQL server.
|
|
70
|
+
|
|
71
|
+
This method is a no-op if the connection is already closed.
|
|
72
|
+
"""
|
|
73
|
+
if self._cursor:
|
|
74
|
+
self._cursor.close()
|
|
75
|
+
if self._conn:
|
|
76
|
+
self._conn.close()
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from sqlalchemy import Engine, URL, Connection, create_engine, text, CursorResult
|
|
2
|
+
from sqlalchemy.exc import TimeoutError
|
|
3
|
+
|
|
4
|
+
from typica.connection import DBConnectionMeta
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PostgreConnector:
|
|
8
|
+
|
|
9
|
+
_meta: DBConnectionMeta
|
|
10
|
+
_engine: Engine
|
|
11
|
+
_conn: Connection
|
|
12
|
+
|
|
13
|
+
def __init__(self, meta: DBConnectionMeta) -> None:
|
|
14
|
+
"""
|
|
15
|
+
Initialize the Postgre connector with the given connection metadata.
|
|
16
|
+
|
|
17
|
+
:param meta: The metadata of the database connection.
|
|
18
|
+
:type meta: DBConnectionMeta
|
|
19
|
+
"""
|
|
20
|
+
self._meta = meta
|
|
21
|
+
|
|
22
|
+
def __enter__(self) -> Connection:
|
|
23
|
+
"""
|
|
24
|
+
Connect to the PostgreSQL server and return the connection object.
|
|
25
|
+
|
|
26
|
+
:return: The connection object.
|
|
27
|
+
:rtype: Connection
|
|
28
|
+
:raises ValueError: If the connection to the PostgreSQL server fails.
|
|
29
|
+
"""
|
|
30
|
+
self.connect()
|
|
31
|
+
return self._conn
|
|
32
|
+
|
|
33
|
+
def __exit__(self, exc_type, exc_value, exc_traceback) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Close the connection to the PostgreSQL server.
|
|
36
|
+
|
|
37
|
+
This method is called when the context manager exits its scope.
|
|
38
|
+
"""
|
|
39
|
+
self.close()
|
|
40
|
+
|
|
41
|
+
def execute_text(self, sql: str) -> CursorResult:
|
|
42
|
+
try:
|
|
43
|
+
res = self._conn.execute(text(sql))
|
|
44
|
+
return res
|
|
45
|
+
except Exception as e:
|
|
46
|
+
raise e
|
|
47
|
+
|
|
48
|
+
def connect(self) -> Connection:
|
|
49
|
+
"""
|
|
50
|
+
Establish a connection to the PostgreSQL server.
|
|
51
|
+
|
|
52
|
+
:return: The connection object.
|
|
53
|
+
:rtype: Connection
|
|
54
|
+
:raises ValueError: If the connection to the PostgreSQL server fails.
|
|
55
|
+
:raises Exception: If any other error occurs during the connection.
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
self._engine = create_engine(
|
|
59
|
+
URL.create(
|
|
60
|
+
drivername="postgresql",
|
|
61
|
+
username=self._meta.username,
|
|
62
|
+
password=self._meta.password,
|
|
63
|
+
host=self._meta.host,
|
|
64
|
+
port=int(self._meta.port), # type: ignore
|
|
65
|
+
database=self._meta.database,
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
self._conn = self._engine.connect()
|
|
69
|
+
|
|
70
|
+
return self._conn
|
|
71
|
+
except TimeoutError:
|
|
72
|
+
raise ValueError("PostgreSQL connection timed out.")
|
|
73
|
+
except Exception as e:
|
|
74
|
+
raise e
|
|
75
|
+
|
|
76
|
+
def close(self) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Close the connection to the PostgreSQL server.
|
|
79
|
+
|
|
80
|
+
This method is a no-op if the connection is already closed.
|
|
81
|
+
"""
|
|
82
|
+
if self._conn:
|
|
83
|
+
self._conn.close()
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from redis import Redis
|
|
2
|
+
from redis.asyncio import Redis as AsyncRedis
|
|
3
|
+
from redis.exceptions import TimeoutError
|
|
4
|
+
|
|
5
|
+
from typica.connection import RedisConnectionMeta
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RedisConnector:
|
|
9
|
+
|
|
10
|
+
_meta: RedisConnectionMeta
|
|
11
|
+
_client: Redis
|
|
12
|
+
|
|
13
|
+
def __init__(self, meta: RedisConnectionMeta) -> None:
|
|
14
|
+
"""
|
|
15
|
+
Initialize the Redis connector with the given connection metadata.
|
|
16
|
+
|
|
17
|
+
:param meta: The metadata of the database connection.
|
|
18
|
+
:type meta: RedisConnectionMeta
|
|
19
|
+
"""
|
|
20
|
+
self._meta = meta
|
|
21
|
+
|
|
22
|
+
def __enter__(self):
|
|
23
|
+
"""
|
|
24
|
+
Connect to the Redis server and return the connection object.
|
|
25
|
+
|
|
26
|
+
:return: The connection object.
|
|
27
|
+
:rtype: RedisConnector
|
|
28
|
+
:raises ValueError: If the connection to the Redis server fails.
|
|
29
|
+
"""
|
|
30
|
+
self.connect()
|
|
31
|
+
if self._client is None:
|
|
32
|
+
raise ValueError("Redis not connected.")
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
def __call__(self, *args, **kwds) -> bool:
|
|
36
|
+
"""
|
|
37
|
+
Check if the connection is already established.
|
|
38
|
+
|
|
39
|
+
:return: True if the connection is available, False otherwise.
|
|
40
|
+
:rtype: bool
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
if self._client is None:
|
|
44
|
+
raise ValueError("Redis not connected.")
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
48
|
+
"""
|
|
49
|
+
Close the connection to the Redis server.
|
|
50
|
+
|
|
51
|
+
This method is called when the context manager exits its scope.
|
|
52
|
+
"""
|
|
53
|
+
self.close()
|
|
54
|
+
|
|
55
|
+
def connect(self, other_database: int | None = None) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Establish a connection to the Redis server.
|
|
58
|
+
|
|
59
|
+
:param other_database: The ID of an alternative database to connect to.
|
|
60
|
+
If not provided, the default database ID will be used.
|
|
61
|
+
:type other_database: int | None
|
|
62
|
+
:raises ValueError: If the connection to the Redis server fails.
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
|
|
66
|
+
self._client = Redis(
|
|
67
|
+
host=str(self._meta.host),
|
|
68
|
+
port=int(self._meta.port), # type: ignore
|
|
69
|
+
username=self._meta.username,
|
|
70
|
+
password=self._meta.password,
|
|
71
|
+
db=other_database if other_database else self._meta.database,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
except TimeoutError:
|
|
75
|
+
raise ValueError("Redis connection timed out.")
|
|
76
|
+
except Exception as e:
|
|
77
|
+
raise e
|
|
78
|
+
|
|
79
|
+
def close(self) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Close the connection to the Redis server.
|
|
82
|
+
|
|
83
|
+
This method is a no-op if the connection is already closed.
|
|
84
|
+
"""
|
|
85
|
+
if self._client:
|
|
86
|
+
self._client.close()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class AsyncRedisConnector:
|
|
90
|
+
|
|
91
|
+
_meta: RedisConnectionMeta
|
|
92
|
+
_client: AsyncRedis
|
|
93
|
+
|
|
94
|
+
def __init__(self, meta: RedisConnectionMeta) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Initialize the Redis connector with the given connection metadata.
|
|
97
|
+
|
|
98
|
+
:param meta: The metadata of the database connection.
|
|
99
|
+
:type meta: RedisConnectionMeta
|
|
100
|
+
"""
|
|
101
|
+
self._meta = meta
|
|
102
|
+
|
|
103
|
+
async def __enter__(self):
|
|
104
|
+
"""
|
|
105
|
+
Connect to the Redis server and return the connection object.
|
|
106
|
+
|
|
107
|
+
:return: The connection object.
|
|
108
|
+
:rtype: RedisConnector
|
|
109
|
+
:raises ValueError: If the connection to the Redis server fails.
|
|
110
|
+
"""
|
|
111
|
+
await self.connect()
|
|
112
|
+
if self._client is None:
|
|
113
|
+
raise ValueError("Redis not connected.")
|
|
114
|
+
return self
|
|
115
|
+
|
|
116
|
+
async def __call__(self, *args, **kwds) -> bool:
|
|
117
|
+
"""
|
|
118
|
+
Check if the connection is already established.
|
|
119
|
+
|
|
120
|
+
:return: True if the connection is available, False otherwise.
|
|
121
|
+
:rtype: bool
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
if self._client is None:
|
|
125
|
+
raise ValueError("Redis not connected.")
|
|
126
|
+
return True
|
|
127
|
+
|
|
128
|
+
async def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
129
|
+
"""
|
|
130
|
+
Close the connection to the Redis server.
|
|
131
|
+
|
|
132
|
+
This method is called when the context manager exits its scope.
|
|
133
|
+
"""
|
|
134
|
+
await self.close()
|
|
135
|
+
|
|
136
|
+
async def connect(self, other_database: int | None = None) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Establish a connection to the Redis server.
|
|
139
|
+
|
|
140
|
+
:param other_database: The alternative database name to connect to.
|
|
141
|
+
:raises ValueError: If the connection to the Redis server fails.
|
|
142
|
+
:raises Exception: If any other error occurs during the connection.
|
|
143
|
+
"""
|
|
144
|
+
try:
|
|
145
|
+
|
|
146
|
+
self._client = AsyncRedis(
|
|
147
|
+
host=str(self._meta.host),
|
|
148
|
+
port=int(self._meta.port), # type: ignore
|
|
149
|
+
username=self._meta.username,
|
|
150
|
+
password=self._meta.password,
|
|
151
|
+
db=other_database if other_database else self._meta.database,
|
|
152
|
+
)
|
|
153
|
+
except TimeoutError:
|
|
154
|
+
raise ValueError("Redis connection timed out.")
|
|
155
|
+
except Exception as e:
|
|
156
|
+
raise e
|
|
157
|
+
|
|
158
|
+
async def close(self) -> None:
|
|
159
|
+
"""
|
|
160
|
+
Close the connection to the Redis server.
|
|
161
|
+
|
|
162
|
+
This method is a no-op if the connection is already closed.
|
|
163
|
+
"""
|
|
164
|
+
if self._client:
|
|
165
|
+
await self._client.close()
|
|
@@ -42,6 +42,7 @@ class EnumV2(Enum):
|
|
|
42
42
|
"""
|
|
43
43
|
return self._description_
|
|
44
44
|
|
|
45
|
+
|
|
45
46
|
class Operator(EnumV2):
|
|
46
47
|
equal = ("eq", "value is equals to")
|
|
47
48
|
unequal = ("ne", "value isn't equals to")
|
|
@@ -61,9 +62,9 @@ class FilterOption(EnumV2):
|
|
|
61
62
|
mustnt = ("mustnt", "List of filter mustn't exact")
|
|
62
63
|
should = ("should", "List of filter should exact")
|
|
63
64
|
shouldnt = ("shouldnt", "List of filter shouldn't exact")
|
|
64
|
-
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
|
|
67
|
+
class LocationLevel(EnumV2):
|
|
67
68
|
CONTINENT = ("continent", "Continent level data")
|
|
68
69
|
COUNTRY = ("country", "Country level data")
|
|
69
70
|
PROVINCE = ("province", "Province level data")
|
|
@@ -72,9 +73,9 @@ class LocationLevel(str, EnumV2):
|
|
|
72
73
|
SUBDISTRICT = ("subdistrict", "Subdistrict level data")
|
|
73
74
|
|
|
74
75
|
|
|
75
|
-
class MedallionTypes(
|
|
76
|
-
LAKE = ("lake",
|
|
77
|
-
BRONZE = ("bronze",
|
|
78
|
-
SILVER = ("silver",
|
|
79
|
-
GOLD = ("gold",
|
|
80
|
-
OTHER = ("other",
|
|
76
|
+
class MedallionTypes(EnumV2):
|
|
77
|
+
LAKE = ("lake", "Lake data")
|
|
78
|
+
BRONZE = ("bronze", "bronze level Medallion")
|
|
79
|
+
SILVER = ("silver", "silver level Medallion")
|
|
80
|
+
GOLD = ("gold", "gold level Medallion")
|
|
81
|
+
OTHER = ("other", "other than any level Medallion")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|