ecodev-core 0.0.41__tar.gz → 0.0.42__tar.gz

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.

Files changed (30) hide show
  1. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/PKG-INFO +1 -1
  2. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/app_activity.py +21 -3
  3. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/backup.py +12 -2
  4. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/safe_utils.py +31 -14
  5. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/pyproject.toml +1 -1
  6. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/LICENSE.md +0 -0
  7. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/README.md +0 -0
  8. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/__init__.py +0 -0
  9. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/app_rights.py +0 -0
  10. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/app_user.py +0 -0
  11. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/auth_configuration.py +0 -0
  12. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/authentication.py +0 -0
  13. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/check_dependencies.py +0 -0
  14. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/custom_equal.py +0 -0
  15. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/db_connection.py +0 -0
  16. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/db_filters.py +0 -0
  17. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/db_insertion.py +0 -0
  18. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/db_retrieval.py +0 -0
  19. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/deployment.py +0 -0
  20. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/email_sender.py +0 -0
  21. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/enum_utils.py +0 -0
  22. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/es_connection.py +0 -0
  23. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/list_utils.py +0 -0
  24. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/logger.py +0 -0
  25. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/pandas_utils.py +0 -0
  26. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/permissions.py +0 -0
  27. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/pydantic_utils.py +0 -0
  28. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/read_write.py +0 -0
  29. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/settings.py +0 -0
  30. {ecodev_core-0.0.41 → ecodev_core-0.0.42}/ecodev_core/sqlmodel_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ecodev-core
3
- Version: 0.0.41
3
+ Version: 0.0.42
4
4
  Summary: Low level sqlmodel/fastapi/pydantic building blocks
5
5
  License: MIT
6
6
  Author: Thomas Epelbaum
@@ -3,11 +3,14 @@ Module implementing a simple monitoring table
3
3
  """
4
4
  import inspect
5
5
  from datetime import datetime
6
- from typing import Dict
7
6
  from typing import Optional
8
7
 
8
+ from sqlmodel import cast
9
9
  from sqlmodel import col
10
+ from sqlmodel import extract
10
11
  from sqlmodel import Field
12
+ from sqlmodel import func
13
+ from sqlmodel import Integer
11
14
  from sqlmodel import select
12
15
  from sqlmodel import Session
13
16
  from sqlmodel import SQLModel
@@ -53,7 +56,7 @@ class AppActivity(AppActivityBase, table=True): # type: ignore
53
56
 
54
57
 
55
58
  def dash_monitor(method: str,
56
- token: Dict,
59
+ token: dict,
57
60
  application: str,
58
61
  relevant_option: Optional[str] = None):
59
62
  """
