orionis 0.383.0__py3-none-any.whl → 0.384.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.
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.383.0"
8
+ VERSION = "0.384.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionis
3
- Version: 0.383.0
3
+ Version: 0.384.0
4
4
  Summary: Orionis Framework – Elegant, Fast, and Powerful.
5
5
  Home-page: https://github.com/orionis-framework/framework
6
6
  Author: Raul Mauricio Uñate Castro
@@ -247,7 +247,7 @@ orionis/foundation/providers/path_resolver_provider.py,sha256=rXvaVc5sSqmDgRzWJo
247
247
  orionis/foundation/providers/progress_bar_provider.py,sha256=75Jr4iEgUOUGl8Di1DioeP5_HRQlR-1lVzPmS96sWjA,737
248
248
  orionis/foundation/providers/workers_provider.py,sha256=WWlji3C69_-Y0c42aZDbR_bmcE_qZEh2SaA_cNkCivI,702
249
249
  orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
- orionis/metadata/framework.py,sha256=BqO4gDTSWamxPbPJV_8Vzu2LN3mlPQPQ_sZ8CFxPQ0E,4960
250
+ orionis/metadata/framework.py,sha256=oMBUNYD0ebJNCgTheoBBP_gk5ABdN2u9b86Tkm3zOVk,4960
251
251
  orionis/metadata/package.py,sha256=tqLfBRo-w1j_GN4xvzUNFyweWYFS-qhSgAEc-AmCH1M,5452
252
252
  orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
253
253
  orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -380,12 +380,11 @@ orionis/test/exceptions/value.py,sha256=r3tVWTE3gNp7of2gXk71NN-VYoAlOpB0kulw0LOJ
380
380
  orionis/test/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
381
381
  orionis/test/output/dumper.py,sha256=5_SrMWTlmdqDbPA6ggnhTrI2gaUMr6aA0xTNYpOLFMk,4202
382
382
  orionis/test/output/printer.py,sha256=gHDa2Q_q2ZnWM7j_JpCnrjzfKQrT-lMCcnVp7-2fUyU,17625
383
- orionis/test/record/history.py,sha256=EOQcloMVdhlNl2lU9igQz8H4b-OtKtiwh2pgr_QZWOI,13186
384
383
  orionis/test/records/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
385
384
  orionis/test/records/logs.py,sha256=EOQcloMVdhlNl2lU9igQz8H4b-OtKtiwh2pgr_QZWOI,13186
386
385
  orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
387
386
  orionis/test/view/render.py,sha256=zd7xDvVfmQ2HxZamDTzL2-z2PpyL99EaolbbM7wTah4,5014
388
- orionis-0.383.0.dist-info/licenses/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
387
+ orionis-0.384.0.dist-info/licenses/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
389
388
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
390
389
  tests/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
391
390
  tests/example/test_example.py,sha256=-NNP8odGdR5XrXK7w5vEvdVVGgPcoLFLJWf-ALf4GwU,1057
@@ -486,8 +485,8 @@ tests/support/wrapper/test_services_wrapper_docdict.py,sha256=nTNrvJkMSPx_aopEQ9
486
485
  tests/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
487
486
  tests/testing/test_testing_result.py,sha256=fnH7hjumNSErAFGITJgq2LHxSzvPF2tdtmHL9kyAv-Y,4409
488
487
  tests/testing/test_testing_unit.py,sha256=d3CRGo6608fMzYcZKIKapjx_af2aigqWiKSiuK9euIY,7600
