data-sourcerer 0.5.0__tar.gz → 0.6.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.
Files changed (136) hide show
  1. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/PKG-INFO +5 -1
  2. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/README.md +4 -0
  3. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/__init__.py +1 -1
  4. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage_provider/services/azure.py +25 -2
  5. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/question/styles.tcss +1 -1
  6. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/utils.py +14 -1
  7. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/settings.py +2 -0
  8. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/.gitignore +0 -0
  9. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/LICENSE +0 -0
  10. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/pyproject.toml +0 -0
  11. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/__init__.py +0 -0
  12. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/access_credentials/__init__.py +0 -0
  13. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/access_credentials/entities.py +0 -0
  14. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/access_credentials/exceptions.py +0 -0
  15. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/access_credentials/repositories.py +0 -0
  16. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/access_credentials/services.py +0 -0
  17. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/file_system/__init__.py +0 -0
  18. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/file_system/entities.py +0 -0
  19. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/file_system/exceptions.py +0 -0
  20. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/file_system/services.py +0 -0
  21. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/package_meta/__init__.py +0 -0
  22. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/package_meta/entities.py +0 -0
  23. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/package_meta/services.py +0 -0
  24. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/settings/__init__.py +0 -0
  25. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/settings/entities.py +0 -0
  26. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/settings/repositories.py +0 -0
  27. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/settings/services.py +0 -0
  28. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/shared/__init__.py +0 -0
  29. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/shared/entities.py +0 -0
  30. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/storage/__init__.py +0 -0
  31. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/storage/entities.py +0 -0
  32. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/storage/repositories.py +0 -0
  33. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/storage_provider/__init__.py +0 -0
  34. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/storage_provider/entities.py +0 -0
  35. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/storage_provider/exceptions.py +0 -0
  36. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/domain/storage_provider/services.py +0 -0
  37. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/__init__.py +0 -0
  38. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/access_credentials/__init__.py +0 -0
  39. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/access_credentials/exceptions.py +0 -0
  40. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/access_credentials/registry.py +0 -0
  41. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/access_credentials/repositories.py +0 -0
  42. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/access_credentials/services.py +0 -0
  43. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/db/__init__.py +0 -0
  44. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/db/config.py +0 -0
  45. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/db/models.py +0 -0
  46. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/file_system/__init__.py +0 -0
  47. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/file_system/exceptions.py +0 -0
  48. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/file_system/services.py +0 -0
  49. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/package_meta/__init__.py +0 -0
  50. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/package_meta/services.py +0 -0
  51. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/settings/__init__.py +0 -0
  52. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/settings/repositories.py +0 -0
  53. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/settings/services.py +0 -0
  54. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage/__init__.py +0 -0
  55. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage/repositories.py +0 -0
  56. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage/services.py +0 -0
  57. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage_provider/__init__.py +0 -0
  58. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage_provider/exceptions.py +0 -0
  59. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage_provider/registry.py +0 -0
  60. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage_provider/services/__init__.py +0 -0
  61. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage_provider/services/gcp.py +0 -0
  62. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/storage_provider/services/s3.py +0 -0
  63. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/infrastructure/utils.py +0 -0
  64. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/__init__.py +0 -0
  65. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/app.py +0 -0
  66. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/di_container.py +0 -0
  67. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/__init__.py +0 -0
  68. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/about/__init__.py +0 -0
  69. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/about/main.py +0 -0
  70. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/about/styles.tcss +0 -0
  71. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/critical_error/__init__.py +0 -0
  72. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/critical_error/main.py +0 -0
  73. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/critical_error/styles.tcss +0 -0
  74. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/file_system_finder/__init__.py +0 -0
  75. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/file_system_finder/main.py +0 -0
  76. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/file_system_finder/styles.tcss +0 -0
  77. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/file_system_finder/widgets/__init__.py +0 -0
  78. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/file_system_finder/widgets/file_system_navigator.py +0 -0
  79. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/__init__.py +0 -0
  80. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/main.py +0 -0
  81. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/__init__.py +0 -0
  82. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/delete_request.py +0 -0
  83. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/download_request.py +0 -0
  84. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/preview_request.py +0 -0
  85. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/refresh_storages_list_request.py +0 -0
  86. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/resizing_rule.py +0 -0
  87. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/select_storage_item.py +0 -0
  88. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/uncheck_files_request.py +0 -0
  89. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/messages/upload_request.py +0 -0
  90. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/mixins/__init__.py +0 -0
  91. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/mixins/resize_containers_watcher_mixin.py +0 -0
  92. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/styles.tcss +0 -0
  93. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/widgets/__init__.py +0 -0
  94. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/widgets/gradient.py +0 -0
  95. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/widgets/resizing_rule.py +0 -0
  96. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/widgets/storage_content.py +0 -0
  97. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/main/widgets/storage_list_sidebar.py +0 -0
  98. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/preview_content/__init__.py +0 -0
  99. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/preview_content/main.py +0 -0
  100. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/preview_content/styles.tcss +0 -0
  101. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/preview_content/text_area_style.py +0 -0
  102. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_list/__init__.py +0 -0
  103. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_list/main.py +0 -0
  104. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_list/messages/__init__.py +0 -0
  105. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_list/messages/reload_credentials_request.py +0 -0
  106. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_list/styles.tcss +0 -0
  107. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_registration/__init__.py +0 -0
  108. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_registration/main.py +0 -0
  109. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/provider_creds_registration/styles.tcss +0 -0
  110. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/question/__init__.py +0 -0
  111. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/question/main.py +0 -0
  112. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/settings/__init__.py +0 -0
  113. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/settings/main.py +0 -0
  114. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/settings/styles.tcss +0 -0
  115. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/shared/__init__.py +0 -0
  116. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/shared/containers.py +0 -0
  117. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/shared/modal_screens.py +0 -0
  118. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/shared/widgets/__init__.py +0 -0
  119. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/shared/widgets/button.py +0 -0
  120. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/shared/widgets/labeled_input.py +0 -0
  121. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/shared/widgets/spinner.py +0 -0
  122. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storage_action_progress/__init__.py +0 -0
  123. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storage_action_progress/main.py +0 -0
  124. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storage_action_progress/styles.tcss +0 -0
  125. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_list/__init__.py +0 -0
  126. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_list/main.py +0 -0
  127. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_list/messages/__init__.py +0 -0
  128. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_list/messages/reload_storages_request.py +0 -0
  129. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_list/styles.tcss +0 -0
  130. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_registration/__init__.py +0 -0
  131. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_registration/main.py +0 -0
  132. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/screens/storages_registration/styles.tcss +0 -0
  133. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/settings.py +0 -0
  134. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/themes/__init__.py +0 -0
  135. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/presentation/themes/github_dark.py +0 -0
  136. {data_sourcerer-0.5.0 → data_sourcerer-0.6.0}/sourcerer/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: data-sourcerer
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: Sourcerer is a terminal cloud storage navigator.
5
5
  Author-email: Bohdana Kuzmenko <bohdana.kuzmenko.dev@gmail.com>
