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/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,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any