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:
voussoir 2017-02-25 22:47:20 -08:00
parent c80e2003ff
commit 5404a1d411
4 changed files with 44 additions and 73 deletions

View file

@ -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__()

View file

@ -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

View file

@ -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

View file

@ -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" %}