al-data-core 0.6.2__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.
- al_data_core-0.6.2/LICENSE +21 -0
- al_data_core-0.6.2/PKG-INFO +167 -0
- al_data_core-0.6.2/README.md +149 -0
- al_data_core-0.6.2/pyproject.toml +58 -0
- al_data_core-0.6.2/setup.cfg +4 -0
- al_data_core-0.6.2/src/al_data_core/__init__.py +5 -0
- al_data_core-0.6.2/src/al_data_core/__main__.py +4 -0
- al_data_core-0.6.2/src/al_data_core/azure_as_processor.py +34 -0
- al_data_core-0.6.2/src/al_data_core/config_processor.py +359 -0
- al_data_core-0.6.2/src/al_data_core/dags_installer.py +131 -0
- al_data_core-0.6.2/src/al_data_core/external_handler_base.py +97 -0
- al_data_core-0.6.2/src/al_data_core/tasks_processor.py +364 -0
- al_data_core-0.6.2/src/al_data_core/templates/v2.0.0/data_core_config_engine_dag.py +61 -0
- al_data_core-0.6.2/src/al_data_core/templates/v2.0.0/data_core_dag.py +131 -0
- al_data_core-0.6.2/src/al_data_core/templates/v3.0.0/data_core_config_engine_dag.py +61 -0
- al_data_core-0.6.2/src/al_data_core/templates/v3.0.0/data_core_dag.py +131 -0
- al_data_core-0.6.2/src/al_data_core.egg-info/PKG-INFO +167 -0
- al_data_core-0.6.2/src/al_data_core.egg-info/SOURCES.txt +20 -0
- al_data_core-0.6.2/src/al_data_core.egg-info/dependency_links.txt +1 -0
- al_data_core-0.6.2/src/al_data_core.egg-info/entry_points.txt +2 -0
- al_data_core-0.6.2/src/al_data_core.egg-info/requires.txt +2 -0
- al_data_core-0.6.2/src/al_data_core.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AL Data Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: al-data-core
|
|
3
|
+
Version: 0.6.2
|
|
4
|
+
Summary: Generic data pipeline engine for Airflow (config, processor, DAG factory).
|
|
5
|
+
Author-email: AL Data Labs <pypi@aldatalabs.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://aldatalabs.com
|
|
8
|
+
Keywords: airflow,data-engineering,etl,dag
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: al-data-utils>=0.3.1
|
|
16
|
+
Requires-Dist: pandas
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# al-data-core
|
|
20
|
+
|
|
21
|
+
Generic Airflow data pipeline engine. Install once, configure per project.
|
|
22
|
+
|
|
23
|
+
## Python and Setup
|
|
24
|
+
|
|
25
|
+
- Python: 3.10+
|
|
26
|
+
- Packaging: setuptools (src layout)
|
|
27
|
+
|
|
28
|
+
Install locally in editable mode:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install -e .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Requires `al-data-utils` to be installed first.
|
|
35
|
+
|
|
36
|
+
## Project Structure
|
|
37
|
+
|
|
38
|
+
- src/al_data_core
|
|
39
|
+
|
|
40
|
+
Main modules under `src/al_data_core`:
|
|
41
|
+
|
|
42
|
+
- `config_processor` — `DataCoreConfig`
|
|
43
|
+
- `tasks_processor` — `TaskProcessor`
|
|
44
|
+
- `azure_as_processor` — `run_azure_as_refresh`
|
|
45
|
+
- `external_handler_base` — `ExternalHandlerBase`, `discover_handlers` (used for XLS and API handlers)
|
|
46
|
+
- `dags_installer` — CLI for copying DAG templates
|
|
47
|
+
|
|
48
|
+
## DAG Templates
|
|
49
|
+
|
|
50
|
+
After installing, copy the ready-to-use DAG templates to your Airflow dags folder:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
al-data-core copy-dags # latest → /opt/airflow/dags
|
|
54
|
+
al-data-core copy-dags /my/dags # custom path
|
|
55
|
+
al-data-core copy-dags --version v2.0.0 # specific Airflow version
|
|
56
|
+
al-data-core list-versions # show available versions
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Available versions:
|
|
60
|
+
|
|
61
|
+
- `v2.0.0` — Airflow 2.x
|
|
62
|
+
- `v3.0.0` — Airflow 3.x
|
|
63
|
+
|
|
64
|
+
Two files are copied:
|
|
65
|
+
|
|
66
|
+
- `data_core_dag.py` — main DAG file, reads `data_core_tasks_config.yaml` and registers all project DAGs
|
|
67
|
+
- `data_core_config_engine_dag.py` — runs every 15 min, queries config DB and YAML, writes `data_core_tasks_config.yaml`
|
|
68
|
+
|
|
69
|
+
## Project Layout (per-project repo)
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
dags/
|
|
73
|
+
├── data_core_dag.py <- copied from template
|
|
74
|
+
├── data_core_config_engine_dag.py <- copied from template
|
|
75
|
+
└── data_core/
|
|
76
|
+
├── data_core_config.yaml <- project config
|
|
77
|
+
├── .configs/data_core/data_core_tasks_config.yaml <- generated by config engine dag
|
|
78
|
+
├── data_core_handler_sql/
|
|
79
|
+
│ └── sql_queries/
|
|
80
|
+
│ └── <scope>/
|
|
81
|
+
│ └── <param_code>.sql
|
|
82
|
+
├── data_core_handler_xls/ <- optional, project-specific
|
|
83
|
+
└── data_core_handler_api/ <- optional, project-specific
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## data_core_config.yaml
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
CONFIG:
|
|
90
|
+
config_connection_variable: my_mssql_secret # Airflow variable name
|
|
91
|
+
mappings:
|
|
92
|
+
config_get_tables_list: integrations_db.config.get_tables_list
|
|
93
|
+
config_parameters: integrations_db.config.parameters
|
|
94
|
+
config_fn_get_param_values: integrations_db.config.fn_get_param_values
|
|
95
|
+
config_calc_date_ranges: integrations_db.config.calc_date_ranges
|
|
96
|
+
config_update_param_values: integrations_db.config.update_param_values
|
|
97
|
+
|
|
98
|
+
DAGS:
|
|
99
|
+
my_project_ods_dag:
|
|
100
|
+
schedule_interval: '5 */1 * * *'
|
|
101
|
+
scopes: ['ODS_SOURCE']
|
|
102
|
+
tags: ['my_project']
|
|
103
|
+
my_project_dw_dag:
|
|
104
|
+
schedule_interval: '30 */1 * * *'
|
|
105
|
+
scopes: ['DW_TARGET']
|
|
106
|
+
tags: ['my_project']
|
|
107
|
+
azure_as: # optional: refresh semantic model after ETL
|
|
108
|
+
connection_variable: my_azure_as_secret
|
|
109
|
+
models:
|
|
110
|
+
- name: MyModel
|
|
111
|
+
refresh_request: {Type: Full, CommitMode: transactional, MaxParallelism: 2, RetryCount: 2, Objects: []}
|
|
112
|
+
|
|
113
|
+
ODS_SOURCE:
|
|
114
|
+
enabled: true
|
|
115
|
+
source_type: mssql
|
|
116
|
+
source_connection_variable: source_mssql_secret
|
|
117
|
+
destination_connection_variable: dest_mssql_secret
|
|
118
|
+
|
|
119
|
+
DW_TARGET:
|
|
120
|
+
enabled: true
|
|
121
|
+
destination_connection_variable: dest_mssql_secret
|
|
122
|
+
|
|
123
|
+
XLS:
|
|
124
|
+
enabled: true
|
|
125
|
+
handler: data_core_handler_xls # opts this scope into handler-based dispatch instead of seq_code-based copy/merge
|
|
126
|
+
|
|
127
|
+
ods_britix_api:
|
|
128
|
+
enabled: true
|
|
129
|
+
handler: data_core_handler_api/britix24
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Handlers
|
|
133
|
+
|
|
134
|
+
A scope opts into handler-based dispatch by setting `handler` to its handlers folder (relative to `data_core_config.yaml`, or an absolute path) — the value *is* the path, so `TaskProcessor` doesn't hardcode scope_code names and adding a new handler scope needs only config, never a template change. Two layouts are supported:
|
|
135
|
+
|
|
136
|
+
* **One file per param_code** — file name matches the task's `param_code` exactly.
|
|
137
|
+
* **One generic handler per scope** — when the folder holds a single handler file, it serves every param_code in the scope and distinguishes tasks via `self.context.param_code`.
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
# dags/data_core/data_core_handler_xls/fact_sales_plan.py
|
|
141
|
+
from al_data_core.external_handler_base import ExternalHandlerBase
|
|
142
|
+
|
|
143
|
+
class MySalesHandler(ExternalHandlerBase):
|
|
144
|
+
def proceed(self) -> None:
|
|
145
|
+
...
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
# dags/data_core/data_core_handler_api/britix24/bitrix_ingest.py
|
|
150
|
+
from al_data_core.external_handler_base import ExternalHandlerBase
|
|
151
|
+
|
|
152
|
+
class BitrixIngestHandler(ExternalHandlerBase):
|
|
153
|
+
def proceed(self) -> None:
|
|
154
|
+
scope = self.context.scope_config
|
|
155
|
+
entity = scope['entities'][self.context.param_code]
|
|
156
|
+
...
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`TaskProcessor` constructs the handler with no arguments, sets `handler.context` to a `HandlerContext` (scope_code, param_code, scope_config, config_file_path, params_details, debug), then calls `proceed()` — handlers read run-time settings from `self.context` instead of hardcoding them. Discovery happens at task-run time, not DAG-parse time, so a broken handler file can't fail the whole DAG file's parse and handler modules aren't re-imported every scheduler cycle. Each file must define exactly one `ExternalHandlerBase` subclass.
|
|
160
|
+
|
|
161
|
+
## Development Guides
|
|
162
|
+
|
|
163
|
+
- `RELEASING.md` — release flow and Azure Blob publish steps
|
|
164
|
+
|
|
165
|
+
## Changelog
|
|
166
|
+
|
|
167
|
+
See `CHANGELOG.md` for release notes.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# al-data-core
|
|
2
|
+
|
|
3
|
+
Generic Airflow data pipeline engine. Install once, configure per project.
|
|
4
|
+
|
|
5
|
+
## Python and Setup
|
|
6
|
+
|
|
7
|
+
- Python: 3.10+
|
|
8
|
+
- Packaging: setuptools (src layout)
|
|
9
|
+
|
|
10
|
+
Install locally in editable mode:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install -e .
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires `al-data-utils` to be installed first.
|
|
17
|
+
|
|
18
|
+
## Project Structure
|
|
19
|
+
|
|
20
|
+
- src/al_data_core
|
|
21
|
+
|
|
22
|
+
Main modules under `src/al_data_core`:
|
|
23
|
+
|
|
24
|
+
- `config_processor` — `DataCoreConfig`
|
|
25
|
+
- `tasks_processor` — `TaskProcessor`
|
|
26
|
+
- `azure_as_processor` — `run_azure_as_refresh`
|
|
27
|
+
- `external_handler_base` — `ExternalHandlerBase`, `discover_handlers` (used for XLS and API handlers)
|
|
28
|
+
- `dags_installer` — CLI for copying DAG templates
|
|
29
|
+
|
|
30
|
+
## DAG Templates
|
|
31
|
+
|
|
32
|
+
After installing, copy the ready-to-use DAG templates to your Airflow dags folder:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
al-data-core copy-dags # latest → /opt/airflow/dags
|
|
36
|
+
al-data-core copy-dags /my/dags # custom path
|
|
37
|
+
al-data-core copy-dags --version v2.0.0 # specific Airflow version
|
|
38
|
+
al-data-core list-versions # show available versions
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Available versions:
|
|
42
|
+
|
|
43
|
+
- `v2.0.0` — Airflow 2.x
|
|
44
|
+
- `v3.0.0` — Airflow 3.x
|
|
45
|
+
|
|
46
|
+
Two files are copied:
|
|
47
|
+
|
|
48
|
+
- `data_core_dag.py` — main DAG file, reads `data_core_tasks_config.yaml` and registers all project DAGs
|
|
49
|
+
- `data_core_config_engine_dag.py` — runs every 15 min, queries config DB and YAML, writes `data_core_tasks_config.yaml`
|
|
50
|
+
|
|
51
|
+
## Project Layout (per-project repo)
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
dags/
|
|
55
|
+
├── data_core_dag.py <- copied from template
|
|
56
|
+
├── data_core_config_engine_dag.py <- copied from template
|
|
57
|
+
└── data_core/
|
|
58
|
+
├── data_core_config.yaml <- project config
|
|
59
|
+
├── .configs/data_core/data_core_tasks_config.yaml <- generated by config engine dag
|
|
60
|
+
├── data_core_handler_sql/
|
|
61
|
+
│ └── sql_queries/
|
|
62
|
+
│ └── <scope>/
|
|
63
|
+
│ └── <param_code>.sql
|
|
64
|
+
├── data_core_handler_xls/ <- optional, project-specific
|
|
65
|
+
└── data_core_handler_api/ <- optional, project-specific
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## data_core_config.yaml
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
CONFIG:
|
|
72
|
+
config_connection_variable: my_mssql_secret # Airflow variable name
|
|
73
|
+
mappings:
|
|
74
|
+
config_get_tables_list: integrations_db.config.get_tables_list
|
|
75
|
+
config_parameters: integrations_db.config.parameters
|
|
76
|
+
config_fn_get_param_values: integrations_db.config.fn_get_param_values
|
|
77
|
+
config_calc_date_ranges: integrations_db.config.calc_date_ranges
|
|
78
|
+
config_update_param_values: integrations_db.config.update_param_values
|
|
79
|
+
|
|
80
|
+
DAGS:
|
|
81
|
+
my_project_ods_dag:
|
|
82
|
+
schedule_interval: '5 */1 * * *'
|
|
83
|
+
scopes: ['ODS_SOURCE']
|
|
84
|
+
tags: ['my_project']
|
|
85
|
+
my_project_dw_dag:
|
|
86
|
+
schedule_interval: '30 */1 * * *'
|
|
87
|
+
scopes: ['DW_TARGET']
|
|
88
|
+
tags: ['my_project']
|
|
89
|
+
azure_as: # optional: refresh semantic model after ETL
|
|
90
|
+
connection_variable: my_azure_as_secret
|
|
91
|
+
models:
|
|
92
|
+
- name: MyModel
|
|
93
|
+
refresh_request: {Type: Full, CommitMode: transactional, MaxParallelism: 2, RetryCount: 2, Objects: []}
|
|
94
|
+
|
|
95
|
+
ODS_SOURCE:
|
|
96
|
+
enabled: true
|
|
97
|
+
source_type: mssql
|
|
98
|
+
source_connection_variable: source_mssql_secret
|
|
99
|
+
destination_connection_variable: dest_mssql_secret
|
|
100
|
+
|
|
101
|
+
DW_TARGET:
|
|
102
|
+
enabled: true
|
|
103
|
+
destination_connection_variable: dest_mssql_secret
|
|
104
|
+
|
|
105
|
+
XLS:
|
|
106
|
+
enabled: true
|
|
107
|
+
handler: data_core_handler_xls # opts this scope into handler-based dispatch instead of seq_code-based copy/merge
|
|
108
|
+
|
|
109
|
+
ods_britix_api:
|
|
110
|
+
enabled: true
|
|
111
|
+
handler: data_core_handler_api/britix24
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Handlers
|
|
115
|
+
|
|
116
|
+
A scope opts into handler-based dispatch by setting `handler` to its handlers folder (relative to `data_core_config.yaml`, or an absolute path) — the value *is* the path, so `TaskProcessor` doesn't hardcode scope_code names and adding a new handler scope needs only config, never a template change. Two layouts are supported:
|
|
117
|
+
|
|
118
|
+
* **One file per param_code** — file name matches the task's `param_code` exactly.
|
|
119
|
+
* **One generic handler per scope** — when the folder holds a single handler file, it serves every param_code in the scope and distinguishes tasks via `self.context.param_code`.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
# dags/data_core/data_core_handler_xls/fact_sales_plan.py
|
|
123
|
+
from al_data_core.external_handler_base import ExternalHandlerBase
|
|
124
|
+
|
|
125
|
+
class MySalesHandler(ExternalHandlerBase):
|
|
126
|
+
def proceed(self) -> None:
|
|
127
|
+
...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# dags/data_core/data_core_handler_api/britix24/bitrix_ingest.py
|
|
132
|
+
from al_data_core.external_handler_base import ExternalHandlerBase
|
|
133
|
+
|
|
134
|
+
class BitrixIngestHandler(ExternalHandlerBase):
|
|
135
|
+
def proceed(self) -> None:
|
|
136
|
+
scope = self.context.scope_config
|
|
137
|
+
entity = scope['entities'][self.context.param_code]
|
|
138
|
+
...
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`TaskProcessor` constructs the handler with no arguments, sets `handler.context` to a `HandlerContext` (scope_code, param_code, scope_config, config_file_path, params_details, debug), then calls `proceed()` — handlers read run-time settings from `self.context` instead of hardcoding them. Discovery happens at task-run time, not DAG-parse time, so a broken handler file can't fail the whole DAG file's parse and handler modules aren't re-imported every scheduler cycle. Each file must define exactly one `ExternalHandlerBase` subclass.
|
|
142
|
+
|
|
143
|
+
## Development Guides
|
|
144
|
+
|
|
145
|
+
- `RELEASING.md` — release flow and Azure Blob publish steps
|
|
146
|
+
|
|
147
|
+
## Changelog
|
|
148
|
+
|
|
149
|
+
See `CHANGELOG.md` for release notes.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "al-data-core"
|
|
3
|
+
version = "0.6.2"
|
|
4
|
+
description = "Generic data pipeline engine for Airflow (config, processor, DAG factory)."
|
|
5
|
+
authors = [{ name = "AL Data Labs", email = "pypi@aldatalabs.com" }]
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
keywords = ["airflow", "data-engineering", "etl", "dag"]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Programming Language :: Python :: 3",
|
|
11
|
+
"Operating System :: OS Independent",
|
|
12
|
+
"Topic :: Software Development :: Libraries",
|
|
13
|
+
]
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
requires-python = ">=3.10"
|
|
16
|
+
dependencies = [
|
|
17
|
+
"al-data-utils>=0.3.1",
|
|
18
|
+
"pandas",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://aldatalabs.com"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
[build-system]
|
|
26
|
+
requires = ["setuptools>=77"]
|
|
27
|
+
build-backend = "setuptools.build_meta"
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
al-data-core = "al_data_core.dags_installer:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
package-dir = {"" = "src"}
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.package-data]
|
|
39
|
+
al_data_core = ["templates/**/*.py"]
|
|
40
|
+
|
|
41
|
+
# Ruff configuration
|
|
42
|
+
[tool.ruff]
|
|
43
|
+
exclude = [
|
|
44
|
+
".git",
|
|
45
|
+
".venv",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
target-version = "py313"
|
|
49
|
+
|
|
50
|
+
line-length = 88
|
|
51
|
+
indent-width = 4
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
[tool.ruff.format]
|
|
55
|
+
quote-style = "single"
|
|
56
|
+
indent-style = "space"
|
|
57
|
+
skip-magic-trailing-comma = true
|
|
58
|
+
line-ending = "auto"
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from al_data_core.config_processor import DataCoreConfig
|
|
2
|
+
from al_data_core.tasks_processor import TaskProcessor
|
|
3
|
+
from al_data_core.external_handler_base import ExternalHandlerBase, discover_handlers
|
|
4
|
+
|
|
5
|
+
__all__ = ['DataCoreConfig', 'TaskProcessor', 'ExternalHandlerBase', 'discover_handlers']
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from al_data_utils import airflow_utils
|
|
2
|
+
from al_data_utils.logging_utils import info
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def run_azure_as_refresh(azure_as_cfg: dict, model_cfg: dict) -> None:
|
|
6
|
+
"""
|
|
7
|
+
Refresh a single Azure Analysis Services semantic model.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
azure_as_cfg : dict
|
|
12
|
+
Must contain ``connection_variable`` — the Airflow variable name that
|
|
13
|
+
holds a dict with keys: tenant_id, client_id, client_secret, rollout,
|
|
14
|
+
server_name.
|
|
15
|
+
model_cfg : dict
|
|
16
|
+
Must contain ``name`` (model name) and ``refresh_request`` (the XMLA
|
|
17
|
+
refresh payload dict passed to SemanticModels.refresh_models).
|
|
18
|
+
"""
|
|
19
|
+
from al_data_utils.azure_as_utils import SemanticModels
|
|
20
|
+
|
|
21
|
+
conn = airflow_utils.get_variable_value_dict(azure_as_cfg['connection_variable'])
|
|
22
|
+
|
|
23
|
+
sm = SemanticModels(
|
|
24
|
+
tenant_id=conn['tenant_id'],
|
|
25
|
+
client_id=conn['client_id'],
|
|
26
|
+
client_secret=conn['client_secret'],
|
|
27
|
+
rollout=conn['rollout'],
|
|
28
|
+
server_name=conn['server_name'],
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
model_name = model_cfg['name']
|
|
32
|
+
info(f'Starting Azure AS refresh for model: {model_name}')
|
|
33
|
+
sm.refresh_models([(model_name, model_cfg['refresh_request'])])
|
|
34
|
+
info(f'Azure AS refresh completed for model: {model_name}')
|