thestage 0.6.2__py3-none-any.whl → 0.6.4__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.
Files changed (177) hide show
  1. thestage/.env +4 -5
  2. thestage/__init__.py +3 -3
  3. thestage/__main__.py +9 -9
  4. thestage/cli_command.py +56 -56
  5. thestage/cli_command_helper.py +51 -51
  6. thestage/color_scheme/color_scheme.py +7 -7
  7. thestage/config/__init__.py +18 -18
  8. thestage/config/config_storage.py +5 -5
  9. thestage/config/env_base.py +7 -7
  10. thestage/controllers/__init__.py +0 -0
  11. thestage/controllers/base_controller.py +67 -67
  12. thestage/controllers/config_controller.py +137 -137
  13. thestage/controllers/container_controller.py +389 -389
  14. thestage/controllers/instance_controller.py +183 -183
  15. thestage/controllers/project_controller.py +810 -810
  16. thestage/controllers/utils_controller.py +32 -32
  17. thestage/debug_main.dist.py +28 -28
  18. thestage/entities/__init__.py +0 -0
  19. thestage/entities/container.py +17 -17
  20. thestage/entities/enums/__init__.py +0 -0
  21. thestage/entities/enums/order_direction_type.py +6 -6
  22. thestage/entities/enums/shell_type.py +7 -7
  23. thestage/entities/enums/tail_output_type.py +6 -6
  24. thestage/entities/enums/yes_no_response.py +7 -7
  25. thestage/entities/file_item.py +27 -27
  26. thestage/entities/project_inference_simulator.py +18 -18
  27. thestage/entities/project_inference_simulator_model.py +17 -17
  28. thestage/entities/project_task.py +19 -19
  29. thestage/entities/rented_instance.py +19 -19
  30. thestage/entities/self_hosted_instance.py +18 -18
  31. thestage/exceptions/__init__.py +0 -0
  32. thestage/exceptions/auth_exception.py +6 -6
  33. thestage/exceptions/base_exception.py +13 -13
  34. thestage/exceptions/business_logic_exception.py +6 -6
  35. thestage/exceptions/config_exception.py +6 -6
  36. thestage/exceptions/file_system_exception.py +6 -6
  37. thestage/exceptions/git_access_exception.py +17 -17
  38. thestage/exceptions/remote_server_exception.py +24 -24
  39. thestage/git/ProgressPrinter.py +22 -22
  40. thestage/helpers/__init__.py +0 -0
  41. thestage/helpers/error_handler.py +115 -115
  42. thestage/helpers/exception_hook.py +14 -14
  43. thestage/helpers/logger/__init__.py +0 -0
  44. thestage/helpers/logger/app_logger.py +50 -50
  45. thestage/helpers/ssh_util.py +38 -38
  46. thestage/i18n/en_GB/messages.po +947 -947
  47. thestage/i18n/translation.py +9 -9
  48. thestage/main.py +36 -36
  49. thestage/services/.env +6 -6
  50. thestage/services/__init__.py +0 -0
  51. thestage/services/abstract_mapper.py +9 -9
  52. thestage/services/abstract_service.py +87 -87
  53. thestage/services/app_config_service.py +52 -52
  54. thestage/services/clients/__init__.py +0 -0
  55. thestage/services/clients/git/__init__.py +0 -0
  56. thestage/services/clients/git/git_client.py +436 -436
  57. thestage/services/clients/thestage_api/__init__.py +0 -0
  58. thestage/services/clients/thestage_api/api_client.py +718 -718
  59. thestage/services/clients/thestage_api/core/api_client_core.py +108 -108
  60. thestage/services/clients/thestage_api/core/http_client_exception.py +12 -12
  61. thestage/services/clients/thestage_api/dtos/__init__.py +0 -0
  62. thestage/services/clients/thestage_api/dtos/base_response.py +13 -13
  63. thestage/services/clients/thestage_api/dtos/cloud_provider_region.py +19 -19
  64. thestage/services/clients/thestage_api/dtos/container_param_request.py +11 -11
  65. thestage/services/clients/thestage_api/dtos/container_response.py +67 -67
  66. thestage/services/clients/thestage_api/dtos/docker_container_assigned_device.py +10 -10
  67. thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_request.py +13 -13
  68. thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_response.py +13 -13
  69. thestage/services/clients/thestage_api/dtos/docker_container_mapping.py +10 -10
  70. thestage/services/clients/thestage_api/dtos/entity_filter_request.py +14 -14
  71. thestage/services/clients/thestage_api/dtos/enums/__init__.py +0 -0
  72. thestage/services/clients/thestage_api/dtos/enums/container_pending_action.py +10 -10
  73. thestage/services/clients/thestage_api/dtos/enums/container_status.py +17 -17
  74. thestage/services/clients/thestage_api/dtos/enums/cpu_type.py +8 -8
  75. thestage/services/clients/thestage_api/dtos/enums/currency_type.py +10 -10
  76. thestage/services/clients/thestage_api/dtos/enums/daemon_status.py +9 -9
  77. thestage/services/clients/thestage_api/dtos/enums/disk_type.py +7 -7
  78. thestage/services/clients/thestage_api/dtos/enums/drive_type.py +7 -7
  79. thestage/services/clients/thestage_api/dtos/enums/gpu_name.py +8 -8
  80. thestage/services/clients/thestage_api/dtos/enums/inference_model_status.py +9 -9
  81. thestage/services/clients/thestage_api/dtos/enums/inference_simulator_status.py +15 -15
  82. thestage/services/clients/thestage_api/dtos/enums/instance_rented_status.py +17 -17
  83. thestage/services/clients/thestage_api/dtos/enums/instance_type.py +7 -7
  84. thestage/services/clients/thestage_api/dtos/enums/location_region.py +11 -11
  85. thestage/services/clients/thestage_api/dtos/enums/power_status.py +10 -10
  86. thestage/services/clients/thestage_api/dtos/enums/provider_name.py +11 -11
  87. thestage/services/clients/thestage_api/dtos/enums/selfhosted_status.py +10 -10
  88. thestage/services/clients/thestage_api/dtos/enums/task_execution_status.py +12 -12
  89. thestage/services/clients/thestage_api/dtos/enums/task_status.py +12 -12
  90. thestage/services/clients/thestage_api/dtos/frontend_status.py +10 -10
  91. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py +13 -13
  92. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py +13 -13
  93. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_request.py +12 -12
  94. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_response.py +12 -12
  95. thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py +10 -10
  96. thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_response.py +13 -13
  97. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_request.py +14 -14
  98. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_response.py +12 -12
  99. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_request.py +12 -12
  100. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_response.py +13 -13
  101. thestage/services/clients/thestage_api/dtos/inference_simulator_model_response.py +11 -11
  102. thestage/services/clients/thestage_api/dtos/inference_simulator_response.py +11 -11
  103. thestage/services/clients/thestage_api/dtos/installed_service.py +17 -17
  104. thestage/services/clients/thestage_api/dtos/instance_detected_gpus.py +20 -20
  105. thestage/services/clients/thestage_api/dtos/instance_rented_response.py +71 -71
  106. thestage/services/clients/thestage_api/dtos/logging_controller/docker_container_log_stream_request.py +7 -7
  107. thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_request.py +13 -13
  108. thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_response.py +14 -14
  109. thestage/services/clients/thestage_api/dtos/logging_controller/task_log_stream_request.py +7 -7
  110. thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_request.py +21 -21
  111. thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_response.py +14 -14
  112. thestage/services/clients/thestage_api/dtos/paginated_entity_list.py +11 -11
  113. thestage/services/clients/thestage_api/dtos/pagination_data.py +10 -10
  114. thestage/services/clients/thestage_api/dtos/price_definition.py +14 -14
  115. thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_request.py +7 -7
  116. thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_response.py +10 -10
  117. thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py +8 -8
  118. thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_response.py +6 -6
  119. thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_request.py +15 -15
  120. thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +10 -10
  121. thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py +13 -13
  122. thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_response.py +10 -10
  123. thestage/services/clients/thestage_api/dtos/project_response.py +32 -32
  124. thestage/services/clients/thestage_api/dtos/selfhosted_instance_response.py +56 -56
  125. thestage/services/clients/thestage_api/dtos/sftp_path_helper.py +13 -13
  126. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_request.py +8 -8
  127. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_response.py +11 -11
  128. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_request.py +8 -8
  129. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_response.py +11 -11
  130. thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_request.py +7 -7
  131. thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_response.py +12 -12
  132. thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_request.py +10 -10
  133. thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_response.py +12 -12
  134. thestage/services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py +9 -9
  135. thestage/services/clients/thestage_api/dtos/task_controller/task_view_response.py +12 -12
  136. thestage/services/clients/thestage_api/dtos/user_controller/user_profile.py +12 -12
  137. thestage/services/clients/thestage_api/dtos/validate_token_response.py +11 -11
  138. thestage/services/config_provider/__init__.py +0 -0
  139. thestage/services/config_provider/config_provider.py +237 -237
  140. thestage/services/connect/connect_service.py +193 -196
  141. thestage/services/connect/dto/remote_server_config.py +9 -9
  142. thestage/services/container/__init__.py +0 -0
  143. thestage/services/container/container_service.py +374 -374
  144. thestage/services/container/mapper/__init__.py +0 -0
  145. thestage/services/container/mapper/container_mapper.py +30 -30
  146. thestage/services/core_files/config_entity.py +26 -26
  147. thestage/services/filesystem_service.py +133 -133
  148. thestage/services/instance/__init__.py +0 -0
  149. thestage/services/instance/instance_service.py +303 -303
  150. thestage/services/instance/mapper/__init__.py +0 -0
  151. thestage/services/instance/mapper/instance_mapper.py +24 -24
  152. thestage/services/instance/mapper/selfhosted_mapper.py +33 -33
  153. thestage/services/logging/byte_print_style.py +5 -5
  154. thestage/services/logging/dto/log_message.py +15 -15
  155. thestage/services/logging/dto/log_type.py +6 -6
  156. thestage/services/logging/exception/log_polling_exception.py +6 -6
  157. thestage/services/logging/logging_constants.py +3 -3
  158. thestage/services/logging/logging_service.py +367 -367
  159. thestage/services/project/__init__.py +0 -0
  160. thestage/services/project/dto/inference_simulator_dto.py +22 -22
  161. thestage/services/project/dto/inference_simulator_model_dto.py +20 -20
  162. thestage/services/project/dto/project_config.py +14 -14
  163. thestage/services/project/mapper/__init__.py +0 -0
  164. thestage/services/project/mapper/project_inference_simulator_mapper.py +21 -21
  165. thestage/services/project/mapper/project_inference_simulator_model_mapper.py +21 -21
  166. thestage/services/project/mapper/project_task_mapper.py +22 -22
  167. thestage/services/project/project_service.py +1253 -1253
  168. thestage/services/remote_server_service.py +609 -609
  169. thestage/services/service_factory.py +97 -97
  170. thestage/services/task/dto/task_dto.py +40 -40
  171. thestage/services/validation_service.py +61 -61
  172. {thestage-0.6.2.dist-info → thestage-0.6.4.dist-info}/LICENSE.txt +12 -12
  173. {thestage-0.6.2.dist-info → thestage-0.6.4.dist-info}/METADATA +3 -2
  174. thestage-0.6.4.dist-info/RECORD +176 -0
  175. {thestage-0.6.2.dist-info → thestage-0.6.4.dist-info}/WHEEL +1 -1
  176. thestage-0.6.2.dist-info/RECORD +0 -176
  177. {thestage-0.6.2.dist-info → thestage-0.6.4.dist-info}/entry_points.txt +0 -0
