checkpoint
This commit is contained in:
parent
0b85c309f8
commit
de60770d20
3 changed files with 182 additions and 107 deletions
|
@ -72,6 +72,32 @@ def _helper_comma_split(s):
|
|||
s = [x for x in s if x]
|
||||
return s
|
||||
|
||||
def create_tag(easybake_string):
|
||||
notes = P.easybake(easybake_string)
|
||||
notes = [{'action': action, 'tagname': tagname} for (action, tagname) in notes]
|
||||
return notes
|
||||
|
||||
def delete_tag(tag):
|
||||
tag = tag.split('.')[-1].split('+')[0]
|
||||
tag = P.get_tag(tag)
|
||||
|
||||
tag.delete()
|
||||
return {'action': 'delete_tag', 'tagname': tag.name}
|
||||
|
||||
def delete_synonym(synonym):
|
||||
synonym = synonym.split('+')[-1].split('.')[-1]
|
||||
synonym = phototagger.normalize_tagname(synonym)
|
||||
try:
|
||||
master_tag = P.get_tag(synonym)
|
||||
except phototagger.NoSuchTag:
|
||||
flask.abort(404, 'That synonym doesnt exist')
|
||||
|
||||
if synonym not in master_tag.synonyms():
|
||||
flask.abort(400, 'That name is not a synonym')
|
||||
|
||||
master_tag.remove_synonym(synonym)
|
||||
return {'action':'delete_synonym', 'synonym': synonym}
|
||||
|
||||
def edit_params(original, modifications):
|
||||
new_params = original.to_dict()
|
||||
new_params.update(modifications)
|
||||
|
@ -111,16 +137,6 @@ def P_tag(tagname):
|
|||
except phototagger.NoSuchTag as e:
|
||||
flask.abort(404, 'That tag doesnt exist: %s' % e)
|
||||
|
||||
def truthystring(s):
|
||||
if isinstance(s, (bool, int)) or s is None:
|
||||
return s
|
||||
s = s.lower()
|
||||
if s in {'1', 'true', 't', 'yes', 'y', 'on'}:
|
||||
return True
|
||||
if s in {'null', 'none'}:
|
||||
return None
|
||||
return False
|
||||
|
||||
def read_filebytes(filepath, range_min, range_max):
|
||||
range_span = range_max - range_min
|
||||
|
||||
|
@ -130,7 +146,7 @@ def read_filebytes(filepath, range_min, range_max):
|
|||
sent_amount = 0
|
||||
with f:
|
||||
while sent_amount < range_span:
|
||||
print(sent_amount)
|
||||
#print(sent_amount)
|
||||
chunk = f.read(FILE_READ_CHUNK)
|
||||
if len(chunk) == 0:
|
||||
break
|
||||
|
@ -138,6 +154,17 @@ def read_filebytes(filepath, range_min, range_max):
|
|||
yield chunk
|
||||
sent_amount += len(chunk)
|
||||
|
||||
def seconds_to_hms(seconds):
|
||||
seconds = math.ceil(seconds)
|
||||
(minutes, seconds) = divmod(seconds, 60)
|
||||
(hours, minutes) = divmod(minutes, 60)
|
||||
parts = []
|
||||
if hours: parts.append(hours)
|
||||
if minutes: parts.append(minutes)
|
||||
parts.append(seconds)
|
||||
hms = ':'.join('%02d' % part for part in parts)
|
||||
return hms
|
||||
|
||||
def send_file(filepath):
|
||||
'''
|
||||
Range-enabled file sending.
|
||||
|
@ -202,31 +229,15 @@ def send_file(filepath):
|
|||
)
|
||||
return response
|
||||
|
||||
def create_tag(easybake_string):
|
||||
notes = P.easybake(easybake_string)
|
||||
notes = [{'action': action, 'tagname': tagname} for (action, tagname) in notes]
|
||||
return notes
|
||||
|
||||
def delete_tag(tag):
|
||||
tag = tag.split('.')[-1].split('+')[0]
|
||||
tag = P.get_tag(tag)
|
||||
|
||||
tag.delete()
|
||||
return {'action': 'delete_tag', 'tagname': tag.name, 'tagid': tag.id}
|
||||
|
||||
def delete_synonym(synonym):
|
||||
synonym = synonym.split('+')[-1].split('.')[-1]
|
||||
synonym = phototagger.normalize_tagname(synonym)
|
||||
try:
|
||||
master_tag = P.get_tag(synonym)
|
||||
except phototagger.NoSuchTag:
|
||||
flask.abort(404, 'That synonym doesnt exist')
|
||||
|
||||
if synonym not in master_tag.synonyms():
|
||||
flask.abort(400, 'That name is not a synonym')
|
||||
|
||||
master_tag.remove_synonym(synonym)
|
||||
return {'action':'delete_synonym', 'synonym': synonym}
|
||||
def truthystring(s):
|
||||
if isinstance(s, (bool, int)) or s is None:
|
||||
return s
|
||||
s = s.lower()
|
||||
if s in {'1', 'true', 't', 'yes', 'y', 'on'}:
|
||||
return True
|
||||
if s in {'null', 'none'}:
|
||||
return None
|
||||
return False
|
||||
|
||||
####################################################################################################
|
||||
####################################################################################################
|
||||
|
@ -246,17 +257,6 @@ def jsonify_album(album, minimal=False):
|
|||
|
||||
return j
|
||||
|
||||
def seconds_to_hms(seconds):
|
||||
seconds = math.ceil(seconds)
|
||||
(minutes, seconds) = divmod(seconds, 60)
|
||||
(hours, minutes) = divmod(minutes, 60)
|
||||
parts = []
|
||||
if hours: parts.append(hours)
|
||||
if minutes: parts.append(minutes)
|
||||
parts.append(seconds)
|
||||
hms = ':'.join('%02d' % part for part in parts)
|
||||
return hms
|
||||
|
||||
def jsonify_photo(photo):
|
||||
tags = photo.tags()
|
||||
tags.sort(key=lambda x: x.name)
|
||||
|
@ -268,7 +268,7 @@ def jsonify_photo(photo):
|
|||
'ratio': photo.ratio,
|
||||
'area': photo.area,
|
||||
'bytes': photo.bytes,
|
||||
'duration': seconds_to_hms(photo.duration) if photo.duration else None,
|
||||
'duration': seconds_to_hms(photo.duration) if photo.duration is not None else None,
|
||||
'duration_int': photo.duration,
|
||||
'bytestring': photo.bytestring(),
|
||||
'has_thumbnail': bool(photo.thumbnail),
|
||||
|
@ -474,7 +474,7 @@ def get_search_core():
|
|||
photos = list(P.search(**search_kwargs))
|
||||
photos = [jsonify_photo(photo) for photo in photos]
|
||||
warns = [str(warning.message) for warning in catcher]
|
||||
print(warns)
|
||||
#print(warns)
|
||||
|
||||
# TAGS ON THIS PAGE
|
||||
total_tags = set()
|
||||
|
@ -572,10 +572,20 @@ def get_thumbnail(photoid):
|
|||
flask.abort(404, 'That file doesnt have a thumbnail')
|
||||
return send_file(path)
|
||||
|
||||
@site.route('/album/<albumid>', methods=['POST'])
|
||||
@give_session_token
|
||||
def post_edit_album(albumid):
|
||||
'''
|
||||
Edit the album's title and description.
|
||||
Apply a tag to every photo in the album.
|
||||
'''
|
||||
|
||||
@site.route('/photo/<photoid>', methods=['POST'])
|
||||
@give_session_token
|
||||
def post_edit_photo(photoid):
|
||||
print(request.form)
|
||||
'''
|
||||
Add and remove tags from photos.
|
||||
'''
|
||||
response = {}
|
||||
photo = P_photo(photoid)
|
||||
|
||||
|
@ -595,17 +605,21 @@ def post_edit_photo(photoid):
|
|||
try:
|
||||
tag = P.get_tag(tag)
|
||||
except phototagger.NoSuchTag:
|
||||
return flask.Response('{"error": "That tag doesnt exist", "tagname":"%s"}'%tag, status=404)
|
||||
response = {'error': 'That tag doesnt exist', 'tagname': tag}
|
||||
return make_json_response(response, status=404)
|
||||
|
||||
method(tag)
|
||||
response['action'] = action
|
||||
response['tagid'] = tag.id
|
||||
#response['tagid'] = tag.id
|
||||
response['tagname'] = tag.name
|
||||
return json.dumps(response)
|
||||
return make_json_response(response)
|
||||
|
||||
@site.route('/tags', methods=['POST'])
|
||||
@give_session_token
|
||||
def post_edit_tags():
|
||||
'''
|
||||
Create and delete tags and synonyms.
|
||||
'''
|
||||
print(request.form)
|
||||
status = 200
|
||||
if 'create_tag' in request.form:
|
||||
|
@ -618,13 +632,18 @@ def post_edit_tags():
|
|||
action = 'delete_tag'
|
||||
method = delete_tag
|
||||
else:
|
||||
status = 400
|
||||
response = {'error': ERROR_INVALID_ACTION}
|
||||
|
||||
if status == 200:
|
||||
status = 400
|
||||
tag = request.form[action].strip()
|
||||
if tag == '':
|
||||
response = {'error': ERROR_NO_TAG_GIVEN}
|
||||
status = 400
|
||||
|
||||
if status == 200:
|
||||
# expect the worst
|
||||
status = 400
|
||||
try:
|
||||
response = method(tag)
|
||||
except phototagger.TagTooShort:
|
||||
|
|
|
@ -14,8 +14,8 @@ def easytagger():
|
|||
P.export_tags(specific_tag=i)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
continue
|
||||
P.easybake(i)
|
||||
else:
|
||||
P.easybake(i)
|
||||
|
||||
def photag(photoid):
|
||||
photo = P.get_photo_by_id(photoid)
|
||||
|
|
|
@ -18,12 +18,12 @@ import warnings
|
|||
sys.path.append('C:\\git\\else\\Bytestring'); import bytestring
|
||||
sys.path.append('C:\\git\\else\\SpinalTap'); import spinal
|
||||
|
||||
ID_LENGTH = 12
|
||||
VALID_TAG_CHARS = string.ascii_lowercase + string.digits + '_'
|
||||
MIN_TAG_NAME_LENGTH = 1
|
||||
MAX_TAG_NAME_LENGTH = 32
|
||||
DEFAULT_ID_LENGTH = 12
|
||||
DEFAULT_DBNAME = 'phototagger.db'
|
||||
DEFAULT_THUMBDIR = '_site_thumbnails'
|
||||
DEFAULT_THUMBDIR = '_etiquette\\site_thumbnails'
|
||||
THUMBNAIL_WIDTH = 400
|
||||
THUMBNAIL_HEIGHT = 400
|
||||
|
||||
|
@ -33,6 +33,7 @@ try:
|
|||
ffprobe_path='C:\\software\\ffmpeg\\bin\\ffprobe.exe',
|
||||
)
|
||||
except converter.ffmpeg.FFMpegError:
|
||||
traceback.print_exc()
|
||||
ffmpeg = None
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
@ -161,6 +162,7 @@ CREATE INDEX IF NOT EXISTS index_albumrel_photoid on album_photo_rel(photoid);
|
|||
CREATE INDEX IF NOT EXISTS index_photo_id on photos(id);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_path on photos(filepath);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_created on photos(created);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_extension on photos(extension);
|
||||
|
||||
-- Tag
|
||||
CREATE INDEX IF NOT EXISTS index_tag_id on tags(id);
|
||||
|
@ -378,19 +380,18 @@ def hyphen_range(s):
|
|||
raise OutOfOrder(s, low, high)
|
||||
return low, high
|
||||
|
||||
def fit_into_bounds(iw, ih, fw, fh):
|
||||
def fit_into_bounds(image_width, image_height, frame_width, frame_height):
|
||||
'''
|
||||
Given the w+h of the image and the w+h of the frame,
|
||||
return new w+h that fits the image into the frame
|
||||
while maintaining the aspect ratio and leaving blank space
|
||||
everywhere else
|
||||
while maintaining the aspect ratio.
|
||||
'''
|
||||
ratio = min(fw/iw, fh/ih)
|
||||
ratio = min(frame_width/image_width, frame_height/image_height)
|
||||
|
||||
w = int(iw * ratio)
|
||||
h = int(ih * ratio)
|
||||
new_width = int(image_width * ratio)
|
||||
new_height = int(image_height * ratio)
|
||||
|
||||
return (w, h)
|
||||
return (new_width, new_height)
|
||||
|
||||
def get_mimetype(filepath):
|
||||
extension = os.path.splitext(filepath)[1].replace('.', '')
|
||||
|
@ -420,6 +421,8 @@ def normalize_filepath(filepath):
|
|||
'''
|
||||
Remove some bad characters.
|
||||
'''
|
||||
filepath = filepath.replace('/', os.sep)
|
||||
filepath = filepath.replace('\\', os.sep)
|
||||
filepath = filepath.replace('<', '')
|
||||
filepath = filepath.replace('>', '')
|
||||
return filepath
|
||||
|
@ -713,7 +716,7 @@ class PDBAlbumMixin:
|
|||
album.add_photo(photo, commit=False)
|
||||
|
||||
if commit:
|
||||
self.sql.commit()
|
||||
self.commit()
|
||||
return album
|
||||
|
||||
|
||||
|
@ -1096,7 +1099,7 @@ class PDBTagMixin:
|
|||
self.cur.execute('INSERT INTO tags VALUES(?, ?)', [tagid, tagname])
|
||||
if commit:
|
||||
log.debug('Commiting - new_tag')
|
||||
self.sql.commit()
|
||||
self.commit()
|
||||
tag = Tag(self, [tagid, tagname])
|
||||
return tag
|
||||
|
||||
|
@ -1139,8 +1142,9 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin):
|
|||
'''
|
||||
def __init__(self, databasename=DEFAULT_DBNAME, thumbnail_folder=DEFAULT_THUMBDIR, id_length=None):
|
||||
if id_length is None:
|
||||
self.id_length = ID_LENGTH
|
||||
self.id_length = DEFAULT_ID_LENGTH
|
||||
self.databasename = databasename
|
||||
self.database_abspath = os.path.abspath(databasename)
|
||||
self.thumbnail_folder = os.path.abspath(thumbnail_folder)
|
||||
os.makedirs(thumbnail_folder, exist_ok=True)
|
||||
self.sql = sqlite3.connect(databasename)
|
||||
|
@ -1149,6 +1153,7 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin):
|
|||
for statement in statements:
|
||||
self.cur.execute(statement)
|
||||
|
||||
self.on_commit_queue = []
|
||||
self._cached_frozen_children = None
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -1157,6 +1162,15 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin):
|
|||
def _uncache(self):
|
||||
self._cached_frozen_children = None
|
||||
|
||||
def commit(self):
|
||||
while self.on_commit_queue:
|
||||
task = self.on_commit_queue.pop()
|
||||
print(task)
|
||||
args = task.get('args', [])
|
||||
kwargs = task.get('kwargs', {})
|
||||
task['action'](*args, **kwargs)
|
||||
self.sql.commit()
|
||||
|
||||
def digest_directory(self, directory, exclude_directories=None, exclude_filenames=None, commit=True):
|
||||
'''
|
||||
Create an album, and add the directory's contents to it.
|
||||
|
@ -1201,7 +1215,7 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin):
|
|||
|
||||
if commit:
|
||||
log.debug('Commiting - digest')
|
||||
self.sql.commit()
|
||||
self.commit()
|
||||
return album
|
||||
|
||||
def digest_new_files(
|
||||
|
@ -1209,7 +1223,7 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin):
|
|||
directory,
|
||||
exclude_directories=None,
|
||||
exclude_filenames=None,
|
||||
recurse=True,
|
||||
recurse=False,
|
||||
commit=True
|
||||
):
|
||||
'''
|
||||
|
@ -1248,7 +1262,7 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin):
|
|||
photo = self.new_photo(filepath, commit=False)
|
||||
if commit:
|
||||
log.debug('Committing - digest_new_files')
|
||||
self.sql.commit()
|
||||
self.commit()
|
||||
|
||||
|
||||
def easybake(self, string):
|
||||
|
@ -1309,7 +1323,7 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin):
|
|||
tags = [create_or_get(t) for t in tag_parts]
|
||||
for (higher, lower) in zip(tags, tags[1:]):
|
||||
try:
|
||||
lower.join(higher)
|
||||
lower.join_group(higher)
|
||||
note = ('join_group', '%s.%s' % (higher.name, lower.name))
|
||||
output_notes.append(note)
|
||||
except GroupExists:
|
||||
|
@ -1447,7 +1461,7 @@ class GroupableMixin:
|
|||
self.photodb.cur.execute('INSERT INTO tag_group_rel VALUES(?, ?)', [self.id, member.id])
|
||||
if commit:
|
||||
log.debug('Commiting - add to group')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def children(self):
|
||||
self.photodb.cur.execute('SELECT * FROM tag_group_rel WHERE parentid == ?', [self.id])
|
||||
|
@ -1491,7 +1505,7 @@ class GroupableMixin:
|
|||
self.photodb.cur.execute('DELETE FROM tag_group_rel WHERE memberid == ?', [self.id])
|
||||
if commit:
|
||||
log.debug('Committing - delete tag')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def parent(self):
|
||||
'''
|
||||
|
@ -1505,7 +1519,7 @@ class GroupableMixin:
|
|||
parentid = fetch[SQL_TAGGROUP['parentid']]
|
||||
return self.group_getter(id=parentid)
|
||||
|
||||
def join(self, group, commit=True):
|
||||
def join_group(self, group, commit=True):
|
||||
'''
|
||||
Leave the current group, then call `group.add(self)`.
|
||||
'''
|
||||
|
@ -1528,7 +1542,7 @@ class GroupableMixin:
|
|||
self.photodb.cur.execute('DELETE FROM tag_group_rel WHERE memberid == ?', [self.id])
|
||||
if commit:
|
||||
log.debug('Committing - leave group')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def walk_children(self):
|
||||
yield self
|
||||
|
@ -1559,7 +1573,7 @@ class Album(ObjectBase, GroupableMixin):
|
|||
self.photodb.cur.execute('INSERT INTO album_photo_rel VALUES(?, ?)', [self.id, photo.id])
|
||||
if commit:
|
||||
log.debug('Committing - add photo to album')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def add_tag_to_all(self, tag, nested_children=True):
|
||||
tag = self.photodb.get_tag(tag)
|
||||
|
@ -1577,7 +1591,7 @@ class Album(ObjectBase, GroupableMixin):
|
|||
self.photodb.cur.execute('DELETE FROM album_photo_rel WHERE albumid == ?', [self.id])
|
||||
if commit:
|
||||
log.debug('Committing - delete album')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def edit(self, title=None, description=None, commit=True):
|
||||
if title is None:
|
||||
|
@ -1592,7 +1606,7 @@ class Album(ObjectBase, GroupableMixin):
|
|||
self.description = description
|
||||
if commit:
|
||||
log.debug('Committing - edit album')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def has_photo(self, photo):
|
||||
if not isinstance(photo, Photo):
|
||||
|
@ -1620,10 +1634,12 @@ class Album(ObjectBase, GroupableMixin):
|
|||
return
|
||||
self.photodb.cur.execute(
|
||||
'DELETE FROM album_photo_rel WHERE albumid == ? AND photoid == ?',
|
||||
[self.id, photo.id])
|
||||
[self.id, photo.id]
|
||||
)
|
||||
if commit:
|
||||
self.photodb.commit()
|
||||
|
||||
def walk_photos(self):
|
||||
print('hi')
|
||||
yield from self.photos()
|
||||
children = self.walk_children()
|
||||
# The first yield is itself
|
||||
|
@ -1642,9 +1658,9 @@ class Photo(ObjectBase):
|
|||
self.photodb = photodb
|
||||
self.id = row_tuple[SQL_PHOTO['id']]
|
||||
self.real_filepath = row_tuple[SQL_PHOTO['filepath']]
|
||||
self.real_filepath = self.real_filepath.replace('/', os.sep)
|
||||
self.real_filepath = self.real_filepath.replace('\\', os.sep)
|
||||
self.filepath = normalize_filepath(self.real_filepath)
|
||||
self.real_filepath = normalize_filepath(self.real_filepath)
|
||||
self.filepath = self.real_filepath
|
||||
self.basename = os.path.basename(self.real_filepath)
|
||||
self.extension = row_tuple[SQL_PHOTO['extension']]
|
||||
self.width = row_tuple[SQL_PHOTO['width']]
|
||||
self.height = row_tuple[SQL_PHOTO['height']]
|
||||
|
@ -1654,7 +1670,6 @@ class Photo(ObjectBase):
|
|||
self.duration = row_tuple[SQL_PHOTO['duration']]
|
||||
self.created = row_tuple[SQL_PHOTO['created']]
|
||||
self.thumbnail = row_tuple[SQL_PHOTO['thumbnail']]
|
||||
self.basename = self.real_filepath.split(os.sep)[-1]
|
||||
|
||||
def __repr__(self):
|
||||
return 'Photo:{id}'.format(id=self.id)
|
||||
|
@ -1683,7 +1698,7 @@ class Photo(ObjectBase):
|
|||
self.photodb.cur.execute('INSERT INTO photo_tag_rel VALUES(?, ?)', [self.id, tag.id])
|
||||
if commit:
|
||||
log.debug('Committing - add photo tag')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def albums(self):
|
||||
'''
|
||||
|
@ -1711,7 +1726,7 @@ class Photo(ObjectBase):
|
|||
self.photodb.cur.execute('DELETE FROM album_photo_rel WHERE photoid == ?', [self.id])
|
||||
if commit:
|
||||
log.debug('Committing - delete photo')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
@time_me
|
||||
def generate_thumbnail(self, commit=True, **special):
|
||||
|
@ -1739,7 +1754,12 @@ class Photo(ObjectBase):
|
|||
pass
|
||||
else:
|
||||
(width, height) = image.size
|
||||
(new_width, new_height) = fit_into_bounds(width, height, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)
|
||||
(new_width, new_height) = fit_into_bounds(
|
||||
image_width=width,
|
||||
image_height=height,
|
||||
frame_width=THUMBNAIL_WIDTH,
|
||||
frame_height=THUMBNAIL_HEIGHT,
|
||||
)
|
||||
if new_width < width:
|
||||
image = image.resize((new_width, new_height))
|
||||
image.save(hopeful_filepath, quality=50)
|
||||
|
@ -1751,10 +1771,10 @@ class Photo(ObjectBase):
|
|||
try:
|
||||
if probe.video:
|
||||
size = fit_into_bounds(
|
||||
iw=probe.video.video_width,
|
||||
ih=probe.video.video_height,
|
||||
fw=THUMBNAIL_WIDTH,
|
||||
fh=THUMBNAIL_HEIGHT,
|
||||
image_width=probe.video.video_width,
|
||||
image_height=probe.video.video_height,
|
||||
frame_width=THUMBNAIL_WIDTH,
|
||||
frame_height=THUMBNAIL_HEIGHT,
|
||||
)
|
||||
size = '%dx%d' % size
|
||||
duration = probe.video.duration
|
||||
|
@ -1778,7 +1798,7 @@ class Photo(ObjectBase):
|
|||
|
||||
if commit:
|
||||
log.debug('Committing - generate thumbnail')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
return self.thumbnail
|
||||
|
||||
|
@ -1811,6 +1831,9 @@ class Photo(ObjectBase):
|
|||
|
||||
@time_me
|
||||
def reload_metadata(self, commit=True):
|
||||
'''
|
||||
Load the file's height, width, etc as appropriate for this type of file.
|
||||
'''
|
||||
self.bytes = os.path.getsize(self.real_filepath)
|
||||
self.width = None
|
||||
self.height = None
|
||||
|
@ -1833,7 +1856,7 @@ class Photo(ObjectBase):
|
|||
try:
|
||||
probe = ffmpeg.probe(self.real_filepath)
|
||||
if probe and probe.video:
|
||||
self.duration = probe.video.duration
|
||||
self.duration = probe.format.duration or probe.video.duration
|
||||
self.width = probe.video.video_width
|
||||
self.height = probe.video.video_height
|
||||
except:
|
||||
|
@ -1851,12 +1874,13 @@ class Photo(ObjectBase):
|
|||
self.area = self.width * self.height
|
||||
self.ratio = round(self.width / self.height, 2)
|
||||
|
||||
self.photodb.cur.execute('UPDATE photos SET width=?, height=?, area=?, ratio=?, duration=?, bytes=? WHERE id==?',
|
||||
self.photodb.cur.execute(
|
||||
'UPDATE photos SET width=?, height=?, area=?, ratio=?, duration=?, bytes=? WHERE id==?',
|
||||
[self.width, self.height, self.area, self.ratio, self.duration, self.bytes, self.id],
|
||||
)
|
||||
if commit:
|
||||
log.debug('Committing - reload metadata')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def remove_tag(self, tag, commit=True):
|
||||
tag = self.photodb.get_tag(tag)
|
||||
|
@ -1870,7 +1894,39 @@ class Photo(ObjectBase):
|
|||
)
|
||||
if commit:
|
||||
log.debug('Committing - remove photo tag')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def rename_file(self, new_filename, move=False, commit=True):
|
||||
'''
|
||||
Rename the file on the disk as well as in the database.
|
||||
If `move` is True, allow this operation to move the file.
|
||||
Otherwise, slashes will be considered an error.
|
||||
'''
|
||||
current_dir = os.path.normcase(os.path.dirname(self.real_filepath))
|
||||
new_filename = normalize_filepath(new_filename)
|
||||
new_dir = os.path.normcase(os.path.dirname(new_filename))
|
||||
if new_dir == '':
|
||||
new_dir = current_dir
|
||||
new_abspath = os.path.join(new_dir, new_filename)
|
||||
else:
|
||||
new_abspath = os.path.abspath(new_filename)
|
||||
new_dir = os.path.normcase(os.path.dirname(new_abspath))
|
||||
if (new_dir != current_dir) and not move:
|
||||
raise ValueError('Cannot move the file without param move=True')
|
||||
new_basename = os.path.basename(new_abspath)
|
||||
os.link(self.real_filepath, new_abspath)
|
||||
self.photodb.cur.execute(
|
||||
'UPDATE photos SET filepath = ? WHERE filepath == ?',
|
||||
[new_abspath, self.real_filepath]
|
||||
)
|
||||
if commit:
|
||||
os.remove(self.real_filepath)
|
||||
self.photodb.commit()
|
||||
else:
|
||||
queue_action = {'action': os.remove, 'args': [self.real_filepath]}
|
||||
self.photodb.on_commit_queue.append(queue_action)
|
||||
self.real_filepath = new_abspath
|
||||
self.basename = os.path.basename(new_abspath)
|
||||
|
||||
def tags(self):
|
||||
'''
|
||||
|
@ -1912,12 +1968,12 @@ class Tag(ObjectBase, GroupableMixin):
|
|||
return hash(self.name)
|
||||
|
||||
def __repr__(self):
|
||||
r = 'Tag:{id}:{name}'.format(name=self.name, id=self.id)
|
||||
return r
|
||||
rep = 'Tag:{id}:{name}'.format(name=self.name, id=self.id)
|
||||
return rep
|
||||
|
||||
def __str__(self):
|
||||
r = 'Tag:{name}'.format(name=self.name)
|
||||
return r
|
||||
rep = 'Tag:{name}'.format(name=self.name)
|
||||
return rep
|
||||
|
||||
def add_synonym(self, synname, commit=True):
|
||||
synname = normalize_tagname(synname)
|
||||
|
@ -1937,7 +1993,7 @@ class Tag(ObjectBase, GroupableMixin):
|
|||
|
||||
if commit:
|
||||
log.debug('Committing - add synonym')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def convert_to_synonym(self, mastertag, commit=True):
|
||||
'''
|
||||
|
@ -1974,7 +2030,7 @@ class Tag(ObjectBase, GroupableMixin):
|
|||
mastertag.add_synonym(self.name, commit=False)
|
||||
if commit:
|
||||
log.debug('Committing - convert to synonym')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def delete(self, delete_children=False, commit=True):
|
||||
log.debug('Deleting tag {tag:r}'.format(tag=self))
|
||||
|
@ -1985,7 +2041,7 @@ class Tag(ObjectBase, GroupableMixin):
|
|||
self.photodb.cur.execute('DELETE FROM tag_synonyms WHERE mastername == ?', [self.name])
|
||||
if commit:
|
||||
log.debug('Committing - delete tag')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def qualified_name(self):
|
||||
'''
|
||||
|
@ -2015,7 +2071,7 @@ class Tag(ObjectBase, GroupableMixin):
|
|||
self.photodb.cur.execute('DELETE FROM tag_synonyms WHERE name == ?', [synname])
|
||||
if commit:
|
||||
log.debug('Committing - remove synonym')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def rename(self, new_name, apply_to_synonyms=True, commit=True):
|
||||
'''
|
||||
|
@ -2026,7 +2082,7 @@ class Tag(ObjectBase, GroupableMixin):
|
|||
return
|
||||
|
||||
try:
|
||||
existing = self.photodb.get_tag(new_name)
|
||||
self.photodb.get_tag(new_name)
|
||||
except NoSuchTag:
|
||||
pass
|
||||
else:
|
||||
|
@ -2044,7 +2100,7 @@ class Tag(ObjectBase, GroupableMixin):
|
|||
self.name = new_name
|
||||
if commit:
|
||||
log.debug('Committing - rename tag')
|
||||
self.photodb.sql.commit()
|
||||
self.photodb.commit()
|
||||
|
||||
def synonyms(self):
|
||||
self.photodb.cur.execute('SELECT name FROM tag_synonyms WHERE mastername == ?', [self.name])
|
||||
|
|
Loading…
Reference in a new issue