src-connectors 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.
- src_connectors-0.1.0/PKG-INFO +184 -0
- src_connectors-0.1.0/README.md +129 -0
- src_connectors-0.1.0/common/.gitkeep +0 -0
- src_connectors-0.1.0/common/__init__.py +0 -0
- src_connectors-0.1.0/pyproject.toml +107 -0
- src_connectors-0.1.0/src_connectors/__init__.py +18 -0
- src_connectors-0.1.0/src_connectors/src_base/__init__.py +3 -0
- src_connectors-0.1.0/src_connectors/src_base/connector.py +31 -0
- src_connectors-0.1.0/src_connectors/src_spark/__init__.py +6 -0
- src_connectors-0.1.0/src_connectors/src_spark/configs/__init__.py +6 -0
- src_connectors-0.1.0/src_connectors/src_spark/configs/base.py +30 -0
- src_connectors-0.1.0/src_connectors/src_spark/configs/core_config.py +138 -0
- src_connectors-0.1.0/src_connectors/src_spark/configs/iceberg.py +205 -0
- src_connectors-0.1.0/src_connectors/src_spark/configs/jdbc.py +81 -0
- src_connectors-0.1.0/src_connectors/src_spark/connector.py +235 -0
- src_connectors-0.1.0/src_connectors/src_sqlserver/__init__.py +3 -0
- src_connectors-0.1.0/src_connectors/src_sqlserver/connector.py +167 -0
- src_connectors-0.1.0/variables/__init__.py +0 -0
- src_connectors-0.1.0/variables/helper.py +120 -0
- src_connectors-0.1.0/variables/spark.py +113 -0
- src_connectors-0.1.0/variables/sqlserver.py +31 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: src-connectors
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: High-performance data connectors for SQL Server, Spark, Iceberg, and JDBC.
|
|
5
|
+
Author: canh.ld
|
|
6
|
+
Requires-Python: >=3.11,<4.0
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Provides-Extra: all
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Provides-Extra: docs
|
|
15
|
+
Provides-Extra: oracle
|
|
16
|
+
Provides-Extra: postgres
|
|
17
|
+
Provides-Extra: spark
|
|
18
|
+
Provides-Extra: sqlserver
|
|
19
|
+
Provides-Extra: trino
|
|
20
|
+
Requires-Dist: mkdocs (>=1.6.0,<2.0.0) ; extra == "docs"
|
|
21
|
+
Requires-Dist: mkdocs-material (>=9.6.0,<10.0.0) ; extra == "docs"
|
|
22
|
+
Requires-Dist: mypy (>=1.17.0,<2.0.0) ; extra == "dev"
|
|
23
|
+
Requires-Dist: numpy (>=1.24.0) ; extra == "spark"
|
|
24
|
+
Requires-Dist: oracledb (>=3.2.0,<4.0.0) ; extra == "all"
|
|
25
|
+
Requires-Dist: oracledb (>=3.2.0,<4.0.0) ; extra == "oracle"
|
|
26
|
+
Requires-Dist: pandas (>=2.0.0) ; extra == "spark"
|
|
27
|
+
Requires-Dist: pandas (>=2.3.0,<3.0.0)
|
|
28
|
+
Requires-Dist: pre-commit (>=4.3.0,<5.0.0) ; extra == "dev"
|
|
29
|
+
Requires-Dist: psycopg[binary] (>=3.2.0,<4.0.0) ; extra == "all"
|
|
30
|
+
Requires-Dist: psycopg[binary] (>=3.2.0,<4.0.0) ; extra == "postgres"
|
|
31
|
+
Requires-Dist: pyarrow (>=14.0.0) ; extra == "spark"
|
|
32
|
+
Requires-Dist: pyarrow (>=21.0.0,<22.0.0)
|
|
33
|
+
Requires-Dist: pydantic (>=2.11.0,<3.0.0)
|
|
34
|
+
Requires-Dist: pyodbc (==5.3.0) ; extra == "all"
|
|
35
|
+
Requires-Dist: pyodbc (==5.3.0) ; extra == "sqlserver"
|
|
36
|
+
Requires-Dist: pyspark (>=3.5.0,<4.0.0) ; extra == "all"
|
|
37
|
+
Requires-Dist: pyspark (>=3.5.0,<4.0.0) ; extra == "spark"
|
|
38
|
+
Requires-Dist: pytest (>=9.0.3,<10.0.0) ; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest-cov (>=6.2.0,<7.0.0) ; extra == "dev"
|
|
40
|
+
Requires-Dist: python-dotenv (>=1.2.2,<2.0.0)
|
|
41
|
+
Requires-Dist: requests (>=2.33.1,<3.0.0)
|
|
42
|
+
Requires-Dist: ruff (>=0.12.0,<1.0.0) ; extra == "dev"
|
|
43
|
+
Requires-Dist: sqlalchemy (==2.0.49) ; extra == "sqlserver"
|
|
44
|
+
Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0) ; extra == "all"
|
|
45
|
+
Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0) ; extra == "oracle"
|
|
46
|
+
Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0) ; extra == "postgres"
|
|
47
|
+
Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0) ; extra == "trino"
|
|
48
|
+
Requires-Dist: structlog (>=25.4.0,<26.0.0)
|
|
49
|
+
Requires-Dist: tenacity (>=9.1.0,<10.0.0)
|
|
50
|
+
Requires-Dist: tqdm (>=4.66.0,<5.0.0)
|
|
51
|
+
Requires-Dist: trino (>=0.336.0,<1.0.0) ; extra == "all"
|
|
52
|
+
Requires-Dist: trino (>=0.336.0,<1.0.0) ; extra == "trino"
|
|
53
|
+
Description-Content-Type: text/markdown
|
|
54
|
+
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="https://img.icons8.com/dt/200/database-connectivity.png" alt="src-connectors Logo" width="160" />
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
<h1 align="center">src-connectors</h1>
|
|
60
|
+
|
|
61
|
+
<p align="center">
|
|
62
|
+
<strong>The ultimate library for high-speed data connectivity, querying, and reading.</strong>
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
<p align="center">
|
|
66
|
+
<a href="#"><img src="https://img.shields.io/badge/version-0.1.0-blue.svg" alt="Version"></a>
|
|
67
|
+
<a href="#"><img src="https://img.shields.io/badge/python-3.11+-green.svg" alt="Python Versions"></a>
|
|
68
|
+
<a href="#"><img src="https://img.shields.io/badge/license-MIT-orange.svg" alt="License"></a>
|
|
69
|
+
</p>
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 📖 What is src-connectors?
|
|
74
|
+
|
|
75
|
+
**src-connectors** is a professional-grade Python library designed to simplify the complexity of connecting to, querying, and reading data from multiple sources. It provides a standardized, high-performance interface for data engineers and analysts to pull data into their applications without worrying about underlying driver intricacies or memory management.
|
|
76
|
+
|
|
77
|
+
Whether you are fetching a small sample for exploration or streaming billions of rows for a production pipeline, **src-connectors** ensures your data access is reliable, secure, and fast.
|
|
78
|
+
|
|
79
|
+
**Current Support:**
|
|
80
|
+
- **SQL Server**: Robust connectivity via `pyodbc` with support for high-speed batched reads.
|
|
81
|
+
- **Apache Spark**: Modular engine setup supporting **Iceberg** catalogs (Hadoop/REST/S3) and **JDBC** data sources.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 🚀 Getting Started
|
|
86
|
+
|
|
87
|
+
### Installation
|
|
88
|
+
|
|
89
|
+
Install `src-connectors` utilizing `pip` or `Poetry`. Choose your extras based on the platforms you need to query:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Using pip for a specific extra
|
|
93
|
+
pip install "src-connectors[spark,sqlserver]"
|
|
94
|
+
|
|
95
|
+
# Using Poetry (Recommended)
|
|
96
|
+
poetry add "src-connectors[all]"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Quick Start
|
|
100
|
+
|
|
101
|
+
1. **Querying SQL Server**: Fetch data directly into a DataFrame.
|
|
102
|
+
```python
|
|
103
|
+
from src_connectors import SQLServerConnector
|
|
104
|
+
|
|
105
|
+
connector = SQLServerConnector()
|
|
106
|
+
# Reading data into a pandas DataFrame
|
|
107
|
+
df = connector.execute_query("SELECT TOP 10 * FROM orders", output_type="dataframe")
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
2. **Reading from Iceberg (Spark Engine)**: Standardized data access for big data.
|
|
111
|
+
```python
|
|
112
|
+
from src_connectors import SparkConnector
|
|
113
|
+
|
|
114
|
+
# Initialize and configure the Iceberg catalog
|
|
115
|
+
connector = SparkConnector(spark_master="local[*]")
|
|
116
|
+
connector.configure_iceberg({"iceberg_warehouse": "prod_catalog"})
|
|
117
|
+
# --- Step 4: Execute Query using Spark SQL ---
|
|
118
|
+
# Execute a query and fetch results
|
|
119
|
+
df = connector.execute_query("SELECT * FROM prod_catalog.db.table", output_type="dataframe")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 📚 Documentation
|
|
125
|
+
|
|
126
|
+
For in-depth architectural overviews, detailed configuration settings, and complex usage examples, please refer to the unified documentation in the `docs/` folder:
|
|
127
|
+
|
|
128
|
+
- [Index Overview](docs/index.md)
|
|
129
|
+
- [SQL Server Connector Guide](docs/sqlserver.md)
|
|
130
|
+
- [Apache Spark (Iceberg & JDBC) Guide](docs/spark.md)
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 🏗 Architecture & Design
|
|
135
|
+
|
|
136
|
+
The library is built on a **Modular Connector Pattern**. Every component focuses on a specific data source while sharing a common execution interface. This decoupling allows engineers to inject custom configurations without breaking the core read/query logic.
|
|
137
|
+
|
|
138
|
+
<p align="center">
|
|
139
|
+
<strong>Execution Logic:</strong><br>
|
|
140
|
+
<code>Connector Initialization</code> → <code>Component Configuration</code> → <code>Unified Connection</code> → <code>Optimized Query Execution</code>
|
|
141
|
+
</p>
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## ✨ Key Features
|
|
146
|
+
|
|
147
|
+
- **Querying Consistency**: One standard `execute_query()` method across all connectors, supporting SQL and Spark SQL.
|
|
148
|
+
- **Optimized Data Reading**: Native support for returning DataFrames (Pandas/Spark), Lists of Dictionaries, or NumPy Arrays.
|
|
149
|
+
- **Memory-Safe Batching**: Integrated `stream=True` functionality for reading large datasets through Python Generators to prevent memory overflow.
|
|
150
|
+
- **Enterprise Configuration**: Layered settings management allowing for Environment defaults with per-query overwrites.
|
|
151
|
+
- **Security-First**: Automatic protection and masking of credentials in all logs and metadata exports.
|
|
152
|
+
- **Cloud-Ready Big Data**: Specialized support for Iceberg REST Catalogs, OAuth2, and MinIO/S3 compatible storage.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 🛠 Supported Data Sources
|
|
157
|
+
|
|
158
|
+
| Connector | Source | Driver/Engine | Role |
|
|
159
|
+
| :--- | :--- | :--- | :--- |
|
|
160
|
+
| `SQLServerConnector` | SQL Server | `pyodbc` | Query & Read |
|
|
161
|
+
| `SparkConnector` | Spark / Iceberg / JDBC | `pyspark` | Query & Big Data Read |
|
|
162
|
+
| `OracleConnector` | Oracle DB | `oracledb` | *Coming Soon* |
|
|
163
|
+
| `PostgresConnector` | PostgreSQL | `psycopg3` | *Planned* |
|
|
164
|
+
| `TrinoConnector` | Trino | `trino` | *Planned* |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 🔮 Roadmap
|
|
169
|
+
|
|
170
|
+
We are expanding **src-connectors** to become the default data access layer for all modern infrastructures:
|
|
171
|
+
|
|
172
|
+
- **Federated Query Engines**: Adding Trino and Presto support for cross-catalog querying.
|
|
173
|
+
- **Streaming Sinks**: Support for writing queried data into Kafka or RabbitMQ.
|
|
174
|
+
- **Advanced Authentication**: Native integration with AWS Secrets Manager, Azure Key Vault, and HashiCorp Vault.
|
|
175
|
+
- **Observability**: Built-in OpenTelemetry hooks to track query performance and latency.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 🤝 Contributing & License
|
|
180
|
+
|
|
181
|
+
Contributions, issues, and feature requests are welcome! Feel free to check the [issues page](#).
|
|
182
|
+
|
|
183
|
+
This project is licensed under the terms of the **MIT** license.
|
|
184
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://img.icons8.com/dt/200/database-connectivity.png" alt="src-connectors Logo" width="160" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">src-connectors</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>The ultimate library for high-speed data connectivity, querying, and reading.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="#"><img src="https://img.shields.io/badge/version-0.1.0-blue.svg" alt="Version"></a>
|
|
13
|
+
<a href="#"><img src="https://img.shields.io/badge/python-3.11+-green.svg" alt="Python Versions"></a>
|
|
14
|
+
<a href="#"><img src="https://img.shields.io/badge/license-MIT-orange.svg" alt="License"></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 📖 What is src-connectors?
|
|
20
|
+
|
|
21
|
+
**src-connectors** is a professional-grade Python library designed to simplify the complexity of connecting to, querying, and reading data from multiple sources. It provides a standardized, high-performance interface for data engineers and analysts to pull data into their applications without worrying about underlying driver intricacies or memory management.
|
|
22
|
+
|
|
23
|
+
Whether you are fetching a small sample for exploration or streaming billions of rows for a production pipeline, **src-connectors** ensures your data access is reliable, secure, and fast.
|
|
24
|
+
|
|
25
|
+
**Current Support:**
|
|
26
|
+
- **SQL Server**: Robust connectivity via `pyodbc` with support for high-speed batched reads.
|
|
27
|
+
- **Apache Spark**: Modular engine setup supporting **Iceberg** catalogs (Hadoop/REST/S3) and **JDBC** data sources.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🚀 Getting Started
|
|
32
|
+
|
|
33
|
+
### Installation
|
|
34
|
+
|
|
35
|
+
Install `src-connectors` utilizing `pip` or `Poetry`. Choose your extras based on the platforms you need to query:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Using pip for a specific extra
|
|
39
|
+
pip install "src-connectors[spark,sqlserver]"
|
|
40
|
+
|
|
41
|
+
# Using Poetry (Recommended)
|
|
42
|
+
poetry add "src-connectors[all]"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Quick Start
|
|
46
|
+
|
|
47
|
+
1. **Querying SQL Server**: Fetch data directly into a DataFrame.
|
|
48
|
+
```python
|
|
49
|
+
from src_connectors import SQLServerConnector
|
|
50
|
+
|
|
51
|
+
connector = SQLServerConnector()
|
|
52
|
+
# Reading data into a pandas DataFrame
|
|
53
|
+
df = connector.execute_query("SELECT TOP 10 * FROM orders", output_type="dataframe")
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
2. **Reading from Iceberg (Spark Engine)**: Standardized data access for big data.
|
|
57
|
+
```python
|
|
58
|
+
from src_connectors import SparkConnector
|
|
59
|
+
|
|
60
|
+
# Initialize and configure the Iceberg catalog
|
|
61
|
+
connector = SparkConnector(spark_master="local[*]")
|
|
62
|
+
connector.configure_iceberg({"iceberg_warehouse": "prod_catalog"})
|
|
63
|
+
# --- Step 4: Execute Query using Spark SQL ---
|
|
64
|
+
# Execute a query and fetch results
|
|
65
|
+
df = connector.execute_query("SELECT * FROM prod_catalog.db.table", output_type="dataframe")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 📚 Documentation
|
|
71
|
+
|
|
72
|
+
For in-depth architectural overviews, detailed configuration settings, and complex usage examples, please refer to the unified documentation in the `docs/` folder:
|
|
73
|
+
|
|
74
|
+
- [Index Overview](docs/index.md)
|
|
75
|
+
- [SQL Server Connector Guide](docs/sqlserver.md)
|
|
76
|
+
- [Apache Spark (Iceberg & JDBC) Guide](docs/spark.md)
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 🏗 Architecture & Design
|
|
81
|
+
|
|
82
|
+
The library is built on a **Modular Connector Pattern**. Every component focuses on a specific data source while sharing a common execution interface. This decoupling allows engineers to inject custom configurations without breaking the core read/query logic.
|
|
83
|
+
|
|
84
|
+
<p align="center">
|
|
85
|
+
<strong>Execution Logic:</strong><br>
|
|
86
|
+
<code>Connector Initialization</code> → <code>Component Configuration</code> → <code>Unified Connection</code> → <code>Optimized Query Execution</code>
|
|
87
|
+
</p>
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## ✨ Key Features
|
|
92
|
+
|
|
93
|
+
- **Querying Consistency**: One standard `execute_query()` method across all connectors, supporting SQL and Spark SQL.
|
|
94
|
+
- **Optimized Data Reading**: Native support for returning DataFrames (Pandas/Spark), Lists of Dictionaries, or NumPy Arrays.
|
|
95
|
+
- **Memory-Safe Batching**: Integrated `stream=True` functionality for reading large datasets through Python Generators to prevent memory overflow.
|
|
96
|
+
- **Enterprise Configuration**: Layered settings management allowing for Environment defaults with per-query overwrites.
|
|
97
|
+
- **Security-First**: Automatic protection and masking of credentials in all logs and metadata exports.
|
|
98
|
+
- **Cloud-Ready Big Data**: Specialized support for Iceberg REST Catalogs, OAuth2, and MinIO/S3 compatible storage.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 🛠 Supported Data Sources
|
|
103
|
+
|
|
104
|
+
| Connector | Source | Driver/Engine | Role |
|
|
105
|
+
| :--- | :--- | :--- | :--- |
|
|
106
|
+
| `SQLServerConnector` | SQL Server | `pyodbc` | Query & Read |
|
|
107
|
+
| `SparkConnector` | Spark / Iceberg / JDBC | `pyspark` | Query & Big Data Read |
|
|
108
|
+
| `OracleConnector` | Oracle DB | `oracledb` | *Coming Soon* |
|
|
109
|
+
| `PostgresConnector` | PostgreSQL | `psycopg3` | *Planned* |
|
|
110
|
+
| `TrinoConnector` | Trino | `trino` | *Planned* |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 🔮 Roadmap
|
|
115
|
+
|
|
116
|
+
We are expanding **src-connectors** to become the default data access layer for all modern infrastructures:
|
|
117
|
+
|
|
118
|
+
- **Federated Query Engines**: Adding Trino and Presto support for cross-catalog querying.
|
|
119
|
+
- **Streaming Sinks**: Support for writing queried data into Kafka or RabbitMQ.
|
|
120
|
+
- **Advanced Authentication**: Native integration with AWS Secrets Manager, Azure Key Vault, and HashiCorp Vault.
|
|
121
|
+
- **Observability**: Built-in OpenTelemetry hooks to track query performance and latency.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 🤝 Contributing & License
|
|
126
|
+
|
|
127
|
+
Contributions, issues, and feature requests are welcome! Feel free to check the [issues page](#).
|
|
128
|
+
|
|
129
|
+
This project is licensed under the terms of the **MIT** license.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "src-connectors"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "High-performance data connectors for SQL Server, Spark, Iceberg, and JDBC."
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "canh.ld" }
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.11,<4.0"
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
"requests>=2.33.1,<3.0.0",
|
|
13
|
+
"python-dotenv>=1.2.2,<2.0.0",
|
|
14
|
+
"tqdm>=4.66.0,<5.0.0",
|
|
15
|
+
|
|
16
|
+
# Data handling
|
|
17
|
+
"pandas>=2.3.0,<3.0.0",
|
|
18
|
+
"pyarrow>=21.0.0,<22.0.0",
|
|
19
|
+
|
|
20
|
+
# Validation / config
|
|
21
|
+
"pydantic>=2.11.0,<3.0.0",
|
|
22
|
+
|
|
23
|
+
# Retry / resiliency
|
|
24
|
+
"tenacity>=9.1.0,<10.0.0",
|
|
25
|
+
|
|
26
|
+
# Logging
|
|
27
|
+
"structlog>=25.4.0,<26.0.0"
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[tool.poetry]
|
|
31
|
+
# Giữ cấu trúc flat layout để nhận diện các module ngang hàng root
|
|
32
|
+
packages = [
|
|
33
|
+
{ include = "src_connectors" },
|
|
34
|
+
{ include = "variables" },
|
|
35
|
+
{ include = "common" }
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.optional-dependencies]
|
|
39
|
+
postgres = [
|
|
40
|
+
"psycopg[binary]>=3.2.0,<4.0.0",
|
|
41
|
+
"sqlalchemy>=2.0.0,<3.0.0"
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
trino = [
|
|
45
|
+
"trino>=0.336.0,<1.0.0",
|
|
46
|
+
"sqlalchemy>=2.0.0,<3.0.0"
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
sqlserver = [
|
|
50
|
+
"pyodbc==5.3.0",
|
|
51
|
+
"sqlalchemy==2.0.49"
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
oracle = [
|
|
55
|
+
"oracledb>=3.2.0,<4.0.0",
|
|
56
|
+
"sqlalchemy>=2.0.0,<3.0.0"
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
spark = [
|
|
60
|
+
"pyspark>=3.5.0,<4.0.0",
|
|
61
|
+
"pandas>=2.0.0",
|
|
62
|
+
"pyarrow>=14.0.0",
|
|
63
|
+
"numpy>=1.24.0"
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
# Định nghĩa group 'all' để lệnh cài đặt ban đầu không bị báo WARNING
|
|
67
|
+
all = [
|
|
68
|
+
"psycopg[binary]>=3.2.0,<4.0.0",
|
|
69
|
+
"trino>=0.336.0,<1.0.0",
|
|
70
|
+
"pyodbc==5.3.0",
|
|
71
|
+
"oracledb>=3.2.0,<4.0.0",
|
|
72
|
+
"pyspark>=3.5.0,<4.0.0",
|
|
73
|
+
"sqlalchemy>=2.0.0,<3.0.0"
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
dev = [
|
|
77
|
+
"pytest>=9.0.3,<10.0.0",
|
|
78
|
+
"pytest-cov>=6.2.0,<7.0.0",
|
|
79
|
+
"ruff>=0.12.0,<1.0.0",
|
|
80
|
+
"mypy>=1.17.0,<2.0.0",
|
|
81
|
+
"pre-commit>=4.3.0,<5.0.0"
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
docs = [
|
|
85
|
+
"mkdocs>=1.6.0,<2.0.0",
|
|
86
|
+
"mkdocs-material>=9.6.0,<10.0.0"
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[tool.ruff]
|
|
90
|
+
line-length = 100
|
|
91
|
+
target-version = "py311"
|
|
92
|
+
|
|
93
|
+
[tool.pytest.ini_options]
|
|
94
|
+
pythonpath = [
|
|
95
|
+
"."
|
|
96
|
+
]
|
|
97
|
+
testpaths = [
|
|
98
|
+
"tests"
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
[tool.mypy]
|
|
102
|
+
python_version = "3.11"
|
|
103
|
+
ignore_missing_imports = true
|
|
104
|
+
|
|
105
|
+
[build-system]
|
|
106
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
107
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
__all__ = ["SQLServerConnector", "SparkConnector"]
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def __getattr__(name: str) -> Any:
|
|
8
|
+
if name == "SQLServerConnector":
|
|
9
|
+
from src_connectors.src_sqlserver.connector import SQLServerConnector
|
|
10
|
+
|
|
11
|
+
return SQLServerConnector
|
|
12
|
+
|
|
13
|
+
if name == "SparkConnector":
|
|
14
|
+
from src_connectors.src_spark.connector import SparkConnector
|
|
15
|
+
|
|
16
|
+
return SparkConnector
|
|
17
|
+
|
|
18
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
class BaseConnector(ABC):
|
|
5
|
+
"""
|
|
6
|
+
Abstract base class for database connectors.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def connect(self) -> Any:
|
|
11
|
+
"""Establish a connection to the database."""
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def close(self) -> None:
|
|
16
|
+
"""Close the database connection."""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def execute_query(
|
|
21
|
+
self,
|
|
22
|
+
query: str,
|
|
23
|
+
params: Optional[tuple] = None,
|
|
24
|
+
stream: bool = False,
|
|
25
|
+
batch_size: int = 1000,
|
|
26
|
+
output_type: str = "list",
|
|
27
|
+
**kwargs: Any
|
|
28
|
+
) -> Any:
|
|
29
|
+
"""Execute a query and return the results."""
|
|
30
|
+
pass
|
|
31
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from src_connectors.src_spark.connector import SparkConnector
|
|
2
|
+
from src_connectors.src_spark.configs.core_config import SparkCoreConfig
|
|
3
|
+
from src_connectors.src_spark.configs.iceberg import SparkIcebergConfig
|
|
4
|
+
from src_connectors.src_spark.configs.jdbc import SparkJdbcConfig
|
|
5
|
+
|
|
6
|
+
__all__ = ["SparkConnector", "SparkCoreConfig", "SparkIcebergConfig", "SparkJdbcConfig"]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from src_connectors.src_spark.configs.core_config import SparkCoreConfig
|
|
2
|
+
from src_connectors.src_spark.configs.iceberg import SparkIcebergConfig
|
|
3
|
+
from src_connectors.src_spark.configs.jdbc import SparkJdbcConfig
|
|
4
|
+
from src_connectors.src_spark.configs.base import SparkBaseComponent
|
|
5
|
+
|
|
6
|
+
__all__ = ["SparkCoreConfig", "SparkIcebergConfig", "SparkJdbcConfig", "SparkBaseComponent"]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
|
|
4
|
+
class SparkBaseComponent(ABC):
|
|
5
|
+
"""
|
|
6
|
+
Abstract base class for Spark components.
|
|
7
|
+
|
|
8
|
+
This class defines the interface for components that require
|
|
9
|
+
specific Spark configurations and external packages.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def get_spark_config(self) -> Dict:
|
|
14
|
+
"""
|
|
15
|
+
Return Spark configuration settings.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
dict: A dictionary of Spark configuration keys and values.
|
|
19
|
+
"""
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def get_required_spark_packages(self) -> List:
|
|
24
|
+
"""
|
|
25
|
+
Return a list of required Spark packages.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
list: A list of Maven coordinates or package names.
|
|
29
|
+
"""
|
|
30
|
+
pass
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from typing import Dict, List, Any, Optional
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
|
+
|
|
4
|
+
from src_connectors.src_spark.configs.base import SparkBaseComponent
|
|
5
|
+
from variables.spark import SparkVariables
|
|
6
|
+
|
|
7
|
+
# Load environment-based defaults
|
|
8
|
+
_spark_defaults = SparkVariables.get_spark_base_config()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SparkCoreConfig(BaseModel, SparkBaseComponent):
|
|
12
|
+
"""
|
|
13
|
+
Configuration model for core Apache Spark engine settings.
|
|
14
|
+
|
|
15
|
+
This class manages Spark core parameters including resource allocation (memory, cores),
|
|
16
|
+
cluster connectivity, and runtime dependencies. Defaults are initialized from
|
|
17
|
+
environment variables.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# Cluster & Application Settings
|
|
21
|
+
spark_master: str = Field(
|
|
22
|
+
default=_spark_defaults.get("SPARK_MASTER") or "local[*]",
|
|
23
|
+
description="The Spark master URL to connect to."
|
|
24
|
+
)
|
|
25
|
+
spark_driver_host: str = Field(
|
|
26
|
+
default=_spark_defaults.get("SPARK_DRIVER_HOST") or "127.0.0.1",
|
|
27
|
+
description="Hostname or IP address for the driver to listen on."
|
|
28
|
+
)
|
|
29
|
+
spark_driver_bind_address: str = Field(
|
|
30
|
+
default=_spark_defaults.get("SPARK_DRIVER_BIND_ADDRESS") or "127.0.0.1",
|
|
31
|
+
description="Address to bind to for the driver."
|
|
32
|
+
)
|
|
33
|
+
spark_app_name: str = Field(
|
|
34
|
+
default=_spark_defaults.get("SPARK_APP_NAME") or "SparkApp",
|
|
35
|
+
description="The name of the Spark application."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Resource Management
|
|
39
|
+
spark_executor_memory: str = Field(
|
|
40
|
+
default=_spark_defaults.get("SPARK_EXECUTOR_MEMORY") or "2g",
|
|
41
|
+
description="Amount of memory to use per executor process."
|
|
42
|
+
)
|
|
43
|
+
spark_executor_cores: int = Field(
|
|
44
|
+
default=int(_spark_defaults.get("SPARK_EXECUTOR_CORES") or 2),
|
|
45
|
+
description="The number of cores to use on each executor."
|
|
46
|
+
)
|
|
47
|
+
spark_driver_memory: str = Field(
|
|
48
|
+
default=_spark_defaults.get("SPARK_DRIVER_MEMORY") or "4g",
|
|
49
|
+
description="Amount of memory to use for the driver process."
|
|
50
|
+
)
|
|
51
|
+
spark_driver_cores: int = Field(
|
|
52
|
+
default=int(_spark_defaults.get("SPARK_DRIVER_CORES") or 2),
|
|
53
|
+
description="Number of cores to use for the driver process."
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# Dependencies & Runtime
|
|
57
|
+
spark_jars: Optional[str] = Field(
|
|
58
|
+
default=_spark_defaults.get("SPARK_LOCAL_JARS") or "",
|
|
59
|
+
description="Comma-separated local jar paths."
|
|
60
|
+
)
|
|
61
|
+
spark_jars_packages: Optional[str] = Field(
|
|
62
|
+
default=_spark_defaults.get("SPARK_JARS_PACKAGES") or "",
|
|
63
|
+
description="Comma-separated Maven coordinates of jars to include."
|
|
64
|
+
)
|
|
65
|
+
spark_jars_ivy: str = Field(
|
|
66
|
+
default=_spark_defaults.get("SPARK_JARS_IVY") or "/tmp/.ivy2",
|
|
67
|
+
description="Path to local Ivy repository for dependency resolution."
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Environment & Versioning
|
|
71
|
+
spark_version: str = Field(
|
|
72
|
+
default=_spark_defaults.get("SPARK_VERSION") or "3.0.0",
|
|
73
|
+
description="Target Spark version."
|
|
74
|
+
)
|
|
75
|
+
spark_minor_version: str = Field(
|
|
76
|
+
default=_spark_defaults.get("SPARK_MINOR_VERSION") or "3.0",
|
|
77
|
+
description="Target Spark minor version."
|
|
78
|
+
)
|
|
79
|
+
spark_local_dir: str = Field(
|
|
80
|
+
default=_spark_defaults.get("SPARK_LOCAL_DIR") or "/tmp/spark",
|
|
81
|
+
description="Directory for Spark 'scratch' space (map outputs, RDD spills)."
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def get_spark_config(self) -> Dict[str, Any]:
|
|
85
|
+
"""
|
|
86
|
+
Generates a dictionary of Spark configuration properties.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Dict[str, Any]: Flat dictionary of 'spark.*' configuration keys and values.
|
|
90
|
+
"""
|
|
91
|
+
config = {
|
|
92
|
+
"spark.master": self.spark_master,
|
|
93
|
+
"spark.app.name": self.spark_app_name,
|
|
94
|
+
"spark.executor.memory": self.spark_executor_memory,
|
|
95
|
+
"spark.executor.cores": self.spark_executor_cores,
|
|
96
|
+
"spark.driver.memory": self.spark_driver_memory,
|
|
97
|
+
"spark.driver.cores": self.spark_driver_cores,
|
|
98
|
+
"spark.jars.ivy": self.spark_jars_ivy,
|
|
99
|
+
"spark.local.dir": self.spark_local_dir,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Handle Driver Host logic:
|
|
103
|
+
# Force 127.0.0.1 ONLY if running in local mode to avoid RPC errors on dev machines.
|
|
104
|
+
# In cluster mode (K8s/YARN), we let Spark/Cluster Manager handle it or use provided host.
|
|
105
|
+
is_local = self.spark_master.startswith("local")
|
|
106
|
+
if is_local:
|
|
107
|
+
config["spark.driver.host"] = self.spark_driver_host
|
|
108
|
+
config["spark.driver.bindAddress"] = self.spark_driver_bind_address
|
|
109
|
+
else:
|
|
110
|
+
# In cluster mode, only apply if explicitly provided (not default 127.0.0.1)
|
|
111
|
+
if self.spark_driver_host != "127.0.0.1":
|
|
112
|
+
config["spark.driver.host"] = self.spark_driver_host
|
|
113
|
+
if self.spark_driver_bind_address != "127.0.0.1":
|
|
114
|
+
config["spark.driver.bindAddress"] = self.spark_driver_bind_address
|
|
115
|
+
|
|
116
|
+
# Handle Jars and Packages logic priority
|
|
117
|
+
if self.spark_jars:
|
|
118
|
+
config["spark.jars"] = self.spark_jars
|
|
119
|
+
elif self.spark_jars_packages:
|
|
120
|
+
config["spark.jars.packages"] = self.spark_jars_packages
|
|
121
|
+
|
|
122
|
+
return config
|
|
123
|
+
|
|
124
|
+
def get_required_spark_packages(self) -> List[str]:
|
|
125
|
+
"""
|
|
126
|
+
Returns a list of required Spark packages.
|
|
127
|
+
If local jars are provided, packages are usually skipped to avoid conflicts.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
List[str]: A list of cleaned Maven package coordinates.
|
|
131
|
+
"""
|
|
132
|
+
if self.spark_jars:
|
|
133
|
+
return []
|
|
134
|
+
|
|
135
|
+
if not self.spark_jars_packages:
|
|
136
|
+
return []
|
|
137
|
+
|
|
138
|
+
return [pkg.strip() for pkg in self.spark_jars_packages.split(",") if pkg.strip()]
|