digitalkin 0.2.14__py3-none-any.whl → 0.2.16__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.
@@ -1,7 +1,8 @@
1
1
  """This module contains the abstract base class for filesystem strategies."""
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from enum import Enum, auto
4
+ from datetime import datetime
5
+ from typing import Any, Literal
5
6
 
6
7
  from pydantic import BaseModel, Field
7
8
 
@@ -9,63 +10,230 @@ from digitalkin.services.base_strategy import BaseStrategy
9
10
 
10
11
 
11
12
  class FilesystemServiceError(Exception):
12
- """Base exception for Setup service errors."""
13
+ """Base exception for Filesystem service errors."""
13
14
 
14
15
 
15
- class FileType(Enum):
16
- """Enum defining the types of data that can be stored."""
17
-
18
- DOCUMENT = auto()
19
- IMAGE = auto()
20
- VIDEO = auto()
21
- AUDIO = auto()
22
- ARCHIVE = auto()
23
- OTHER = auto()
24
-
25
-
26
- class FilesystemData(BaseModel):
16
+ class FilesystemRecord(BaseModel):
27
17
  """Data model for filesystem operations."""
28
18
 
29
- kin_context: str = Field(description="The context of the file in the filesystem")
19
+ id: str = Field(description="Unique identifier for the file (UUID)")
20
+ context: str = Field(description="The context of the file in the filesystem")
30
21
  name: str = Field(description="The name of the file")
31
- file_type: FileType = Field(default=FileType.DOCUMENT, description="The type of data stored")
32
- url: str = Field(description="The URL of the file in the filesystem")
22
+ file_type: str = Field(default="UNSPECIFIED", description="The type of data stored")
23
+ content_type: str = Field(default="application/octet-stream", description="The MIME type of the file")
24
+ size_bytes: int = Field(default=0, description="Size of the file in bytes")
25
+ checksum: str = Field(default="", description="SHA-256 checksum of the file content")
26
+ metadata: dict[str, Any] | None = Field(default=None, description="Additional metadata for the file")
27
+ storage_url: str = Field(description="Internal URL for accessing the file content")
28
+ status: str = Field(default="UNSPECIFIED", description="Current status of the file")
29
+ content: bytes | None = Field(default=None, description="The content of the file")
30
+
31
+
32
+ class FileFilter(BaseModel):
33
+ """Filter criteria for querying files."""
34
+
35
+ names: list[str] | None = Field(default=None, description="Filter by file names (exact matches)")
36
+ file_ids: list[str] | None = Field(default=None, description="Filter by file IDs")
37
+ file_types: (
38
+ list[
39
+ Literal[
40
+ "UNSPECIFIED",
41
+ "DOCUMENT",
42
+ "IMAGE",
43
+ "AUDIO",
44
+ "VIDEO",
45
+ "ARCHIVE",
46
+ "CODE",
47
+ "OTHER",
48
+ ]
49
+ ]
50
+ | None
51
+ ) = Field(default=None, description="Filter by file types")
52
+ created_after: datetime | None = Field(default=None, description="Filter files created after this timestamp")
53
+ created_before: datetime | None = Field(default=None, description="Filter files created before this timestamp")
54
+ updated_after: datetime | None = Field(default=None, description="Filter files updated after this timestamp")
55
+ updated_before: datetime | None = Field(default=None, description="Filter files updated before this timestamp")
56
+ status: str | None = Field(default=None, description="Filter by file status")
57
+ content_type_prefix: str | None = Field(default=None, description="Filter by content type prefix (e.g., 'image/')")
58
+ min_size_bytes: int | None = Field(default=None, description="Filter files with minimum size")
59
+ max_size_bytes: int | None = Field(default=None, description="Filter files with maximum size")
60
+ prefix: str | None = Field(default=None, description="Filter by path prefix (e.g., 'folder1/')")
61
+ content_type: str | None = Field(default=None, description="Filter by content type")
62
+
63
+
64
+ class UploadFileData(BaseModel):
65
+ """Data model for uploading a file."""
66
+
67
+ content: bytes = Field(description="The content of the file")
68
+ name: str = Field(description="The name of the file")
69
+ file_type: Literal[
70
+ "UNSPECIFIED",
71
+ "DOCUMENT",
72
+ "IMAGE",
73
+ "AUDIO",
74
+ "VIDEO",
75
+ "ARCHIVE",
76
+ "CODE",
77
+ "OTHER",
78
+ ] = Field(description="The type of the file")
79
+ content_type: str | None = Field(default=None, description="The content type of the file")
80
+ metadata: dict[str, Any] | None = Field(default=None, description="The metadata of the file")
81
+ replace_if_exists: bool = Field(default=False, description="Whether to replace the file if it already exists")
33
82
 
34
83
 
35
84
  class FilesystemStrategy(BaseStrategy, ABC):
36
- """Abstract base class for filesystem strategies."""
85
+ """Abstract base class for filesystem strategies.
86
+
87
+ This strategy provides comprehensive file management capabilities including
88
+ upload, retrieval, update, and deletion operations with rich metadata support,
89
+ filtering, and pagination.
90
+ """
37
91
 
38
- def __init__(self, mission_id: str, setup_version_id: str, config: dict[str, str]) -> None:
92
+ def __init__(self, mission_id: str, setup_version_id: str, config: dict[str, Any] | None = None) -> None:
39
93
  """Initialize the strategy.
40
94
 
41
95
  Args:
42
96
  mission_id: The ID of the mission this strategy is associated with
43
97
  setup_version_id: The ID of the setup version this strategy is associated with
44
- config: configuration dictionary for the filesystem strategy
98
+ config: Configuration for the filesystem strategy
45
99
  """
