Move export functions to their own module.
This commit is contained in:
		
							parent
							
								
									4f03815a30
								
							
						
					
					
						commit
						821a5f3371
					
				
					 6 changed files with 105 additions and 89 deletions
				
			
		|  | @ -20,7 +20,6 @@ Documentation is still a work in progress. In general, I use: | |||
| - Debate whether the `UserMixin.login` method should accept usernames or I should standardize the usage of IDs only internally. | ||||
| - Ability to access user page and user photos by user's ID, not just username. | ||||
| - Should album size be cached on disk? | ||||
| - Organize the tag exporter functions better. | ||||
| - Replace columns like area, ratio, bitrate by using expression indices or views (`width * height` etc). | ||||
| - Add some way to support large image albums without flooding the search results. Considering a "hidden" property so that a handful of representative images can appear in the search results, and the rest can be found on the actual Album page. | ||||
| - Add a `Photo.merge` to combine duplicate entries. | ||||
|  |  | |||
|  | @ -6,3 +6,4 @@ from . import jsonify | |||
| from . import objects | ||||
| from . import photodb | ||||
| from . import searchhelpers | ||||
| from . import tag_export | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ from . import exceptions | |||
| from . import helpers | ||||
| from . import objects | ||||
| from . import searchhelpers | ||||
| from . import tag_export | ||||
| 
 | ||||
