|
8 | 8 |
|
9 | 9 | class LocalStorage(BaseStorage):
|
10 | 10 | """Local file system storage implementation."""
|
11 |
| - |
| 11 | + |
12 | 12 | def __init__(self, base_dir: str = None):
|
13 | 13 | """
|
14 | 14 | Initialize local storage.
|
15 |
| - |
| 15 | +
|
16 | 16 | Args:
|
17 | 17 | base_dir: Base directory for all operations. If None, uses current directory.
|
18 | 18 | """
|
19 | 19 | self.base_dir = base_dir or os.path.dirname(
|
20 | 20 | os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
21 | 21 | )
|
22 |
| - |
| 22 | + |
23 | 23 | def _get_full_path(self, path: str) -> str:
|
24 | 24 | """Get absolute path by combining base_dir and path."""
|
25 | 25 | if os.path.isabs(path):
|
26 | 26 | return path
|
27 | 27 | return os.path.join(self.base_dir, path)
|
28 |
| - |
29 |
| - def save_file(self, file_data: BinaryIO, path: str) -> str: |
| 28 | + |
| 29 | + def save_file(self, file_data: BinaryIO, path: str) -> dict: |
30 | 30 | """Save a file to local storage."""
|
31 | 31 | full_path = self._get_full_path(path)
|
32 |
| - |
33 |
| - # Ensure directory exists |
| 32 | + |
34 | 33 | os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
35 |
| - |
36 |
| - # Write file |
| 34 | + |
37 | 35 | if hasattr(file_data, 'save'):
|
38 |
| - # Handle Flask's FileStorage objects |
39 | 36 | file_data.save(full_path)
|
40 | 37 | else:
|
41 |
| - # Handle regular file-like objects |
42 | 38 | with open(full_path, 'wb') as f:
|
43 | 39 | shutil.copyfileobj(file_data, f)
|
44 |
| - |
45 |
| - return path |
46 |
| - |
| 40 | + |
| 41 | + return { |
| 42 | + 'storage_type': 'local' |
| 43 | + } |
| 44 | + |
47 | 45 | def get_file(self, path: str) -> BinaryIO:
|
48 | 46 | """Get a file from local storage."""
|
49 | 47 | full_path = self._get_full_path(path)
|
50 |
| - |
| 48 | + |
51 | 49 | if not os.path.exists(full_path):
|
52 | 50 | raise FileNotFoundError(f"File not found: {full_path}")
|
53 |
| - |
| 51 | + |
54 | 52 | return open(full_path, 'rb')
|
55 |
| - |
| 53 | + |
56 | 54 | def delete_file(self, path: str) -> bool:
|
57 | 55 | """Delete a file from local storage."""
|
58 | 56 | full_path = self._get_full_path(path)
|
59 |
| - |
| 57 | + |
60 | 58 | if not os.path.exists(full_path):
|
61 | 59 | return False
|
62 |
| - |
| 60 | + |
63 | 61 | os.remove(full_path)
|
64 | 62 | return True
|
65 |
| - |
| 63 | + |
66 | 64 | def file_exists(self, path: str) -> bool:
|
67 | 65 | """Check if a file exists in local storage."""
|
68 | 66 | full_path = self._get_full_path(path)
|
69 | 67 | return os.path.exists(full_path)
|
70 |
| - |
| 68 | + |
71 | 69 | def list_files(self, directory: str) -> List[str]:
|
72 | 70 | """List all files in a directory in local storage."""
|
73 | 71 | full_path = self._get_full_path(directory)
|
74 |
| - |
| 72 | + |
75 | 73 | if not os.path.exists(full_path):
|
76 | 74 | return []
|
77 |
| - |
| 75 | + |
78 | 76 | result = []
|
79 | 77 | for root, _, files in os.walk(full_path):
|
80 | 78 | for file in files:
|
81 | 79 | rel_path = os.path.relpath(os.path.join(root, file), self.base_dir)
|
82 | 80 | result.append(rel_path)
|
83 |
| - |
| 81 | + |
84 | 82 | return result
|
85 | 83 |
|
86 | 84 | def process_file(self, path: str, processor_func: Callable, **kwargs):
|
87 | 85 | """
|
88 | 86 | Process a file using the provided processor function.
|
89 |
| - |
| 87 | +
|
90 | 88 | For local storage, we can directly pass the full path to the processor.
|
91 |
| - |
| 89 | +
|
92 | 90 | Args:
|
93 | 91 | path: Path to the file
|
94 | 92 | processor_func: Function that processes the file
|
95 | 93 | **kwargs: Additional arguments to pass to the processor function
|
96 |
| - |
| 94 | +
|
97 | 95 | Returns:
|
98 | 96 | The result of the processor function
|
99 | 97 | """
|
100 | 98 | full_path = self._get_full_path(path)
|
101 |
| - |
| 99 | + |
102 | 100 | if not os.path.exists(full_path):
|
103 | 101 | raise FileNotFoundError(f"File not found: {full_path}")
|
104 |
| - |
| 102 | + |
105 | 103 | return processor_func(file_path=full_path, **kwargs)
|
0 commit comments