cosmotech-acceleration-library 1.0.0__py3-none-any.whl

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.
Files changed (141) hide show
  1. cosmotech/coal/__init__.py +8 -0
  2. cosmotech/coal/aws/__init__.py +23 -0
  3. cosmotech/coal/aws/s3.py +235 -0
  4. cosmotech/coal/azure/__init__.py +23 -0
  5. cosmotech/coal/azure/adx/__init__.py +26 -0
  6. cosmotech/coal/azure/adx/auth.py +125 -0
  7. cosmotech/coal/azure/adx/ingestion.py +329 -0
  8. cosmotech/coal/azure/adx/query.py +56 -0
  9. cosmotech/coal/azure/adx/runner.py +217 -0
  10. cosmotech/coal/azure/adx/store.py +255 -0
  11. cosmotech/coal/azure/adx/tables.py +118 -0
  12. cosmotech/coal/azure/adx/utils.py +71 -0
  13. cosmotech/coal/azure/blob.py +109 -0
  14. cosmotech/coal/azure/functions.py +72 -0
  15. cosmotech/coal/azure/storage.py +74 -0
  16. cosmotech/coal/cosmotech_api/__init__.py +36 -0
  17. cosmotech/coal/cosmotech_api/connection.py +96 -0
  18. cosmotech/coal/cosmotech_api/dataset/__init__.py +26 -0
  19. cosmotech/coal/cosmotech_api/dataset/converters.py +164 -0
  20. cosmotech/coal/cosmotech_api/dataset/download/__init__.py +19 -0
  21. cosmotech/coal/cosmotech_api/dataset/download/adt.py +119 -0
  22. cosmotech/coal/cosmotech_api/dataset/download/common.py +140 -0
  23. cosmotech/coal/cosmotech_api/dataset/download/file.py +216 -0
  24. cosmotech/coal/cosmotech_api/dataset/download/twingraph.py +188 -0
  25. cosmotech/coal/cosmotech_api/dataset/utils.py +132 -0
  26. cosmotech/coal/cosmotech_api/parameters.py +48 -0
  27. cosmotech/coal/cosmotech_api/run.py +25 -0
  28. cosmotech/coal/cosmotech_api/run_data.py +173 -0
  29. cosmotech/coal/cosmotech_api/run_template.py +108 -0
  30. cosmotech/coal/cosmotech_api/runner/__init__.py +28 -0
  31. cosmotech/coal/cosmotech_api/runner/data.py +38 -0
  32. cosmotech/coal/cosmotech_api/runner/datasets.py +364 -0
  33. cosmotech/coal/cosmotech_api/runner/download.py +146 -0
  34. cosmotech/coal/cosmotech_api/runner/metadata.py +42 -0
  35. cosmotech/coal/cosmotech_api/runner/parameters.py +157 -0
  36. cosmotech/coal/cosmotech_api/twin_data_layer.py +512 -0
  37. cosmotech/coal/cosmotech_api/workspace.py +127 -0
  38. cosmotech/coal/csm/__init__.py +6 -0
  39. cosmotech/coal/csm/engine/__init__.py +47 -0
  40. cosmotech/coal/postgresql/__init__.py +22 -0
  41. cosmotech/coal/postgresql/runner.py +93 -0
  42. cosmotech/coal/postgresql/store.py +98 -0
  43. cosmotech/coal/singlestore/__init__.py +17 -0
  44. cosmotech/coal/singlestore/store.py +100 -0
  45. cosmotech/coal/store/__init__.py +42 -0
  46. cosmotech/coal/store/csv.py +44 -0
  47. cosmotech/coal/store/native_python.py +25 -0
  48. cosmotech/coal/store/pandas.py +26 -0
  49. cosmotech/coal/store/pyarrow.py +23 -0
  50. cosmotech/coal/store/store.py +79 -0
  51. cosmotech/coal/utils/__init__.py +18 -0
  52. cosmotech/coal/utils/api.py +68 -0
  53. cosmotech/coal/utils/logger.py +10 -0
  54. cosmotech/coal/utils/postgresql.py +236 -0
  55. cosmotech/csm_data/__init__.py +6 -0
  56. cosmotech/csm_data/commands/__init__.py +6 -0
  57. cosmotech/csm_data/commands/adx_send_data.py +92 -0
  58. cosmotech/csm_data/commands/adx_send_runnerdata.py +119 -0
  59. cosmotech/csm_data/commands/api/__init__.py +6 -0
  60. cosmotech/csm_data/commands/api/api.py +50 -0
  61. cosmotech/csm_data/commands/api/postgres_send_runner_metadata.py +119 -0
  62. cosmotech/csm_data/commands/api/rds_load_csv.py +90 -0
  63. cosmotech/csm_data/commands/api/rds_send_csv.py +74 -0
  64. cosmotech/csm_data/commands/api/rds_send_store.py +74 -0
  65. cosmotech/csm_data/commands/api/run_load_data.py +120 -0
  66. cosmotech/csm_data/commands/api/runtemplate_load_handler.py +66 -0
  67. cosmotech/csm_data/commands/api/tdl_load_files.py +76 -0
  68. cosmotech/csm_data/commands/api/tdl_send_files.py +82 -0
  69. cosmotech/csm_data/commands/api/wsf_load_file.py +66 -0
  70. cosmotech/csm_data/commands/api/wsf_send_file.py +68 -0
  71. cosmotech/csm_data/commands/az_storage_upload.py +76 -0
  72. cosmotech/csm_data/commands/s3_bucket_delete.py +107 -0
  73. cosmotech/csm_data/commands/s3_bucket_download.py +118 -0
  74. cosmotech/csm_data/commands/s3_bucket_upload.py +128 -0
  75. cosmotech/csm_data/commands/store/__init__.py +6 -0
  76. cosmotech/csm_data/commands/store/dump_to_azure.py +120 -0
  77. cosmotech/csm_data/commands/store/dump_to_postgresql.py +107 -0
  78. cosmotech/csm_data/commands/store/dump_to_s3.py +169 -0
  79. cosmotech/csm_data/commands/store/list_tables.py +48 -0
  80. cosmotech/csm_data/commands/store/load_csv_folder.py +43 -0
  81. cosmotech/csm_data/commands/store/load_from_singlestore.py +96 -0
  82. cosmotech/csm_data/commands/store/reset.py +31 -0
  83. cosmotech/csm_data/commands/store/store.py +37 -0
  84. cosmotech/csm_data/main.py +57 -0
  85. cosmotech/csm_data/utils/__init__.py +6 -0
  86. cosmotech/csm_data/utils/click.py +18 -0
  87. cosmotech/csm_data/utils/decorators.py +75 -0
  88. cosmotech/orchestrator_plugins/csm-data/__init__.py +11 -0
  89. cosmotech/orchestrator_plugins/csm-data/templates/api/postgres_send_runner_metadata.json +40 -0
  90. cosmotech/orchestrator_plugins/csm-data/templates/api/rds_load_csv.json +27 -0
  91. cosmotech/orchestrator_plugins/csm-data/templates/api/rds_send_csv.json +27 -0
  92. cosmotech/orchestrator_plugins/csm-data/templates/api/rds_send_store.json +27 -0
  93. cosmotech/orchestrator_plugins/csm-data/templates/api/run_load_data.json +30 -0
  94. cosmotech/orchestrator_plugins/csm-data/templates/api/runtemplate_load_handler.json +27 -0
  95. cosmotech/orchestrator_plugins/csm-data/templates/api/tdl_load_files.json +32 -0
  96. cosmotech/orchestrator_plugins/csm-data/templates/api/tdl_send_files.json +27 -0
  97. cosmotech/orchestrator_plugins/csm-data/templates/api/try_api_connection.json +9 -0
  98. cosmotech/orchestrator_plugins/csm-data/templates/api/wsf_load_file.json +36 -0
  99. cosmotech/orchestrator_plugins/csm-data/templates/api/wsf_send_file.json +36 -0
  100. cosmotech/orchestrator_plugins/csm-data/templates/main/adx_send_runnerdata.json +29 -0
  101. cosmotech/orchestrator_plugins/csm-data/templates/main/az_storage_upload.json +25 -0
  102. cosmotech/orchestrator_plugins/csm-data/templates/main/s3_bucket_delete.json +31 -0
  103. cosmotech/orchestrator_plugins/csm-data/templates/main/s3_bucket_download.json +34 -0
  104. cosmotech/orchestrator_plugins/csm-data/templates/main/s3_bucket_upload.json +35 -0
  105. cosmotech/orchestrator_plugins/csm-data/templates/store/store_dump_to_azure.json +35 -0
  106. cosmotech/orchestrator_plugins/csm-data/templates/store/store_dump_to_postgresql.json +34 -0
  107. cosmotech/orchestrator_plugins/csm-data/templates/store/store_dump_to_s3.json +36 -0
  108. cosmotech/orchestrator_plugins/csm-data/templates/store/store_list_tables.json +15 -0
  109. cosmotech/orchestrator_plugins/csm-data/templates/store/store_load_csv_folder.json +18 -0
  110. cosmotech/orchestrator_plugins/csm-data/templates/store/store_load_from_singlestore.json +34 -0
  111. cosmotech/orchestrator_plugins/csm-data/templates/store/store_reset.json +15 -0
  112. cosmotech/translation/coal/__init__.py +6 -0
  113. cosmotech/translation/coal/en-US/coal/common/data_transfer.yml +6 -0
  114. cosmotech/translation/coal/en-US/coal/common/errors.yml +9 -0
  115. cosmotech/translation/coal/en-US/coal/common/file_operations.yml +6 -0
  116. cosmotech/translation/coal/en-US/coal/common/progress.yml +6 -0
  117. cosmotech/translation/coal/en-US/coal/common/timing.yml +5 -0
  118. cosmotech/translation/coal/en-US/coal/common/validation.yml +8 -0
  119. cosmotech/translation/coal/en-US/coal/cosmotech_api/connection.yml +10 -0
  120. cosmotech/translation/coal/en-US/coal/cosmotech_api/run_data.yml +2 -0
  121. cosmotech/translation/coal/en-US/coal/cosmotech_api/run_template.yml +8 -0
  122. cosmotech/translation/coal/en-US/coal/cosmotech_api/runner.yml +16 -0
  123. cosmotech/translation/coal/en-US/coal/cosmotech_api/solution.yml +5 -0
  124. cosmotech/translation/coal/en-US/coal/cosmotech_api/workspace.yml +7 -0
  125. cosmotech/translation/coal/en-US/coal/services/adx.yml +59 -0
  126. cosmotech/translation/coal/en-US/coal/services/api.yml +8 -0
  127. cosmotech/translation/coal/en-US/coal/services/azure_storage.yml +14 -0
  128. cosmotech/translation/coal/en-US/coal/services/database.yml +19 -0
  129. cosmotech/translation/coal/en-US/coal/services/dataset.yml +68 -0
  130. cosmotech/translation/coal/en-US/coal/services/postgresql.yml +28 -0
  131. cosmotech/translation/coal/en-US/coal/services/s3.yml +9 -0
  132. cosmotech/translation/coal/en-US/coal/solution.yml +3 -0
  133. cosmotech/translation/coal/en-US/coal/web.yml +2 -0
  134. cosmotech/translation/csm_data/__init__.py +6 -0
  135. cosmotech/translation/csm_data/en-US/csm-data.yml +434 -0
  136. cosmotech_acceleration_library-1.0.0.dist-info/METADATA +255 -0
  137. cosmotech_acceleration_library-1.0.0.dist-info/RECORD +141 -0
  138. cosmotech_acceleration_library-1.0.0.dist-info/WHEEL +5 -0
  139. cosmotech_acceleration_library-1.0.0.dist-info/entry_points.txt +2 -0
  140. cosmotech_acceleration_library-1.0.0.dist-info/licenses/LICENSE +17 -0
  141. cosmotech_acceleration_library-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,127 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+ import pathlib
