Rename variable 'row_tuple' to 'db_row'; Improve some docstrings

This commit is contained in:
voussoir 2017-03-03 21:15:31 -08:00
parent d71d7b03c2
commit c3a4fa443b
5 changed files with 80 additions and 66 deletions

View file

@ -171,13 +171,13 @@ class GroupableMixin:
class Album(ObjectBase, GroupableMixin): class Album(ObjectBase, GroupableMixin):
def __init__(self, photodb, row_tuple): def __init__(self, photodb, db_row):
self.photodb = photodb self.photodb = photodb
if isinstance(row_tuple, (list, tuple)): if isinstance(db_row, (list, tuple)):
row_tuple = {constants.SQL_ALBUM_COLUMNS[index]: value for (index, value) in enumerate(row_tuple)} db_row = {constants.SQL_ALBUM_COLUMNS[index]: value for (index, value) in enumerate(db_row)}
self.id = row_tuple['id'] self.id = db_row['id']
self.title = row_tuple['title'] self.title = db_row['title']
self.description = row_tuple['description'] self.description = db_row['description']
self.name = 'Album %s' % self.id self.name = 'Album %s' % self.id
self.group_getter = self.photodb.get_album self.group_getter = self.photodb.get_album
@ -285,27 +285,25 @@ class Album(ObjectBase, GroupableMixin):
else: else:
return total return total
def walk_photos(self): def walk_photos(self):
yield from self.photos() yield from self.photos()
children = self.walk_children() children = self.walk_children()
# The first yield is itself # The first yield is itself
next(children) next(children)
for child in children: for child in children:
print(child)
yield from child.walk_photos() yield from child.walk_photos()
class Bookmark(ObjectBase): class Bookmark(ObjectBase):
def __init__(self, photodb, row_tuple): def __init__(self, photodb, db_row):
self.photodb = photodb self.photodb = photodb
if isinstance(row_tuple, (list, tuple)): if isinstance(db_row, (list, tuple)):
row_tuple = {constants.SQL_BOOKMARK_COLUMNS[index]: value for (index, value) in enumerate(row_tuple)} db_row = {constants.SQL_BOOKMARK_COLUMNS[index]: value for (index, value) in enumerate(db_row)}
self.id = row_tuple['id'] self.id = db_row['id']
self.title = row_tuple['title'] self.title = db_row['title']
self.url = row_tuple['url'] self.url = db_row['url']
self.author_id = row_tuple['author_id'] self.author_id = db_row['author_id']
def __repr__(self): def __repr__(self):
return 'Bookmark:{id}'.format(id=self.id) return 'Bookmark:{id}'.format(id=self.id)
@ -339,34 +337,34 @@ class Photo(ObjectBase):
Photo objects cannot exist without a corresponding PhotoDB object, because Photo objects cannot exist without a corresponding PhotoDB object, because
Photos are not the actual image data, just the database entry. Photos are not the actual image data, just the database entry.
''' '''
def __init__(self, photodb, row_tuple): def __init__(self, photodb, db_row):
self.photodb = photodb self.photodb = photodb
if isinstance(row_tuple, (list, tuple)): if isinstance(db_row, (list, tuple)):
row_tuple = {constants.SQL_PHOTO_COLUMNS[index]: value for (index, value) in enumerate(row_tuple)} db_row = {constants.SQL_PHOTO_COLUMNS[index]: value for (index, value) in enumerate(db_row)}
self.real_filepath = helpers.normalize_filepath(row_tuple['filepath'], allowed=':\\/') self.real_filepath = helpers.normalize_filepath(db_row['filepath'], allowed=':\\/')
self.real_path = pathclass.Path(self.real_filepath) self.real_path = pathclass.Path(self.real_filepath)
self.id = row_tuple['id'] self.id = db_row['id']
self.created = row_tuple['created'] self.created = db_row['created']
self.author_id = row_tuple['author_id'] self.author_id = db_row['author_id']
self.filepath = row_tuple['override_filename'] or self.real_path.absolute_path self.filepath = db_row['override_filename'] or self.real_path.absolute_path
self.basename = row_tuple['override_filename'] or self.real_path.basename self.basename = db_row['override_filename'] or self.real_path.basename
self.extension = row_tuple['extension'] self.extension = db_row['extension']
self.tagged_at = row_tuple['tagged_at'] self.tagged_at = db_row['tagged_at']
if self.extension == '': if self.extension == '':
self.dot_extension = '' self.dot_extension = ''
else: else:
self.dot_extension = '.' + self.extension self.dot_extension = '.' + self.extension
self.area = row_tuple['area'] self.area = db_row['area']
self.bytes = row_tuple['bytes'] self.bytes = db_row['bytes']
self.duration = row_tuple['duration'] self.duration = db_row['duration']
self.width = row_tuple['width'] self.width = db_row['width']
self.height = row_tuple['height'] self.height = db_row['height']
self.ratio = row_tuple['ratio'] self.ratio = db_row['ratio']
self.thumbnail = row_tuple['thumbnail'] self.thumbnail = db_row['thumbnail']
self.mimetype = helpers.get_mimetype(self.real_filepath) self.mimetype = helpers.get_mimetype(self.real_filepath)
if self.mimetype is None: if self.mimetype is None:
@ -736,12 +734,12 @@ class Tag(ObjectBase, GroupableMixin):
''' '''
A Tag, which can be applied to Photos for organization. A Tag, which can be applied to Photos for organization.
''' '''
def __init__(self, photodb, row_tuple): def __init__(self, photodb, db_row):
self.photodb = photodb self.photodb = photodb
if isinstance(row_tuple, (list, tuple)): if isinstance(db_row, (list, tuple)):
row_tuple = {constants.SQL_TAG_COLUMNS[index]: value for (index, value) in enumerate(row_tuple)} db_row = {constants.SQL_TAG_COLUMNS[index]: value for (index, value) in enumerate(db_row)}
self.id = row_tuple['id'] self.id = db_row['id']
self.name = row_tuple['name'] self.name = db_row['name']
self.group_getter = self.photodb.get_tag self.group_getter = self.photodb.get_tag
self._cached_qualified_name = None self._cached_qualified_name = None
@ -913,13 +911,13 @@ class User(ObjectBase):
''' '''
A dear friend of ours. A dear friend of ours.
''' '''
def __init__(self, photodb, row_tuple): def __init__(self, photodb, db_row):
self.photodb = photodb self.photodb = photodb
if isinstance(row_tuple, (list, tuple)): if isinstance(db_row, (list, tuple)):
row_tuple = {constants.SQL_USER_COLUMNS[index]: value for (index, value) in enumerate(row_tuple)} db_row = {constants.SQL_USER_COLUMNS[index]: value for (index, value) in enumerate(db_row)}
self.id = row_tuple['id'] self.id = db_row['id']
self.username = row_tuple['username'] self.username = db_row['username']
self.created = row_tuple['created'] self.created = db_row['created']
def __repr__(self): def __repr__(self):
rep = 'User:{id}:{username}'.format(id=self.id, username=self.username) rep = 'User:{id}:{username}'.format(id=self.id, username=self.username)