46
100
  super().__init__(mission_id, setup_version_id)
47
- self.config: dict[str, str] = config
101
+ self.config = config
48
102
 
49
103
  @abstractmethod
50
- def upload(self, content: bytes, name: str, file_type: FileType) -> FilesystemData:
51
- """Create a new file in the filesystem."""
104
+ def upload_files(
105
+ self,
106
+ files: list[UploadFileData],
107
+ ) -> tuple[list[FilesystemRecord], int, int]:
108
+ """Upload multiple files to the system.
52
109
 
53
- @abstractmethod
54
- def get(self, name: str) -> FilesystemData:
55
- """Get file from the filesystem."""
110
+ This method allows batch uploading of files with validation and
111
+ error handling for each individual file. Files are processed
112
+ atomically - if one fails, others may still succeed.
113
+
114
+ Args:
115
+ files: List of tuples containing (content, name, file_type, content_type, metadata, replace_if_exists)
116
+
117
+ Returns:
118
+ tuple[list[FilesystemRecord], int, int]: List of uploaded files, total uploaded count, total failed count
119
+ """
56
120
 
57
121
  @abstractmethod
58
- def get_batch(self, names: list[str]) -> dict[str, FilesystemData | None]:
59
- """Get files from the filesystem."""
122
+ def get_file(
123
+ self,
124
+ file_id: str,
125
+ *,
126
+ include_content: bool = False,
127
+ ) -> tuple[FilesystemRecord, bytes | None]:
128
+ """Get a specific file by ID or name.
129
+
130
+ This method fetches detailed information about a single file,
131
+ with optional content inclusion. Supports lookup by either
132
+ unique ID or name within a context.
133
+
134
+ Args:
135
+ file_id: The ID of the file to be retrieved
136
+ include_content: Whether to include file content in response
137
+
138
+ Returns:
139
+ tuple[FilesystemRecord, bytes | None]: Metadata about the retrieved file and optional content
140
+ """
60
141
 
61
142
  @abstractmethod
62
- def get_all(self) -> list[FilesystemData]:
63
- """Get all files from the filesystem."""
143
+ def get_files(
144
+ self,
145
+ filters: FileFilter,
146
+ *,
147
+ list_size: int = 100,
148
+ offset: int = 0,
149
+ order: str | None = None,
150
+ include_content: bool = False,
151
+ ) -> tuple[list[FilesystemRecord], int]:
152
+ """Get multiple files by various criteria.
153
+
154
+ This method provides efficient retrieval of multiple files using:
155
+ - File IDs
156
+ - File names
157
+ - Path prefix
158
+ With support for:
159
+ - Pagination for large result sets
160
+ - Optional content inclusion
161
+ - Total count of matching files
162
+
163
+ Args:
164
+ filters: Filter criteria for the files
165
+ list_size: Number of files to return per page
166
+ offset: Offset to start listing files from
167
+ order: Field to order results by
168
+ include_content: Whether to include file content in response
169
+
170
+ Returns:
171
+ tuple[list[FilesystemRecord], int]: List of files and total count
172
+ """
64
173
 
65
174
  @abstractmethod
66
- def update(self, name: str, content: bytes, file_type: FileType) -> FilesystemData:
67
- """Update files in the filesystem."""
175
+ def update_file(
176
+ self,
177
+ file_id: str,
178
+ content: bytes | None = None,
179
+ file_type: Literal[
180
+ "UNSPECIFIED",
181
+ "DOCUMENT",
182
+ "IMAGE",
183
+ "VIDEO",
184
+ "AUDIO",
185
+ "ARCHIVE",
186
+ "CODE",
187
+ "OTHER",
188
+ ]
189
+ | None = None,
190
+ content_type: str | None = None,
191
+ metadata: dict[str, Any] | None = None,
192
+ new_name: str | None = None,
193
+ status: str | None = None,
194
+ ) -> FilesystemRecord:
195
+ """Update file metadata, content, or both.
196
+
197
+ This method allows updating various aspects of a file:
198
+ - Rename files
199
+ - Update content and content type
200
+ - Modify metadata
201
+ - Create new versions
202
+
203
+ Args:
204
+ file_id: The ID of the file to be updated
205
+ content: Optional new content of the file
206
+ file_type: Optional new type of data
207
+ content_type: Optional new MIME type
208
+ metadata: Optional new metadata (will merge with existing)
209
+ new_name: Optional new name for the file
210
+ status: Optional new status for the file
211
+
212
+ Returns:
213
+ FilesystemRecord: Metadata about the updated file
214
+ """
68
215
 
69
216
  @abstractmethod
70
- def delete(self, name: str) -> bool:
71
- """Delete file from the filesystem."""
217
+ def delete_files(
218
+ self,
219
+ filters: FileFilter,
220
+ *,
221
+ permanent: bool = False,
222
+ force: bool = False,
223
+ ) -> tuple[dict[str, bool], int, int]:
224
+ """Delete multiple files.
225
+
226
+ This method supports batch deletion of files with options for:
227
+ - Soft deletion (marking as deleted)
228
+ - Permanent deletion
229
+ - Force deletion of files in use
230
+ - Individual error reporting per file
231
+
232
+ Args:
233
+ filters: Filter criteria for the files
234
+ permanent: Whether to permanently delete the files
235
+ force: Whether to force delete even if files are in use
236
+
237
+ Returns:
238
+ tuple[dict[str, bool], int, int]: Results per file, total deleted count, total failed count
239
+ """