ecodev-core 0.0.35__py3-none-any.whl → 0.0.36__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.
Potentially problematic release.
This version of ecodev-core might be problematic. Click here for more details.
- ecodev_core/__init__.py +4 -1
- ecodev_core/deployment.py +16 -0
- ecodev_core/es_connection.py +76 -0
- ecodev_core/list_utils.py +7 -0
- ecodev_core/logger.py +16 -0
- ecodev_core/read_write.py +12 -0
- ecodev_core/settings.py +43 -0
- {ecodev_core-0.0.35.dist-info → ecodev_core-0.0.36.dist-info}/METADATA +3 -1
- {ecodev_core-0.0.35.dist-info → ecodev_core-0.0.36.dist-info}/RECORD +11 -8
- {ecodev_core-0.0.35.dist-info → ecodev_core-0.0.36.dist-info}/LICENSE.md +0 -0
- {ecodev_core-0.0.35.dist-info → ecodev_core-0.0.36.dist-info}/WHEEL +0 -0
ecodev_core/__init__.py
CHANGED
|
@@ -40,6 +40,7 @@ from ecodev_core.db_insertion import get_raw_df
|
|
|
40
40
|
from ecodev_core.db_retrieval import count_rows
|
|
41
41
|
from ecodev_core.db_retrieval import get_rows
|
|
42
42
|
from ecodev_core.db_retrieval import ServerSideField
|
|
43
|
+
from ecodev_core.deployment import Deployment
|
|
43
44
|
from ecodev_core.email_sender import send_email
|
|
44
45
|
from ecodev_core.enum_utils import enum_converter
|
|
45
46
|
from ecodev_core.list_utils import first_func_or_default
|
|
@@ -65,6 +66,7 @@ from ecodev_core.pydantic_utils import CustomFrozen
|
|
|
65
66
|
from ecodev_core.pydantic_utils import Frozen
|
|
66
67
|
from ecodev_core.pydantic_utils import OrmFrozen
|
|
67
68
|
from ecodev_core.read_write import load_json_file
|
|
69
|
+
from ecodev_core.read_write import load_yaml_file
|
|
68
70
|
from ecodev_core.read_write import make_dir
|
|
69
71
|
from ecodev_core.read_write import write_json_file
|
|
70
72
|
from ecodev_core.safe_utils import boolify
|
|
@@ -75,6 +77,7 @@ from ecodev_core.safe_utils import safe_clt
|
|
|
75
77
|
from ecodev_core.safe_utils import SafeTestCase
|
|
76
78
|
from ecodev_core.safe_utils import SimpleReturn
|
|
77
79
|
from ecodev_core.safe_utils import stringify
|
|
80
|
+
from ecodev_core.settings import Settings
|
|
78
81
|
|
|
79
82
|
__all__ = [
|
|
80
83
|
'AUTH', 'Token', 'get_app_services', 'attempt_to_log', 'get_current_user', 'is_admin_user',
|
|
@@ -89,4 +92,4 @@ __all__ = [
|
|
|
89
92
|
'fastapi_monitor', 'dash_monitor', 'is_monitoring_user', 'get_recent_activities', 'select_user',
|
|
90
93
|
'get_access_token', 'safe_get_user', 'backup', 'group_by', 'get_excelfile', 'upsert_new_user',
|
|
91
94
|
'datify', 'safe_drop_columns', 'get_value', 'is_null', 'send_email', 'first_func_or_default',
|
|
92
|
-
'sort_by_keys', 'sort_by_values']
|
|
95
|
+
'sort_by_keys', 'sort_by_values', 'Settings', 'load_yaml_file', 'Deployment']
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module implementing all types of deployment
|
|
3
|
+
"""
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from enum import unique
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@unique
|
|
9
|
+
class Deployment(str, Enum):
|
|
10
|
+
"""
|
|
11
|
+
Enum listing all types of deployment
|
|
12
|
+
"""
|
|
13
|
+
LOCAL = 'local'
|
|
14
|
+
NON_PROD = 'nonprod'
|
|
15
|
+
PREPROD = 'preprod'
|
|
16
|
+
PROD = 'prod'
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module implementing a connection to an elastic search instance, and basic insertion/retrieval.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
import progressbar
|
|
8
|
+
from elasticsearch import Elasticsearch
|
|
9
|
+
from elasticsearch import helpers
|
|
10
|
+
from pydantic_settings import BaseSettings
|
|
11
|
+
from pydantic_settings import SettingsConfigDict
|
|
12
|
+
|
|
13
|
+
from ecodev_core.logger import logger_get
|
|
14
|
+
|
|
15
|
+
ES_CLIENT: Union[Elasticsearch, None] = None
|
|
16
|
+
log = logger_get(__name__)
|
|
17
|
+
ES_BATCH_SIZE = 5000
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ESAuth(BaseSettings):
|
|
21
|
+
"""
|
|
22
|
+
Simple ES authentication configuration class
|
|
23
|
+
"""
|
|
24
|
+
host: str
|
|
25
|
+
user: str
|
|
26
|
+
password: str
|
|
27
|
+
port: int
|
|
28
|
+
index: str
|
|
29
|
+
model_config = SettingsConfigDict(env_file='.env', env_prefix='ES_')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
ES_AUTH = ESAuth() # type: ignore
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_es_client():
|
|
36
|
+
"""
|
|
37
|
+
Get the elasticsearch client
|
|
38
|
+
"""
|
|
39
|
+
global ES_CLIENT
|
|
40
|
+
|
|
41
|
+
if ES_CLIENT is None:
|
|
42
|
+
ES_CLIENT = Elasticsearch(f'http://{ES_AUTH.host}:{ES_AUTH.port}/',
|
|
43
|
+
basic_auth=[ES_AUTH.user, ES_AUTH.password])
|
|
44
|
+
|
|
45
|
+
return ES_CLIENT
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def create_es_index(body: dict) -> None:
|
|
49
|
+
"""
|
|
50
|
+
create an es index
|
|
51
|
+
"""
|
|
52
|
+
client = get_es_client()
|
|
53
|
+
try:
|
|
54
|
+
client.indices.delete(index=ES_AUTH.index)
|
|
55
|
+
except Exception:
|
|
56
|
+
pass
|
|
57
|
+
client.indices.create(index=ES_AUTH.index, body=body)
|
|
58
|
+
log.info(f'index {ES_AUTH.index} created')
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def insert_es_fields(operations: list[dict], batch_size: int = ES_BATCH_SIZE) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Generic es insertion
|
|
64
|
+
"""
|
|
65
|
+
client = get_es_client()
|
|
66
|
+
batches = [list(operations)[i:i + batch_size] for i in range(0, len(operations), batch_size)]
|
|
67
|
+
log.info('indexing fields')
|
|
68
|
+
for batch in progressbar.progressbar(batches, redirect_stdout=False):
|
|
69
|
+
helpers.bulk(client, batch, index=ES_AUTH.index)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def retrieve_es_fields(body: dict[str, Any]) -> list[dict]:
|
|
73
|
+
"""
|
|
74
|
+
Core call to the elasticsearch index
|
|
75
|
+
"""
|
|
76
|
+
return get_es_client().search(index=ES_AUTH.index, body=body)
|
ecodev_core/list_utils.py
CHANGED
|
@@ -118,3 +118,10 @@ def first_transformed_or_default(sequence: List[Any], transformation: Callable)
|
|
|
118
118
|
or default value if no non-trivial transformed elements are found.
|
|
119
119
|
"""
|
|
120
120
|
return next((fx for elt in sequence if (fx := transformation(elt)) is not None), None)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def dict_to_class(data: dict):
|
|
124
|
+
"""
|
|
125
|
+
Convert a (possibly nested) dictionary to a class.
|
|
126
|
+
"""
|
|
127
|
+
return {k: type(k, (), dict_to_class(v)) if isinstance(v, dict) else v for k, v in data.items()}
|
ecodev_core/logger.py
CHANGED
|
@@ -5,6 +5,9 @@ import logging
|
|
|
5
5
|
import sys
|
|
6
6
|
import traceback
|
|
7
7
|
|
|
8
|
+
LIBS = ['azure', 'passlib', 'trimesh', 'fiona',
|
|
9
|
+
'urllib3', 'botocore', 'boto', 'boto3', 's3transfer']
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
def log_critical(message: str, logger):
|
|
10
13
|
"""
|
|
@@ -18,11 +21,24 @@ def logger_get(name, level=logging.DEBUG):
|
|
|
18
21
|
"""
|
|
19
22
|
Main method called by all other modules to log
|
|
20
23
|
"""
|
|
24
|
+
logging.basicConfig(level=level, stream=sys.stdout)
|
|
25
|
+
for lib in LIBS:
|
|
26
|
+
_safe_log_setter(lib)
|
|
21
27
|
logger = logging.getLogger(name)
|
|
22
28
|
config_log(logger, level, MyFormatter())
|
|
23
29
|
return logger
|
|
24
30
|
|
|
25
31
|
|
|
32
|
+
def _safe_log_setter(lib: str) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Safe logger. ERROR level not to be swamped by verbose library info.
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
logging.getLogger(lib).setLevel(logging.ERROR)
|
|
38
|
+
except Exception:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
26
42
|
class MyFormatter(logging.Formatter):
|
|
27
43
|
"""
|
|
28
44
|
Formatter to print %(filename)s:%(funcName)s:%(lineno)d on 24 characters
|
ecodev_core/read_write.py
CHANGED
|
@@ -8,6 +8,8 @@ from typing import Dict
|
|
|
8
8
|
from typing import List
|
|
9
9
|
from typing import Union
|
|
10
10
|
|
|
11
|
+
import yaml
|
|
12
|
+
|
|
11
13
|
|
|
12
14
|
def write_json_file(json_data: Union[Dict, List], file_path: Path):
|
|
13
15
|
"""
|
|
@@ -28,6 +30,16 @@ def load_json_file(file_path: Path):
|
|
|
28
30
|
return loaded_json
|
|
29
31
|
|
|
30
32
|
|
|
33
|
+
def load_yaml_file(file_path: Path):
|
|
34
|
+
"""
|
|
35
|
+
Load a yaml file at file_path location
|
|
36
|
+
"""
|
|
37
|
+
with open(file_path) as file:
|
|
38
|
+
loaded_yaml = yaml.safe_load(file)
|
|
39
|
+
|
|
40
|
+
return loaded_yaml
|
|
41
|
+
|
|
42
|
+
|
|
31
43
|
def make_dir(directory: Path):
|
|
32
44
|
"""
|
|
33
45
|
Helper that create the directory "directory" if it doesn't exist yet
|
ecodev_core/settings.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module defining a dynamic setting class
|
|
3
|
+
"""
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from pydantic.utils import deep_update
|
|
7
|
+
from pydantic_settings import BaseSettings
|
|
8
|
+
from pydantic_settings import SettingsConfigDict
|
|
9
|
+
|
|
10
|
+
from ecodev_core.deployment import Deployment
|
|
11
|
+
from ecodev_core.list_utils import dict_to_class
|
|
12
|
+
from ecodev_core.read_write import load_yaml_file
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DeploymentSetting(BaseSettings):
|
|
16
|
+
"""
|
|
17
|
+
Settings class used to load the deployment type from environment variables.
|
|
18
|
+
"""
|
|
19
|
+
environment: str = 'local'
|
|
20
|
+
model_config = SettingsConfigDict(env_file='.env')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
DEPLOYMENT = Deployment(DeploymentSetting().environment.lower())
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Settings:
|
|
27
|
+
"""
|
|
28
|
+
Dynami setting class, loading yaml configuration from config file, possibly overwriting some of
|
|
29
|
+
this configuration with additional information coming from a secret file.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, base_path: Path = Path('/app'), deployment: Deployment = DEPLOYMENT):
|
|
33
|
+
"""
|
|
34
|
+
Dynamically setting Settings attributes, doing so recursively. Attributes are loaded
|
|
35
|
+
from config file, possibly overwriting some of this configuration with additional
|
|
36
|
+
information coming from a secret file.
|
|
37
|
+
"""
|
|
38
|
+
self.deployment = deployment
|
|
39
|
+
data = load_yaml_file(base_path / 'config' / f'{deployment.value}.yaml')
|
|
40
|
+
if (secrets_file := base_path / 'secrets' / f'{deployment.value}.yaml').exists():
|
|
41
|
+
data = deep_update(data, load_yaml_file(secrets_file))
|
|
42
|
+
for k, v in dict_to_class(data).items():
|
|
43
|
+
setattr(self, k, v)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ecodev-core
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.36
|
|
4
4
|
Summary: Low level sqlmodel/fastapi/pydantic building blocks
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Thomas Epelbaum
|
|
@@ -33,6 +33,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
33
33
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
34
34
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
35
35
|
Classifier: Typing :: Typed
|
|
36
|
+
Requires-Dist: elasticsearch (>=8.14.0,<9.0.0)
|
|
36
37
|
Requires-Dist: fastapi (>=0,<1)
|
|
37
38
|
Requires-Dist: httpx (>=0,<1)
|
|
38
39
|
Requires-Dist: numpy (>=1,<2)
|
|
@@ -40,6 +41,7 @@ Requires-Dist: openpyxl (>=3,<4)
|
|
|
40
41
|
Requires-Dist: orjson (>=3.10.5,<4.0.0)
|
|
41
42
|
Requires-Dist: pandas (>=2,<3)
|
|
42
43
|
Requires-Dist: passlib[bcyrypt] (>=1,<2)
|
|
44
|
+
Requires-Dist: progressbar2 (>=4.4.2,<5.0.0)
|
|
43
45
|
Requires-Dist: psycopg2-binary (>=2,<3)
|
|
44
46
|
Requires-Dist: pydantic (==2.9.2)
|
|
45
47
|
Requires-Dist: pydantic-settings (>=2,<3)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
ecodev_core/__init__.py,sha256=
|
|
1
|
+
ecodev_core/__init__.py,sha256=gIm_-wiXh8YyM-7xSQ07uNFNlPyAngmw45Sd062CT-k,5152
|
|
2
2
|
ecodev_core/app_activity.py,sha256=_rU5uPfttHxXX5IaCuTA7K9We5w2qluJ3Xpf6i12HhY,3763
|
|
3
3
|
ecodev_core/app_rights.py,sha256=RZPdDtydFqc_nFj96huKAc56BS0qS6ScKv4Kghqd6lc,726
|
|
4
4
|
ecodev_core/app_user.py,sha256=r1bqA4H08x53XmxmjwyGKl_PFjYQazzBbVErdkztqeE,2947
|
|
@@ -11,17 +11,20 @@ ecodev_core/db_connection.py,sha256=bc5MujZ57f204wTsuNVdn1JdP-zBzkDJxHmdxBDTiNs,
|
|
|
11
11
|
ecodev_core/db_filters.py,sha256=T_5JVF27UEu7sC6NOm7-W3_Y0GLfbWQO_EeTXcD2cv8,5041
|
|
12
12
|
ecodev_core/db_insertion.py,sha256=RSCyAlUObbBlWJuMRX-YFY4VgtWqYLdwRqMWw--x95Y,3646
|
|
13
13
|
ecodev_core/db_retrieval.py,sha256=IxyF3ZtKgACLiNFggK7boKggvMRKYDRD2IimxU4dap4,7345
|
|
14
|
+
ecodev_core/deployment.py,sha256=z8ACI00EtKknXOB8xyPwYIXTvPjIDOH9z9cBGEU0YrA,281
|
|
14
15
|
ecodev_core/email_sender.py,sha256=XD7jAVXhGzvbiHqMhK9_aTEIS70Lw_CmPeAxRZGji-Y,1610
|
|
15
16
|
ecodev_core/enum_utils.py,sha256=BkQ4YQ97tXBYmMcQiSIi0mbioD5CgVU79myg1BBAXuA,556
|
|
16
|
-
ecodev_core/
|
|
17
|
-
ecodev_core/
|
|
17
|
+
ecodev_core/es_connection.py,sha256=3z8KWF9yUzCW4xC9nhLlIcoW3Gw6m19MvH4Z6nxy7R4,1967
|
|
18
|
+
ecodev_core/list_utils.py,sha256=OltBlhp0COYPD8tc5eruqQq5nlVA7vp7fPYhTwXu6Ww,4632
|
|
19
|
+
ecodev_core/logger.py,sha256=_v63vq7jh72RRkzajHB9QkRfEPcwCMNcLh7maLeKwRg,3596
|
|
18
20
|
ecodev_core/pandas_utils.py,sha256=Juc6gvPnoBiSVF2SR6_vfMi5W-QEkY3fnpo5ROB1L9s,2191
|
|
19
21
|
ecodev_core/permissions.py,sha256=WAx-ilMu8LlQp2sjJVdkhNQieytEaEm8577ZF1HWeTY,502
|
|
20
22
|
ecodev_core/pydantic_utils.py,sha256=e3GH50JmcpTmd2UgrB94QSwWOlOCW3WIlVdyX9C4T-U,741
|
|
21
|
-
ecodev_core/read_write.py,sha256=
|
|
23
|
+
ecodev_core/read_write.py,sha256=YIGRERvFHU7vy-JIaCWAza4CPMysLRUHKJxN-ZgFmu0,1208
|
|
22
24
|
ecodev_core/safe_utils.py,sha256=JCfxo6fcznjsL-XHNJ1TKo1UvfJB83WT5jpTFmtJwsE,6160
|
|
25
|
+
ecodev_core/settings.py,sha256=lgC0GFi3nH9FxUlf2azzzKNT9-i2thl4UMKLxQHL9Xg,1559
|
|
23
26
|
ecodev_core/sqlmodel_utils.py,sha256=t57H3QPtKRy4ujic1clMK_2L4p0yjGJLZbDjHPZ8M94,453
|
|
24
|
-
ecodev_core-0.0.
|
|
25
|
-
ecodev_core-0.0.
|
|
26
|
-
ecodev_core-0.0.
|
|
27
|
-
ecodev_core-0.0.
|
|
27
|
+
ecodev_core-0.0.36.dist-info/LICENSE.md,sha256=jebQDe1ib9LAODuNvcSoo2CoqS6P0_q8--mMTICh_kI,1074
|
|
28
|
+
ecodev_core-0.0.36.dist-info/METADATA,sha256=9OpeiKjWbClyXKtL2jirg96XdzVZRH9wiOs_QL5SEvc,3478
|
|
29
|
+
ecodev_core-0.0.36.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
30
|
+
ecodev_core-0.0.36.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|