View file

@ -541,14 +541,16 @@ class PDBPhotoMixin:
''' '''
PHOTO PROPERTIES PHOTO PROPERTIES
area, width, height, ratio, bytes, duration: area, width, height, ratio, bytes, duration:
A hyphen_range string representing min and max. Or just a number for lower bound. A hyphen_range string representing min and max. Or just a number
for lower bound.
TAGS AND FILTERS TAGS AND FILTERS
authors: authors:
A list of User objects, or usernames, or user ids. A list of User objects, or usernames, or user ids.
created: created:
A hyphen_range string respresenting min and max. Or just a number for lower bound. A hyphen_range string respresenting min and max. Or just a number
for lower bound.
extension: extension:
A string or list of strings of acceptable file extensions. A string or list of strings of acceptable file extensions.
@ -558,16 +560,20 @@ class PDBPhotoMixin:
Including '*' will forbid all extensions Including '*' will forbid all extensions
filename: filename:
A string or list of strings which will be split into words. The file's basename A string or list of strings in the form of an expression.
must include every word, NOT case-sensitive. Match is CASE-INSENSITIVE.
Examples:
'.pdf AND (programming OR "survival guide")'
'.pdf programming python' (implicitly AND each term)
has_tags: has_tags:
If True, require that the Photo has >=1 tag. If True, require that the Photo has >=1 tag.
If False, require that the Photo has no tags. If False, require that the Photo has no tags.
If None, not considered. If None, any amount is okay.
mimetype: mimetype:
A string or list of strings of acceptable mimetypes. 'image', 'video', ... A string or list of strings of acceptable mimetypes.
'image', 'video', ...
tag_musts: tag_musts:
A list of tag names or Tag objects. A list of tag names or Tag objects.
@ -582,8 +588,11 @@ class PDBPhotoMixin:
Photos MUST NOT have ANY tag in the list. Photos MUST NOT have ANY tag in the list.
tag_expression: tag_expression:
A string like 'family AND (animals OR vacation)' to filter by. A string or list of strings in the form of an expression.
Can NOT be used with the must, may, forbid style search. Can NOT be used with the must, may, forbid style search.
Examples:
'family AND (animals OR vacation)'
'family vacation outdoors' (implicitly AND each term)
QUERY OPTIONS QUERY OPTIONS
limit: limit:
@ -598,13 +607,15 @@ class PDBPhotoMixin:
Descending is assumed if not provided. Descending is assumed if not provided.
warning_bag: warning_bag:
Invalid search queries will add a warning to the bag and try their best to continue. If provided, invalid search queries will add a warning to the bag
Otherwise they may raise exceptions. and try their best to continue. The generator will yield the bag
back to you as the final object.
Without the bag, exceptions may be raised.
give_back_parameters: give_back_parameters:
If True, the generator's first yield will be a dictionary of all the cleaned up, normalized If True, the generator's first yield will be a dictionary of all the
parameters. The user may have given us loads of trash, so we should show them the formatting cleaned up, normalized parameters. The user may have given us loads
we want. of trash, so we should show them the formatting we want.
''' '''
start_time = time.time() start_time = time.time()
@ -791,7 +802,6 @@ class PDBPhotoMixin:
#print('Failed has_tags=True') #print('Failed has_tags=True')
continue continue
if tag_expression: if tag_expression:
success = expression_tree.evaluate( success = expression_tree.evaluate(
photo_tags, photo_tags,
@ -819,7 +829,6 @@ class PDBPhotoMixin:
if limit is not None and photos_received >= limit: if limit is not None and photos_received >= limit:
break break
photos_received += 1 photos_received += 1
yield photo yield photo
@ -1383,7 +1392,7 @@ class PhotoDB(PDBAlbumMixin, PDBBookmarkMixin, PDBPhotoMixin, PDBTagMixin, PDBUs
things = cur.fetchall() things = cur.fetchall()
for thing in things: for thing in things:
thing = thing_map['class'](self, row_tuple=thing) thing = thing_map['class'](self, db_row=thing)
yield thing yield thing

View file

@ -153,7 +153,6 @@ 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 = shlex.split(filename_terms)
if not filename_terms: if not filename_terms:
return None return None
@ -280,6 +279,11 @@ def normalize_tag_expression(expression):
if not isinstance(expression, str): if not isinstance(expression, str):
expression = ' '.join(expression) expression = ' '.join(expression)
expression = expression.strip()
if not expression:
return None
return expression return expression
def normalize_tag_mmf(tags, photodb, warning_bag=None): def normalize_tag_mmf(tags, photodb, warning_bag=None):

View file

@ -484,16 +484,19 @@ def get_search_core():
# The search has converted many arguments into sets or other types. # The search has converted many arguments into sets or other types.
# Convert them back into something that will display nicely on the search form. # Convert them back into something that will display nicely on the search form.
join_helper = lambda x: ', '.join(x) if x else None join_helper = lambda x: ', '.join(x) if x else None
tagname_helper = lambda tags: [tag.qualified_name() for tag in tags] if tags else None
filename_helper = lambda fn: ' '.join('"%s"' % part if ' ' in part else part for part in fn) if fn else None
search_kwargs['extension'] = join_helper(search_kwargs['extension']) search_kwargs['extension'] = join_helper(search_kwargs['extension'])
search_kwargs['extension_not'] = join_helper(search_kwargs['extension_not']) search_kwargs['extension_not'] = join_helper(search_kwargs['extension_not'])
search_kwargs['mimetype'] = join_helper(search_kwargs['mimetype']) search_kwargs['mimetype'] = join_helper(search_kwargs['mimetype'])
search_kwargs['filename'] = filename_helper(search_kwargs['filename'])
tagname_helper = lambda tags: [tag.qualified_name() for tag in tags] if tags else None
search_kwargs['tag_musts'] = tagname_helper(search_kwargs['tag_musts']) search_kwargs['tag_musts'] = tagname_helper(search_kwargs['tag_musts'])
search_kwargs['tag_mays'] = tagname_helper(search_kwargs['tag_mays']) search_kwargs['tag_mays'] = tagname_helper(search_kwargs['tag_mays'])
search_kwargs['tag_forbids'] = tagname_helper(search_kwargs['tag_forbids']) search_kwargs['tag_forbids'] = tagname_helper(search_kwargs['tag_forbids'])
#quoted_helper = lambda text: '"%s"' % text if ' ' in text else text
#filename_helper = lambda fn: ' '.join(quoted_helper(part) for part in fn) if fn else None
#search_kwargs['filename'] = filename_helper(search_kwargs['filename'])
search_results = list(search_generator) search_results = list(search_generator)
warnings = set() warnings = set()
photos = [] photos = []

View file

@ -37,7 +37,7 @@ def upgrade_3_to_4(sql):
''' '''
cur = sql.cursor() cur = sql.cursor()
cur.execute('ALTER TABLE photos ADD COLUMN author_id TEXT') cur.execute('ALTER TABLE photos ADD COLUMN author_id TEXT')
cur.execute('CREATE INDEX IF NOT EXISTS index_photo_author on photos(author_id)') cur.execute('CREATE INDEX IF NOT EXISTS index_photo_author ON photos(author_id)')
def upgrade_4_to_5(sql): def upgrade_4_to_5(sql):
''' '''
@ -52,8 +52,8 @@ def upgrade_4_to_5(sql):
author_id TEXT author_id TEXT
) )
''') ''')
cur.execute('CREATE INDEX IF NOT EXISTS index_bookmark_id on bookmarks(id)') cur.execute('CREATE INDEX IF NOT EXISTS index_bookmark_id ON bookmarks(id)')
cur.execute('CREATE INDEX IF NOT EXISTS index_bookmark_author on bookmarks(author_id)') cur.execute('CREATE INDEX IF NOT EXISTS index_bookmark_author ON bookmarks(author_id)')
def upgrade_all(database_filename): def upgrade_all(database_filename):
''' '''