saviialib 1.3.0__tar.gz → 1.4.0__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 saviialib might be problematic. Click here for more details.

Files changed (65) hide show
  1. {saviialib-1.3.0 → saviialib-1.4.0}/PKG-INFO +5 -3
  2. {saviialib-1.3.0 → saviialib-1.4.0}/pyproject.toml +2 -2
  3. saviialib-1.4.0/src/saviialib/__init__.py +77 -0
  4. saviialib-1.3.0/src/saviialib/general_types/api/epii_api_types.py → saviialib-1.4.0/src/saviialib/general_types/api/saviia_api_types.py +2 -39
  5. saviialib-1.4.0/src/saviialib/general_types/api/saviia_backup_api_types.py +24 -0
  6. saviialib-1.4.0/src/saviialib/general_types/api/saviia_thies_api_types.py +31 -0
  7. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/sharepoint_client/clients/sharepoint_rest_api.py +7 -4
  8. saviialib-1.4.0/src/saviialib/services/backup/api.py +36 -0
  9. saviialib-1.4.0/src/saviialib/services/backup/controllers/__init__.py +0 -0
  10. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/controllers/types/__init__.py +1 -1
  11. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/controllers/types/upload_backup_to_sharepoint_types.py +2 -2
  12. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/controllers/upload_backup_to_sharepoint.py +5 -5
  13. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/use_cases/types/__init__.py +1 -1
  14. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/use_cases/types/upload_backup_to_sharepoint_types.py +1 -1
  15. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/use_cases/upload_backup_to_sharepoint.py +2 -2
  16. saviialib-1.4.0/src/saviialib/services/backup/utils/__init__.py +3 -0
  17. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/utils/upload_backup_to_sharepoint_utils.py +1 -1
  18. saviialib-1.4.0/src/saviialib/services/thies/__init__.py +0 -0
  19. saviialib-1.4.0/src/saviialib/services/thies/api.py +35 -0
  20. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/thies}/controllers/types/update_thies_data_types.py +2 -4
  21. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/thies}/controllers/update_thies_data.py +4 -4
  22. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/thies}/use_cases/components/create_thies_statistics_file.py +10 -1
  23. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/thies}/use_cases/types/update_thies_data_types.py +1 -1
  24. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/thies}/use_cases/update_thies_data.py +20 -13
  25. saviialib-1.3.0/src/saviialib/__init__.py +0 -9
  26. saviialib-1.3.0/src/saviialib/general_types/api/__init__.py +0 -3
  27. saviialib-1.3.0/src/saviialib/services/epii/api.py +0 -94
  28. saviialib-1.3.0/src/saviialib/services/epii/utils/__init__.py +0 -3
  29. {saviialib-1.3.0 → saviialib-1.4.0}/LICENSE +0 -0
  30. {saviialib-1.3.0 → saviialib-1.4.0}/README.md +0 -0
  31. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/general_types/__init__.py +0 -0
  32. {saviialib-1.3.0/src/saviialib/general_types/error_types → saviialib-1.4.0/src/saviialib/general_types/api}/__init__.py +0 -0
  33. {saviialib-1.3.0/src/saviialib/general_types/error_types/api → saviialib-1.4.0/src/saviialib/general_types/error_types}/__init__.py +0 -0
  34. {saviialib-1.3.0/src/saviialib/libs/ftp_client/clients → saviialib-1.4.0/src/saviialib/general_types/error_types/api}/__init__.py +0 -0
  35. /saviialib-1.3.0/src/saviialib/general_types/error_types/api/epii_api_error_types.py → /saviialib-1.4.0/src/saviialib/general_types/error_types/api/saviia_api_error_types.py +0 -0
  36. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/general_types/error_types/common/__init__.py +0 -0
  37. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/general_types/error_types/common/common_types.py +0 -0
  38. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/directory_client/__init__.py +0 -0
  39. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/directory_client/client/os_client.py +0 -0
  40. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/directory_client/directory_client.py +0 -0
  41. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/directory_client/directory_client_contract.py +0 -0
  42. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/directory_client/types/directory_client_types.py +0 -0
  43. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/files_client/__init__.py +0 -0
  44. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/files_client/clients/aiofiles_client.py +0 -0
  45. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/files_client/clients/csv_client.py +0 -0
  46. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/files_client/files_client.py +0 -0
  47. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/files_client/files_client_contract.py +0 -0
  48. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/files_client/types/files_client_types.py +0 -0
  49. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/ftp_client/__init__.py +0 -0
  50. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/libs/ftp_client/clients}/__init__.py +0 -0
  51. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/ftp_client/clients/aioftp_client.py +0 -0
  52. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/ftp_client/clients/ftplib_client.py +0 -0
  53. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/ftp_client/ftp_client.py +0 -0
  54. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/ftp_client/ftp_client_contract.py +0 -0
  55. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/ftp_client/types/__init__.py +0 -0
  56. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/ftp_client/types/ftp_client_types.py +0 -0
  57. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/sharepoint_client/__init__.py +0 -0
  58. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/sharepoint_client/sharepoint_client.py +0 -0
  59. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/sharepoint_client/sharepoint_client_contract.py +0 -0
  60. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/sharepoint_client/types/sharepoint_client_types.py +0 -0
  61. {saviialib-1.3.0 → saviialib-1.4.0}/src/saviialib/libs/zero_dependency/utils/datetime_utils.py +0 -0
  62. {saviialib-1.3.0/src/saviialib/services/epii/controllers → saviialib-1.4.0/src/saviialib/services/backup}/__init__.py +0 -0
  63. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/backup}/use_cases/constants/upload_backup_to_sharepoint_constants.py +0 -0
  64. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/thies}/use_cases/components/thies_bp.py +0 -0
  65. {saviialib-1.3.0/src/saviialib/services/epii → saviialib-1.4.0/src/saviialib/services/thies}/utils/update_thies_data_utils.py +0 -0
@@ -1,8 +1,9 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: saviialib
3
- Version: 1.3.0
3
+ Version: 1.4.0
4
4
  Summary: A client library for IoT projects in the RCER initiative
5
5
  License: MIT
6
+ License-File: LICENSE
6
7
  Author: pedropablozavalat
7
8
  Requires-Python: >=3.11,<4.0
8
9
  Classifier: License :: OSI Approved :: MIT License
@@ -10,15 +11,16 @@ Classifier: Programming Language :: Python :: 3
10
11
  Classifier: Programming Language :: Python :: 3.11
11
12
  Classifier: Programming Language :: Python :: 3.12
12
13
  Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
13
15
  Requires-Dist: aiofiles
14
16
  Requires-Dist: aioftp
15
17
  Requires-Dist: aiohttp
16
18
  Requires-Dist: bitarray
17
19
  Requires-Dist: build
20
+ Requires-Dist: certifi
18
21
  Requires-Dist: dotenv (>=0.9.9,<0.10.0)
19
22
  Requires-Dist: numpy (>=2.2.0,<2.4.0)
20
23
  Requires-Dist: pandas (>=2.2.3,<2.3.1)
21
- Requires-Dist: pytest-cov (>=6.1.1,<7.0.0)
22
24
  Description-Content-Type: text/markdown
23
25
 
24
26
  # SAVIIA Library
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "saviialib"
3
- version = "1.3.0"
3
+ version = "1.4.0"
4
4
  description = "A client library for IoT projects in the RCER initiative"
5
5
  authors = ["pedropablozavalat"]
6
6
  license = "MIT"
@@ -12,11 +12,11 @@ aioftp = "*"
12
12
  aiohttp = "*"
13
13
  aiofiles = "*"
14
14
  dotenv = "^0.9.9"
15
- pytest-cov="^6.1.1"
16
15
  build="*"
17
16
  numpy = ">=2.2.0,<2.4.0"
18
17
  pandas = ">=2.2.3,<2.3.1"
19
18
  bitarray="*"
19
+ certifi="*"
20
20
 
21
21
  [tool.poetry.group.dev.dependencies]
22
22
  pytest = "8.3.5"