6
6
  License: MIT
@@ -59,6 +59,10 @@ engineers to view and manage files across multiple cloud providers like
59
59
 
60
60
  ## 🪄 Installation
61
61
 
62
+ ```bash
63
+ pipx install data-sourcerer
64
+ ```
65
+ or
62
66
  ```bash
63
67
  pip install data-sourcerer
64
68
  ```
@@ -22,6 +22,10 @@ engineers to view and manage files across multiple cloud providers like
22
22
 
23
23
  ## 🪄 Installation
24
24
 
25
+ ```bash
26
+ pipx install data-sourcerer
27
+ ```
28
+ or
25
29
  ```bash
26
30
  pip install data-sourcerer
27
31
  ```
@@ -14,4 +14,4 @@ The application is structured using a clean architecture approach with:
14
14
 
15
15
  name = "sourcerer"
16
16
  package_name = "data_sourcerer"
17
- __version__ = "0.5.0"
17
+ __version__ = "0.6.0"
@@ -6,12 +6,14 @@ interface for various cloud storage providers.
6
6
  """
7
7
 
8
8
  import os.path
9
+ import threading
9
10
  from collections.abc import Callable
10
11
  from pathlib import Path
11
12
  from typing import Any
12
13
 
13
14
  from azure.mgmt.storage import StorageManagementClient
14
15
  from azure.storage.blob import BlobServiceClient
16
+ from cachetools import LRUCache
15
17
  from platformdirs import user_downloads_dir
16
18
 
17
19
  from sourcerer.domain.shared.entities import StorageProvider
@@ -37,6 +39,8 @@ from sourcerer.infrastructure.utils import generate_uuid, is_text_file
37
39
 
38
40
  @storage_provider(StorageProvider.AzureStorage)
39
41
  class AzureStorageProviderService(BaseStorageProviderService):
42
+ MAX_CACHE_SIZE = 10
43
+
40
44
  def __init__(self, credentials: Any):
41
45
  """
42
46
  Initialize the service with Azure credentials.
@@ -48,6 +52,12 @@ class AzureStorageProviderService(BaseStorageProviderService):
48
52
  self.subscription_id = credentials.subscription_id
49
53
  self.cloud_suffix = credentials.cloud_suffix
