SCUDO 0.1.0__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.
scudo-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: SCUDO
3
+ Version: 0.1.0
4
+ Summary: Shared Core Utilities for DataHub Operations
5
+ Author: CNIC
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: pandas
8
+ Requires-Dist: adbc-driver-manager
9
+ Requires-Dist: adbc-driver-flightsql
scudo-0.1.0/README.md ADDED
@@ -0,0 +1,4 @@
1
+ # SCUDO - Shared Core Utilities for DataHub Operations
2
+
3
+
4
+
@@ -0,0 +1,19 @@
1
+ [project]
2
+ name = "SCUDO"
3
+ version = "0.1.0"
4
+ description = "Shared Core Utilities for DataHub Operations"
5
+ authors = [{ name = "CNIC" }]
6
+ requires-python = ">=3.12"
7
+
8
+ dependencies = [
9
+ "pandas",
10
+ "adbc-driver-manager",
11
+ "adbc-driver-flightsql"
12
+ ]
13
+
14
+ [build-system]
15
+ requires = ["setuptools"]
16
+ build-backend = "setuptools.build_meta"
17
+
18
+ [tool.setuptools.packages.find]
19
+ where = ["src"]
scudo-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: SCUDO
3
+ Version: 0.1.0
4
+ Summary: Shared Core Utilities for DataHub Operations
5
+ Author: CNIC
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: pandas
8
+ Requires-Dist: adbc-driver-manager
9
+ Requires-Dist: adbc-driver-flightsql
@@ -0,0 +1,19 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/SCUDO.egg-info/PKG-INFO
4
+ src/SCUDO.egg-info/SOURCES.txt
5
+ src/SCUDO.egg-info/dependency_links.txt
6
+ src/SCUDO.egg-info/requires.txt
7
+ src/SCUDO.egg-info/top_level.txt
8
+ src/cudo/__init__.py
9
+ src/cudo/doris/__init__.py
10
+ src/cudo/doris/client.py
11
+ src/cudo/doris/pymysql.py
12
+ src/cudo/minio/__init__.py
13
+ src/cudo/minio/minio.py
14
+ src/cudo/spark/__init__.py
15
+ src/cudo/spark/spark.py
16
+ src/cudo/utils/__init__.py
17
+ src/cudo/utils/clinic.py
18
+ src/cudo/utils/logging.py
19
+ src/cudo/utils/vcf.py
@@ -0,0 +1,3 @@
1
+ pandas
2
+ adbc-driver-manager
3
+ adbc-driver-flightsql
@@ -0,0 +1 @@
1
+ cudo
File without changes
File without changes
@@ -0,0 +1,310 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ '''
5
+ # Doris Flight SQL Client (ADBC)
6
+
7
+ Python client for interacting with Apache Doris using Arrow Flight SQL via ADBC.
8
+
9
+ This class provides:
10
+ - Simple connection handling
11
+ - Query execution
12
+ - Optimized DataFrame fetching (`fetch_df`)
13
+ - Optional Arrow-based and partition-based methods
14
+ - Timing and logging utilities
15
+
16
+ ## Requirements
17
+
18
+ ```bash
19
+ pip install adbc_driver_manager adbc_driver_flightsql pandas
20
+ ```
21
+
22
+ ## Example
23
+ client = DorisFlightSQLClient(
24
+ uri="grpc://127.0.0.1:9090",
25
+ username="root",
26
+ password=""
27
+ )
28
+
29
+ df = client.query("SELECT * FROM my_table LIMIT 1000;")
30
+ print(df.head())
31
+
32
+ client.close()
33
+ '''
34
+
35
+ import adbc_driver_manager
36
+ import adbc_driver_flightsql.dbapi as flight_sql
37
+ import pandas as pd
38
+ from datetime import datetime
39
+ from typing import Optional
40
+
41
+
42
+
43
+ class DorisFlightSQLClient:
44
+ '''
45
+ Apache Doris Flight SQL client using ADBC (DB-API 2.0).
46
+ This client wraps the ADBC Flight SQL driver and provides optimized
47
+ methods for querying data into pandas DataFrames.
48
+
49
+ Parameters
50
+ ----------
51
+ uri : str
52
+ Flight SQL endpoint (e.g., "grpc://127.0.0.1:9090").
53
+
54
+ username : str
55
+ Database username.
56
+
57
+ password : str
58
+ Database password.
59
+
60
+ Attributes
61
+ ----------
62
+ conn : flight_sql.Connection
63
+ Active database connection.
64
+
65
+ cursor : flight_sql.Cursor
66
+ Cursor used for executing queries.
67
+
68
+ Notes
69
+ -----
70
+ - Uses `fetch_df()` by default for best performance.
71
+ - Compatible with Apache Doris Arrow Flight SQL service.
72
+ '''
73
+
74
+ def __init__(self, uri: str, username: str, password: str) -> None:
75
+ self.uri = uri
76
+ self.db_kwargs = {
77
+ adbc_driver_manager.DatabaseOptions.USERNAME.value: username,
78
+ adbc_driver_manager.DatabaseOptions.PASSWORD.value: password,
79
+ }
80
+
81
+ self.conn: Optional[flight_sql.Connection] = None
82
+ self.cursor: Optional[flight_sql.Cursor] = None
83
+
84
+ self._connect()
85
+
86
+
87
+ # ------------------------------------------------------------------
88
+ # Connection Handling
89
+ # ------------------------------------------------------------------
90
+
91
+ def _connect(self) -> None:
92
+ '''
93
+ Establish a connection and create a cursor.
94
+ '''
95
+ try:
96
+ self.conn = flight_sql.connect(uri=self.uri, db_kwargs=self.db_kwargs)
97
+ self.cursor = self.conn.cursor()
98
+ except Exception as e:
99
+ raise RuntimeError("Connection failed") from e
100
+
101
+ def close(self) -> None:
102
+ '''
103
+ Close cursor and connection.
104
+ '''
105
+ try:
106
+ if self.cursor:
107
+ self.cursor.close()
108
+ finally:
109
+ if self.conn:
110
+ self.conn.close()
111
+
112
+
113
+ # ------------------------------------------------------------------
114
+ # Core Query Method
115
+ # ------------------------------------------------------------------
116
+
117
+ def query(self, sql: str, params: dict | None = None) -> pd.DataFrame:
118
+ '''
119
+ Execute a SQL query and return a pandas DataFrame.
120
+
121
+ This method uses `fetch_df()` (ADBC optimized path),
122
+ which is faster than converting from Arrow manually.
123
+
124
+ Parameters
125
+ ----------
126
+ sql : str
127
+ SQL query string.
128
+
129
+ params : dict, optional
130
+ Parameters to safely inject into SQL.
131
+
132
+ Returns
133
+ -------
134
+ pandas.DataFrame
135
+ Query result as a DataFrame.
136
+
137
+ Example
138
+ -------
139
+ >>> df = client.query("SELECT * FROM table LIMIT 100;")
140
+
141
+ '''
142
+ if not self.cursor:
143
+ raise RuntimeError("Cursor is not initialized.")
144
+
145
+ sql = self._render_sql(sql, params=params)
146
+
147
+ start_time = datetime.now()
148
+
149
+ try:
150
+ self.cursor.execute(sql)
151
+ df = self.cursor.fetch_df()
152
+ except Exception as e:
153
+ raise RuntimeError("Query execution failed") from e
154
+
155
+ duration = datetime.now() - start_time
156
+
157
+ print("\n##################")
158
+ print(f"Query executed in: {duration}")
159
+ print(df.info(memory_usage="deep"))
160
+
161
+ return df
162
+
163
+
164
+ # ------------------------------------------------------------------
165
+ # Alternative Methods
166
+ # ------------------------------------------------------------------
167
+
168
+ def query_arrow(self, sql: str, params: dict | None = None) -> pd.DataFrame:
169
+ '''
170
+ Execute query using Arrow fetch, then convert to pandas.
171
+
172
+ Slower than `query()` but useful for debugging or Arrow workflows.
173
+
174
+ Parameters
175
+ ----------
176
+ sql : str
177
+ SQL query.
178
+
179
+ params : dict, optional
180
+ Parameters to safely inject into SQL.
181
+
182
+ Returns
183
+ -------
184
+ pandas.DataFrame
185
+ '''
186
+ sql = self._render_sql(sql, params=params)
187
+
188
+ start_time = datetime.now()
189
+
190
+ try:
191
+ self.cursor.execute(sql)
192
+ arrow_data = self.cursor.fetchallarrow()
193
+ df = arrow_data.to_pandas()
194
+ except Exception as e:
195
+ raise RuntimeError("Arrow query execution failed") from e
196
+
197
+ duration = datetime.now() - start_time
198
+
199
+ print("\n##################")
200
+ print(f"Arrow fetch in: {duration}, bytes: {arrow_data.nbytes}")
201
+ print(df.info(memory_usage="deep"))
202
+
203
+ return df
204
+
205
+
206
+ def query_partition(self, sql: str, params: dict | None = None) -> pd.DataFrame:
207
+ '''
208
+ Execute query using partitioned reads.
209
+
210
+ Useful for parallel processing of large datasets.
211
+
212
+ Parameters
213
+ ----------
214
+ sql : str
215
+ SQL query.
216
+
217
+ params : dict, optional
218
+ Parameters to safely inject into SQL.
219
+
220
+ Returns
221
+ -------
222
+ pandas.DataFrame
223
+ '''
224
+ sql = self._render_sql(sql, params=params)
225
+
226
+ start_time = datetime.now()
227
+
228
+ try:
229
+ partitions, schema = self.cursor.adbc_execute_partitions(sql)
230
+ # Example: read first partition (extendable to parallel processing)
231
+ self.cursor.adbc_read_partition(partitions[0])
232
+ arrow_data = self.cursor.fetchallarrow()
233
+ df = arrow_data.to_pandas()
234
+ except Exception as e:
235
+ raise RuntimeError("Partition query execution failed") from e
236
+
237
+ duration = datetime.now() - start_time
238
+
239
+ print("\n##################")
240
+ print(f"Partitions: {len(partitions)}, time: {duration}")
241
+ print(df.info(memory_usage="deep"))
242
+
243
+ return df
244
+
245
+
246
+ # ------------------------------------------------------------------
247
+ # Utility Methods
248
+ # ------------------------------------------------------------------
249
+
250
+ def _render_sql(self, sql: str, params: dict | None = None) -> str:
251
+ '''
252
+ Render SQL using simple parameter substitution.
253
+
254
+ Parameters
255
+ ----------
256
+ sql : str
257
+ SQL query with `{param}` placeholders.
258
+
259
+ params : dict, optional
260
+ Dictionary of parameters.
261
+
262
+ Returns
263
+ -------
264
+ str
265
+ Rendered SQL string.
266
+ '''
267
+ if params:
268
+ safe_params = {}
269
+ for k, v in params.items():
270
+ if isinstance(v, (int, float)):
271
+ safe_params[k] = v
272
+ elif isinstance(v, str):
273
+ safe_params[k] = "'" + v.replace("'", "''") + "'"
274
+ else:
275
+ raise ValueError(f"Unsafe parameter type for {k}: {type(v)}")
276
+ try:
277
+ return sql.format(**safe_params)
278
+ except KeyError as e:
279
+ raise ValueError(f"Missing SQL parameter: {e}") from e
280
+
281
+
282
+ def execute(self, sql: str) -> None:
283
+ '''
284
+ Execute a SQL statement without returning results.
285
+
286
+ Useful for DDL or INSERT operations.
287
+
288
+ Parameters
289
+ ----------
290
+ sql : str
291
+ '''
292
+ if not self.cursor:
293
+ raise RuntimeError("Cursor is not initialized.")
294
+
295
+ print(f"\n### Executing SQL ###\n{sql}")
296
+ self.cursor.execute(sql)
297
+
298
+
299
+ def __enter__(self):
300
+ ''' Context manager entry.'''
301
+ return self
302
+
303
+
304
+ def __exit__(self, exc_type, exc_val, exc_tb):
305
+ ''' Context manager exit (auto-close).'''
306
+ if exc_type:
307
+ print(f"[DorisFlightSQLClient] Exception: {exc_val}")
308
+ self.close()
309
+ return False # always propagate errors
310
+