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 new_path.normcase == old_path.normcase: | ||||||
|  |             # If they are equivalent but differently cased, just rename. | ||||||
|  |             action = os.rename | ||||||
|  |             args = [old_path.absolute_path, new_path.absolute_path] | ||||||
|  |         else: | ||||||
|  |             # Delete the original, leaving only the new copy / hardlink. | ||||||
|  |             action = os.remove | ||||||
|  |             args = [old_path.absolute_path] | ||||||
|  |          | ||||||
|         if commit: |         if commit: | ||||||
|             if new_path == old_path: |             action(*args) | ||||||
|                 # If they are equivalent but differently cased paths, just |  | ||||||
|                 # rename. |  | ||||||
|                 os.rename(old_path.absolute_path, new_path.absolute_path) |  | ||||||
|             else: |  | ||||||
|                 # Delete the original hardlink or copy. |  | ||||||
|                 os.remove(old_path.absolute_path) |  | ||||||
|             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