MSTR-Robotics-magerdaniel 0.3.12__tar.gz → 0.5.1__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.
- mstr_robotics_magerdaniel-0.5.1/MSTR_Robotics_magerdaniel.egg-info/PKG-INFO +68 -0
- mstr_robotics_magerdaniel-0.5.1/MSTR_Robotics_magerdaniel.egg-info/SOURCES.txt +39 -0
- mstr_robotics_magerdaniel-0.5.1/MSTR_Robotics_magerdaniel.egg-info/requires.txt +30 -0
- mstr_robotics_magerdaniel-0.5.1/PKG-INFO +68 -0
- mstr_robotics_magerdaniel-0.5.1/README.md +36 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/__init__.py +7 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/_connectors.py +289 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/_export.py +38 -0
- {mstr_robotics_magerdaniel-0.3.12 → mstr_robotics_magerdaniel-0.5.1}/mstr_robotics/_helper.py +201 -187
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/_lu_data.py +138 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/_mod_prj_obj.py +80 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/_pa_etl.py +270 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/_paths.py +91 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/dossier.py +339 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/json_compare.py +819 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers/_fetch_static_data.py +109 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers/_osi_find_bi_data.py +110 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers/_osi_object_analysis.py +88 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers/_osi_specific_analysis.py +165 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers/_run_mstr_report_wizzard.py +236 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers/_server_config.py +113 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers/mstr_osi_mcp.py +57 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/ms_azure.py +127 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mstr_classes.py +415 -0
- {mstr_robotics_magerdaniel-0.3.12 → mstr_robotics_magerdaniel-0.5.1}/mstr_robotics/mstr_pandas.py +53 -48
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/navigation.py +380 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/osi_exporter/__init__.py +1 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/osi_exporter/export_dashboard.py +653 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/prepare_ai_data.py +614 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/read_out_prj_obj.py +1311 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/redis_db.py +473 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/regam.py +279 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/report.py +427 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/select_mig_objects.py +218 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/setup.py +370 -0
- mstr_robotics_magerdaniel-0.5.1/mstr_robotics/user_rag.py +294 -0
- mstr_robotics_magerdaniel-0.5.1/pyproject.toml +83 -0
- {mstr_robotics_magerdaniel-0.3.12 → mstr_robotics_magerdaniel-0.5.1}/setup.cfg +4 -4
- mstr_robotics_magerdaniel-0.3.12/LICENSE +0 -0
- mstr_robotics_magerdaniel-0.3.12/MANIFEST.in +0 -1
- mstr_robotics_magerdaniel-0.3.12/MSTR_Robotics_magerdaniel.egg-info/PKG-INFO +0 -50
- mstr_robotics_magerdaniel-0.3.12/MSTR_Robotics_magerdaniel.egg-info/SOURCES.txt +0 -22
- mstr_robotics_magerdaniel-0.3.12/MSTR_Robotics_magerdaniel.egg-info/requires.txt +0 -7
- mstr_robotics_magerdaniel-0.3.12/PKG-INFO +0 -50
- mstr_robotics_magerdaniel-0.3.12/README.md +0 -19
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/_connectors.py +0 -247
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/_lu_data.py +0 -53
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/_mod_prj_obj.py +0 -67
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/dossier.py +0 -204
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/mstr_classes.py +0 -383
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/navigation.py +0 -207
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/prepare_AI_data.py +0 -171
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/read_out_prj_obj.py +0 -1017
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/report.py +0 -457
- mstr_robotics_magerdaniel-0.3.12/mstr_robotics/user_RAG.py +0 -174
- mstr_robotics_magerdaniel-0.3.12/setup.py +0 -34
- {mstr_robotics_magerdaniel-0.3.12 → mstr_robotics_magerdaniel-0.5.1}/MSTR_Robotics_magerdaniel.egg-info/dependency_links.txt +0 -0
- {mstr_robotics_magerdaniel-0.3.12 → mstr_robotics_magerdaniel-0.5.1}/MSTR_Robotics_magerdaniel.egg-info/top_level.txt +0 -0
- {mstr_robotics_magerdaniel-0.3.12/mstr_robotics → mstr_robotics_magerdaniel-0.5.1/mstr_robotics/mcp_servers}/__init__.py +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: MSTR-Robotics-magerdaniel
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: Automation toolkit for MicroStrategy / Strategy One: object read-out, migration, comparison, RAG and OSI export.
|
|
5
|
+
Author-email: Daniel Mager <danielmager@gmx.de>
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: mstrio-py>=11.6
|
|
9
|
+
Requires-Dist: pandas>=2.2
|
|
10
|
+
Requires-Dist: numpy>=2.0
|
|
11
|
+
Requires-Dist: requests>=2.31
|
|
12
|
+
Requires-Dist: PyYAML>=6.0
|
|
13
|
+
Requires-Dist: ruamel.yaml>=0.18
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0
|
|
15
|
+
Requires-Dist: openpyxl>=3.1
|
|
16
|
+
Provides-Extra: rag
|
|
17
|
+
Requires-Dist: openai>=1.0; extra == "rag"
|
|
18
|
+
Requires-Dist: flashtext>=2.7; extra == "rag"
|
|
19
|
+
Provides-Extra: redis
|
|
20
|
+
Requires-Dist: redis>=5.0; extra == "redis"
|
|
21
|
+
Provides-Extra: azure
|
|
22
|
+
Requires-Dist: azure-storage-blob>=12.0; extra == "azure"
|
|
23
|
+
Provides-Extra: servers
|
|
24
|
+
Requires-Dist: mcp; extra == "servers"
|
|
25
|
+
Requires-Dist: MSTR-Robotics-magerdaniel[rag]; extra == "servers"
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: MSTR-Robotics-magerdaniel[azure,rag,redis,servers]; extra == "all"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Requires-Dist: vulture; extra == "dev"
|
|
31
|
+
Requires-Dist: jupyter; extra == "dev"
|
|
32
|
+
|
|
33
|
+
# MSTR Robotics
|
|
34
|
+
|
|
35
|
+
A Python toolkit for MicroStrategy automation, object comparison, and Redis-based BI analysis.
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- **Object Comparison**: Compare MicroStrategy objects between environments using JSON diff analysis
|
|
40
|
+
- **Redis Integration**: Store and analyze BI metadata using Redis
|
|
41
|
+
- **Migration Tools**: Automate MicroStrategy object migration workflows
|
|
42
|
+
|
|
43
|
+
## Project Structure
|
|
44
|
+
|
|
45
|
+
- `mstr_robotics/` - Main package with core functionality
|
|
46
|
+
- `notebooks/` - Jupyter notebooks for analysis and exploration
|
|
47
|
+
- `Dansfiles/` - Migration and automation scripts
|
|
48
|
+
- `config/` - Configuration files (YAML, JSON)
|
|
49
|
+
- `export/` - Export utilities and logs
|
|
50
|
+
- `alt/` - Alternative implementations and experiments
|
|
51
|
+
|
|
52
|
+
## Setup
|
|
53
|
+
|
|
54
|
+
1. Clone the repository
|
|
55
|
+
2. Create virtual environment: `python -m venv .venv`
|
|
56
|
+
3. Activate: `.venv\Scripts\Activate.ps1`
|
|
57
|
+
4. Install dependencies: `pip install -r requirements.txt`
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
The Jupyter notebooks in `notebooks/` are the primary entry points (object
|
|
62
|
+
export, schema monitoring, migration, REGAM regression testing).
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
- Python 3.12 required
|
|
67
|
+
- Uses Redis for data storage
|
|
68
|
+
- Jupyter notebooks for exploratory analysis
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
MSTR_Robotics_magerdaniel.egg-info/PKG-INFO
|
|
4
|
+
MSTR_Robotics_magerdaniel.egg-info/SOURCES.txt
|
|
5
|
+
MSTR_Robotics_magerdaniel.egg-info/dependency_links.txt
|
|
6
|
+
MSTR_Robotics_magerdaniel.egg-info/requires.txt
|
|
7
|
+
MSTR_Robotics_magerdaniel.egg-info/top_level.txt
|
|
8
|
+
mstr_robotics/__init__.py
|
|
9
|
+
mstr_robotics/_connectors.py
|
|
10
|
+
mstr_robotics/_export.py
|
|
11
|
+
mstr_robotics/_helper.py
|
|
12
|
+
mstr_robotics/_lu_data.py
|
|
13
|
+
mstr_robotics/_mod_prj_obj.py
|
|
14
|
+
mstr_robotics/_pa_etl.py
|
|
15
|
+
mstr_robotics/_paths.py
|
|
16
|
+
mstr_robotics/dossier.py
|
|
17
|
+
mstr_robotics/json_compare.py
|
|
18
|
+
mstr_robotics/ms_azure.py
|
|
19
|
+
mstr_robotics/mstr_classes.py
|
|
20
|
+
mstr_robotics/mstr_pandas.py
|
|
21
|
+
mstr_robotics/navigation.py
|
|
22
|
+
mstr_robotics/prepare_ai_data.py
|
|
23
|
+
mstr_robotics/read_out_prj_obj.py
|
|
24
|
+
mstr_robotics/redis_db.py
|
|
25
|
+
mstr_robotics/regam.py
|
|
26
|
+
mstr_robotics/report.py
|
|
27
|
+
mstr_robotics/select_mig_objects.py
|
|
28
|
+
mstr_robotics/setup.py
|
|
29
|
+
mstr_robotics/user_rag.py
|
|
30
|
+
mstr_robotics/mcp_servers/__init__.py
|
|
31
|
+
mstr_robotics/mcp_servers/_fetch_static_data.py
|
|
32
|
+
mstr_robotics/mcp_servers/_osi_find_bi_data.py
|
|
33
|
+
mstr_robotics/mcp_servers/_osi_object_analysis.py
|
|
34
|
+
mstr_robotics/mcp_servers/_osi_specific_analysis.py
|
|
35
|
+
mstr_robotics/mcp_servers/_run_mstr_report_wizzard.py
|
|
36
|
+
mstr_robotics/mcp_servers/_server_config.py
|
|
37
|
+
mstr_robotics/mcp_servers/mstr_osi_mcp.py
|
|
38
|
+
mstr_robotics/osi_exporter/__init__.py
|
|
39
|
+
mstr_robotics/osi_exporter/export_dashboard.py
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
mstrio-py>=11.6
|
|
2
|
+
pandas>=2.2
|
|
3
|
+
numpy>=2.0
|
|
4
|
+
requests>=2.31
|
|
5
|
+
PyYAML>=6.0
|
|
6
|
+
ruamel.yaml>=0.18
|
|
7
|
+
python-dotenv>=1.0
|
|
8
|
+
openpyxl>=3.1
|
|
9
|
+
|
|
10
|
+
[all]
|
|
11
|
+
MSTR-Robotics-magerdaniel[azure,rag,redis,servers]
|
|
12
|
+
|
|
13
|
+
[azure]
|
|
14
|
+
azure-storage-blob>=12.0
|
|
15
|
+
|
|
16
|
+
[dev]
|
|
17
|
+
ruff
|
|
18
|
+
vulture
|
|
19
|
+
jupyter
|
|
20
|
+
|
|
21
|
+
[rag]
|
|
22
|
+
openai>=1.0
|
|
23
|
+
flashtext>=2.7
|
|
24
|
+
|
|
25
|
+
[redis]
|
|
26
|
+
redis>=5.0
|
|
27
|
+
|
|
28
|
+
[servers]
|
|
29
|
+
mcp
|
|
30
|
+
MSTR-Robotics-magerdaniel[rag]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: MSTR-Robotics-magerdaniel
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: Automation toolkit for MicroStrategy / Strategy One: object read-out, migration, comparison, RAG and OSI export.
|
|
5
|
+
Author-email: Daniel Mager <danielmager@gmx.de>
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: mstrio-py>=11.6
|
|
9
|
+
Requires-Dist: pandas>=2.2
|
|
10
|
+
Requires-Dist: numpy>=2.0
|
|
11
|
+
Requires-Dist: requests>=2.31
|
|
12
|
+
Requires-Dist: PyYAML>=6.0
|
|
13
|
+
Requires-Dist: ruamel.yaml>=0.18
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0
|
|
15
|
+
Requires-Dist: openpyxl>=3.1
|
|
16
|
+
Provides-Extra: rag
|
|
17
|
+
Requires-Dist: openai>=1.0; extra == "rag"
|
|
18
|
+
Requires-Dist: flashtext>=2.7; extra == "rag"
|
|
19
|
+
Provides-Extra: redis
|
|
20
|
+
Requires-Dist: redis>=5.0; extra == "redis"
|
|
21
|
+
Provides-Extra: azure
|
|
22
|
+
Requires-Dist: azure-storage-blob>=12.0; extra == "azure"
|
|
23
|
+
Provides-Extra: servers
|
|
24
|
+
Requires-Dist: mcp; extra == "servers"
|
|
25
|
+
Requires-Dist: MSTR-Robotics-magerdaniel[rag]; extra == "servers"
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: MSTR-Robotics-magerdaniel[azure,rag,redis,servers]; extra == "all"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Requires-Dist: vulture; extra == "dev"
|
|
31
|
+
Requires-Dist: jupyter; extra == "dev"
|
|
32
|
+
|
|
33
|
+
# MSTR Robotics
|
|
34
|
+
|
|
35
|
+
A Python toolkit for MicroStrategy automation, object comparison, and Redis-based BI analysis.
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- **Object Comparison**: Compare MicroStrategy objects between environments using JSON diff analysis
|
|
40
|
+
- **Redis Integration**: Store and analyze BI metadata using Redis
|
|
41
|
+
- **Migration Tools**: Automate MicroStrategy object migration workflows
|
|
42
|
+
|
|
43
|
+
## Project Structure
|
|
44
|
+
|
|
45
|
+
- `mstr_robotics/` - Main package with core functionality
|
|
46
|
+
- `notebooks/` - Jupyter notebooks for analysis and exploration
|
|
47
|
+
- `Dansfiles/` - Migration and automation scripts
|
|
48
|
+
- `config/` - Configuration files (YAML, JSON)
|
|
49
|
+
- `export/` - Export utilities and logs
|
|
50
|
+
- `alt/` - Alternative implementations and experiments
|
|
51
|
+
|
|
52
|
+
## Setup
|
|
53
|
+
|
|
54
|
+
1. Clone the repository
|
|
55
|
+
2. Create virtual environment: `python -m venv .venv`
|
|
56
|
+
3. Activate: `.venv\Scripts\Activate.ps1`
|
|
57
|
+
4. Install dependencies: `pip install -r requirements.txt`
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
The Jupyter notebooks in `notebooks/` are the primary entry points (object
|
|
62
|
+
export, schema monitoring, migration, REGAM regression testing).
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
- Python 3.12 required
|
|
67
|
+
- Uses Redis for data storage
|
|
68
|
+
- Jupyter notebooks for exploratory analysis
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# MSTR Robotics
|
|
2
|
+
|
|
3
|
+
A Python toolkit for MicroStrategy automation, object comparison, and Redis-based BI analysis.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Object Comparison**: Compare MicroStrategy objects between environments using JSON diff analysis
|
|
8
|
+
- **Redis Integration**: Store and analyze BI metadata using Redis
|
|
9
|
+
- **Migration Tools**: Automate MicroStrategy object migration workflows
|
|
10
|
+
|
|
11
|
+
## Project Structure
|
|
12
|
+
|
|
13
|
+
- `mstr_robotics/` - Main package with core functionality
|
|
14
|
+
- `notebooks/` - Jupyter notebooks for analysis and exploration
|
|
15
|
+
- `Dansfiles/` - Migration and automation scripts
|
|
16
|
+
- `config/` - Configuration files (YAML, JSON)
|
|
17
|
+
- `export/` - Export utilities and logs
|
|
18
|
+
- `alt/` - Alternative implementations and experiments
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
1. Clone the repository
|
|
23
|
+
2. Create virtual environment: `python -m venv .venv`
|
|
24
|
+
3. Activate: `.venv\Scripts\Activate.ps1`
|
|
25
|
+
4. Install dependencies: `pip install -r requirements.txt`
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
The Jupyter notebooks in `notebooks/` are the primary entry points (object
|
|
30
|
+
export, schema monitoring, migration, REGAM regression testing).
|
|
31
|
+
|
|
32
|
+
## Development
|
|
33
|
+
|
|
34
|
+
- Python 3.12 required
|
|
35
|
+
- Uses Redis for data storage
|
|
36
|
+
- Jupyter notebooks for exploratory analysis
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import uuid
|
|
3
|
+
|
|
4
|
+
from mstr_robotics._helper import Misc
|
|
5
|
+
|
|
6
|
+
i_msic = Misc()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MstrApi:
|
|
10
|
+
def get_prj_tbl(self, conn):
|
|
11
|
+
inst_u = f"{conn.base_url}/api/model/tables"
|
|
12
|
+
r = conn.get(inst_u)
|
|
13
|
+
return r
|
|
14
|
+
|
|
15
|
+
def get_base_formula_(self, conn, base_formula_id):
|
|
16
|
+
|
|
17
|
+
inst_u = f"{conn.base_url}/api/model/formulas/{base_formula_id}?showExpressionAs=tokens"
|
|
18
|
+
r = conn.get(inst_u).json()
|
|
19
|
+
return r
|
|
20
|
+
|
|
21
|
+
def get_dossier_prp_l(self, conn, dossier_id):
|
|
22
|
+
endpoint = f"/api/documents/{dossier_id}/prompts"
|
|
23
|
+
prp_l = conn.get(endpoint=endpoint).json()
|
|
24
|
+
return prp_l
|
|
25
|
+
|
|
26
|
+
def get_proj_obj_by_id_l(self, conn, obj_id_l, org_def_fg=False):
|
|
27
|
+
obj_prop_path_d_l = []
|
|
28
|
+
endpoint = f"{conn.base_url}/api/searches/objects?includeAncestors=true&showNavigationPath=true"
|
|
29
|
+
obj_id_l = list(set(obj_id_l))
|
|
30
|
+
obj_id_l = [x for x in obj_id_l if x is not None]
|
|
31
|
+
body_d = {"projectIdAndObjectIds": [{"projectId": conn.project_id, "objectIds": obj_id_l}]}
|
|
32
|
+
body_d = json.dumps(body_d)
|
|
33
|
+
response = conn.post(endpoint, data=body_d)
|
|
34
|
+
response_d = response.json()
|
|
35
|
+
try:
|
|
36
|
+
if response_d["totalItems"] > 0:
|
|
37
|
+
for prop in response_d["result"]:
|
|
38
|
+
if not org_def_fg:
|
|
39
|
+
obj_prop_path_d = {}
|
|
40
|
+
|
|
41
|
+
obj_prop_path_d["id"] = prop["id"]
|
|
42
|
+
obj_prop_path_d["name"] = prop["name"]
|
|
43
|
+
obj_prop_path_d["obj_type"] = prop["type"]
|
|
44
|
+
# obj_prop_path_d["description"]=prop["description"]
|
|
45
|
+
obj_prop_path_d["subtype"] = prop["subtype"]
|
|
46
|
+
obj_prop_path_d["dateCreated"] = prop["dateCreated"]
|
|
47
|
+
obj_prop_path_d["dateModified"] = prop["dateModified"]
|
|
48
|
+
obj_prop_path_d["version"] = prop["version"]
|
|
49
|
+
obj_prop_path_d["dateModified"] = prop["dateModified"]
|
|
50
|
+
obj_prop_path_d["owner"] = prop["owner"]["name"]
|
|
51
|
+
fold_path = ""
|
|
52
|
+
for fold in prop["ancestors"]:
|
|
53
|
+
fold_path += "/" + fold["name"]
|
|
54
|
+
|
|
55
|
+
obj_prop_path_d["fold_path"] = fold_path
|
|
56
|
+
obj_prop_path_d_l.append(obj_prop_path_d)
|
|
57
|
+
else:
|
|
58
|
+
obj_prop_path_d_l.append(prop)
|
|
59
|
+
return obj_prop_path_d_l
|
|
60
|
+
except Exception as e:
|
|
61
|
+
print(e)
|
|
62
|
+
return {}
|
|
63
|
+
|
|
64
|
+
def get_ele_prp_ans(self, conn, report_id, instance_id, prompt_id, att_form_str=None, offset=0, limit=200):
|
|
65
|
+
# get availeble objects from an element prompt
|
|
66
|
+
# be carefull, this can be an performance issue
|
|
67
|
+
# if the attribute has too many elements
|
|
68
|
+
rest_limit = limit
|
|
69
|
+
all_values = []
|
|
70
|
+
while rest_limit >= 0:
|
|
71
|
+
if att_form_str is None:
|
|
72
|
+
inst_u = f"{conn.base_url}/api/reports/{report_id}/instances/{instance_id}/prompts/{prompt_id}/elements?offset={offset}&limit={limit}"
|
|
73
|
+
else:
|
|
74
|
+
inst_u = f"{conn.base_url}/api/reports/{report_id}/instances/{instance_id}/prompts/{prompt_id}/elements?offset={offset}&limit={limit}&searchPattern={att_form_str}"
|
|
75
|
+
r = conn.get(inst_u, headers=conn.headers)
|
|
76
|
+
|
|
77
|
+
all_values.append(r.json()["elements"])
|
|
78
|
+
rest_limit = int(r.headers["x-mstr-total-count"]) - offset
|
|
79
|
+
offset += limit
|
|
80
|
+
return all_values
|
|
81
|
+
|
|
82
|
+
def get_cube_att_eleme_d_l(self, conn, cube_id, att_id):
|
|
83
|
+
url = f"{conn.base_url}/api/cubes/{cube_id}/attributes/{att_id}/elements?offset=0&limit=1000&elementIdFormat=TERSE_LONG"
|
|
84
|
+
at_ele_l = conn.get(url).json()
|
|
85
|
+
return at_ele_l
|
|
86
|
+
|
|
87
|
+
def create_dossier_instance(self, conn, dossier_id, body=None, error_msg=None):
|
|
88
|
+
endpoint = f"{conn.base_url}/api/dossiers/{dossier_id}/instances"
|
|
89
|
+
return conn.post(url=endpoint, json=body).json()["mid"]
|
|
90
|
+
|
|
91
|
+
def get_prp_ans(self, conn, report_id, instance_id, prompt_id, offset=0, limit=200):
|
|
92
|
+
# get availeble objects from an object prompt
|
|
93
|
+
rest_limit = limit
|
|
94
|
+
prp_ans_base_l = []
|
|
95
|
+
while rest_limit >= 0:
|
|
96
|
+
inst_u = f"{conn.base_url}/api/reports/{report_id}/instances/{instance_id}/prompts/{prompt_id}/objects?offset={offset}&limit={limit}"
|
|
97
|
+
r = conn.get(inst_u, headers=conn.headers)
|
|
98
|
+
prp_ans_base_l.extend(r.json()["objects"])
|
|
99
|
+
rest_limit = int(r.headers["x-mstr-total-count"]) - offset
|
|
100
|
+
offset += limit
|
|
101
|
+
|
|
102
|
+
return prp_ans_base_l
|
|
103
|
+
|
|
104
|
+
def cr_short_cut(self, conn, object_id, object_type, folder_id):
|
|
105
|
+
# create an short.
|
|
106
|
+
short_cut_folder_j = f'{{"folderId": "{folder_id}"}}'
|
|
107
|
+
short_cut_url = f"{conn.base_url}/api/objects/{object_id}/type/{str(object_type)}/shortcuts"
|
|
108
|
+
short_cut_obj_j = conn.post(short_cut_url, data=short_cut_folder_j)
|
|
109
|
+
return short_cut_obj_j
|
|
110
|
+
|
|
111
|
+
def rename_object(self, conn, object_id, object_type, new_name, desc_str):
|
|
112
|
+
# rename an existing object
|
|
113
|
+
# if an object of the same type allready exists in
|
|
114
|
+
# the same folder, it simply adds a random string
|
|
115
|
+
# fuck nows the meaning of flags=70. I just took it over
|
|
116
|
+
# from the swagger page
|
|
117
|
+
base_url = f"{conn.base_url}/api/objects/{object_id}?type={object_type}&flags=70"
|
|
118
|
+
try:
|
|
119
|
+
# short_cut_obj.alter(name=str(new_name) , description=str(desc_str))
|
|
120
|
+
body = "{" + f'"name":"{new_name}","description":"{str(desc_str)}"' + "}"
|
|
121
|
+
resp = conn.put(base_url, data=str(body))
|
|
122
|
+
except Exception:
|
|
123
|
+
# short_cut_obj.alter(name=str(new_name+ uuid.uuid1().hex), description=str(desc_str))
|
|
124
|
+
body = {"name": str(new_name + uuid.uuid1().hex), "description": str(desc_str)}
|
|
125
|
+
body = "{" + f'"name":"{new_name}{uuid.uuid1().hex}","description":"{str(desc_str)}"' + "}"
|
|
126
|
+
resp = conn.put(base_url, data=str(body))
|
|
127
|
+
|
|
128
|
+
return resp
|
|
129
|
+
|
|
130
|
+
def get_project_name(self, conn, project_id):
|
|
131
|
+
# provides a readable project name for humans
|
|
132
|
+
project_resp = conn.get(f"{conn.base_url}/api/projects")
|
|
133
|
+
project_name = ""
|
|
134
|
+
for p in project_resp.json():
|
|
135
|
+
if p["id"] == project_id:
|
|
136
|
+
project_name = p["name"]
|
|
137
|
+
|
|
138
|
+
if project_name != "":
|
|
139
|
+
return project_name
|
|
140
|
+
else:
|
|
141
|
+
raise
|
|
142
|
+
|
|
143
|
+
def get_prompt_def(self, conn, prompt_id):
|
|
144
|
+
inst_u = f"{conn.base_url}/api/model/prompts/{prompt_id}?showExpressionAs=tree"
|
|
145
|
+
r = conn.get(inst_u, headers=conn.headers)
|
|
146
|
+
return r.json()
|
|
147
|
+
|
|
148
|
+
def get_custom_group(self, conn, custom_group_id, show_expression_as="tokens"):
|
|
149
|
+
url = f"{conn.base_url}/api/model/customGroups/{custom_group_id}?showExpressionAs={show_expression_as}"
|
|
150
|
+
custom_group_def = conn.get(url)
|
|
151
|
+
return custom_group_def.json()
|
|
152
|
+
|
|
153
|
+
def get_consolidation(self, conn, consolidation_id):
|
|
154
|
+
url = f"{conn.base_url}/api/model/consolidations/{consolidation_id}"
|
|
155
|
+
consolidation_def = conn.get(url)
|
|
156
|
+
return consolidation_def.json()
|
|
157
|
+
|
|
158
|
+
def get_derived_element(self, conn, derived_element_id):
|
|
159
|
+
url = f"{conn.base_url}/api/model/derivedElements/{derived_element_id}"
|
|
160
|
+
derived_element_def = conn.get(url).json()
|
|
161
|
+
return derived_element_def
|
|
162
|
+
|
|
163
|
+
def get_hier_att(self, conn, hier_id, displayForms="All", offset=0, limit=200):
|
|
164
|
+
# Available displayForms: all, browseForms, reportDisplayForms, customForms, unknown
|
|
165
|
+
# I develope initially to get the form_ids for attribute qualification prompts
|
|
166
|
+
# what I like here is, that you get th most relevant infos of attributes
|
|
167
|
+
# in an simple way
|
|
168
|
+
rest_limit = limit
|
|
169
|
+
prp_ans_base_l = []
|
|
170
|
+
while rest_limit >= 0:
|
|
171
|
+
inst_u = f"{conn.base_url}/api/hierarchies/{hier_id}/attributes?displayForms={displayForms}&offset={offset}&limit={limit}"
|
|
172
|
+
r = conn.get(inst_u, headers=conn.headers)
|
|
173
|
+
prp_ans_base_l.append(r.json())
|
|
174
|
+
rest_limit = int(r.headers["x-mstr-total-count"]) - offset
|
|
175
|
+
offset += limit
|
|
176
|
+
|
|
177
|
+
return prp_ans_base_l
|
|
178
|
+
|
|
179
|
+
def get_report_sql(self, conn, report_id, instance_id):
|
|
180
|
+
# if a report runs into an error due to wrong SQL or
|
|
181
|
+
# doesn't return data, this can bee a big help
|
|
182
|
+
|
|
183
|
+
url = f"{conn.base_url}/api/v2/reports/{report_id}/instances/{instance_id}/sqlView"
|
|
184
|
+
rep_sql = conn.get(url)
|
|
185
|
+
return rep_sql
|
|
186
|
+
|
|
187
|
+
def get_report_all_def(
|
|
188
|
+
self, conn, report_id, show_expression_as="tokens", show_filter_tokens="true", show_advanced_properties="true"
|
|
189
|
+
):
|
|
190
|
+
url = f"{conn.base_url}/api/model/reports/{report_id}?showExpressionAs={show_expression_as}&showFilterTokens={show_filter_tokens}&showAdvancedProperties={show_advanced_properties}"
|
|
191
|
+
report_def = conn.get(url)
|
|
192
|
+
return report_def.json()
|
|
193
|
+
|
|
194
|
+
def get_cube_all_def(
|
|
195
|
+
self, conn, cube_id, showExpressionAs="tokens", showFilterTokens="true", showAdvancedProperties="true"
|
|
196
|
+
):
|
|
197
|
+
url = f"{conn.base_url}/api/model/cubes/{cube_id}?showExpressionAs={showExpressionAs}&showFilterTokens={showFilterTokens}&showAdvancedProperties={showAdvancedProperties}"
|
|
198
|
+
cube_all_def_d = conn.get(url).json()
|
|
199
|
+
return cube_all_def_d
|
|
200
|
+
|
|
201
|
+
def get_report_raw(self, conn, report_id, instance_id):
|
|
202
|
+
# normaly I use the report libraries from mstrio
|
|
203
|
+
# to fetch the data. Sometimes they bring back an error. so this one is for trouble
|
|
204
|
+
# shooting
|
|
205
|
+
url = f"{conn.base_url}/api/v2/reports/{report_id}/instances/{instance_id}/sqlView"
|
|
206
|
+
rep_sql = conn.get(url)
|
|
207
|
+
return rep_sql
|
|
208
|
+
|
|
209
|
+
def _get_vis_raw_metric_val(self, conn, dossier_id, instance_id, chapter_key, visual_key, offset=0, limit=100):
|
|
210
|
+
# reads out the metric values of a visualisation
|
|
211
|
+
# primary use is to read out REGAM JOBs
|
|
212
|
+
# technicaly it's an interim solution as I hope there will be
|
|
213
|
+
# a standard class in mstrio to export data from visuals
|
|
214
|
+
total = limit + 1
|
|
215
|
+
raw_val_l = []
|
|
216
|
+
metric_guid_d = {}
|
|
217
|
+
while total > offset:
|
|
218
|
+
regam_jobs_col_l = []
|
|
219
|
+
regam_job_metric_guid_l = []
|
|
220
|
+
# endpoint brings back data and the definition of the visual
|
|
221
|
+
url = f"{conn.base_url}/api/v2/dossiers/{dossier_id}/instances/{instance_id}/chapters/{chapter_key}/visualizations/{visual_key}?offset={offset}&limit={limit}"
|
|
222
|
+
data_viz = conn.get(url).json()
|
|
223
|
+
# read out the metric_id's in the viz
|
|
224
|
+
|
|
225
|
+
for m in data_viz["definition"]["grid"]["columns"][0]["elements"]:
|
|
226
|
+
regam_jobs_col_l.append(m["name"])
|
|
227
|
+
if "derived" in m.keys():
|
|
228
|
+
metric_guid_d["derived"] = m["derived"]
|
|
229
|
+
else:
|
|
230
|
+
metric_guid_d["derived"] = False
|
|
231
|
+
|
|
232
|
+
metric_guid_d["id"] = m["id"]
|
|
233
|
+
regam_job_metric_guid_l.append(metric_guid_d.copy())
|
|
234
|
+
|
|
235
|
+
# read out the metric values. values & ID's are machted over the order
|
|
236
|
+
regam_jobs_val_l = data_viz["data"]["metricValues"]["raw"]
|
|
237
|
+
raw_val_l.extend(i_msic.list_to_dict(list_in_l=regam_jobs_val_l, col_l=regam_jobs_col_l))
|
|
238
|
+
total = data_viz["data"]["paging"]["total"]
|
|
239
|
+
offset += limit
|
|
240
|
+
|
|
241
|
+
return {"metric_val_l": raw_val_l, "metric_guid_l": regam_job_metric_guid_l}
|
|
242
|
+
|
|
243
|
+
def get_dossier_def(self, conn, dossier_id):
|
|
244
|
+
url = f"{conn.base_url}/api/v2/dossiers/{dossier_id}/definition"
|
|
245
|
+
doss_hier = conn.get(url)
|
|
246
|
+
doss_hier_d = doss_hier.json()
|
|
247
|
+
doss_hier_d["type"] = 55
|
|
248
|
+
doss_hier_d["subtype"] = 14081
|
|
249
|
+
|
|
250
|
+
return doss_hier_d
|
|
251
|
+
|
|
252
|
+
def get_dossier_detail(self, conn, dossier_id, instance_id, chapter_key, vis_id):
|
|
253
|
+
url = f"{conn.base_url}/api/v2/dossiers/{dossier_id}/instances/"
|
|
254
|
+
url += f"{instance_id}/chapters/{chapter_key}/visualizations/{vis_id}?offset=0&limit=100000"
|
|
255
|
+
return conn.get(url).json()
|
|
256
|
+
|
|
257
|
+
def get_v2_cube_instance(self, conn, cube_id, offset_val, limit_val):
|
|
258
|
+
url = f"{conn.base_url}/api/v2/cubes/{cube_id}/instances?offset={offset_val}&limit={limit_val}"
|
|
259
|
+
return conn.post(url)
|
|
260
|
+
|
|
261
|
+
def run_mstr_search(self, conn, search_id, limit=50, includeAcl="false"):
|
|
262
|
+
all_results = []
|
|
263
|
+
offset = 0
|
|
264
|
+
totalItems = 0
|
|
265
|
+
while True:
|
|
266
|
+
url = f"{conn.base_url}/api/searchObjects/{search_id}/results?offset={offset}&limit={limit}&includeAncestors=false&includeAcl={includeAcl}"
|
|
267
|
+
response = conn.get(url)
|
|
268
|
+
results = response.json()
|
|
269
|
+
totalItems += results["totalItems"]
|
|
270
|
+
all_results.extend(results["result"])
|
|
271
|
+
|
|
272
|
+
if results["totalItems"] < limit:
|
|
273
|
+
break
|
|
274
|
+
|
|
275
|
+
offset += limit
|
|
276
|
+
|
|
277
|
+
all_result_d = {"totalItems": totalItems, "result": all_results}
|
|
278
|
+
return all_result_d
|
|
279
|
+
|
|
280
|
+
def get_open_prp_stat(self, conn, report_id, instance_id):
|
|
281
|
+
url = f"{conn.base_url}/api/reports/{report_id}/instances/{instance_id}/status"
|
|
282
|
+
stat = conn.get(url)
|
|
283
|
+
|
|
284
|
+
try:
|
|
285
|
+
status = stat.json()["status"]
|
|
286
|
+
except Exception:
|
|
287
|
+
print(stat)
|
|
288
|
+
status = 1
|
|
289
|
+
return status
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class FileIo:
|
|
5
|
+
# this class handels th io
|
|
6
|
+
# with the folder sytems
|
|
7
|
+
|
|
8
|
+
def write_JSON_to_file(self, data, file_name):
|
|
9
|
+
# writes data to file,
|
|
10
|
+
# used here forREGAM logs
|
|
11
|
+
with open(file_name, "w") as outfile:
|
|
12
|
+
outfile.write(json.dumps(data, indent=4))
|
|
13
|
+
|
|
14
|
+
def write_list_to_JSON_to_file(self, obj_l, file_name_key="file_name"):
|
|
15
|
+
for obj in obj_l:
|
|
16
|
+
try:
|
|
17
|
+
file_name = obj["file_name_key"]
|
|
18
|
+
self.write_JSON_to_file(data=obj.pop(file_name_key), file_name=file_name)
|
|
19
|
+
except Exception:
|
|
20
|
+
print(obj)
|
|
21
|
+
|
|
22
|
+
def load_JSON_files(self, file_path):
|
|
23
|
+
with open(file_path, "r") as file:
|
|
24
|
+
rag_obj_l = json.load(file)
|
|
25
|
+
|
|
26
|
+
return rag_obj_l
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class GetObjJson:
|
|
30
|
+
def extract_obj_JSON(self, conn, obj_id, obj_type_id):
|
|
31
|
+
pass
|
|
32
|
+
"""
|
|
33
|
+
get_attribute(connection: Connection, id: str, changeset_id: Optional[str] = None,
|
|
34
|
+
show_expression_as: Optional[List[str]] = None,
|
|
35
|
+
show_potential_tables: Optional[str] = None, show_fields: Optional[str] = None,
|
|
36
|
+
fields: Optional[str] = None):
|
|
37
|
+
"""
|
|
38
|
+
return
|