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