@@ -0,0 +1,77 @@
1
+ # read version from installed package
2
+ from importlib.metadata import version
3
+
4
+ __version__ = version("saviialib")
5
+
6
+ from .general_types.api.saviia_api_types import SaviiaAPIConfig
7
+
8
+ from typing import Dict, Type, Any, overload, Literal, List
9
+
10
+ from saviialib.services.backup.api import SaviiaBackupAPI
11
+ from saviialib.services.thies.api import SaviiaThiesAPI
12
+ from saviialib.general_types.api.saviia_thies_api_types import SaviiaThiesConfig
13
+ from saviialib.general_types.api.saviia_backup_api_types import SaviiaBackupConfig
14
+
15
+
16
+ class SaviiaAPI:
17
+ API_REGISTRY: Dict[str, Type] = {
18
+ "thies": SaviiaThiesAPI,
19
+ "backup": SaviiaBackupAPI,
20
+ }
21
+
22
+ @overload
23
+ def get(self, name: Literal["thies"]) -> SaviiaThiesAPI: ...
24
+ @overload
25
+ def get(self, name: Literal["backup"]) -> SaviiaBackupAPI: ...
26
+
27
+ def __init__(self, config: SaviiaAPIConfig):
28
+ """
29
+ Receive a dictionary of configurations, with the same key
30
+ as those registered in API_REGISTRY.
31
+
32
+ :params configs: Dictionary of configurations for each API.
33
+
34
+ Example:
35
+ configs = {
36
+ "thies": SaviiaThiesConfig(...),
37
+ "backup": SaviiaBackupConfig(...)
38
+ }
39
+ """
40
+ self._instances: Dict[str, Any] = {}
41
+
42
+ for name, api_class in SaviiaAPI.API_REGISTRY.items():
43
+ if name == "thies":
44
+ service_config = SaviiaThiesConfig(
45
+ ftp_host=config.ftp_host,
46
+ ftp_port=config.ftp_port,
47
+ ftp_user=config.ftp_user,
48
+ ftp_password=config.ftp_password,
49
+ sharepoint_client_id=config.sharepoint_client_id,
50
+ sharepoint_client_secret=config.sharepoint_client_secret,
51
+ sharepoint_tenant_id=config.sharepoint_tenant_id,
52
+ sharepoint_tenant_name=config.sharepoint_tenant_name,
53
+ sharepoint_site_name=config.sharepoint_site_name,
54
+ logger=config.logger,
55
+ )
56
+ elif name == "backup":
57
+ service_config = SaviiaBackupConfig(
58
+ sharepoint_client_id=config.sharepoint_client_id,
59
+ sharepoint_client_secret=config.sharepoint_client_secret,
60
+ sharepoint_tenant_id=config.sharepoint_tenant_id,
61
+ sharepoint_tenant_name=config.sharepoint_tenant_name,
62
+ sharepoint_site_name=config.sharepoint_site_name,
63
+ logger=config.logger,
64
+ )
65
+
66
+ self._instances[name] = api_class(service_config)
67
+
68
+ def get(self, name: Literal["thies", "backup"]) -> Any:
69
+ """Returns the API instance associated with the given name."""
70
+ try:
71
+ return self._instances[name]
72
+ except KeyError:
73
+ raise ValueError(f"API '{name}' is not registered or not configured.")
74
+
75
+ def list_available(self) -> List[str]:
76
+ """List of available registered APIs."""
77
+ return list(self._instances.keys())
@@ -3,9 +3,9 @@ from logging import Logger
3
3
 
4
4
 
5
5
  @dataclass