50
54
 
55
+ self._storage_management_client: StorageManagementClient | None = None
56
+ self._blob_service_clients_lock = threading.Lock()
57
+ self._blob_service_clients: LRUCache[str, BlobServiceClient] = LRUCache(
58
+ maxsize=self.MAX_CACHE_SIZE
59
+ )
60
+
51
61
  def get_accounts_client(self) -> StorageManagementClient:
52
62
  """
53
63
  Get the Azure accounts client.
@@ -55,7 +65,13 @@ class AzureStorageProviderService(BaseStorageProviderService):
55
65
  Returns:
56
66
  Any: Azure accounts client
57
67
  """
58
- return StorageManagementClient(self.credentials, self.subscription_id)
68
+ if self._storage_management_client:
69
+ return self._storage_management_client
70
+
71
+ self._storage_management_client = StorageManagementClient(
72
+ self.credentials, self.subscription_id
73
+ )
74
+ return self._storage_management_client
59
75
 
60
76
  def get_containers_client(self, storage: str):
61
77
  """
@@ -69,12 +85,19 @@ class AzureStorageProviderService(BaseStorageProviderService):
69
85
  BlobServiceClient: An instance of the BlobServiceClient, configured with the
70
86
  account URL and credentials.
71
87
  """
88
+ with self._blob_service_clients_lock:
89
+ if (client := self._blob_service_clients.get(storage)) is not None:
90
+ return client
91
+
72
92
  account_url = "https://{account}.{cloud_suffix}"
73
- return BlobServiceClient(
93
+ client = BlobServiceClient(
74
94
  account_url.format(account=storage, cloud_suffix=self.cloud_suffix),
75
95
  credential=self.credentials,
76
96
  retry_connect=0,
77
97
  )
98
+ with self._blob_service_clients_lock:
99
+ self._blob_service_clients[storage] = client
100
+ return client
78
101
 
79
102
  def list_storages(self) -> list[Storage]:
80
103
  """
@@ -6,7 +6,7 @@ QuestionScreen {
6
6
  padding: 1 2 0 2;
7
7
  margin: 0 0;
8
8
  width: 50;
9
- height: 8;
9
+ height: 10;
10
10
  border: solid $warning-darken-1;
11
11
 
12
12
  & > Static {
@@ -4,7 +4,9 @@ Utility functions for the presentation layer.
4
4
  This module provides helper functions for the presentation layer,
5
5
  particularly for retrieving and initializing storage provider services.
6
6
  """
7
+ from threading import Lock
7
8
 
9
+ from cachetools import LRUCache
8
10
  from dependency_injector.wiring import Provide
9
11
 
10
12
  from sourcerer.domain.access_credentials.repositories import BaseCredentialsRepository
@@ -15,6 +17,10 @@ from sourcerer.infrastructure.access_credentials.registry import (
15
17
  )
16
18
  from sourcerer.infrastructure.storage_provider.registry import storage_provider_registry
17
19
  from sourcerer.presentation.di_container import DiContainer
20
+ from sourcerer.settings import MAX_CREDENTIALS_CACHE_SIZE
21
+
22
+ _provider_service_cache: LRUCache = LRUCache(maxsize=MAX_CREDENTIALS_CACHE_SIZE)
23
+ _provider_service_cache_lock = Lock()
18
24
 
19
25
 
20
26
  def get_provider_service_by_access_uuid(
@@ -60,6 +66,10 @@ def get_provider_service_by_access_credentials(
60
66
  authenticated credentials.
61
67
  """
62
68
 
69
+ with _provider_service_cache_lock:
70
+ if credentials.uuid in _provider_service_cache:
71
+ return _provider_service_cache[credentials.uuid]
72
+
63
73
  credentials_service = access_credential_method_registry.get_by_provider_and_name(
64
74
  credentials.provider, credentials.credentials_type
65
75
  )
@@ -79,4 +89,7 @@ def get_provider_service_by_access_credentials(
79
89
  )
80
90
  except CredentialsAuthError:
81
91
  return None
82
- return provider_service_class(auth_credentials)
92
+ service = provider_service_class(auth_credentials)
93
+ with _provider_service_cache_lock:
94
+ _provider_service_cache[credentials.uuid] = service
95
+ return service
@@ -76,3 +76,5 @@ TEXT_EXTENSIONS = {
76
76
  PAGE_SIZE = 100
77
77
  PREVIEW_LENGTH_LIMIT = 10_000
78
78
  PREVIEW_LIMIT_SIZE = 2 * 1024 * 1024 # 2 MB
79
+
80
+ MAX_CREDENTIALS_CACHE_SIZE = 30
File without changes