-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathphoto_repository.py
151 lines (137 loc) · 5.17 KB
/
photo_repository.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
from collections import defaultdict
import json
import os
from typing import Dict, List
class Photo:
def __init__(
self,
name: str,
iso: int,
speed: str,
exposure_time: str,
white_balance: str,
capture_date: str,
dng_path: str,
jpg_path: str,
):
self.name = name
self.iso = iso
self.speed = speed
self.exposure_time = exposure_time
self.white_balance = white_balance
self.capture_date = capture_date
self.dng_path = dng_path
self.jpg_path = jpg_path
def to_dict(self):
"""
Gets the Photo as a Dict to be serialized.
Returns:
The photo as a Dict.
"""
return {
"name": self.name,
"iso": self.iso,
"speed": self.speed,
"exposure_time": self.exposure_time,
"white_balance": self.white_balance,
"capture_date": self.capture_date,
"dng_path": self.dng_path,
"jpg_path": self.jpg_path,
}
@staticmethod
def from_dict(data):
"""
Returns a Photo from a Dict.
Returns:
A Photo filled by the Dict's content.
"""
return Photo(
name=data["name"],
iso=data["iso"],
speed=data["speed"],
exposure_time=data["exposure_time"],
white_balance=data["white_balance"],
capture_date=data["capture_date"],
dng_path=data["dng_path"],
jpg_path=data["jpg_path"],
)
class PhotoRepository:
def __init__(self, repository: str) -> None:
self.repository: str = repository
self.photos: Dict[str, Photo] = {} # Maps photo names to Photo objects
def add_photo(self, photo: Photo) -> None:
"""Adds a photo to the directory. Overwrites any existing photo with the same name."""
self.photos[photo.name] = photo
self.save_to_json()
def get_photo(self, name: str) -> Photo:
"""Retrieves a photo by its name."""
return self.photos.get(name)
def remove_photo(self, name: str) -> bool:
"""Removes a photo by its name. Returns True if photo was removed, False if not found."""
if name in self.photos:
del self.photos[name]
self.save_to_json()
return True
return False
def save_to_json(self) -> None:
"""Saves all photos to a JSON file within the directory."""
data = {name: photo.to_dict() for name, photo in self.photos.items()}
with open(os.path.join(self.repository, "photos.json"), "w") as f:
json.dump(data, f, indent=4)
def load_from_json(self) -> None:
"""Loads all photos from a JSON file within the directory."""
json_path = os.path.join(self.repository, "photos.json")
if os.path.exists(json_path):
need_to_clean_json_file = self.load_from_json_and_check(
json_path)
if need_to_clean_json_file:
self.save_to_json()
def organize_photos_by_date(self) -> Dict[str, List[Dict]]:
"""
Organizes photos by their capture dates.
Returns:
Photos organized by date
"""
photos_by_date = defaultdict(list)
for photo in self.photos.values():
photos_by_date[photo.capture_date].append(photo.to_dict())
# Sort photos within each date and dates themselves (most recent first)
sorted_photos_by_date = {date: sorted(photos, key=lambda x: x['name'])
for date, photos in sorted(photos_by_date.items(), reverse=True)}
return sorted_photos_by_date
def load_from_json_and_check(self, directory_path: str) -> bool:
"""
Loads all photos from a JSON file within the directory.
Arguments:
directory_path - the path of the directory
Returns:
True if the repository file needs to be refreshed (e.g. photos deleted)
"""
with open(directory_path, "r") as f:
need_to_clean_json_file = False
data = json.load(f)
for name, photo_dict in data.items():
photo = Photo.from_dict(photo_dict)
jpgExists = False
if photo.jpg_path != None:
if os.path.exists(os.path.join(self.repository, photo.jpg_path)):
jpgExists = True
else:
jpgExists = False
photo.jpg_path = None
need_to_clean_json_file = True
else:
jpgExists = False
dngExists = False
if photo.dng_path != None:
if os.path.exists(os.path.join(self.repository, photo.dng_path)):
dngExists = True
else:
dngExists = False
photo.dng_path = None
need_to_clean_json_file = True
else:
dngExists = False
if jpgExists or dngExists:
self.photos[name] = photo
return need_to_clean_json_file