6
- class EpiiAPIConfig:
6
+ class SaviiaAPIConfig:
7
7
  """
8
- Configuration for Epii API.
8
+ Configuration for SAVIIA API.
9
9
 
10
10
  Attributes:
11
11
  ftp_port (int): Port number of the FTP server.
@@ -30,7 +30,6 @@ class EpiiAPIConfig:
30
30
  sharepoint_site_name: str
31
31
  logger: Logger
32
32
 
33
-
34
33
  @dataclass
35
34
  class FtpClientConfig:
36
35
  ftp_host: str
@@ -46,39 +45,3 @@ class SharepointConfig:
46
45
  sharepoint_tenant_id: str
47
46
  sharepoint_tenant_name: str
48
47
  sharepoint_site_name: str
49
-
50
-
51
- @dataclass
52
- class EpiiUpdateThiesConfig:
53
- ftp_port: int
54
- ftp_host: str
55
- ftp_user: str
56
- ftp_password: str
57
- sharepoint_client_id: str
58
- sharepoint_client_secret: str
59
- sharepoint_tenant_id: str
60
- sharepoint_tenant_name: str
61
- sharepoint_site_name: str
62
- logger: Logger
63
-
64
-
65
- @dataclass
66
- class EpiiSharepointBackupConfig:
67
- """
68
- Configuration for backing up files to SharePoint.
69
-
70
- Attributes:
71
- sharepoint_client_id (str): Client ID for SharePoint authentication.
72
- sharepoint_client_secret (str): Client secret for SharePoint authentication.
73
- sharepoint_tenant_id (str): Tenant ID for SharePoint authentication.
74
- sharepoint_tenant_name (str): Tenant name for SharePoint.
75
- sharepoint_site_name (str): Site name in SharePoint.
76
- local_backup_source_path (str): Local path to backup.
77
- """
78
-
79
- sharepoint_client_id: str
80
- sharepoint_client_secret: str
81
- sharepoint_tenant_id: str
82
- sharepoint_tenant_name: str
83
- sharepoint_site_name: str
84
- logger: Logger
@@ -0,0 +1,24 @@
1
+ from dataclasses import dataclass
2
+ from logging import Logger
3
+
4
+
5
+ @dataclass
6
+ class SaviiaBackupConfig:
7
+ """
8
+ Configuration for backing up files to SharePoint.
9
+
10
+ Attributes:
11
+ sharepoint_client_id (str): Client ID for SharePoint authentication.
12
+ sharepoint_client_secret (str): Client secret for SharePoint authentication.
13
+ sharepoint_tenant_id (str): Tenant ID for SharePoint authentication.
14
+ sharepoint_tenant_name (str): Tenant name for SharePoint.
15
+ sharepoint_site_name (str): Site name in SharePoint.
16
+ local_backup_source_path (str): Local path to backup.
17
+ """
18
+
19
+ sharepoint_client_id: str
20
+ sharepoint_client_secret: str
21
+ sharepoint_tenant_id: str
22
+ sharepoint_tenant_name: str
23
+ sharepoint_site_name: str
24
+ logger: Logger
@@ -0,0 +1,31 @@
1
+ from dataclasses import dataclass
2
+ from logging import Logger
3
+
4
+
5
+ @dataclass
6
+ class SaviiaThiesConfig:
7
+ """
8
+ Configuration for Saviia Thies.
9
+
10
+ Attributes:
11
+ ftp_port (int): Port number of the FTP server.
12
+ ftp_host (str): Hostname or IP address of the FTP server.
13
+ ftp_user (str): Username for the FTP server.
14
+ ftp_password (str): Password for the FTP server.
15
+ sharepoint_client_id (str): Client ID for SharePoint authentication.
16
+ sharepoint_client_secret (str): Client secret for SharePoint authentication.
17
+ sharepoint_tenant_id (str): Tenant ID for SharePoint authentication.
18
+ sharepoint_tenant_name (str): Tenant name for SharePoint.
19
+ sharepoint_site_name (str): Site name in SharePoint.
20
+ """
21
+
22
+ ftp_host: str
23
+ ftp_port: int
24
+ ftp_user: str
25
+ ftp_password: str
26
+ sharepoint_client_id: str
27
+ sharepoint_client_secret: str
28
+ sharepoint_tenant_id: str
29
+ sharepoint_tenant_name: str
30
+ sharepoint_site_name: str
31
+ logger: Logger
@@ -1,7 +1,9 @@
1
1
  from typing import Any
2
2
  import json
3
- from aiohttp import ClientError, ClientSession
3
+ from aiohttp import ClientError, ClientSession, TCPConnector
4
4
  from dotenv import load_dotenv
5
+ import ssl
6
+ import certifi
5
7
 
6
8
  from saviialib.libs.sharepoint_client.sharepoint_client_contract import (
7
9
  SharepointClientContract,
@@ -15,7 +17,7 @@ from saviialib.libs.sharepoint_client.types.sharepoint_client_types import (
15
17
  )
16
18
 
17
19
  load_dotenv()
18
-
20
+ ssl_context = ssl.create_default_context(cafile=certifi.where())
19
21
 
20
22
  class SharepointRestAPI(SharepointClientContract):
21
23
  def __init__(self, args: SharepointClientInitArgs):
@@ -51,7 +53,7 @@ class SharepointRestAPI(SharepointClientContract):
51
53
  "Content-Type": "application/x-www-form-urlencoded",
52
54
  }
53
55
 
54
- async with ClientSession() as session:
56
+ async with ClientSession(connector=TCPConnector(ssl=ssl_context)) as session:
55
57
  # Load access token
56
58
  response = await session.post(url, data=payload, headers=headers)
57
59
  if response.status != 200:
@@ -75,8 +77,9 @@ class SharepointRestAPI(SharepointClientContract):
75
77
  "Content-Type": "application/json",
76
78
  }
77
79
  self.base_url = f"{site_url}/sites/{self.site_name}/_api/"
80
+ connector = TCPConnector(ssl=ssl_context)
78
81
  self.session = ClientSession(
79
- headers=self.base_headers, base_url=self.base_url
82
+ headers=self.base_headers, base_url=self.base_url, connector=connector
80
83
  )
81
84
  return self
82
85
  except ClientError as error:
@@ -0,0 +1,36 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from .controllers.upload_backup_to_sharepoint import (
4
+ UploadBackupToSharepointControllerInput,
5
+ )
6
+ from .controllers.upload_backup_to_sharepoint import UploadBackupToSharepointController
7
+ from saviialib.general_types.api.saviia_backup_api_types import SaviiaBackupConfig
8
+
9
+
10
+ class SaviiaBackupAPI:
11
+ """
12
+ EpiiAPI is a service class that provides methods to interact with Patagonia Center system.
13
+ """
14
+
15
+ def __init__(self, config: SaviiaBackupConfig):
16
+ self.config = config
17
+
18
+ async def upload_backup_to_sharepoint(
19
+ self, local_backup_source_path: str, sharepoint_destination_path: str
20
+ ) -> Dict[str, Any]:
21
+ """Migrate a backup folder from Home assistant to Sharepoint directory.
22
+ Args:
23
+ local_backup_source_path (str): Local path to backup.
24
+ Returns:
25
+ response (dict): A dictionary containing the response from the upload operation.
26
+ This dictionary will typically include information about the success or
27
+ failure of the upload, as well as any relevant metadata.
28
+ """
29
+
30
+ controller = UploadBackupToSharepointController(
31
+ UploadBackupToSharepointControllerInput(
32
+ self.config, local_backup_source_path, sharepoint_destination_path
33
+ )
34
+ )
35
+ response = await controller.execute()
36
+ return response.__dict__
@@ -1,4 +1,4 @@
1
- from .update_thies_data_types import (
1
+ from ....thies.controllers.types.update_thies_data_types import (
2
2
  UpdateThiesDataControllerInput,
3
3
  UpdateThiesDataControllerOutput,
4
4
  )
@@ -1,12 +1,12 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import Dict
3
3
 
4
- from saviialib.general_types.api.epii_api_types import EpiiSharepointBackupConfig
4
+ from saviialib.general_types.api.saviia_backup_api_types import SaviiaBackupConfig
5
5
 
6
6
 
7
7
  @dataclass
8
8
  class UploadBackupToSharepointControllerInput:
9
- config: EpiiSharepointBackupConfig
9
+ config: SaviiaBackupConfig
10
10
  local_backup_source_path: str
11
11
  sharepoint_destination_path: str
12
12
 
@@ -1,7 +1,7 @@
1
1
  from http import HTTPStatus
2
- from saviialib.general_types.api.epii_api_types import SharepointConfig
2
+ from saviialib.general_types.api.saviia_api_types import SharepointConfig
3
3
 
4
- from saviialib.general_types.error_types.api.epii_api_error_types import (
4
+ from saviialib.general_types.error_types.api.saviia_api_error_types import (
5
5
  BackupUploadError,
6
6
  BackupSourcePathError,
7
7
  BackupEmptyError,
@@ -10,14 +10,14 @@ from saviialib.general_types.error_types.common.common_types import (
10
10
  EmptyDataError,
11
11
  SharepointClientError,
12
12
  )
13
- from saviialib.services.epii.controllers.types.upload_backup_to_sharepoint_types import (
13
+ from saviialib.services.backup.controllers.types.upload_backup_to_sharepoint_types import (
14
14
  UploadBackupToSharepointControllerInput,
15
15
  UploadBackupToSharepointControllerOutput,
16
16
  )
17
- from saviialib.services.epii.use_cases.types.upload_backup_to_sharepoint_types import (
17
+ from saviialib.services.backup.use_cases.types.upload_backup_to_sharepoint_types import (
18
18
  UploadBackupToSharepointUseCaseInput,
19
19
  )
20
- from saviialib.services.epii.use_cases.upload_backup_to_sharepoint import (
20
+ from saviialib.services.backup.use_cases.upload_backup_to_sharepoint import (
21
21
  UploadBackupToSharepointUsecase,
22
22
  )
23
23
 
@@ -1,4 +1,4 @@
1
- from .update_thies_data_types import (
1
+ from ....thies.use_cases.types.update_thies_data_types import (
2
2
  FtpClientConfig,
3
3
  SharepointConfig,
4
4
  UpdateThiesDataUseCaseInput,
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from saviialib.general_types.api.epii_api_types import SharepointConfig
2
+ from saviialib.general_types.api.saviia_api_types import SharepointConfig
3
3
  from logging import Logger
4
4
 
5
5
 
@@ -2,7 +2,7 @@ import asyncio
2
2
  from time import time
3
3
  from saviialib.libs.zero_dependency.utils.datetime_utils import today, datetime_to_str
4
4
  from logging import Logger
5
- from saviialib.general_types.error_types.api.epii_api_error_types import (
5
+ from saviialib.general_types.error_types.api.saviia_api_error_types import (
6
6
  BackupEmptyError,
7
7
  BackupSourcePathError,
8
8
  BackupUploadError,
@@ -23,7 +23,7 @@ from saviialib.libs.sharepoint_client import (
23
23
  SpUploadFileArgs,
24
24
  SpCreateFolderArgs,
25
25
  )
26
- from saviialib.services.epii.utils.upload_backup_to_sharepoint_utils import (
26
+ from saviialib.services.backup.utils.upload_backup_to_sharepoint_utils import (
27
27
  calculate_percentage_uploaded,
28
28
  count_files_in_directory,
29
29
  extract_error_message,
@@ -0,0 +1,3 @@
1
+ from ...thies.utils.update_thies_data_utils import parse_execute_response
2
+
3
+ __all__ = ["parse_execute_response"]
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  from logging import Logger
3
3
  from typing import List, Dict, Optional
4
- from saviialib.general_types.error_types.api.epii_api_error_types import (
4
+ from saviialib.general_types.error_types.api.saviia_api_error_types import (
5
5
  BackupSourcePathError,
6
6
  )
7
7
  from saviialib.libs.directory_client import DirectoryClient, DirectoryClientArgs
@@ -0,0 +1,35 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from .controllers.types.update_thies_data_types import UpdateThiesDataControllerInput
4
+ from .controllers.update_thies_data import UpdateThiesDataController
5
+ from saviialib.general_types.api.saviia_thies_api_types import (
6
+ SaviiaThiesConfig,
7
+ )
8
+
9
+
10
+ class SaviiaThiesAPI:
11
+ def __init__(self, config: SaviiaThiesConfig) -> None:
12
+ self.config = config
13
+
14
+ async def update_thies_data(
15
+ self, sharepoint_folders_path: List[str], ftp_server_folders_path: List[str]
16
+ ) -> Dict[str, Any]:
17
+ """Updates data from a THIES Data Logger by connecting to an FTP server
18
+ and transferring data to specified Sharepoint folders.
19
+
20
+ Args:
21
+ sharepoint_folders_path (list): List of Sharepoint folder paths for AVG and EXT data.
22
+ The AVG path must be the first element.
23
+ ftp_server_folders_path (list): List of FTP server folder paths for AVG and EXT data.
24
+ The AVG path must be the first element.
25
+
26
+ Returns:
27
+ dict: A dictionary representation of the API response.
28
+ """
29
+ controller = UpdateThiesDataController(
30
+ UpdateThiesDataControllerInput(
31
+ self.config, sharepoint_folders_path, ftp_server_folders_path
32
+ )
33
+ )
34
+ response = await controller.execute()
35
+ return response.__dict__
@@ -1,13 +1,11 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import Dict
3
- from saviialib.general_types.api.epii_api_types import (
4
- EpiiUpdateThiesConfig,
5
- )
3
+ from saviialib.general_types.api.saviia_thies_api_types import SaviiaThiesConfig
6
4
 
7
5
 
8
6
  @dataclass
9
7
  class UpdateThiesDataControllerInput:
10
- config: EpiiUpdateThiesConfig
8
+ config: SaviiaThiesConfig
11
9
  sharepoint_folders_path: list
12
10
  ftp_server_folders_path: list
13
11
 
@@ -1,6 +1,6 @@
1
1
  from http import HTTPStatus
2
2
 
3
- from saviialib.general_types.error_types.api.epii_api_error_types import (
3
+ from saviialib.general_types.error_types.api.saviia_api_error_types import (
4
4
  SharePointFetchingError,
5
5
  ThiesConnectionError,
6
6
  ThiesFetchingError,
@@ -12,16 +12,16 @@ from saviialib.general_types.error_types.common.common_types import (
12
12
  FtpClientError,
13
13
  SharepointClientError,
14
14
  )
15
- from saviialib.services.epii.controllers.types.update_thies_data_types import (
15
+ from saviialib.services.thies.controllers.types.update_thies_data_types import (
16
16
  UpdateThiesDataControllerInput,
17
17
  UpdateThiesDataControllerOutput,
18
18
  )
19
- from saviialib.services.epii.use_cases.types import (
19
+ from saviialib.services.backup.use_cases.types import (
20
20
  UpdateThiesDataUseCaseInput,
21
21
  SharepointConfig,
22
22
  FtpClientConfig,
23
23
  )
24
- from saviialib.services.epii.use_cases.update_thies_data import (
24
+ from saviialib.services.thies.use_cases.update_thies_data import (
25
25
  UpdateThiesDataUseCase,
26
26
  )
27
27
 
@@ -70,7 +70,7 @@ UNITS = {
70
70
 
71
71
 
72
72
  async def create_thies_daily_statistics_file(
73
- os_client: DirectoryClient, logger: Logger, daily_files: List[str]
73
+ os_client: DirectoryClient, logger: Logger
74
74
  ) -> None:
75
75
  logger.debug("[thies_synchronization_lib] Creating Daily Statistics ...")
76
76
  csv_client = FilesClient(FilesClientInitArgs(client_name="csv_client"))
@@ -127,6 +127,15 @@ async def create_thies_daily_statistics_file(
127
127
  if max_col not in row:
128
128
  max_val = 0
129
129
 
130
+ if (mean < min_val or mean > max_val) and col not in ["WD"]:
131
+ logger.warning(
132
+ f"[thies_synchronization_lib] Inconsistent data for {col}: "
133
+ f"min {min_val}, max {max_val}, mean {mean}. "
134
+ )
135
+ mean = (min_val + max_val) / 2
136
+ logger.warning(
137
+ f"[thies_synchronization_lib] Mean value corrected to {mean}.")
138
+
130
139
  if col in ["WD"]: # Avoid error
131
140
  rows.append(
132
141
  {
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import Dict, List
3
- from saviialib.general_types.api.epii_api_types import FtpClientConfig, SharepointConfig
3
+ from saviialib.general_types.api.saviia_api_types import FtpClientConfig, SharepointConfig
4
4
  from logging import Logger
5
5
 
6
6
 
@@ -1,4 +1,4 @@
1
- from saviialib.general_types.error_types.api.epii_api_error_types import (
1
+ from saviialib.general_types.error_types.api.saviia_api_error_types import (
2
2
  SharePointFetchingError,
3
3
  SharePointDirectoryError,
4
4
  SharePointUploadError,
@@ -26,16 +26,17 @@ from saviialib.libs.sharepoint_client import (
26
26
  from saviialib.libs.directory_client import DirectoryClient, DirectoryClientArgs
27
27
 
28
28
  from saviialib.libs.files_client import FilesClient, FilesClientInitArgs, WriteArgs
29
- from saviialib.services.epii.use_cases.types import (
29
+ from saviialib.services.backup.use_cases.types import (
30
30
  FtpClientConfig,
31
31
  SharepointConfig,
32
32
  UpdateThiesDataUseCaseInput,
33
33
  )
34
- from saviialib.services.epii.utils import (
34
+ from saviialib.services.backup.utils import (
35
35
  parse_execute_response,
36
36
  )
37
37
  from saviialib.libs.zero_dependency.utils.datetime_utils import today, datetime_to_str
38
38
  from .components.create_thies_statistics_file import create_thies_daily_statistics_file
39
+ from typing import Set, Dict, List
39
40
 
40
41
 
41
42
  class UpdateThiesDataUseCase:
@@ -66,7 +67,7 @@ class UpdateThiesDataUseCase:
66
67
  def _initialize_thies_ftp_client(self, config: FtpClientConfig) -> FTPClient:
67
68
  """Initialize the FTP client."""
68
69
  try:
69
- return FTPClient(FtpClientInitArgs(config, client_name="ftplib_client"))
70
+ return FTPClient(FtpClientInitArgs(config, client_name="aioftp_client"))
70
71
  except RuntimeError as error:
71
72
  raise FtpClientError(error)
72
73
 
@@ -95,7 +96,7 @@ class UpdateThiesDataUseCase:
95
96
  reason=f"The current folder '{folder_name}' doesn't exist."
96
97
  )
97
98
 
98
- async def fetch_cloud_file_names(self) -> set[str]:
99
+ async def fetch_cloud_file_names(self) -> Set[str]:
99
100
  """Fetch file names from the RCER cloud."""
100
101
  await self._validate_sharepoint_current_folders()
101
102
  try:
@@ -113,7 +114,7 @@ class UpdateThiesDataUseCase:
113
114
  except Exception as error:
114
115
  raise SharePointFetchingError(reason=error)
115
116
 
116
- async def fetch_thies_file_names(self) -> set[str]:
117
+ async def fetch_thies_file_names(self) -> Set[str]:
117
118
  """Fetch file names from the THIES FTP server."""
118
119
  try:
119
120
  thies_files = set()
@@ -131,7 +132,7 @@ class UpdateThiesDataUseCase:
131
132
  except ConnectionAbortedError as error:
132
133
  raise ThiesFetchingError(reason=error)
133
134
 
134
- async def fetch_thies_file_content(self) -> dict[str, bytes]:
135
+ async def fetch_thies_file_content(self) -> Dict[str, bytes]:
135
136
  """Fetch the content of files from the THIES FTP server."""
136
137
  try:
137
138
  content_files = {}
@@ -165,8 +166,8 @@ class UpdateThiesDataUseCase:
165
166
  raise ThiesFetchingError(reason=error)
166
167
 
167
168
  async def upload_thies_files_to_sharepoint(
168
- self, files: dict
169
- ) -> dict[str, list[str]]:
169
+ self, files: Dict
170
+ ) -> Dict[str, List[str]]:
170
171
  """Upload files to SharePoint and categorize the results."""
171
172
  upload_results = {"failed_files": [], "new_files": []}
172
173
 
@@ -269,7 +270,15 @@ class UpdateThiesDataUseCase:
269
270
  FtpReadFileArgs(file_path)
270
271
  )
271
272
  except FileNotFoundError as error:
272
- raise ThiesFetchingError(reason=str(error))
273
+ reason = str(error) + ". The file might not be available yet for statistics."
274
+ self.logger.warning(
275
+ "[thies_synchronization_lib] Warning: %s", reason
276
+ )
277
+ self.logger.warning(
278
+ "[thies_synchronization_lib] Skipping the creation of daily statistics %s",
279
+ filename,
280
+ )
281
+ return
273
282
  # Destination local folder
274
283
  self.logger.debug(file_path)
275
284
 
@@ -305,9 +314,7 @@ class UpdateThiesDataUseCase:
305
314
  dest_folder,
306
315
  )
307
316
  # Read the files with ThiesDayData class
308
- await create_thies_daily_statistics_file(
309
- self.os_client, self.logger, daily_files
310
- )
317
+ await create_thies_daily_statistics_file(self.os_client, self.logger)
311
318
 
312
319
  async def execute(self):
313
320
  """Synchronize data from the THIES Center to the cloud."""
@@ -1,9 +0,0 @@
1
- # read version from installed package
2
- from importlib.metadata import version
3
-
4
- __version__ = version("saviialib")
5
-
6
- from .services.epii.api import EpiiAPI
7
- from .general_types.api.epii_api_types import EpiiAPIConfig
8
-
9
- __all__ = ["EpiiAPI", "EpiiAPIConfig"]
@@ -1,3 +0,0 @@
1
- from .epii_api_types import EpiiUpdateThiesConfig, EpiiSharepointBackupConfig
2
-
3
- __all__ = ["EpiiUpdateThiesConfig", "EpiiSharepointBackupConfig"]
@@ -1,94 +0,0 @@
1
- from typing import Any, Dict, List
2
-
3
- from .controllers.types.update_thies_data_types import UpdateThiesDataControllerInput
4
- from .controllers.types.upload_backup_to_sharepoint_types import (
5
- UploadBackupToSharepointControllerInput,
6
- )
7
- from .controllers.update_thies_data import UpdateThiesDataController
8
- from .controllers.upload_backup_to_sharepoint import UploadBackupToSharepointController
9
- from saviialib.general_types.api.epii_api_types import (
10
- EpiiUpdateThiesConfig,
11
- EpiiSharepointBackupConfig,
12
- EpiiAPIConfig,
13
- )
14
-
15
-
16
- class EpiiAPI:
17
- """
18
- EpiiAPI is a service class that provides methods to interact with Patagonia Center system.
19
- """
20
-
21
- def __init__(self, config: EpiiAPIConfig):
22
- self.ftp_port = config.ftp_port
23
- self.ftp_host = config.ftp_host
24
- self.ftp_user = config.ftp_user
25
- self.ftp_password = config.ftp_password
26
- self.sharepoint_client_id = config.sharepoint_client_id
27
- self.sharepoint_client_secret = config.sharepoint_client_secret
28
- self.sharepoint_tenant_id = config.sharepoint_tenant_id
29
- self.sharepoint_tenant_name = config.sharepoint_tenant_name
30
- self.sharepoint_site_name = config.sharepoint_site_name
31
- self.logger = config.logger
32
-
33
- async def update_thies_data(
34
- self, sharepoint_folders_path: List[str], ftp_server_folders_path: List[str]
35
- ) -> Dict[str, Any]:
36
- """Updates data from a THIES Data Logger by connecting to an FTP server
37
- and transferring data to specified Sharepoint folders.
38
-
39
- Args:
40
- sharepoint_folders_path (list): List of Sharepoint folder paths for AVG and EXT data.
41
- The AVG path must be the first element.
42
- ftp_server_folders_path (list): List of FTP server folder paths for AVG and EXT data.
43
- The AVG path must be the first element.
44
-
45
- Returns:
46
- dict: A dictionary representation of the API response.
47
- """
48
- config = EpiiUpdateThiesConfig(
49
- ftp_port=self.ftp_port,
50
- ftp_host=self.ftp_host,
51
- ftp_user=self.ftp_user,
52
- ftp_password=self.ftp_password,
53
- sharepoint_client_id=self.sharepoint_client_id,
54
- sharepoint_client_secret=self.sharepoint_client_secret,
55
- sharepoint_site_name=self.sharepoint_site_name,
56
- sharepoint_tenant_id=self.sharepoint_tenant_id,
57
- sharepoint_tenant_name=self.sharepoint_tenant_name,
58
- logger=self.logger,
59
- )
60
- controller = UpdateThiesDataController(
61
- UpdateThiesDataControllerInput(
62
- config, sharepoint_folders_path, ftp_server_folders_path
63
- )
64
- )
65
- response = await controller.execute()
66
- return response.__dict__
67
-
68
- async def upload_backup_to_sharepoint(
69
- self, local_backup_source_path: str, sharepoint_destination_path: str
70
- ) -> Dict[str, Any]:
71
- """Migrate a backup folder from Home assistant to Sharepoint directory.
72
- Args:
73
- local_backup_source_path (str): Local path to backup.
74
- Returns:
75
- response (dict): A dictionary containing the response from the upload operation.
76
- This dictionary will typically include information about the success or
77
- failure of the upload, as well as any relevant metadata.
78
- """
79
- config = EpiiSharepointBackupConfig(
80
- sharepoint_client_id=self.sharepoint_client_id,
81
- sharepoint_client_secret=self.sharepoint_client_secret,
82
- sharepoint_site_name=self.sharepoint_site_name,
83
- sharepoint_tenant_id=self.sharepoint_tenant_id,
84
- sharepoint_tenant_name=self.sharepoint_tenant_name,
85
- logger=self.logger,
86
- )
87
-
88
- controller = UploadBackupToSharepointController(
89
- UploadBackupToSharepointControllerInput(
90
- config, local_backup_source_path, sharepoint_destination_path
91
- )
92
- )
93
- response = await controller.execute()
94
- return response.__dict__
@@ -1,3 +0,0 @@
1
- from .update_thies_data_utils import parse_execute_response
2
-
3
- __all__ = ["parse_execute_response"]
File without changes
File without changes