commons-metrics 0.0.15__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.
@@ -0,0 +1,203 @@
1
+
2
+ from contextlib import contextmanager
3
+ from psycopg2.extras import execute_values
4
+
5
+
6
+ class UpdateDesignSystemComponents:
7
+
8
+ # ---------------UTILITY FUNCTIONS---------------#
9
+ def __init__(self, connection):
10
+ self.connection = connection
11
+
12
+ @contextmanager
13
+ def get_db_cursor(self):
14
+ """
15
+ Context manager para manejo automático de cursor
16
+ """
17
+ cursor = None
18
+ try:
19
+ cursor = self.connection.connection.cursor()
20
+ yield cursor
21
+ finally:
22
+ if cursor:
23
+ cursor.close()
24
+
25
+
26
+
27
+ def create_new_components(self, components, identifier):
28
+ """
29
+ Crea nuevos componentes en la base de datos usando un solo query
30
+ """
31
+ if not components:
32
+ return
33
+
34
+ # Preparar los datos para la inserción masiva
35
+ values_to_insert = []
36
+ for comp in components:
37
+ values_to_insert.append((
38
+ comp['technical_name'], # technical_name
39
+ identifier, # type_id
40
+ comp['folder'], # folder
41
+ comp['class'], # class_name (array de clases)
42
+ 'ACTIVE', # status (ACTIVE | DEPRECATED)
43
+ ))
44
+
45
+ # Query de inserción masiva
46
+ insert_query = """
47
+ INSERT INTO schmetrc.component(technical_name, type_id, folder, class_name, status)
48
+ VALUES %s
49
+ RETURNING id, technical_name;
50
+ """
51
+
52
+ try:
53
+ with self.get_db_cursor() as cursor:
54
+ # Ejecutar la inserción masiva
55
+ result = execute_values(
56
+ cursor,
57
+ insert_query,
58
+ values_to_insert,
59
+ template=None,
60
+ page_size=100,
61
+ fetch=True
62
+ )
63
+
64
+ # Confirmar la transacción
65
+ self.connection.connection.commit()
66
+
67
+ print(f"✅ {len(values_to_insert)} componentes creados exitosamente en la base de datos:")
68
+ for row in result:
69
+ print(f" - ID: {row[0]}, Nombre: {row[1]}")
70
+
71
+ except Exception as e:
72
+ # Revertir en caso de error
73
+ self.connection.connection.rollback()
74
+ print(f"❌ Error al crear componentes: {e}")
75
+ raise
76
+
77
+ def deprecate_old_components(self, components):
78
+ """
79
+ Marca componentes antiguos como DEPRECATED en la base de datos
80
+ """
81
+ if not components:
82
+ return
83
+
84
+ # Preparar los nombres técnicos para la actualización
85
+ technical_names = [comp['technical_name'] for comp in components]
86
+
87
+ # Query de actualización masiva
88
+ update_query = """
89
+ UPDATE schmetrc.component
90
+ SET status = 'DEPRECATED'
91
+ WHERE technical_name = ANY(%s)
92
+ RETURNING id, technical_name;
93
+ """
94
+
95
+ try:
96
+ with self.get_db_cursor() as cursor:
97
+ # Ejecutar la actualización masiva
98
+ cursor.execute(update_query, (technical_names,))
99
+ result = cursor.fetchall()
100
+
101
+ # Confirmar la transacción
102
+ self.connection.connection.commit()
103
+
104
+ print(f"⚠️ {len(result)} componentes marcados como DEPRECATED en la base de datos:")
105
+ for row in result:
106
+ print(f" - ID: {row[0]}, Nombre: {row[1]}")
107
+
108
+ except Exception as e:
109
+ # Revertir en caso de error
110
+ self.connection.connection.rollback()
111
+ print(f"❌ Error al marcar componentes como DEPRECATED: {e}")
112
+ raise
113
+
114
+ def update_db_components_info(self, db_components, components_dict):
115
+ """
116
+ Actualiza la información de los componentes en la base de datos:
117
+ - Si cambia el folder o las clases asociadas, se actualizan en la base de datos.
118
+ - Si no hay cambios, no se hace nada.
119
+ """
120
+
121
+ # Preparar listas para actualizaciones
122
+ components_to_update = []
123
+
124
+ for db_comp in db_components:
125
+ tech_name = db_comp['technical_name']
126
+ if tech_name in components_dict:
127
+ comp = components_dict[tech_name]
128
+ # Verificar si hay cambios en folder o class_name
129
+ if (db_comp['folder'] != comp['folder'] or
130
+ set(db_comp['class_name']) != set(comp['class'])):
131
+ components_to_update.append((
132
+ comp['folder'],
133
+ comp['class'],
134
+ tech_name,
135
+ "ACTIVE"
136
+ ))
137
+
138
+ if not components_to_update:
139
+ print("ℹ️ No hay componentes que actualizar en la base de datos.")
140
+ return
141
+
142
+ # Query de actualización masiva usando CTE
143
+ update_query = """
144
+ WITH updates(folder, class_name, technical_name, status) AS (
145
+ VALUES %s
146
+ )
147
+ UPDATE schmetrc.component
148
+ SET folder = updates.folder,
149
+ class_name = updates.class_name,
150
+ status = updates.status
151
+ FROM updates
152
+ WHERE schmetrc.component.technical_name = updates.technical_name
153
+ RETURNING schmetrc.component.id, schmetrc.component.technical_name;
154
+ """
155
+
156
+ try:
157
+ with self.get_db_cursor() as cursor:
158
+ # Ejecutar la actualización masiva
159
+ result = execute_values(
160
+ cursor,
161
+ update_query,
162
+ components_to_update,
163
+ template=None,
164
+ page_size=100,
165
+ fetch=True
166
+ )
167
+
168
+ # Confirmar la transacción
169
+ self.connection.connection.commit()
170
+
171
+ print(f"✅ {len(result)} componentes actualizados en la base de datos:")
172
+ for row in result:
173
+ print(f"🔄 Componente actualizado - ID: {row[0]}, Nombre: {row[1]}")
174
+
175
+ except Exception as e:
176
+ print(f"❌ Error al actualizar componentes en la base de datos: {e}")
177
+ self.connection.connection.rollback()
178
+ raise
179
+
180
+ def update_db(self, db_components, all_components, identifier):
181
+ """
182
+ Actualiza la base de datos con los componentes actuales del proyecto
183
+ """
184
+ # Comparar base de datos con componentes encontrados, y listar las diferencias, obtener los componentes completos
185
+ db_components_dict = {comp['technical_name']: comp for comp in db_components}
186
+ components_dict = {comp['technical_name']: comp for comp in all_components}
187
+
188
+ # Obtener conjuntos de nombres para comparación
189
+ db_component_names = set(db_components_dict.keys())
190
+ component_names = set(components_dict.keys())
191
+
192
+ # Componentes que están en el proyecto pero NO en la base de datos (nuevos)
193
+ missing_in_db_names = component_names - db_component_names
194
+ missing_in_db_components = [components_dict[name] for name in missing_in_db_names]
195
+ self.create_new_components(missing_in_db_components, identifier)
196
+
197
+ # Componentes que están en la base de datos pero NO en el proyecto
198
+ missing_in_names = db_component_names - component_names
199
+ missing_in_components = [db_components_dict[name] for name in missing_in_names]
200
+ self.deprecate_old_components(missing_in_components)
201
+
202
+ # Actualizar información de componentes comunes
203
+ self.update_db_components_info(db_components, components_dict)
@@ -0,0 +1,38 @@
1
+ import boto3
2
+ import json
3
+
4
+ class Util:
5
+ """Utility class for common operations"""
6
+
7
+ @staticmethod
8
+ def get_secret_aws(secret_name: str, logger, region_name: str):
9
+ """
10
+ Retrieves AWS Secrets Manager secret and returns database credentials
11
+ """
12
+ try:
13
+ session = boto3.session.Session()
14
+ client = session.client(
15
+ service_name='secretsmanager',
16
+ region_name=region_name
17
+ )
18
+
19
+ get_secret_value_response = client.get_secret_value(SecretId=secret_name)
20
+ secret_string = get_secret_value_response['SecretString']
21
+ secret_json = json.loads(secret_string)
22
+
23
+ required_keys = ["password", "host", "port", "username", "dbname"]
24
+ missing_keys = [key for key in required_keys if key not in secret_json]
25
+
26
+ if missing_keys:
27
+ msg = f"Missing required keys in AWS secret: {missing_keys}"
28
+ logger.error(msg)
29
+ raise KeyError(msg)
30
+
31
+ return secret_json
32
+
33
+ except Exception as e:
34
+ msg = f"Error getting the secret '{secret_name}': {str(e)}"
35
+ logger.error(msg)
36
+ raise Exception(msg)
37
+
38
+
@@ -0,0 +1,17 @@
1
+ Metadata-Version: 2.4
2
+ Name: commons_metrics
3
+ Version: 0.0.15
4
+ Summary: A simple library for basic statistical calculations
5
+ Author: Bancolombia
6
+ Author-email: omar.david.pino@email.com
7
+ License: MIT
8
+ Requires-Python: >=3.7
9
+ License-File: LICENSE
10
+ Requires-Dist: boto3
11
+ Dynamic: author
12
+ Dynamic: author-email
13
+ Dynamic: license
14
+ Dynamic: license-file
15
+ Dynamic: requires-dist
16
+ Dynamic: requires-python
17
+ Dynamic: summary
@@ -0,0 +1,13 @@
1
+ commons_metrics/__init__.py,sha256=y_liVt7ATvuZ2rUqNKlZ0Xzwo2TKi1sJ1SfYRRtBM6c,434
2
+ commons_metrics/azure_devops_client.py,sha256=sD130ggzZWUsNqkBVNrLH80_AN00CxQ4preP9sBdzHM,16778
3
+ commons_metrics/commons_repos_client.py,sha256=SYIe1fFXM3qlc_G154AmorHScPS3rTsztKqxy3dD28w,4150
4
+ commons_metrics/database.py,sha256=570TtLZ9psNzvIp75UFLYph34cKVEz6eGJgxXyRyjW4,1285
5
+ commons_metrics/github_api_client.py,sha256=yPLsqn_KvQDIXcNp7Ma8qQwWy8svpXNLpDX69vwL9BU,11465
6
+ commons_metrics/repositories.py,sha256=7k3cvIEF_OiMt56C_DAM6V3-4t66SmciiSQ3rGfmEoU,10567
7
+ commons_metrics/update_design_components.py,sha256=QpY0GCCCMjdYOZ7b8oNigU9iTpiGx91CYsyWwN8WVDA,7660
8
+ commons_metrics/util.py,sha256=98zuynalXumQRh-BB0Bcjyoh6vS2BTOUM8tVgr7iS9Q,1225
9
+ commons_metrics-0.0.15.dist-info/licenses/LICENSE,sha256=jsHZ2Sh1wCL74HC25pDDGXCyQ0xgsTAy62FvEnehKIg,1067
10
+ commons_metrics-0.0.15.dist-info/METADATA,sha256=YuGozHIdHx_k_9inq2iS6IKSv85gtJJH15d_aLxoT14,402
11
+ commons_metrics-0.0.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ commons_metrics-0.0.15.dist-info/top_level.txt,sha256=lheUN-3OKdU3A8Tg8Y-1IEB_9i_vVRA0g_FOiUsTQz8,16
13
+ commons_metrics-0.0.15.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Paras Arora
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ commons_metrics