489
- orionis-0.383.0.dist-info/METADATA,sha256=I8CUQ2SmTosK3-sM_gkcoC5aFzXeBpuVGkrb89ZiGZY,4772
490
- orionis-0.383.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
491
- orionis-0.383.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
492
- orionis-0.383.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
493
- orionis-0.383.0.dist-info/RECORD,,
488
+ orionis-0.384.0.dist-info/METADATA,sha256=rjqr90NxqIZulCDdET4d1vP0-NZrfDByOl0OJkpVlXI,4772
489
+ orionis-0.384.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
490
+ orionis-0.384.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
491
+ orionis-0.384.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
492
+ orionis-0.384.0.dist-info/RECORD,,
@@ -1,385 +0,0 @@
1
- import json
2
- import re
3
- import sqlite3
4
- from pathlib import Path
5
- from typing import Dict, List, Optional, Tuple
6
- from orionis.services.environment.env import Env
7
- from orionis.test.exceptions import OrionisTestPersistenceError, OrionisTestValueError
8
- from orionis.test.contracts.logs import ITestLogs
9
-
10
- class TestLogs(ITestLogs):
11
-
12
- def __init__(
13
- self,
14
- storage_path: Optional[str] = None,
15
- db_name: Optional[str] = 'tests.sqlite',
16
- table_name: Optional[str] = 'reports',
17
- ) -> None:
18
- """
19
- Initialize the history storage for test logs.
20
-
21
- Parameters
22
- ----------
23
- storage_path : Optional[str], default=None
24
- Directory path where the database file will be stored. If not provided,
25
- the path is determined from the TEST_DB_PATH environment variable or
26
- defaults to 'orionis/test/logs/storage' in the current working directory.
27
- db_name : Optional[str], default='tests.sqlite'
28
- Name of the SQLite database file. Must be alphanumeric or underscore and
29
- end with '.sqlite'.
30
- table_name : Optional[str], default='reports'
31
- Name of the table to use in the database. Must be alphanumeric or underscore.
32
-
33
- Raises
34
- ------
35
- OrionisTestValueError
36
- If db_name or table_name do not meet the required format.
37
- """
38
-
39
- # Validate db_name: only alphanumeric and underscores, must end with .sqlite
40
- if not isinstance(db_name, str) or not re.fullmatch(r'[a-zA-Z0-9_]+\.sqlite', db_name):
41
- raise OrionisTestValueError("Database name must be alphanumeric/underscore and end with '.sqlite'.")
42
- self.__db_name = db_name
43
-
44
- # Validate table_name: only alphanumeric and underscores
45
- if not isinstance(table_name, str) or not re.fullmatch(r'[a-zA-Z0-9_]+', table_name):
46
- raise OrionisTestValueError("Table name must be alphanumeric/underscore only.")
47
- self.__table_name = table_name
48
-
49
- # Determine database path
50
- db_path = None
51
- if storage_path:
52
- db_path = Path(storage_path).expanduser().resolve()
53
- if db_path.is_dir():
54
- db_path = db_path / self.__db_name
55
- else:
56
- env_path = Env.get("TEST_DB_PATH", None)
57
- if env_path:
58
- db_path = Path(env_path).expanduser().resolve()
59
- if db_path.is_dir():
60
- db_path = db_path / self.__db_name
61
- else:
62
- db_path = Path.cwd() / 'storage/framework/testing' / self.__db_name
63
-
64
- # Ensure parent directory exists
65
- db_path.parent.mkdir(parents=True, exist_ok=True)
66
-
67
- # Store path in environment
68
- Env.set("TEST_DB_PATH", str(db_path), 'path')
69
- self.__db_path = db_path
70
-
71
- # Create a connection to the database, initially set to None
72
- self._conn: Optional[sqlite3.Connection] = None
73
-
74
- def __connect(
75
- self
76
- ) -> None:
77
- """
78
- Establishes a connection to the SQLite database if not already connected.
79
-
80
- Attempts to create a new SQLite connection using the provided database path.
81
- If the connection fails, raises an OrionisTestPersistenceError with the error details.
82
-
83
- Raises
84
- ------
85
- OrionisTestPersistenceError
86
- If a database connection error occurs.
87
- """
88
- if self._conn is None:
89
- try:
90
- self._conn = sqlite3.connect(str(self.__db_path))
91
- except (sqlite3.Error, Exception) as e:
92
- raise OrionisTestPersistenceError(f"Database connection error: {e}")
93
-
94
- def __createTableIfNotExists(
95
- self
96
- ) -> bool:
97
- """
98
- Ensures that the test history table exists in the database.
99
-
100
- Connects to the database and creates the table with the required schema if it does not already exist.
101
- Handles any SQLite errors by rolling back the transaction and raising a custom exception.
102
-
103
- Raises
104
- ------
105
- OrionisTestPersistenceError
106
- If the table creation fails due to a database error.
107
-
108
- Returns
109
- -------
110
- bool
111
- True if the table was created successfully or already exists, False otherwise.
112
- """
113
-
114
- self.__connect()
115
- try:
116
- cursor = self._conn.cursor()
117
- cursor.execute(f'''
118
- CREATE TABLE IF NOT EXISTS {self.__table_name} (
119
- id INTEGER PRIMARY KEY AUTOINCREMENT,
120
- json TEXT NOT NULL,
121
- total_tests INTEGER,
122
- passed INTEGER,
123
- failed INTEGER,
124
- errors INTEGER,
125
- skipped INTEGER,
126
- total_time REAL,
127
- success_rate REAL,
128
- timestamp TEXT
129
- )
130
- ''')
131
- self._conn.commit()
132
- return True
133
- except sqlite3.Error as e:
134
- if self._conn:
135
- self._conn.rollback()
136
- raise OrionisTestPersistenceError(f"Failed to create table: {e}")
137
- finally:
138
- if self._conn:
139
- self.__close()
140
- self._conn = None
141
-
142
- def __insertReport(
143
- self,
144
- report: Dict
145
- ) -> bool:
146
- """
147
- Inserts a test report into the history database table.
148
-
149
- Parameters
150
- ----------
151
- report : Dict
152
- A dictionary containing the report data. Must include the following keys:
153
- - total_tests
154
- - passed
155
- - failed
156
- - errors
157
- - skipped
158
- - total_time
159
- - success_rate
160
- - timestamp
161
-
162
- Raises
163
- ------
164
- OrionisTestPersistenceError
165
- If there is an error inserting the report into the database.
166
- OrionisTestValueError
167
- If required fields are missing from the report.
168
-
169
- Returns
170
- -------
171
- bool
172
- True if the report was successfully inserted, False otherwise.
173
- """
174
-
175
- # Required fields in the report
176
- fields = [
177
- "json", "total_tests", "passed", "failed", "errors",
178
- "skipped", "total_time", "success_rate", "timestamp"
179
- ]
180
-
181
- # Validate report structure
182
- missing = []
183
- for key in fields:
184
- if key not in report and key != "json":
185
- missing.append(key)
186
- if missing:
187
- raise OrionisTestValueError(f"Missing report fields: {missing}")
188
-
189
- # Insert the report into the database
190
- self.__connect()
191
- try:
192
-
193
- # Query to insert the report into the table
194
- query = f'''
195
- INSERT INTO {self.__table_name} (
196
- json, total_tests, passed, failed, errors,
197
- skipped, total_time, success_rate, timestamp
198
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
199
- '''
200
-
201
- # Execute the insert query with the report data
202
- cursor = self._conn.cursor()
203
- cursor.execute(query, (
204
- json.dumps(report),
205
- report["total_tests"],
206
- report["passed"],
207
- report["failed"],
208
- report["errors"],
209
- report["skipped"],
210
- report["total_time"],
211
- report["success_rate"],
212
- report["timestamp"]
213
- ))
214
- self._conn.commit()
215
- return True
216
- except sqlite3.Error as e:
217
- if self._conn:
218
- self._conn.rollback()
219
- raise OrionisTestPersistenceError(f"Failed to insert report: {e}")
220
- finally:
221
- if self._conn:
222
- self.__close()
223
- self._conn = None
224
-
225
- def __getReports(
226
- self,
227
- first: Optional[int] = None,
228
- last: Optional[int] = None
229
- ) -> List[Tuple]:
230
- """
231
- Retrieves a specified number of report records from the database, ordered by their ID.
232
-
233
- Parameters
234
- ----------
235
- first : Optional[int], default=None
236
- The number of earliest reports to retrieve, ordered ascending by ID.
237
- last : Optional[int], default=None
238
- The number of latest reports to retrieve, ordered descending by ID.
239
-
240
- Returns
241
- -------
242
- List[Tuple]
243
- A list of tuples representing the report records.
244
-
245
- Raises
246
- ------
247
- OrionisTestValueError
248
- If both 'first' and 'last' are specified, or if either is not a positive integer.
249
- OrionisTestPersistenceError
250
- If there is an error retrieving reports from the database.
251
- """
252
-
253
- # Validate parameters
254
- if first is not None and last is not None:
255
- raise OrionisTestValueError(
256
- "Cannot specify both 'first' and 'last' parameters. Use one or the other."
257
- )
258
- if first is not None:
259
- if not isinstance(first, int) or first <= 0:
260
- raise OrionisTestValueError("'first' must be an integer greater than 0.")
261
- if last is not None:
262
- if not isinstance(last, int) or last <= 0:
263
- raise OrionisTestValueError("'last' must be an integer greater than 0.")
264
-
265
- order = 'DESC' if last is not None else 'ASC'
266
- quantity = first if first is not None else last
267
-
268
- self.__connect()
269
- try:
270
- cursor = self._conn.cursor()
271
- query = f"SELECT * FROM {self.__table_name} ORDER BY id {order} LIMIT ?"
272
- cursor.execute(query, (quantity,))
273
- results = cursor.fetchall()
274
- return results
275
- except sqlite3.Error as e:
276
- raise OrionisTestPersistenceError(f"Failed to retrieve reports from '{self.__db_name}': {e}")
277
- finally:
278
- if self._conn:
279
- self.__close()
280
- self._conn = None
281
-
282
- def __resetDatabase(
283
- self
284
- ) -> bool:
285
- """
286
- Resets the database by dropping the existing table.
287
- This method connects to the database, drops the table specified by
288
- `self.__table_name` if it exists, commits the changes, and then closes
289
- the connection. If an error occurs during the process, an
290
- OrionisTestPersistenceError is raised.
291
-
292
- Raises
293
- ------
294
- OrionisTestPersistenceError
295
- If the database reset operation fails due to an SQLite error.
296
-
297
- Returns
298
- -------
299
- bool
300
- True if the database was successfully reset, False otherwise.
301
- """
302
-
303
- self.__connect()
304
- try:
305
- cursor = self._conn.cursor()
306
- cursor.execute(f'DROP TABLE IF EXISTS {self.__table_name}')
307
- self._conn.commit()
308
- return True
309
- except sqlite3.Error as e:
310
- raise OrionisTestPersistenceError(f"Failed to reset database: {e}")
311
- finally:
312
- if self._conn:
313
- self.__close()
314
- self._conn = None
315
-
316
- def __close(
317
- self
318
- ) -> None:
319
- """
320
- Closes the current database connection.
321
- This method checks if a database connection exists. If so, it closes the connection and sets the connection attribute to None.
322
-
323
- Returns
324
- -------
325
- None
326
- """
327
-
328
- if self._conn:
329
- self._conn.close()
330
- self._conn = None
331
-
332
- def create(
333
- self,
334
- report: Dict
335
- ) -> bool:
336
- """
337
- Create a new test report in the history database.
338
-
339
- Parameters
340
- ----------
341
- report : Dict
342
- A dictionary containing the test report data.
343
-
344
- Returns
345
- -------
346
- bool
347
- True if the report was successfully created, False otherwise.
348
- """
349
- self.__createTableIfNotExists()
350
- return self.__insertReport(report)
351
-
352
- def reset(
353
- self
354
- ) -> bool:
355
- """
356
- Reset the history database by dropping the existing table.
357
-
358
- Returns
359
- -------
360
- bool
361
- True if the database was successfully reset, False otherwise.
362
- """
363
- return self.__resetDatabase()
364
-
365
- def get(
366
- self,
367
- first: Optional[int] = None,
368
- last: Optional[int] = None
369
- ) -> List[Tuple]:
370
- """
371
- Retrieve test reports from the history database.
372
-
373
- Parameters
374
- ----------
375
- first : Optional[int], default=None
376
- The number of earliest reports to retrieve, ordered ascending by ID.
377
- last : Optional[int], default=None
378
- The number of latest reports to retrieve, ordered descending by ID.
379
-
380
- Returns
381
- -------
382
- List[Tuple]
383
- A list of tuples representing the retrieved reports.
384
- """
385
- return self.__getReports(first, last)