Add more docstrings; Remove unused code

This commit is contained in:
voussoir 2017-03-10 15:01:12 -08:00
parent 3be8813a0a
commit d7cd1e9748
4 changed files with 55 additions and 31 deletions

View file

@ -112,7 +112,9 @@ WARNING_ORDERBY_BADCOL = '"{column}" is not a sorting option. Ignored.'
WARNING_ORDERBY_BADDIRECTION = 'You can\'t order "{column}" by "{direction}". Defaulting to descending.' WARNING_ORDERBY_BADDIRECTION = 'You can\'t order "{column}" by "{direction}". Defaulting to descending.'
# Operational info # Operational info
EXPRESSION_OPERATORS = {'(', ')', 'OR', 'AND', 'NOT'} TRUTHYSTRING_TRUE = {s.lower() for s in ('1', 'true', 't', 'yes', 'y', 'on')}
TRUTHYSTRING_NONE = {s.lower() for s in ('null', 'none')}
ADDITIONAL_MIMETYPES = { ADDITIONAL_MIMETYPES = {
'7z': 'archive', '7z': 'archive',
'gz': 'archive', 'gz': 'archive',

View file

@ -55,6 +55,17 @@ def binding_filler(column_names, values, require_all=True):
Manually aligning question marks and bindings is annoying. Manually aligning question marks and bindings is annoying.
Given the table's column names and a dictionary of {column: value}, Given the table's column names and a dictionary of {column: value},
return the question marks and the list of bindings in the right order. return the question marks and the list of bindings in the right order.
require_all:
If `values` does not contain one of the column names, should we raise
an exception?
Otherwise, that column will simply receive None.
Ex:
column_names=['id', 'name', 'score'],
values={'score': 20, 'id': '1111', 'name': 'James'}
->
returns ('?, ?, ?, ?', ['1111', 'James', 20])
''' '''
values = values.copy() values = values.copy()
for column in column_names: for column in column_names:
@ -70,6 +81,19 @@ def binding_filler(column_names, values, require_all=True):
return (qmarks, bindings) return (qmarks, bindings)
def checkerboard_image(color_1, color_2, image_size, checker_size): def checkerboard_image(color_1, color_2, image_size, checker_size):
'''
Generate a PIL Image with a checkerboard pattern.
color_1:
The color starting in the top left. Either RGB tuple or a string
that PIL understands.
color_2:
The alternate color
image_size:
Tuple of two integers, the image size in pixels.
checker_size:
Tuple of two integers, the size of each checker in pixels.
'''
image = PIL.Image.new('RGB', image_size, color_1) image = PIL.Image.new('RGB', image_size, color_1)
checker = PIL.Image.new('RGB', (checker_size, checker_size), color_2) checker = PIL.Image.new('RGB', (checker_size, checker_size), color_2)
offset = True offset = True
@ -143,6 +167,9 @@ def fit_into_bounds(image_width, image_height, frame_width, frame_height):
return (new_width, new_height) return (new_width, new_height)
def get_mimetype(filepath): def get_mimetype(filepath):
'''
Extension to mimetypes.guess_type which uses my constants.ADDITIONAL_MIMETYPES.
'''
extension = os.path.splitext(filepath)[1].replace('.', '') extension = os.path.splitext(filepath)[1].replace('.', '')
if extension in constants.ADDITIONAL_MIMETYPES: if extension in constants.ADDITIONAL_MIMETYPES:
return constants.ADDITIONAL_MIMETYPES[extension] return constants.ADDITIONAL_MIMETYPES[extension]
@ -154,7 +181,8 @@ def hyphen_range(s):
Given a string like '1-3', return numbers (1, 3) representing lower Given a string like '1-3', return numbers (1, 3) representing lower
and upper bounds. and upper bounds.
Supports bytestring.parsebytes and hh:mm:ss format. Supports bytestring.parsebytes and hh:mm:ss format, for example
'1k-2k', '10:00-20:00', '4gib-'
''' '''
s = s.strip() s = s.strip()
s = s.replace(' ', '') s = s.replace(' ', '')
@ -280,12 +308,19 @@ def select_generator(sql, query, bindings=None):
yield fetch yield fetch
def truthystring(s): def truthystring(s):
'''
Convert strings to True, False, or None based on the options presented
in constants.TRUTHYSTRING_TRUE, constants.TRUTHYSTRING_NONE, or False
for all else.
Case insensitive.
'''
if isinstance(s, (bool, int)) or s is None: if isinstance(s, (bool, int)) or s is None:
return s return s
s = s.lower() s = s.lower()
if s in {'1', 'true', 't', 'yes', 'y', 'on'}: if s in constants.TRUTHYSTRING_TRUE:
return True return True
if s in {'null', 'none'}: if s in constants.TRUTHYSTRING_NONE:
return None return None
return False return False

View file

@ -230,6 +230,14 @@ class Album(ObjectBase, GroupableMixin):
self.photodb.commit() self.photodb.commit()
def add_tag_to_all(self, tag, *, nested_children=True, commit=True): def add_tag_to_all(self, tag, *, nested_children=True, commit=True):
'''
Add this tag to every photo in the album. Saves you from having to
write the for-loop yourself.
nested_children:
If True, add the tag to photos contained in sub-albums.
Otherwise, only local photos.
'''
tag = self.photodb.get_tag(tag) tag = self.photodb.get_tag(tag)
if nested_children: if nested_children:
photos = self.walk_photos() photos = self.walk_photos()
@ -253,6 +261,9 @@ class Album(ObjectBase, GroupableMixin):
self.photodb.commit() self.photodb.commit()
def edit(self, title=None, description=None, *, commit=True): def edit(self, title=None, description=None, *, commit=True):
'''
Change the title or description. Leave None to keep current value.
'''
if title is None: if title is None:
title = self.title title = self.title
if description is None: if description is None:
@ -467,6 +478,9 @@ class Photo(ObjectBase):
return bytestring.bytestring(self.bytes) return bytestring.bytestring(self.bytes)
def copy_tags(self, other_photo): def copy_tags(self, other_photo):
'''
Take all of the tags owned by other_photo and apply them to this photo.
'''
for tag in other_photo.tags(): for tag in other_photo.tags():
self.add_tag(tag) self.add_tag(tag)

View file

@ -145,33 +145,6 @@ def _helper_filenamefilter(subject, terms):
basename = subject.lower() basename = subject.lower()
return all(term in basename for term in terms) return all(term in basename for term in terms)
def operate(operand_stack, operator_stack):
#print('before:', operand_stack, operator_stack)
operator = operator_stack.pop()
if operator == 'NOT':
operand = operand_stack.pop()
value = operand ^ 1
else:
right = operand_stack.pop()
left = operand_stack.pop()
if operator == 'OR':
value = left | right
elif operator == 'AND':
value = left & right
else:
raise ValueError('werwer')
operand_stack.append(value)
#print('after:', operand_stack, operator_stack)
# def raise_no_such_thing(exception_class, thing_id=None, thing_name=None, comment=''):
# if thing_id is not None:
# message = 'ID: %s. %s' % (thing_id, comment)
# elif thing_name is not None:
# message = 'Name: %s. %s' % (thing_name, comment)
# else:
# message = ''
# raise exception_class(message)
def searchfilter_must_may_forbid(photo_tags, tag_musts, tag_mays, tag_forbids, frozen_children): def searchfilter_must_may_forbid(photo_tags, tag_musts, tag_mays, tag_forbids, frozen_children):
if tag_musts and not all(any(option in photo_tags for option in frozen_children[must]) for must in tag_musts): if tag_musts and not all(any(option in photo_tags for option in frozen_children[must]) for must in tag_musts):
#print('Failed musts') #print('Failed musts')