ecodev-core 0.0.67__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.
- ecodev_core/__init__.py +129 -0
- ecodev_core/app_activity.py +126 -0
- ecodev_core/app_rights.py +24 -0
- ecodev_core/app_user.py +92 -0
- ecodev_core/auth_configuration.py +24 -0
- ecodev_core/authentication.py +316 -0
- ecodev_core/backup.py +105 -0
- ecodev_core/check_dependencies.py +179 -0
- ecodev_core/custom_equal.py +27 -0
- ecodev_core/db_connection.py +94 -0
- ecodev_core/db_filters.py +142 -0
- ecodev_core/db_i18n.py +211 -0
- ecodev_core/db_insertion.py +128 -0
- ecodev_core/db_retrieval.py +193 -0
- ecodev_core/db_upsertion.py +382 -0
- ecodev_core/deployment.py +16 -0
- ecodev_core/email_sender.py +60 -0
- ecodev_core/encryption.py +46 -0
- ecodev_core/enum_utils.py +21 -0
- ecodev_core/es_connection.py +79 -0
- ecodev_core/list_utils.py +134 -0
- ecodev_core/logger.py +122 -0
- ecodev_core/pandas_utils.py +69 -0
- ecodev_core/permissions.py +21 -0
- ecodev_core/pydantic_utils.py +33 -0
- ecodev_core/read_write.py +52 -0
- ecodev_core/rest_api_client.py +211 -0
- ecodev_core/rest_api_configuration.py +25 -0
- ecodev_core/safe_utils.py +241 -0
- ecodev_core/settings.py +51 -0
- ecodev_core/sqlmodel_utils.py +16 -0
- ecodev_core/token_banlist.py +18 -0
- ecodev_core/version.py +144 -0
- ecodev_core-0.0.67.dist-info/LICENSE.md +11 -0
- ecodev_core-0.0.67.dist-info/METADATA +87 -0
- ecodev_core-0.0.67.dist-info/RECORD +37 -0
- ecodev_core-0.0.67.dist-info/WHEEL +4 -0
ecodev_core/version.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module implementing the Version table
|
|
3
|
+
"""
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from enum import EnumType
|
|
7
|
+
from enum import unique
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from sqlmodel import desc
|
|
11
|
+
from sqlmodel import Field
|
|
12
|
+
from sqlmodel import Index
|
|
13
|
+
from sqlmodel import select
|
|
14
|
+
from sqlmodel import Session
|
|
15
|
+
from sqlmodel import SQLModel
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@unique
|
|
19
|
+
class ColType(str, Enum):
|
|
20
|
+
"""
|
|
21
|
+
Enum listing all col types allowed to be stored in version
|
|
22
|
+
"""
|
|
23
|
+
STR = 'str'
|
|
24
|
+
BOOL = 'bool'
|
|
25
|
+
INT = 'int'
|
|
26
|
+
FLOAT = 'float'
|
|
27
|
+
DATE = 'datetime'
|
|
28
|
+
ENUM = 'enum'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
COL_TYPES = str | int | bool | float | datetime | Enum | None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Version(SQLModel, table=True): # type: ignore
|
|
35
|
+
"""
|
|
36
|
+
Table handling versioning.
|
|
37
|
+
|
|
38
|
+
Attributes are:
|
|
39
|
+
- table: the table to version
|
|
40
|
+
- column: the column of table to version
|
|
41
|
+
- row_id: the row id of the column of table to version
|
|
42
|
+
- col_type: the column type
|
|
43
|
+
- value: the value to store (previous row/column/table version)
|
|
44
|
+
"""
|
|
45
|
+
__tablename__ = 'version'
|
|
46
|
+
id: Optional[int] = Field(default=None, primary_key=True)
|
|
47
|
+
created_at: datetime = Field(default_factory=datetime.utcnow)
|
|
48
|
+
table: str = Field(index=True)
|
|
49
|
+
column: str = Field(index=True)
|
|
50
|
+
row_id: int = Field(index=True)
|
|
51
|
+
col_type: ColType
|
|
52
|
+
value: str | None = Field(index=True)
|
|
53
|
+
|
|
54
|
+
__table_args__ = (
|
|
55
|
+
Index(
|
|
56
|
+
'version_filter_id',
|
|
57
|
+
'table',
|
|
58
|
+
'row_id',
|
|
59
|
+
'column'
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def from_table_row(cls, table: str,
|
|
65
|
+
column: str,
|
|
66
|
+
row_id: int,
|
|
67
|
+
raw_type: type | EnumType,
|
|
68
|
+
raw_val: COL_TYPES
|
|
69
|
+
) -> 'Version':
|
|
70
|
+
"""
|
|
71
|
+
Create a new Version out of the passed information
|
|
72
|
+
"""
|
|
73
|
+
col_type = _col_type_to_db(raw_type)
|
|
74
|
+
value = _value_to_db(raw_val, col_type)
|
|
75
|
+
return cls(table=table, column=column, row_id=row_id, col_type=col_type, value=value)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_versions(table: str, column: str, row_id: int, session: Session) -> list[Version]:
|
|
79
|
+
"""
|
|
80
|
+
Retrieve all previous versions of a (table, column, row_id) triplet
|
|
81
|
+
"""
|
|
82
|
+
query = select(Version).where(Version.table == table, Version.row_id == row_id,
|
|
83
|
+
Version.column == column).order_by(desc(Version.created_at))
|
|
84
|
+
return session.exec(query).all()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def get_row_versions(table: str, row_id: int, session: Session) -> list[Version]:
|
|
88
|
+
"""
|
|
89
|
+
Retrieve all previous versions of a (table, row_id) couples. Hence all columns previous versions
|
|
90
|
+
"""
|
|
91
|
+
query = select(Version).where(Version.table == table, Version.row_id == row_id
|
|
92
|
+
).order_by(desc(Version.created_at))
|
|
93
|
+
return session.exec(query).all()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _col_type_to_db(col_type: type | EnumType) -> ColType:
|
|
97
|
+
"""
|
|
98
|
+
Forge ColType out of passed col_type
|
|
99
|
+
"""
|
|
100
|
+
if issubclass(int, col_type):
|
|
101
|
+
return ColType.INT
|
|
102
|
+
if issubclass(bool, col_type):
|
|
103
|
+
return ColType.BOOL
|
|
104
|
+
if issubclass(float, col_type):
|
|
105
|
+
return ColType.FLOAT
|
|
106
|
+
if issubclass(str, col_type):
|
|
107
|
+
return ColType.STR
|
|
108
|
+
if issubclass(datetime, col_type):
|
|
109
|
+
return ColType.DATE
|
|
110
|
+
return ColType.ENUM
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _value_to_db(value: COL_TYPES, col_type: ColType) -> str | None:
|
|
114
|
+
"""
|
|
115
|
+
Convert a value to version to it's str version
|
|
116
|
+
"""
|
|
117
|
+
if value is None:
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
match col_type:
|
|
121
|
+
case ColType.BOOL | ColType.STR | ColType.INT | ColType.FLOAT:
|
|
122
|
+
return str(value)
|
|
123
|
+
case ColType.DATE:
|
|
124
|
+
return value.strftime('%Y-%m-%d %H:%M:%S.%f') # type: ignore[union-attr]
|
|
125
|
+
case ColType.ENUM:
|
|
126
|
+
return value.name # type: ignore[union-attr]
|
|
127
|
+
case _:
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def db_to_value(db_value: str | None, col_type: type | EnumType) -> COL_TYPES:
|
|
132
|
+
"""
|
|
133
|
+
Convert back a str version value stored to a real value (types handled listed in ColType)
|
|
134
|
+
NB: assumption that if the type is not known, this is an enum type.
|
|
135
|
+
"""
|
|
136
|
+
if db_value is None:
|
|
137
|
+
return None
|
|
138
|
+
if col_type in [int, str, float]:
|
|
139
|
+
return col_type(db_value)
|
|
140
|
+
if col_type == bool:
|
|
141
|
+
return db_value == 'True'
|
|
142
|
+
if col_type == datetime:
|
|
143
|
+
return datetime.strptime(db_value, '%Y-%m-%d %H:%M:%S.%f')
|
|
144
|
+
return col_type[db_value] # type: ignore[index]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright 2025 - Schneider Electric
|
|
2
|
+
|
|
3
|
+
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,
|
|
4
|
+
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,
|
|
5
|
+
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,
|
|
10
|
+
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,
|
|
11
|
+
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,87 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ecodev-core
|
|
3
|
+
Version: 0.0.67
|
|
4
|
+
Summary: Low level sqlmodel/fastapi/pydantic building blocks
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Thomas Epelbaum
|
|
7
|
+
Author-email: tomepel@gmail.com
|
|
8
|
+
Requires-Python: >=3.11,<4.0
|
|
9
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
|
+
Classifier: Environment :: Web Environment
|
|
11
|
+
Classifier: Framework :: AsyncIO
|
|
12
|
+
Classifier: Framework :: FastAPI
|
|
13
|
+
Classifier: Framework :: Pydantic
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Intended Audience :: System Administrators
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
26
|
+
Classifier: Topic :: Database
|
|
27
|
+
Classifier: Topic :: Database :: Database Engines/Servers
|
|
28
|
+
Classifier: Topic :: Internet
|
|
29
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
30
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
31
|
+
Classifier: Topic :: Software Development
|
|
32
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
33
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
34
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
35
|
+
Classifier: Typing :: Typed
|
|
36
|
+
Requires-Dist: cryptography (>=46,<47)
|
|
37
|
+
Requires-Dist: elasticsearch (>=8.14.0,<9.0.0)
|
|
38
|
+
Requires-Dist: fastapi (>=0,<1)
|
|
39
|
+
Requires-Dist: httpx (>=0,<1)
|
|
40
|
+
Requires-Dist: numpy (>=1,<2)
|
|
41
|
+
Requires-Dist: openpyxl (>=3,<4)
|
|
42
|
+
Requires-Dist: orjson (>=3.10.5,<4.0.0)
|
|
43
|
+
Requires-Dist: pandas (>=2,<3)
|
|
44
|
+
Requires-Dist: passlib[bcyrypt] (>=1,<2)
|
|
45
|
+
Requires-Dist: progressbar2 (>=4.4.2,<5.0.0)
|
|
46
|
+
Requires-Dist: psycopg2-binary (>=2,<3)
|
|
47
|
+
Requires-Dist: pydantic (==2.11.7)
|
|
48
|
+
Requires-Dist: pydantic-settings (>=2,<3)
|
|
49
|
+
Requires-Dist: python-jose[cryptography] (>=3,<4)
|
|
50
|
+
Requires-Dist: pyyaml (>=6,<7)
|
|
51
|
+
Requires-Dist: requests (>=2,<3)
|
|
52
|
+
Requires-Dist: sqladmin (==0.15.2)
|
|
53
|
+
Requires-Dist: sqlmodel (>=0,<1)
|
|
54
|
+
Requires-Dist: uvicorn (==0.28.1)
|
|
55
|
+
Requires-Dist: xlsxwriter (>=3,<4)
|
|
56
|
+
Description-Content-Type: text/markdown
|
|
57
|
+
|
|
58
|
+
# ecodev-core
|
|
59
|
+
|
|
60
|
+
<p align="center">
|
|
61
|
+
<a href="https://github.com/FR-PAR-ECOACT/ecodev-core/actions" target="_blank">
|
|
62
|
+
<img src="https://github.com/FR-PAR-ECOACT/ecodev-core/blob/main/badges/coverage.svg" alt="Coverage">
|
|
63
|
+
</a>
|
|
64
|
+
<a href="https://github.com/FR-PAR-ECOACT/ecodev-core/actions" target="_blank">
|
|
65
|
+
<img src="https://github.com/FR-PAR-ECOACT/ecodev-core/blob/main/badges/pylint.svg" alt="Publish">
|
|
66
|
+
</a>
|
|
67
|
+
<a href="https://github.com/FR-PAR-ECOACT/ecodev-core/actions/workflows/code-quality.yml/badge.svg" target="_blank">
|
|
68
|
+
<img src="https://github.com/FR-PAR-ECOACT/ecodev-core/actions/workflows/code-quality.yml/badge.svg" alt="Package version">
|
|
69
|
+
</a>
|
|
70
|
+
</p>
|
|
71
|
+
|
|
72
|
+
Low level ecoact generic code. Aimed at being published in open source with poetry
|
|
73
|
+
|
|
74
|
+
## Installation of this package
|
|
75
|
+
|
|
76
|
+
You are strongly encouraged to install this package via Docker.
|
|
77
|
+
|
|
78
|
+
Starting from a project with a Docker file:
|
|
79
|
+
* add the module ecodev-core in the `requirements.txt` file
|
|
80
|
+
* make sure the `.env` file includes all required fields (see `BaseSettings` and `AuthenticationConfiguration`)
|
|
81
|
+
* build the new version of the Docker container (typically `docker build --tag xxx .`)
|
|
82
|
+
* run it with docker compose (`dc up -d`).
|
|
83
|
+
|
|
84
|
+
## Documentation
|
|
85
|
+
|
|
86
|
+
Please find it in the [associated mkdoc website!](https://ecodev-doc.lcabox.com/)
|
|
87
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
ecodev_core/__init__.py,sha256=kNgcvv4JFZZKVAObIRqAFjpNuJrQVXF8A5bEJvaQ6Eg,7070
|
|
2
|
+
ecodev_core/app_activity.py,sha256=KBtI-35LBLPDppFB7xjxWthXQrY3Z_aGDnC-HrW8Ea0,4641
|
|
3
|
+
ecodev_core/app_rights.py,sha256=RZPdDtydFqc_nFj96huKAc56BS0qS6ScKv4Kghqd6lc,726
|
|
4
|
+
ecodev_core/app_user.py,sha256=r1bqA4H08x53XmxmjwyGKl_PFjYQazzBbVErdkztqeE,2947
|
|
5
|
+
ecodev_core/auth_configuration.py,sha256=qZ1Dkk7n1AH7w0tVKQ8AYswukOeMZH6mmbixPEAQnJ8,764
|
|
6
|
+
ecodev_core/authentication.py,sha256=JJz_ezjCEBz_RGwFYyPzZHnM6pyk3rLOcKxkV5UESjA,11554
|
|
7
|
+
ecodev_core/backup.py,sha256=rtKJ4XVfJBQcsglkLUnzbaCyQuqFcl8Doc4KBmC2LV8,3984
|
|
8
|
+
ecodev_core/check_dependencies.py,sha256=aFn8GI4eBbuJT8RxsfhSSnlpNYYj_LPOH-tZF0EqfKQ,6917
|
|
9
|
+
ecodev_core/custom_equal.py,sha256=2gRn0qpyJ8-Kw9GQSueu0nLngLrRrwyMPlP6zqPac0U,899
|
|
10
|
+
ecodev_core/db_connection.py,sha256=5cYDfGw2Xp7khwhHlIaqAhRv7WFO3zuKmpTrnfyLMXg,3186
|
|
11
|
+
ecodev_core/db_filters.py,sha256=T_5JVF27UEu7sC6NOm7-W3_Y0GLfbWQO_EeTXcD2cv8,5041
|
|
12
|
+
ecodev_core/db_i18n.py,sha256=P8GWfdBtXTloVjeW6K2_F-VsXUMyQWcE2-F736w8gvM,8305
|
|
13
|
+
ecodev_core/db_insertion.py,sha256=k-r798MMrW1sRb-gb8lQTxyJrb4QP5iZT8GDzCYYwlo,4544
|
|
14
|
+
ecodev_core/db_retrieval.py,sha256=sCP7TDGIcTOK5gT3Inga91bE4S31HbQPw4yI22WJbss,7392
|
|
15
|
+
ecodev_core/db_upsertion.py,sha256=ttngwZzJUQdr9Mc-qkDljJpru5yN3kvAzAMTW84CLHo,13136
|
|
16
|
+
ecodev_core/deployment.py,sha256=z8ACI00EtKknXOB8xyPwYIXTvPjIDOH9z9cBGEU0YrA,281
|
|
17
|
+
ecodev_core/email_sender.py,sha256=V3UGweuq6Iy09Z9to8HzM6JOVDVGHZXHGjUSkW94Tac,1912
|
|
18
|
+
ecodev_core/encryption.py,sha256=eGIjMVqpoi81Y_4JarATCJZoeEyD8NeyRqx8LfcpmKE,1073
|
|
19
|
+
ecodev_core/enum_utils.py,sha256=BkQ4YQ97tXBYmMcQiSIi0mbioD5CgVU79myg1BBAXuA,556
|
|
20
|
+
ecodev_core/es_connection.py,sha256=WC2_BIWBoxgihF1tyHhHsBlcFhM6nZD7eDrPuoJJOqI,2208
|
|
21
|
+
ecodev_core/list_utils.py,sha256=QFchUnD9CvMiBFBUaxkZTyDyEqpIJBwCNPubNUSl8TA,4877
|
|
22
|
+
ecodev_core/logger.py,sha256=_v63vq7jh72RRkzajHB9QkRfEPcwCMNcLh7maLeKwRg,3596
|
|
23
|
+
ecodev_core/pandas_utils.py,sha256=Juc6gvPnoBiSVF2SR6_vfMi5W-QEkY3fnpo5ROB1L9s,2191
|
|
24
|
+
ecodev_core/permissions.py,sha256=WAx-ilMu8LlQp2sjJVdkhNQieytEaEm8577ZF1HWeTY,502
|
|
25
|
+
ecodev_core/pydantic_utils.py,sha256=e3GH50JmcpTmd2UgrB94QSwWOlOCW3WIlVdyX9C4T-U,741
|
|
26
|
+
ecodev_core/read_write.py,sha256=YIGRERvFHU7vy-JIaCWAza4CPMysLRUHKJxN-ZgFmu0,1208
|
|
27
|
+
ecodev_core/rest_api_client.py,sha256=T2PsNicItfWcHZXrni4n8xXOx6euxOk3kXzLIh_Kpcc,7161
|
|
28
|
+
ecodev_core/rest_api_configuration.py,sha256=Gy_8xDMnmNmkBzRQY4CQmqJg-ti1DIAekBj5-nSa8vw,623
|
|
29
|
+
ecodev_core/safe_utils.py,sha256=NT46ddWcMHW6nmKAZiiHH4wdg2VXJqa2RU_01rCFzOk,7552
|
|
30
|
+
ecodev_core/settings.py,sha256=UvaTv8S_HvfFAL-m1Rfqv_geSGcccuV3ziR1o1d5wu4,1795
|
|
31
|
+
ecodev_core/sqlmodel_utils.py,sha256=t57H3QPtKRy4ujic1clMK_2L4p0yjGJLZbDjHPZ8M94,453
|
|
32
|
+
ecodev_core/token_banlist.py,sha256=rKXG9QkfCpjOTr8gBgdX-KYNHAkKvQ9TRnGS99VC9Co,491
|
|
33
|
+
ecodev_core/version.py,sha256=eyIf8KkW_t-hMuYFIoy0cUlNaMewLe6i45m2HKZKh0Q,4403
|
|
34
|
+
ecodev_core-0.0.67.dist-info/LICENSE.md,sha256=8dqVJEbwXjPWjjRKjdLMym5k9Gi8hwtrHh84sti6KIs,1068
|
|
35
|
+
ecodev_core-0.0.67.dist-info/METADATA,sha256=KVLXo_A8m7nP0wJ61DA00fKmtkJTDo_51lhLfpkv170,3582
|
|
36
|
+
ecodev_core-0.0.67.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
37
|
+
ecodev_core-0.0.67.dist-info/RECORD,,
|