| from voussoirkit import cacheclass | ||||
| from voussoirkit import expressionmatch | ||||
|  | @ -176,76 +177,6 @@ def searchfilter_must_may_forbid(photo_tags, tag_musts, tag_mays, tag_forbids, f | |||
| 
 | ||||
|     return True | ||||
| 
 | ||||
| def tag_export_easybake(tags, depth=0): | ||||
|     lines = [] | ||||
|     for tag in tags: | ||||
|         if not hasattr(tag, 'string'): | ||||
|             tag.string = tag.name | ||||
|         children = tag.children() | ||||
|         synonyms = tag.synonyms() | ||||
|         lines.append(tag.string) | ||||
| 
 | ||||
|         for synonym in synonyms: | ||||
|             synonym = tag.string + '+' + synonym | ||||
|             lines.append(synonym) | ||||
| 
 | ||||
|         for child in children: | ||||
|             child.string = tag.string + '.' + child.name | ||||
|         child_bake = tag_export_easybake(children, depth=depth+1) | ||||
|         if child_bake != '': | ||||
|             lines.append(child_bake) | ||||
| 
 | ||||
|     lines = '\n'.join(lines) | ||||
|     return lines | ||||
| 
 | ||||
| def tag_export_json(tags): | ||||
|     def fill(tag): | ||||
|         children = {child.name:fill(child) for child in tag.children()} | ||||
|         return children | ||||
|     result = {} | ||||
|     for tag in tags: | ||||
|         result[tag.name] = fill(tag) | ||||
|     return result | ||||
| 
 | ||||
| def tag_export_qualname_map(tags): | ||||
|     lines = tag_export_easybake(tags) | ||||
|     lines = lines.split('\n') | ||||
|     lines = [line for line in lines if line] | ||||
|     qualname_map = {} | ||||
|     for line in lines: | ||||
|         key = line.split('.')[-1].split('+')[-1] | ||||
|         value = line.split('+')[0] | ||||
|         qualname_map[key] = value | ||||
|     return qualname_map | ||||
| 
 | ||||
| def tag_export_stdout(tags, depth=0): | ||||
|     for tag in tags: | ||||
|         children = tag.children() | ||||
|         synonyms = tag.synonyms() | ||||
| 
 | ||||
|         pad = '    ' * depth | ||||
|         synpad = '    ' * (depth + 1) | ||||
|         print(pad + str(tag)) | ||||
| 
 | ||||
|         for synonym in synonyms: | ||||
|             print(synpad + synonym) | ||||
| 
 | ||||
|         tag_export_stdout(children, depth=depth+1) | ||||
| 
 | ||||
|         if tag.parent() is None: | ||||
|             print() | ||||
| 
 | ||||
| @decorators.time_me | ||||
| def tag_export_totally_flat(tags): | ||||
|     result = {} | ||||
|     for tag in tags: | ||||
|         for child in tag.walk_children(): | ||||
|             children = list(child.walk_children()) | ||||
|             result[child] = children | ||||
|             for synonym in child.synonyms(): | ||||
|                 result[synonym] = children | ||||
|     return result | ||||
| 
 | ||||
| 
 | ||||
| #################################################################################################### | ||||
| #################################################################################################### | ||||
|  | @ -725,7 +656,7 @@ class PDBPhotoMixin: | |||
|             if self._cached_frozen_children: | ||||
|                 frozen_children = self._cached_frozen_children | ||||
|             else: | ||||
|                 frozen_children = self.export_tags(tag_export_totally_flat) | ||||
|                 frozen_children = tag_export.flat_dict(self.get_tags()) | ||||
|                 self._cached_frozen_children = frozen_children | ||||
|         else: | ||||
|             frozen_children = None | ||||
|  | @ -916,20 +847,6 @@ class PDBTagMixin: | |||
|         super().__init__() | ||||
|         self._tag_cache = cacheclass.Cache() | ||||
| 
 | ||||
|     def export_tags(self, exporter=tag_export_stdout, specific_tag=None): | ||||
|         ''' | ||||
|         Send the top-level tags to function `exporter`. | ||||
|         Strings 'start' and 'stop' are sent before and after the tags are sent. | ||||
|         Recursion is to be handled by the exporter. | ||||
|         ''' | ||||
|         if specific_tag is None: | ||||
|             items = list(self.get_tags()) | ||||
|             items = [item for item in items if item.parent() is None] | ||||
|             items.sort(key=lambda x: x.name) | ||||
|         else: | ||||
|             items = [self.get_tag(specific_tag)] | ||||
|         return exporter(items) | ||||
| 
 | ||||
|     def get_tag(self, name=None, id=None): | ||||
|         ''' | ||||
|         Redirect to get_tag_by_id or get_tag_by_name after xor-checking the parameters. | ||||
|  |  | |||
							
								
								
									
										98
									
								
								etiquette/tag_export.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								etiquette/tag_export.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | |||
| def easybake(tags): | ||||
|     ''' | ||||
|     A string where every line is the qualified name of a tag or its synonyms. | ||||
| 
 | ||||
|     people | ||||
|     people.family | ||||
|     people.family.mother | ||||
|     people.family.mother+mom | ||||
|     ''' | ||||
|     lines = [] | ||||
|     tags = list(tags) | ||||
|     for tag in tags: | ||||
|         qualname = tag.qualified_name() | ||||
|         lines.append(qualname) | ||||
|         lines.extend(qualname + '+' + syn for syn in tag.synonyms()) | ||||
|     return '\n'.join(lines) | ||||
| 
 | ||||
| def flat_dict(tags): | ||||
|     ''' | ||||
|     A dictionary where every tag is its own key, and the value is a list | ||||
|     containing itself all of its nested children. | ||||
|     Synonyms not included. | ||||
| 
 | ||||
|     { | ||||
|         people: [people, family, mother], | ||||
|         family: [family, mother], | ||||
|         mother: [mother], | ||||
|     } | ||||
| 
 | ||||
|     The list contains itself so that you can quickly ask whether a user's | ||||
|     requested tag exists in that tree without having to write separate checks | ||||
|     for equaling the main tag versus existing in the rest of the subtree. | ||||
|     ''' | ||||
|     result = {} | ||||
|     for tag in tags: | ||||
|         for child in tag.walk_children(): | ||||
|             children = list(child.walk_children()) | ||||
|             result[child] = children | ||||
|             for synonym in child.synonyms(): | ||||
|                 result[synonym] = children | ||||
|     return result | ||||
| 
 | ||||
| def nested_dict(tags): | ||||
|     ''' | ||||
|     A dictionary where keys are tags, values are recursive dictionaries | ||||
|     of children. | ||||
|     Synonyms not included. | ||||
| 
 | ||||
|     { | ||||
|         people: { | ||||
|             family: { | ||||
|                 mother: {} | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     ''' | ||||
|     result = {} | ||||
|     for tag in tags: | ||||
|         result[tag] = nested_dict(tag) | ||||
| 
 | ||||
|     return result | ||||
| 
 | ||||
| def qualified_names(tags): | ||||
|     ''' | ||||
|     A dictionary where keys are string names, values are qualified names. | ||||
|     Synonyms included. | ||||
| 
 | ||||
|     { | ||||
|         'people': 'people', | ||||
|         'family': 'people.family', | ||||
|         'mother': 'people.family.mother', | ||||
|         'mom': 'people.family.mother', | ||||
|     } | ||||
|     ''' | ||||
|     results = {} | ||||
|     for tag in tags: | ||||
|         qualname = tag.qualified_name() | ||||
|         results[tag.name] = qualname | ||||
|         for synonym in tag.synonyms(): | ||||
|             results[synonym] = qualname | ||||
|     return results | ||||
| 
 | ||||
| def stdout(tags, depth=0): | ||||
|     for tag in tags: | ||||
|         children = tag.children() | ||||
|         synonyms = tag.synonyms() | ||||
| 
 | ||||
|         pad = '    ' * depth | ||||
|         print(pad + tag.name) | ||||
| 
 | ||||
|         synpad = '    ' * (depth + 1) | ||||
|         for synonym in synonyms: | ||||
|             print(synpad + '+' + synonym) | ||||
| 
 | ||||
|         stdout(children, depth=depth+1) | ||||
| 
 | ||||
|         if tag.parent() is None: | ||||
|             print() | ||||
|  | @ -565,7 +565,7 @@ def get_search_core(): | |||
| def get_search_html(): | ||||
|     search_results = get_search_core() | ||||
|     search_kwargs = search_results['search_kwargs'] | ||||
|     qualname_map = P.export_tags(exporter=etiquette.photodb.tag_export_qualname_map) | ||||
|     qualname_map = etiquette.tag_export.qualified_names(P.get_tags()) | ||||
|     session = session_manager.get(request) | ||||
|     response = flask.render_template( | ||||
|         'search.html', | ||||
|  |  | |||
|  | @ -1,9 +1,10 @@ | |||
| # Use with | ||||
| # py -i etiquette_easy.py | ||||
| 
 | ||||
| import etiquette.photodb | ||||
| import etiquette | ||||
| import os | ||||
| import sys | ||||
| 
 | ||||
| P = etiquette.photodb.PhotoDB() | ||||
| import traceback | ||||
| 
 | ||||
|  | @ -13,7 +14,7 @@ def easytagger(): | |||
|         if i.startswith('?'): | ||||
|             i = i.split('?')[1] or None | ||||
|             try: | ||||
|                 P.export_tags(specific_tag=i) | ||||
|                 etiquette.tag_export.stdout([P.get_tag(i)]) | ||||
|             except: | ||||
|                 traceback.print_exc() | ||||
|         else: | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue