checkpoint
fix bug in which renaming photo causes os.remove even when it's an in-place rename on case-insensitive systems; incorporate expressionmatch for filename search; minor comment cleanup
This commit is contained in:
parent
c80e2003ff
commit
5404a1d411
4 changed files with 44 additions and 73 deletions
|
@ -606,7 +606,7 @@ class Photo(ObjectBase):
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
elif self.mimetype == 'audio':
|
elif self.mimetype == 'audio' and constants.ffmpeg:
|
||||||
try:
|
try:
|
||||||
probe = constants.ffmpeg.probe(self.real_filepath)
|
probe = constants.ffmpeg.probe(self.real_filepath)
|
||||||
if probe and probe.audio:
|
if probe and probe.audio:
|
||||||
|
@ -671,12 +671,11 @@ class Photo(ObjectBase):
|
||||||
|
|
||||||
os.makedirs(new_path.parent.absolute_path, exist_ok=True)
|
os.makedirs(new_path.parent.absolute_path, exist_ok=True)
|
||||||
|
|
||||||
if new_path != old_path:
|
if new_path.normcase != old_path.normcase:
|
||||||
# This is different than the absolute == absolute check above,
|
# It's possible on case-insensitive systems to have the paths point
|
||||||
# because this normalizes the paths. It's possible on
|
# to the same place while being differently cased, thus we couldn't
|
||||||
# case-insensitive systems to have the paths point to the same place
|
# make the intermediate link.
|
||||||
# while being differently cased, thus we couldn't make the
|
# Instead, we will do a simple rename in just a moment.
|
||||||
# intermediate link.
|
|
||||||
try:
|
try:
|
||||||
os.link(old_path.absolute_path, new_path.absolute_path)
|
os.link(old_path.absolute_path, new_path.absolute_path)
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -688,18 +687,21 @@ class Photo(ObjectBase):
|
||||||
[new_path.absolute_path, old_path.absolute_path]
|
[new_path.absolute_path, old_path.absolute_path]
|
||||||
)
|
)
|
||||||
|
|
||||||
if commit:
|
if new_path.normcase == old_path.normcase:
|
||||||
if new_path == old_path:
|
# If they are equivalent but differently cased, just rename.
|
||||||
# If they are equivalent but differently cased paths, just
|
action = os.rename
|
||||||
# rename.
|
args = [old_path.absolute_path, new_path.absolute_path]
|
||||||
os.rename(old_path.absolute_path, new_path.absolute_path)
|
|
||||||
else:
|
else:
|
||||||
# Delete the original hardlink or copy.
|
# Delete the original, leaving only the new copy / hardlink.
|
||||||
os.remove(old_path.absolute_path)
|
action = os.remove
|
||||||
|
args = [old_path.absolute_path]
|
||||||
|
|
||||||
|
if commit:
|
||||||
|
action(*args)
|
||||||
self.photodb.log.debug('Committing - rename file')
|
self.photodb.log.debug('Committing - rename file')
|
||||||
self.photodb.commit()
|
self.photodb.commit()
|
||||||
else:
|
else:
|
||||||
queue_action = {'action': os.remove, 'args': [old_path.absolute_path]}
|
queue_action = {'action': args, 'args': args}
|
||||||
self.photodb.on_commit_queue.append(queue_action)
|
self.photodb.on_commit_queue.append(queue_action)
|
||||||
|
|
||||||
self.__reinit__()
|
self.__reinit__()
|
||||||
|
|
|
@ -719,6 +719,19 @@ class PDBPhotoMixin:
|
||||||
expression_tree = expressionmatch.ExpressionTree.parse(tag_expression)
|
expression_tree = expressionmatch.ExpressionTree.parse(tag_expression)
|
||||||
expression_tree.map(self.normalize_tagname)
|
expression_tree.map(self.normalize_tagname)
|
||||||
expression_matcher = searchhelpers.tag_expression_matcher_builder(frozen_children, warning_bag)
|
expression_matcher = searchhelpers.tag_expression_matcher_builder(frozen_children, warning_bag)
|
||||||
|
for node in expression_tree.walk_leaves():
|
||||||
|
if node.token in frozen_children:
|
||||||
|
continue
|
||||||
|
if warning_bag is not None:
|
||||||
|
warning_bag.add(constants.WARNING_NO_SUCH_TAG.format(tag=node.token))
|
||||||
|
node.token = None
|
||||||
|
else:
|
||||||
|
raise_no_such_thing(exceptions.NoSuchTag, thing_name=node.token)
|
||||||
|
expression_tree.prune()
|
||||||
|
|
||||||
|
if filename:
|
||||||
|
filename_tree = expressionmatch.ExpressionTree.parse(filename)
|
||||||
|
filename_tree.map(lambda x: x.lower())
|
||||||
|
|
||||||
photos_received = 0
|
photos_received = 0
|
||||||
|
|
||||||
|
@ -749,7 +762,7 @@ class PDBPhotoMixin:
|
||||||
#print('Failed author')
|
#print('Failed author')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if filename and not _helper_filenamefilter(subject=photo.basename, terms=filename):
|
if filename and not filename_tree.evaluate(photo.basename.lower()):
|
||||||
#print('Failed filename')
|
#print('Failed filename')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -924,6 +937,7 @@ class PDBTagMixin:
|
||||||
else:
|
else:
|
||||||
return tagname
|
return tagname
|
||||||
|
|
||||||
|
|
||||||
class PDBUserMixin:
|
class PDBUserMixin:
|
||||||
def generate_user_id(self):
|
def generate_user_id(self):
|
||||||
'''
|
'''
|
||||||
|
@ -1228,48 +1242,6 @@ class PhotoDB(PDBAlbumMixin, PDBBookmarkMixin, PDBPhotoMixin, PDBTagMixin, PDBUs
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# def digest_new_files(
|
|
||||||
# self,
|
|
||||||
# directory,
|
|
||||||
# exclude_directories=None,
|
|
||||||
# exclude_filenames=None,
|
|
||||||
# recurse=False,
|
|
||||||
# commit=True
|
|
||||||
# ):
|
|
||||||
# '''
|
|
||||||
# Walk the directory and add new files as Photos.
|
|
||||||
# Does NOT create or modify any albums like `digest_directory` does.
|
|
||||||
# '''
|
|
||||||
# if not os.path.isdir(directory):
|
|
||||||
# raise ValueError('Not a directory: %s' % directory)
|
|
||||||
# if exclude_directories is None:
|
|
||||||
# exclude_directories = self.config['digest_exclude_dirs']
|
|
||||||
# if exclude_filenames is None:
|
|
||||||
# exclude_filenames = self.config['digest_exclude_files']
|
|
||||||
|
|
||||||
# directory = spinal.str_to_fp(directory)
|
|
||||||
# generator = spinal.walk_generator(
|
|
||||||
# directory,
|
|
||||||
# exclude_directories=exclude_directories,
|
|
||||||
# exclude_filenames=exclude_filenames,
|
|
||||||
# recurse=recurse,
|
|
||||||
# yield_style='flat',
|
|
||||||
# )
|
|
||||||
# for filepath in generator:
|
|
||||||
# filepath = filepath.absolute_path
|
|
||||||
# try:
|
|
||||||
# self.get_photo_by_path(filepath)
|
|
||||||
# except exceptions.NoSuchPhoto:
|
|
||||||
# # This is what we want.
|
|
||||||
# pass
|
|
||||||
# else:
|
|
||||||
# continue
|
|
||||||
# photo = self.new_photo(filepath, commit=False)
|
|
||||||
# if commit:
|
|
||||||
# self.log.debug('Committing - digest_new_files')
|
|
||||||
# self.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def easybake(self, ebstring):
|
def easybake(self, ebstring):
|
||||||
'''
|
'''
|
||||||
Easily create tags, groups, and synonyms with a string like
|
Easily create tags, groups, and synonyms with a string like
|
||||||
|
|
|
@ -153,7 +153,7 @@ def normalize_filename(filename_terms):
|
||||||
filename_terms = ' '.join(filename_terms)
|
filename_terms = ' '.join(filename_terms)
|
||||||
|
|
||||||
filename_terms = filename_terms.strip()
|
filename_terms = filename_terms.strip()
|
||||||
filename_terms = [term.lower() for term in shlex.split(filename_terms)]
|
filename_terms = shlex.split(filename_terms)
|
||||||
|
|
||||||
if not filename_terms:
|
if not filename_terms:
|
||||||
return None
|
return None
|
||||||
|
@ -331,14 +331,7 @@ def tag_expression_matcher_builder(frozen_children, warning_bag=None):
|
||||||
if not photo_tags:
|
if not photo_tags:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
|
||||||
options = frozen_children[tagname]
|
options = frozen_children[tagname]
|
||||||
except KeyError:
|
|
||||||
if warning_bag is not None:
|
|
||||||
warning_bag.add(constants.WARNING_NO_SUCH_TAG.format(tag=tagname))
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
raise exceptions.NoSuchTag(tagname)
|
|
||||||
|
|
||||||
return any(option in photo_tags for option in options)
|
return any(option in photo_tags for option in options)
|
||||||
|
|
||||||
return matcher
|
return matcher
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
/* Override common.css */
|
/* Override common.css */
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
/*height: 100%;
|
|
||||||
width: 100%;*/
|
|
||||||
}
|
}
|
||||||
#left
|
#left
|
||||||
{
|
{
|
||||||
|
@ -78,8 +76,6 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
/* height: 100%;
|
|
||||||
width: 100%;*/
|
|
||||||
}
|
}
|
||||||
.photo_viewer a
|
.photo_viewer a
|
||||||
{
|
{
|
||||||
|
@ -174,7 +170,15 @@
|
||||||
<!-- THE PHOTO ITSELF -->
|
<!-- THE PHOTO ITSELF -->
|
||||||
<div class="photo_viewer">
|
<div class="photo_viewer">
|
||||||
{% if photo.mimetype == "image" %}
|
{% if photo.mimetype == "image" %}
|
||||||
<div id="photo_img_holder"><img id="photo_img" src="{{link}}" onclick="toggle_hoverzoom()" onload="this.style.opacity=0.99"></div>
|
<div id="photo_img_holder">
|
||||||
|
<img
|
||||||
|
id="photo_img"
|
||||||
|
src="{{link}}"
|
||||||
|
alt="{{photo.basename}}"
|
||||||
|
onclick="toggle_hoverzoom()"
|
||||||
|
onload="this.style.opacity=0.99"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
{% elif photo.mimetype == "video" %}
|
{% elif photo.mimetype == "video" %}
|
||||||
<video src="{{link}}" controls preload=none {%if photo.thumbnail%}poster="/thumbnail/{{photo.id}}.jpg"{%endif%}></video>
|
<video src="{{link}}" controls preload=none {%if photo.thumbnail%}poster="/thumbnail/{{photo.id}}.jpg"{%endif%}></video>
|
||||||
{% elif photo.mimetype == "audio" %}
|
{% elif photo.mimetype == "audio" %}
|
||||||
|
|
Loading…
Reference in a new issue