@@ -101,8 +104,23 @@ def add_activity_to_db(method: str,
101
104
  session.commit()
102
105
 
103
106
 
104
- def get_recent_activities(last_date: str, session: Session):
107
+ def get_recent_activities(last_date: str, session: Session) -> list[AppActivity]:
105
108
  """
106
109
  Returns all activities that happened after last_date
107
110
  """
108
111
  return session.exec(select(AppActivity).where(col(AppActivity.created_at) > last_date)).all()
112
+
113
+
114
+ def get_monthly_activities(last_date: str, session: Session) -> dict[tuple[int, int], int]:
115
+ """
116
+ Returns all activities that happened after last_date, grouped by year month.
117
+ """
118
+ query = (select(
119
+ cast(extract('year', AppActivity.created_at), Integer).label('year'),
120
+ cast(extract('month', AppActivity.created_at), Integer).label('month'),
121
+ func.count().label('count'))
122
+ .where(col(AppActivity.created_at) > last_date)
123
+ .group_by(extract('year', AppActivity.created_at), extract('month', AppActivity.created_at))
124
+ .order_by(extract('year', AppActivity.created_at), extract('month', AppActivity.created_at))
125
+ )
126
+ return dict(sorted(((year, month), value) for year, month, value in session.exec(query).all()))
@@ -43,6 +43,17 @@ def backup(backed_folder: Path, nb_saves: int = 5, additional_id: str = 'default
43
43
  _backup_files(backed_folder, Path.cwd() / f'{additional_id}_files.{timestamp}.tgz', nb_saves)
44
44
 
45
45
 
46
+ def retrieve_most_recent_backup(name: str = 'default_files') -> None:
47
+ """
48
+ Retrieve from backup server the most recent backup of the name family.
49
+ """
50
+ output = run(['lftp', '-c', f'open {BACKUP_URL}; ls'], capture_output=True, text=True)
51
+ all_backups = sorted([x.split(' ')[-1] for x in output.stdout.splitlines() if name in x])
52
+ log.info(f'most recent backup {all_backups[-1]}')
53
+ run(['lftp', '-c', f'open {BACKUP_URL}; get {all_backups[-1]}'])
54
+ return None
55
+
56
+
46
57
  def _backup_db(db_dump_path: Path, nb_saves: int) -> None:
47
58
  """
48
59
  Pg_dump of DB_URL db andwrite on the backup server
@@ -80,8 +91,7 @@ def _get_old_backups(file_to_backup: Path, nb_saves: int) -> List[str]:
80
91
  """
81
92
  Retrieve old versions of file_to_backup in order to erase them (more than nb_saves ago)
82
93
  """
83
- output = run(['lftp', '-c', f'open {BACKUP_URL}; ls'],
84
- capture_output=True, text=True)
94
+ output = run(['lftp', '-c', f'open {BACKUP_URL}; ls'], capture_output=True, text=True)
85
95
  filename_base = file_to_backup.name.split('.')[0]
86
96
  all_backups = sorted([x.split(' ')[-1]
87
97
  for x in output.stdout.splitlines() if filename_base in x])
@@ -144,35 +144,50 @@ def safe_clt(func):
144
144
  return inner_function
145
145
 
146
146
 
147
- def stringify(x: Union[str, float]) -> Union[str, None]:
147
+ def safe_method(func: Callable) -> Any | None:
148
+ """
149
+ Safe execution of a method
150
+ """
151
+ def inner_function(*args, **kwargs):
152
+ try:
153
+ return func(*args, **kwargs)
154
+ except Exception:
155
+ return None
156
+ return inner_function
157
+
158
+
159
+ def stringify(x: Union[str, float], default: str | None = None) -> Union[str, None]:
148
160
  """
149
161
  Safe conversion of a (str, np.nan) value into a (str,None) one
150
162
  """
151
- return _transformify(x, str)
163
+ return _transformify(x, str, default)
152
164
 
153
165
 
154
- def boolify(x: Union[Any]) -> Union[bool, None]:
166
+ def boolify(x: Union[Any], default: bool | None = None) -> Union[bool, None]:
155
167
  """
156
168
  Safe conversion of a (str, np.nan) value into a (str,None) one
157
169
  """
158
- return _transformify(x, _bool_check)
170
+ return _transformify(x, _bool_check, default)
159
171
 
160
172
 
161
- def intify(x: Union[str, float]) -> Union[int, None]:
173
+ def intify(x: Union[str, float], default: int | None = None) -> Union[int, None]:
162
174
  """
163
175
  Safe conversion of a (int, np.nan) value into a (int,None) one
164
176
  """
165
- return _transformify(x, int)
177
+ return _transformify(x, int, default)
166
178
 
167
179
 
168
- def floatify(x: Union[str, float]) -> Union[float, None]:
180
+ def floatify(x: Union[str, float], default: float | None = None) -> Union[float, None]:
169
181
  """
170
182
  Safe conversion of a (float, np.nan) value into a (float,None) one
171
183
  """
172
- return _transformify(x, float)
184
+ return _transformify(x, float, default)
173
185
 
174
186
 
175
- def datify(date: str, date_format: str) -> Union[datetime, None]:
187
+ def datify(date: datetime | str,
188
+ date_format: str,
189
+ default: datetime | None = None
190
+ ) -> Union[datetime, None]:
176
191
  """
177
192
  Safe conversion to a date format
178
193
  """
@@ -180,21 +195,23 @@ def datify(date: str, date_format: str) -> Union[datetime, None]:
180
195
  return None
181
196
  if isinstance(date, datetime):
182
197
  return date
183
- return _transformify(date, lambda x: datetime.strptime(x, date_format))
198
+ return _transformify(date, lambda x: datetime.strptime(x, date_format), default)
184
199
 
185
200
 
186
- def _transformify(x: Union[Any, float], transformation: Callable) -> Union[Any, None]:
201
+ def _transformify(x: Union[Any, float],
202
+ transformation: Callable,
203
+ default: Any | None) -> Union[Any, None]:
187
204
  """
188
205
  Safe conversion of a (Any, np.nan) value into a (Any,None) one thanks to transformation
189
206
  """
190
207
  if x is None or (isinstance(x, float) and np.isnan(x)):
191
- return None
208
+ return default
192
209
 
193
210
  try:
194
- return transformation(x)
211
+ return transformed if (transformed := transformation(x)) is not None else default
195
212
 
196
213
  except ValueError:
197
- return None
214
+ return default
198
215
 
199
216
 
200
217
  def _bool_check(x: Union[Any, float]):
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ecodev-core"
3
- version = "0.0.41"
3
+ version = "0.0.42"
4
4
  description = "Low level sqlmodel/fastapi/pydantic building blocks"
5
5
  authors = ["Thomas Epelbaum <tomepel@gmail.com>",
6
6
  "Olivier Gabriel <olivier.gabriel.geom@gmail.com>",
File without changes
File without changes