8
+
9
+ import cosmotech_api
10
+
11
+ from cosmotech.coal.utils.logger import LOGGER
12
+ from cosmotech.orchestrator.utils.translate import T
13
+
14
+
15
+ def list_workspace_files(
16
+ api_client: cosmotech_api.api_client.ApiClient,
17
+ organization_id: str,
18
+ workspace_id: str,
19
+ file_prefix: str,
20
+ ) -> list[str]:
21
+ """
22
+ Helper function to list all workspace files using a pre-given file prefix
23
+ :param api_client: An api client used to connect to the Cosmo Tech API
24
+ :param organization_id: An ID of an Organization in the Cosmo Tech API
25
+ :param workspace_id: An ID of a Workspace in the Cosmo Tech API
26
+ :param file_prefix: The prefix of the files to find in the Workspace
27
+ :return: A list of existing files inside the workspace
28
+ """
29
+ target_list = []
30
+ api_ws = cosmotech_api.api.workspace_api.WorkspaceApi(api_client)
31
+ LOGGER.info(T("coal.cosmotech_api.workspace.target_is_folder"))
32
+ wsf = api_ws.find_all_workspace_files(organization_id, workspace_id)
33
+ for workspace_file in wsf:
34
+ if workspace_file.file_name.startswith(file_prefix):
35
+ target_list.append(workspace_file.file_name)
36
+
37
+ if not target_list:
38
+ LOGGER.error(
39
+ T("coal.common.errors.data_no_workspace_files").format(file_prefix=file_prefix, workspace_id=workspace_id)
40
+ )
41
+ raise ValueError(
42
+ T("coal.common.errors.data_no_workspace_files").format(file_prefix=file_prefix, workspace_id=workspace_id)
43
+ )
44
+
45
+ return target_list
46
+
47
+
48
+ def download_workspace_file(
49
+ api_client: cosmotech_api.api_client.ApiClient,
50
+ organization_id: str,
51
+ workspace_id: str,
52
+ file_name: str,
53
+ target_dir: pathlib.Path,
54
+ ) -> pathlib.Path:
55
+ """
56
+ Downloads a given file from a workspace to a given directory
57
+ If the file is inside a directory in the workspace, sub-directories will be created.
58
+ :param api_client: An api client used to connect to the Cosmo Tech API
59
+ :param organization_id: An ID of an Organization in the Cosmo Tech API
60
+ :param workspace_id: An ID of a Workspace in the Cosmo Tech API
61
+ :param file_name: The file to download to the workspace
62
+ :param target_dir: The directory in which to write the file
63
+ :return: The path to the created file
64
+ """
65
+ if target_dir.is_file():
66
+ raise ValueError(T("coal.common.file_operations.not_directory").format(target_dir=target_dir))
67
+ api_ws = cosmotech_api.api.workspace_api.WorkspaceApi(api_client)
68
+
69
+ LOGGER.info(T("coal.cosmotech_api.workspace.loading_file").format(file_name=file_name))
70
+
71
+ _file_content = api_ws.download_workspace_file(organization_id, workspace_id, file_name)
72
+
73
+ local_target_file = target_dir / file_name
74
+ local_target_file.parent.mkdir(parents=True, exist_ok=True)
75
+
76
+ with open(local_target_file, "wb") as _file:
77
+ _file.write(_file_content)
78
+
79
+ LOGGER.info(T("coal.cosmotech_api.workspace.file_loaded").format(file=local_target_file))
80
+
81
+ return local_target_file
82
+
83
+
84
+ def upload_workspace_file(
85
+ api_client: cosmotech_api.api_client.ApiClient,
86
+ organization_id: str,
87
+ workspace_id: str,
88
+ file_path: str,
89
+ workspace_path: str,
90
+ overwrite: bool = True,
91
+ ) -> str:
92
+ """
93
+ Upload a local file to a given workspace
94
+
95
+ If workspace_path ends with a "/" it will be considered as a folder inside the workspace
96
+ and the file will keep its current name
97
+
98
+ :param api_client: An api client used to connect to the Cosmo Tech API
99
+ :param organization_id: An ID of an Organization in the Cosmo Tech API
100
+ :param workspace_id: An ID of a Workspace in the Cosmo Tech API
101
+ :param file_path: Path to the file to upload in the workspace
102
+ :param workspace_path: The path inside the workspace to upload the file to
103
+ :param overwrite: Overwrite existing file in the workspace
104
+ :return: The final name of the file uploaded to the workspace
105
+ """
106
+ target_file = pathlib.Path(file_path)
107
+ if not target_file.exists():
108
+ LOGGER.error(T("coal.common.file_operations.not_exists").format(file_path=file_path))
109
+ raise ValueError(T("coal.common.file_operations.not_exists").format(file_path=file_path))
110
+ if not target_file.is_file():
111
+ LOGGER.error(T("coal.common.file_operations.not_single_file").format(file_path=file_path))
112
+ raise ValueError(T("coal.common.file_operations.not_single_file").format(file_path=file_path))
113
+
114
+ api_ws = cosmotech_api.api.workspace_api.WorkspaceApi(api_client)
115
+ destination = workspace_path + target_file.name if workspace_path.endswith("/") else workspace_path
116
+
117
+ LOGGER.info(T("coal.cosmotech_api.workspace.sending_to_api").format(destination=destination))
118
+ try:
119
+ _file = api_ws.upload_workspace_file(
120
+ organization_id, workspace_id, file_path, overwrite, destination=destination
121
+ )
122
+ except cosmotech_api.exceptions.ApiException as e:
123
+ LOGGER.error(T("coal.common.file_operations.already_exists").format(csv_path=destination))
124
+ raise e
125
+
126
+ LOGGER.info(T("coal.cosmotech_api.workspace.file_sent").format(file=_file.file_name))
127
+ return _file.file_name
@@ -0,0 +1,6 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
@@ -0,0 +1,47 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+ import csv
8
+ import glob
9
+ import json
10
+ import os
11
+
12
+
13
+ def apply_simple_csv_parameter_to_simulator(
14
+ simulator,
15
+ parameter_name: str,
16
+ target_attribute_name: str,
17
+ csv_id_column: str = "id",
18
+ csv_value_column: str = "value",
19
+ ):
20
+ """
21
+ Accelerator used to apply CSV parameters directly to a simulator
22
+ Will raise a ValueError if the parameter does not exist
23
+ If an entity is not found, will skip the row in the CSV
24
+ :param simulator: The simulator object to which the parameter will be applied
25
+ :param parameter_name: The name of the parameter fetched from the API
26
+ :param target_attribute_name: Target attribute of the entities listed in the CSV
27
+ :param csv_id_column: Column in the CSV file used for the entity ID
28
+ :param csv_value_column: Column in the CSV file used for the attribute value to change
29
+ :return: None
30
+ """
31
+ parameter_path = os.path.join(os.environ.get("CSM_PARAMETERS_ABSOLUTE_PATH"), parameter_name)
32
+ if os.path.exists(parameter_path):
33
+ csv_files = glob.glob(os.path.join(parameter_path, "*.csv"))
34
+ for csv_filename in csv_files:
35
+ model = simulator.GetModel()
36
+ with open(csv_filename, "r") as csv_file:
37
+ for row in csv.DictReader(csv_file):
38
+ entity_name = row.get(csv_id_column)
39
+ value = json.loads(row.get(csv_value_column))
40
+ entity = model.FindEntityByName(entity_name)
41
+ if entity:
42
+ entity.SetAttributeAsString(target_attribute_name, json.dumps(value))
43
+ else:
44
+ raise ValueError(f"Parameter {parameter_name} does not exists.")
45
+
46
+
47
+ __all__ = ["apply_simple_csv_parameter_to_simulator"]
@@ -0,0 +1,22 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ """
9
+ PostgreSQL integration module.
10
+
11
+ This module provides functions for interacting with PostgreSQL databases.
12
+ """
13
+
14
+ # Re-export functions from the runner module
15
+ from cosmotech.coal.postgresql.runner import (
16
+ send_runner_metadata_to_postgresql,
17
+ )
18
+
19
+ # Re-export functions from the store module
20
+ from cosmotech.coal.postgresql.store import (
21
+ dump_store_to_postgresql,
22
+ )
@@ -0,0 +1,93 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ """
9
+ PostgreSQL runner operations module.
10
+
11
+ This module provides functions for interacting with PostgreSQL databases
12
+ for runner metadata operations.
13
+ """
14
+
15
+ from adbc_driver_postgresql import dbapi
16
+
17
+ from cosmotech.coal.cosmotech_api.connection import get_api_client
18
+ from cosmotech.coal.cosmotech_api.runner.metadata import get_runner_metadata
19
+ from cosmotech.coal.utils.logger import LOGGER
20
+ from cosmotech.coal.utils.postgresql import generate_postgresql_full_uri
21
+ from cosmotech.orchestrator.utils.translate import T
22
+
23
+
24
+ def send_runner_metadata_to_postgresql(
25
+ organization_id: str,
26
+ workspace_id: str,
27
+ runner_id: str,
28
+ postgres_host: str,
29
+ postgres_port: int,
30
+ postgres_db: str,
31
+ postgres_schema: str,
32
+ postgres_user: str,
33
+ postgres_password: str,
34
+ table_prefix: str = "Cosmotech_",
35
+ ) -> None:
36
+ """
37
+ Send runner metadata to a PostgreSQL database.
38
+
39
+ Args:
40
+ organization_id: Organization ID
41
+ workspace_id: Workspace ID
42
+ runner_id: Runner ID
43
+ postgres_host: PostgreSQL host
44
+ postgres_port: PostgreSQL port
45
+ postgres_db: PostgreSQL database name
46
+ postgres_schema: PostgreSQL schema
47
+ postgres_user: PostgreSQL username
48
+ postgres_password: PostgreSQL password
49
+ table_prefix: Table prefix
50
+ """
51
+ # Get runner metadata
52
+ with get_api_client()[0] as api_client:
53
+ runner = get_runner_metadata(api_client, organization_id, workspace_id, runner_id)
54
+
55
+ # Generate PostgreSQL URI
56
+ postgresql_full_uri = generate_postgresql_full_uri(
57
+ postgres_host, str(postgres_port), postgres_db, postgres_user, postgres_password
58
+ )
59
+
60
+ # Connect to PostgreSQL and update runner metadata
61
+ with dbapi.connect(postgresql_full_uri, autocommit=True) as conn:
62
+ with conn.cursor() as curs:
63
+ schema_table = f"{postgres_schema}.{table_prefix}RunnerMetadata"
64
+ sql_create_table = f"""
65
+ CREATE TABLE IF NOT EXISTS {schema_table} (
66
+ id varchar(32) PRIMARY KEY,
67
+ name varchar(256),
68
+ last_run_id varchar(32),
69
+ run_template_id varchar(32)
70
+ );
71
+ """
72
+ sql_upsert = f"""
73
+ INSERT INTO {schema_table} (id, name, last_run_id, run_template_id)
74
+ VALUES(%s, %s, %s, %s)
75
+ ON CONFLICT (id)
76
+ DO
77
+ UPDATE SET name = EXCLUDED.name, last_run_id = EXCLUDED.last_run_id;
78
+ """
79
+ LOGGER.info(T("coal.services.postgresql.creating_table").format(schema_table=schema_table))
80
+ curs.execute(sql_create_table)
81
+ conn.commit()
82
+ LOGGER.info(T("coal.services.postgresql.metadata"))
83
+ curs.execute(
84
+ sql_upsert,
85
+ (
86
+ runner.get("id"),
87
+ runner.get("name"),
88
+ runner.get("lastRunId"),
89
+ runner.get("runTemplateId"),
90
+ ),
91
+ )
92
+ conn.commit()
93
+ LOGGER.info(T("coal.services.postgresql.metadata_updated"))
@@ -0,0 +1,98 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ """
9
+ PostgreSQL store operations module.
10
+
11
+ This module provides functions for interacting with PostgreSQL databases
12
+ for store operations.
13
+ """
14
+
15
+ from time import perf_counter
16
+ import pyarrow
17
+
18
+ from cosmotech.coal.store.store import Store
19
+ from cosmotech.coal.utils.logger import LOGGER
20
+ from cosmotech.coal.utils.postgresql import send_pyarrow_table_to_postgresql
21
+ from cosmotech.orchestrator.utils.translate import T
22
+
23
+
24
+ def dump_store_to_postgresql(
25
+ store_folder: str,
26
+ postgres_host: str,
27
+ postgres_port: int,
28
+ postgres_db: str,
29
+ postgres_schema: str,
30
+ postgres_user: str,
31
+ postgres_password: str,
32
+ table_prefix: str = "Cosmotech_",
33
+ replace: bool = True,
34
+ ) -> None:
35
+ """
36
+ Dump Store data to a PostgreSQL database.
37
+
38
+ Args:
39
+ store_folder: Folder containing the Store
40
+ postgres_host: PostgreSQL host
41
+ postgres_port: PostgreSQL port
42
+ postgres_db: PostgreSQL database name
43
+ postgres_schema: PostgreSQL schema
44
+ postgres_user: PostgreSQL username
45
+ postgres_password: PostgreSQL password
46
+ table_prefix: Table prefix
47
+ replace: Whether to replace existing tables
48
+ """
49
+ _s = Store(store_location=store_folder)
50
+
51
+ tables = list(_s.list_tables())
52
+ if len(tables):
53
+ LOGGER.info(T("coal.services.database.sending_data").format(table=f"{postgres_db}.{postgres_schema}"))
54
+ total_rows = 0
55
+ _process_start = perf_counter()
56
+ for table_name in tables:
57
+ _s_time = perf_counter()
58
+ target_table_name = f"{table_prefix}{table_name}"
59
+ LOGGER.info(T("coal.services.database.table_entry").format(table=target_table_name))
60
+ data = _s.get_table(table_name)
61
+ if not len(data):
62
+ LOGGER.info(T("coal.services.database.no_rows"))
63
+ continue
64
+ _dl_time = perf_counter()
65
+ rows = send_pyarrow_table_to_postgresql(
66
+ data,
67
+ target_table_name,
68
+ postgres_host,
69
+ postgres_port,
70
+ postgres_db,
71
+ postgres_schema,
72
+ postgres_user,
73
+ postgres_password,
74
+ replace,
75
+ )
76
+ total_rows += rows
77
+ _up_time = perf_counter()
78
+ LOGGER.info(T("coal.services.database.row_count").format(count=rows))
79
+ LOGGER.debug(
80
+ T("coal.common.timing.operation_completed").format(
81
+ operation="Load from datastore", time=f"{_dl_time - _s_time:0.3}"
82
+ )
83
+ )
84
+ LOGGER.debug(
85
+ T("coal.common.timing.operation_completed").format(
86
+ operation="Send to postgresql", time=f"{_up_time - _dl_time:0.3}"
87
+ )
88
+ )
89
+ _process_end = perf_counter()
90
+ LOGGER.info(
91
+ T("coal.services.database.rows_fetched").format(
92
+ table="all tables",
93
+ count=total_rows,
94
+ time=f"{_process_end - _process_start:0.3}",
95
+ )
96
+ )
97
+ else:
98
+ LOGGER.info(T("coal.services.database.store_empty"))
@@ -0,0 +1,17 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ """
9
+ SingleStore integration module.
10
+
11
+ This module provides functions for interacting with SingleStore databases.
12
+ """
13
+
14
+ # Re-export functions from the store module
15
+ from cosmotech.coal.singlestore.store import (
16
+ load_from_singlestore,
17
+ )
@@ -0,0 +1,100 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ """
9
+ SingleStore store operations module.
10
+
11
+ This module provides functions for interacting with SingleStore databases
12
+ for store operations.
13
+ """
14
+
15
+ import pathlib
16
+ import time
17
+ import csv
18
+ import singlestoredb as s2
19
+
20
+ from cosmotech.coal.store.csv import store_csv_file
21
+ from cosmotech.coal.store.store import Store
22
+ from cosmotech.coal.utils.logger import LOGGER
23
+ from cosmotech.orchestrator.utils.translate import T
24
+
25
+
26
+ def _get_data(table_name: str, output_directory: str, cursor) -> None:
27
+ """
28
+ Run a SQL query to fetch all data from a table and write them in csv files.
29
+
30
+ Args:
31
+ table_name: Table name
32
+ output_directory: Output directory
33
+ cursor: SingleStore cursor
34
+ """
35
+ start_time = time.perf_counter()
36
+ cursor.execute(f"SELECT * FROM {table_name}")
37
+ rows = cursor.fetchall()
38
+ end_time = time.perf_counter()
39
+ LOGGER.info(
40
+ T("coal.services.database.rows_fetched").format(
41
+ table=table_name, count=len(rows), time=round(end_time - start_time, 2)
42
+ )
43
+ )
44
+ with open(f"{output_directory}/{table_name}.csv", "w", newline="") as csv_stock:
45
+ w = csv.DictWriter(csv_stock, rows[0].keys())
46
+ w.writeheader()
47
+ w.writerows(rows)
48
+
49
+
50
+ def load_from_singlestore(
51
+ single_store_host: str,
52
+ single_store_port: int,
53
+ single_store_db: str,
54
+ single_store_user: str,
55
+ single_store_password: str,
56
+ store_folder: str,
57
+ single_store_tables: str = "",
58
+ ) -> None:
59
+ """
60
+ Load data from SingleStore and store it in the Store.
61
+
62
+ Args:
63
+ single_store_host: SingleStore host
64
+ single_store_port: SingleStore port
65
+ single_store_db: SingleStore database name
66
+ single_store_user: SingleStore username
67
+ single_store_password: SingleStore password
68
+ store_folder: Store folder
69
+ single_store_tables: Comma-separated list of tables to load
70
+ """
71
+ single_store_working_dir = store_folder + "/singlestore"
72
+ if not pathlib.Path.exists(single_store_working_dir):
73
+ pathlib.Path.mkdir(single_store_working_dir)
74
+
75
+ start_full = time.perf_counter()
76
+
77
+ conn = s2.connect(
78
+ host=single_store_host,
79
+ port=single_store_port,
80
+ database=single_store_db,
81
+ user=single_store_user,
82
+ password=single_store_password,
83
+ results_type="dicts",
84
+ )
85
+ with conn:
86
+ with conn.cursor() as cur:
87
+ if single_store_tables == "":
88
+ cur.execute("SHOW TABLES")
89
+ table_names = cur.fetchall()
90
+ else:
91
+ table_names = single_store_tables.split(",")
92
+ LOGGER.info(T("coal.services.database.tables_to_fetch").format(tables=table_names))
93
+ for name in table_names:
94
+ _get_data(name, single_store_working_dir, cur)
95
+ end_full = time.perf_counter()
96
+ LOGGER.info(T("coal.services.database.full_dataset").format(time=round(end_full - start_full, 2)))
97
+
98
+ for csv_path in pathlib.Path(single_store_working_dir).glob("*.csv"):
99
+ LOGGER.info(T("coal.services.azure_storage.found_file").format(file=csv_path.name))
100
+ store_csv_file(csv_path.name[:-4], csv_path, store=Store(False, store_folder))
@@ -0,0 +1,42 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ """
9
+ Store module.
10
+
11
+ This module provides functions for working with the Store,
12
+ including loading and converting data.
13
+ """
14
+
15
+ # Re-export the Store class
16
+ from cosmotech.coal.store.store import Store
17
+
18
+ # Re-export functions from the csv module
19
+ from cosmotech.coal.store.csv import (
20
+ store_csv_file,
21
+ convert_store_table_to_csv,
22
+ )
23
+
24
+ # Re-export functions from the native_python module
25
+ from cosmotech.coal.store.native_python import (
26
+ store_pylist,
27
+ convert_table_as_pylist,
28
+ )
29
+
30
+ # Re-export functions from the pandas module (if available)
31
+
32
+ from cosmotech.coal.store.pandas import (
33
+ store_dataframe,
34
+ convert_store_table_to_dataframe as convert_store_table_to_pandas_dataframe,
35
+ )
36
+
37
+ # Re-export functions from the pyarrow module (if available)
38
+
39
+ from cosmotech.coal.store.pyarrow import (
40
+ store_table,
41
+ convert_store_table_to_dataframe as convert_store_table_to_pyarrow_table,
42
+ )
@@ -0,0 +1,44 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ import pathlib
9
+
10
+ import pyarrow.csv as pc
11
+
12
+ from cosmotech.coal.store.store import Store
13
+
14
+
15
+ def store_csv_file(
16
+ table_name: str,
17
+ csv_path: pathlib.Path,
18
+ replace_existsing_file: bool = False,
19
+ store=Store(),
20
+ ):
21
+ if not csv_path.exists():
22
+ raise FileNotFoundError(f"File {csv_path} does not exists")
23
+
24
+ data = pc.read_csv(csv_path)
25
+ _c = data.column_names
26
+ data = data.rename_columns([Store.sanitize_column(_column) for _column in _c])
27
+
28
+ store.add_table(table_name=table_name, data=data, replace=replace_existsing_file)
29
+
30
+
31
+ def convert_store_table_to_csv(
32
+ table_name: str,
33
+ csv_path: pathlib.Path,
34
+ replace_existsing_file: bool = False,
35
+ store=Store(),
36
+ ):
37
+ if csv_path.name.endswith(".csv") and csv_path.exists() and not replace_existsing_file:
38
+ raise FileExistsError(f"File {csv_path} already exists")
39
+ if not csv_path.name.endswith(".csv"):
40
+ csv_path = csv_path / f"{table_name}.csv"
41
+ folder = csv_path.parent
42
+ folder.mkdir(parents=True, exist_ok=True)
43
+
44
+ pc.write_csv(store.get_table(table_name), csv_path)
@@ -0,0 +1,25 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ import pyarrow as pa
9
+
10
+ from cosmotech.coal.store.store import Store
11
+
12
+
13
+ def store_pylist(
14
+ table_name: str,
15
+ data: list[dict],
16
+ replace_existsing_file: bool = False,
17
+ store=Store(),
18
+ ):
19
+ data = pa.Table.from_pylist(data)
20
+
21
+ store.add_table(table_name=table_name, data=data, replace=replace_existsing_file)
22
+
23
+
24
+ def convert_table_as_pylist(table_name: str, store=Store()):
25
+ return store.get_table(table_name).to_pylist()
@@ -0,0 +1,26 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ import pyarrow
9
+
10
+ from cosmotech.coal.store.store import Store
11
+ import pandas as pd
12
+
13
+
14
+ def store_dataframe(
15
+ table_name: str,
16
+ dataframe: pd.DataFrame,
17
+ replace_existsing_file: bool = False,
18
+ store=Store(),
19
+ ):
20
+ data = pyarrow.Table.from_pandas(dataframe)
21
+
22
+ store.add_table(table_name=table_name, data=data, replace=replace_existsing_file)
23
+
24
+
25
+ def convert_store_table_to_dataframe(table_name: str, store=Store()) -> pd.DataFrame:
26
+ return store.get_table(table_name).to_pandas()
@@ -0,0 +1,23 @@
1
+ # Copyright (C) - 2023 - 2025 - Cosmo Tech
2
+ # This document and all information contained herein is the exclusive property -
3
+ # including all intellectual property rights pertaining thereto - of Cosmo Tech.
4
+ # Any use, reproduction, translation, broadcasting, transmission, distribution,
5
+ # etc., to any person is prohibited unless it has been previously and
6
+ # specifically authorized by written means by Cosmo Tech.
7
+
8
+ from cosmotech.coal.store.store import Store
9
+
10
+ import pyarrow as pa
11
+
12
+
13
+ def store_table(
14
+ table_name: str,
15
+ data: pa.Table,
16
+ replace_existsing_file: bool = False,
17
+ store=Store(),
18
+ ):
19
+ store.add_table(table_name=table_name, data=data, replace=replace_existsing_file)
20
+
21
+
22
+ def convert_store_table_to_dataframe(table_name: str, store=Store()) -> pa.Table:
23
+ return store.get_table(table_name)