File without changes
@@ -1,30 +1,30 @@
1
- from typing import Optional, Tuple
2
-
3
- from thestage.services.clients.thestage_api.dtos.container_response import DockerContainerDto
4
- from thestage.entities.container import DockerContainerEntity
5
- from thestage.services.abstract_mapper import AbstractMapper
6
-
7
-
8
- class ContainerMapper(AbstractMapper):
9
-
10
- def build_entity(self, item: DockerContainerDto) -> Optional[DockerContainerEntity]:
11
- if not item:
12
- return None
13
-
14
- instance_type = ''
15
- instance_slug = ''
16
- if item.instance_rented:
17
- instance_type = 'RENTED'
18
- instance_slug = item.instance_rented.slug
19
- if item.selfhosted_instance:
20
- instance_type = 'SELF-HOSTED'
21
- instance_slug = item.selfhosted_instance.slug
22
-
23
- return DockerContainerEntity(
24
- status=item.frontend_status.status_translation if item.frontend_status else '',
25
- slug=item.slug or '',
26
- title=item.title or '',
27
- instance_type=instance_type,
28
- instance_slug=instance_slug,
29
- docker_image=item.docker_image or '',
30
- )
1
+ from typing import Optional, Tuple
2
+
3
+ from thestage.services.clients.thestage_api.dtos.container_response import DockerContainerDto
4
+ from thestage.entities.container import DockerContainerEntity
5
+ from thestage.services.abstract_mapper import AbstractMapper
6
+
7
+
8
+ class ContainerMapper(AbstractMapper):
9
+
10
+ def build_entity(self, item: DockerContainerDto) -> Optional[DockerContainerEntity]:
11
+ if not item:
12
+ return None
13
+
14
+ instance_type = ''
15
+ instance_slug = ''
16
+ if item.instance_rented:
17
+ instance_type = 'RENTED'
18
+ instance_slug = item.instance_rented.slug
19
+ if item.selfhosted_instance:
20
+ instance_type = 'SELF-HOSTED'
21
+ instance_slug = item.selfhosted_instance.slug
22
+
23
+ return DockerContainerEntity(
24
+ status=item.frontend_status.status_translation if item.frontend_status else '',
25
+ slug=item.slug or '',
26
+ title=item.title or '',
27
+ instance_type=instance_type,
28
+ instance_slug=instance_slug,
29
+ docker_image=item.docker_image or '',
30
+ )
@@ -1,26 +1,26 @@
1
- from typing import Optional, Dict
2
-
3
- from pydantic import BaseModel, Field
4
-
5
- from thestage.cli_command import CliCommand, CliCommandAvailability
6
-
7
-
8
- # saved to file
9
- class MainConfigEntity(BaseModel):
10
- thestage_auth_token: Optional[str] = Field(None, alias='thestage_auth_token')
11
- thestage_api_url: Optional[str] = Field(None, alias='thestage_api_url')
12
-
13
-
14
- # not saved to file
15
- class RuntimeConfigEntity(BaseModel):
16
- working_directory: Optional[str] = Field(None, alias='working_directory')
17
- config_global_path: Optional[str] = Field(None, alias='config_global_path')
18
- allowed_commands: Dict[CliCommand, CliCommandAvailability] = {}
19
- is_token_valid: bool = Field(None, alias='is_token_valid')
20
-
21
-
22
- class ConfigEntity(BaseModel):
23
- global_config_path: str = Field(None, alias='global_config_path')
24
- can_use_inference: bool = Field(None, alias='can_use_inference')
25
- main: MainConfigEntity = Field(default_factory=MainConfigEntity, alias='main')
26
- runtime: RuntimeConfigEntity = Field(default_factory=RuntimeConfigEntity, alias="runtime") # TODO merge with main
1
+ from typing import Optional, Dict
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from thestage.cli_command import CliCommand, CliCommandAvailability
6
+
7
+
8
+ # saved to file
9
+ class MainConfigEntity(BaseModel):
10
+ thestage_auth_token: Optional[str] = Field(None, alias='thestage_auth_token')
11
+ thestage_api_url: Optional[str] = Field(None, alias='thestage_api_url')
12
+
13
+
14
+ # not saved to file
15
+ class RuntimeConfigEntity(BaseModel):
16
+ working_directory: Optional[str] = Field(None, alias='working_directory')
17
+ config_global_path: Optional[str] = Field(None, alias='config_global_path')
18
+ allowed_commands: Dict[CliCommand, CliCommandAvailability] = {}
19
+ is_token_valid: bool = Field(None, alias='is_token_valid')
20
+
21
+
22
+ class ConfigEntity(BaseModel):
23
+ global_config_path: str = Field(None, alias='global_config_path')
24
+ can_use_inference: bool = Field(None, alias='can_use_inference')
25
+ main: MainConfigEntity = Field(default_factory=MainConfigEntity, alias='main')
26
+ runtime: RuntimeConfigEntity = Field(default_factory=RuntimeConfigEntity, alias="runtime") # TODO merge with main
@@ -1,133 +1,133 @@
1
- import json
2
- import os
3
- import shutil
4
- from json import JSONDecodeError
5
- from pathlib import Path
6
- from typing import Optional, List, Dict, Any
7
-
8
- from thestage.entities.file_item import FileItemEntity
9
- from thestage.exceptions.file_system_exception import FileSystemException
10
-
11
-
12
- class FileSystemService:
13
-
14
- def get_ssh_path(self) -> Optional[Path]:
15
- home_path = self.get_home_path()
16
- ssh_path = home_path.joinpath('.ssh')
17
- if not ssh_path.exists():
18
- raise FileSystemException(f"Path does not exist: {ssh_path}")
19
- return ssh_path
20
-
21
- def get_home_path(self) -> Optional[Path]:
22
- try:
23
- return Path.home()
24
- except RuntimeError | OSError as ex1:
25
- raise FileSystemException("Error getting user home path") from ex1
26
-
27
- def create_if_not_exists_dir(self, path: Path) -> Path:
28
- if not path.exists():
29
- try:
30
- path.mkdir(exist_ok=True, parents=True)
31
- except FileNotFoundError as ex1:
32
- raise FileSystemException(message=f"FileNotFoundError (dir): {path}") from ex1
33
- except OSError as ex2:
34
- raise FileSystemException(message=f"Could not create directory: {path}") from ex2
35
- return path
36
-
37
- def create_if_not_exists_file(self, path: Path) -> Path:
38
- if not path.exists():
39
- try:
40
- path.touch(exist_ok=True)
41
- except FileNotFoundError as ex1:
42
- raise FileSystemException(message=f"FileNotFoundError (file): {path}") from ex1
43
- except OSError as ex2:
44
- raise FileSystemException(message=f"Could not create file: {path}") from ex2
45
- return path
46
-
47
- def get_path(self, directory: str, auto_create: bool = True) -> Path:
48
- path = Path(directory)
49
- if auto_create:
50
- self.create_if_not_exists_dir(path)
51
- return path
52
-
53
- def is_folder_empty(self, folder: str, auto_create: bool) -> bool:
54
- path = self.get_path(folder, auto_create)
55
- if not path.exists():
56
- return True
57
- if not path.is_dir():
58
- raise FileSystemException(message=f"Expected directory but found a file: {path}")
59
- objects = os.listdir(path)
60
- if len(objects) == 0:
61
- return True
62
- else:
63
- return False
64
-
65
- def is_folder_exists(self, folder: str, auto_create: bool = True) -> bool:
66
- path = self.get_path(folder, auto_create=auto_create)
67
- if path.exists():
68
- return True
69
- else:
70
- return False
71
-
72
- def find_line_in_text_file(self, file: str, find: str) -> bool:
73
- path = self.get_path(file, auto_create=False)
74
- if path and path.exists():
75
- with open(path, 'r') as file:
76
- for line in file.readlines():
77
- if (find + "\n") == line:
78
- return True
79
- return False
80
-
81
- def add_line_to_text_file(self, file: str, new_line: str):
82
- path = self.get_path(file, auto_create=False)
83
- if path and path.exists():
84
- with open(path, 'a') as file:
85
- file.write(new_line)
86
- file.write('\n')
87
-
88
- # TODO remove this fucking useless shit
89
- def check_if_path_exist(self, file: str) -> bool:
90
- path = self.get_path(file, auto_create=False)
91
- if path.exists():
92
- return True
93
- else:
94
- return False
95
-
96
- def get_path_items(self, folder: str) -> List[FileItemEntity]:
97
- path = self.get_path(folder, auto_create=False)
98
- path_items = []
99
- if not path.exists():
100
- return path_items
101
-
102
- parent = FileItemEntity.build_from_path(path=path)
103
- path_items.append(parent)
104
- if path.is_dir():
105
- objects = os.listdir(path)
106
- if objects:
107
- for item in objects:
108
- elem = path.joinpath(item)
109
- if elem.is_dir():
110
- parent.children.extend(self.get_path_items(folder=str(elem)))
111
- else:
112
- parent.children.append(FileItemEntity.build_from_path(path=elem))
113
- return path_items
114
-
115
- def remove_folder(self, path: str):
116
- real_path = self.get_path(directory=path, auto_create=False)
117
- if real_path and real_path.exists():
118
- shutil.rmtree(real_path)
119
-
120
-
121
- def read_config_file(self, path: Path) -> Dict[str, Any]:
122
- result = {}
123
- try:
124
- if path and path.exists():
125
- with path.open("r") as file:
126
- try:
127
- if os.stat(path).st_size != 0:
128
- result = json.load(file)
129
- except JSONDecodeError as e:
130
- raise Exception(f"Config file is malformed: {path}") from e
131
- except OSError:
132
- raise FileSystemException(f"Could not open config file: {path}")
133
- return result
1
+ import json
2
+ import os
3
+ import shutil
4
+ from json import JSONDecodeError
5
+ from pathlib import Path
6
+ from typing import Optional, List, Dict, Any
7
+
8
+ from thestage.entities.file_item import FileItemEntity
9
+ from thestage.exceptions.file_system_exception import FileSystemException
10
+
11
+
12
+ class FileSystemService:
13
+
14
+ def get_ssh_path(self) -> Optional[Path]:
15
+ home_path = self.get_home_path()
16
+ ssh_path = home_path.joinpath('.ssh')
17
+ if not ssh_path.exists():
18
+ raise FileSystemException(f"Path does not exist: {ssh_path}")
19
+ return ssh_path
20
+
21
+ def get_home_path(self) -> Optional[Path]:
22
+ try:
23
+ return Path.home()
24
+ except RuntimeError | OSError as ex1:
25
+ raise FileSystemException("Error getting user home path") from ex1
26
+
27
+ def create_if_not_exists_dir(self, path: Path) -> Path:
28
+ if not path.exists():
29
+ try:
30
+ path.mkdir(exist_ok=True, parents=True)
31
+ except FileNotFoundError as ex1:
32
+ raise FileSystemException(message=f"FileNotFoundError (dir): {path}") from ex1
33
+ except OSError as ex2:
34
+ raise FileSystemException(message=f"Could not create directory: {path}") from ex2
35
+ return path
36
+
37
+ def create_if_not_exists_file(self, path: Path) -> Path:
38
+ if not path.exists():
39
+ try:
40
+ path.touch(exist_ok=True)
41
+ except FileNotFoundError as ex1:
42
+ raise FileSystemException(message=f"FileNotFoundError (file): {path}") from ex1
43
+ except OSError as ex2:
44
+ raise FileSystemException(message=f"Could not create file: {path}") from ex2
45
+ return path
46
+
47
+ def get_path(self, directory: str, auto_create: bool = True) -> Path:
48
+ path = Path(directory)
49
+ if auto_create:
50
+ self.create_if_not_exists_dir(path)
51
+ return path
52
+
53
+ def is_folder_empty(self, folder: str, auto_create: bool) -> bool:
54
+ path = self.get_path(folder, auto_create)
55
+ if not path.exists():
56
+ return True
57
+ if not path.is_dir():
58
+ raise FileSystemException(message=f"Expected directory but found a file: {path}")
59
+ objects = os.listdir(path)
60
+ if len(objects) == 0:
61
+ return True
62
+ else:
63
+ return False
64
+
65
+ def is_folder_exists(self, folder: str, auto_create: bool = True) -> bool:
66
+ path = self.get_path(folder, auto_create=auto_create)
67
+ if path.exists():
68
+ return True
69
+ else:
70
+ return False
71
+
72
+ def find_line_in_text_file(self, file: str, find: str) -> bool:
73
+ path = self.get_path(file, auto_create=False)
74
+ if path and path.exists():
75
+ with open(path, 'r') as file:
76
+ for line in file.readlines():
77
+ if (find + "\n") == line:
78
+ return True
79
+ return False
80
+
81
+ def add_line_to_text_file(self, file: str, new_line: str):
82
+ path = self.get_path(file, auto_create=False)
83
+ if path and path.exists():
84
+ with open(path, 'a') as file:
85
+ file.write(new_line)
86
+ file.write('\n')
87
+
88
+ # TODO remove this fucking useless shit
89
+ def check_if_path_exist(self, file: str) -> bool:
90
+ path = self.get_path(file, auto_create=False)
91
+ if path.exists():
92
+ return True
93
+ else:
94
+ return False
95
+
96
+ def get_path_items(self, folder: str) -> List[FileItemEntity]:
97
+ path = self.get_path(folder, auto_create=False)
98
+ path_items = []
99
+ if not path.exists():
100
+ return path_items
101
+
102
+ parent = FileItemEntity.build_from_path(path=path)
103
+ path_items.append(parent)
104
+ if path.is_dir():
105
+ objects = os.listdir(path)
106
+ if objects:
107
+ for item in objects:
108
+ elem = path.joinpath(item)
109
+ if elem.is_dir():
110
+ parent.children.extend(self.get_path_items(folder=str(elem)))
111
+ else:
112
+ parent.children.append(FileItemEntity.build_from_path(path=elem))
113
+ return path_items
114
+
115
+ def remove_folder(self, path: str):
116
+ real_path = self.get_path(directory=path, auto_create=False)
117
+ if real_path and real_path.exists():
118
+ shutil.rmtree(real_path)
119
+
120
+
121
+ def read_config_file(self, path: Path) -> Dict[str, Any]:
122
+ result = {}
123
+ try:
124
+ if path and path.exists():
125
+ with path.open("r") as file:
126
+ try:
127
+ if os.stat(path).st_size != 0:
128
+ result = json.load(file)
129
+ except JSONDecodeError as e:
130
+ raise Exception(f"Config file is malformed: {path}") from e
131
+ except OSError:
132
+ raise FileSystemException(f"Could not open config file: {path}")
133
+ return result
File without changes