From d7cd1e9748645958f0bb9a0b10ba23dda2899805 Mon Sep 17 00:00:00 2001 From: Ethan Dalool Date: Fri, 10 Mar 2017 15:01:12 -0800 Subject: [PATCH] Add more docstrings; Remove unused code --- etiquette/constants.py | 4 +++- etiquette/helpers.py | 41 ++++++++++++++++++++++++++++++++++++++--- etiquette/objects.py | 14 ++++++++++++++ etiquette/photodb.py | 27 --------------------------- 4 files changed, 55 insertions(+), 31 deletions(-) diff --git a/etiquette/constants.py b/etiquette/constants.py index 53180dc..9150cef 100644 --- a/etiquette/constants.py +++ b/etiquette/constants.py @@ -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.' # 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 = { '7z': 'archive', 'gz': 'archive', diff --git a/etiquette/helpers.py b/etiquette/helpers.py index 5fe99b4..2393c1f 100644 --- a/etiquette/helpers.py +++ b/etiquette/helpers.py @@ -55,6 +55,17 @@ def binding_filler(column_names, values, require_all=True): Manually aligning question marks and bindings is annoying. 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. + + 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() for column in column_names: @@ -70,6 +81,19 @@ def binding_filler(column_names, values, require_all=True): return (qmarks, bindings) 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) checker = PIL.Image.new('RGB', (checker_size, checker_size), color_2) offset = True @@ -143,6 +167,9 @@ def fit_into_bounds(image_width, image_height, frame_width, frame_height): return (new_width, new_height) def get_mimetype(filepath): + ''' + Extension to mimetypes.guess_type which uses my constants.ADDITIONAL_MIMETYPES. + ''' extension = os.path.splitext(filepath)[1].replace('.', '') if extension in constants.ADDITIONAL_MIMETYPES: 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 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.replace(' ', '') @@ -280,12 +308,19 @@ def select_generator(sql, query, bindings=None): yield fetch 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: return s s = s.lower() - if s in {'1', 'true', 't', 'yes', 'y', 'on'}: + if s in constants.TRUTHYSTRING_TRUE: return True - if s in {'null', 'none'}: + if s in constants.TRUTHYSTRING_NONE: return None return False diff --git a/etiquette/objects.py b/etiquette/objects.py index 2df083d..6b679dd 100644 --- a/etiquette/objects.py +++ b/etiquette/objects.py @@ -230,6 +230,14 @@ class Album(ObjectBase, GroupableMixin): self.photodb.commit() 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) if nested_children: photos = self.walk_photos() @@ -253,6 +261,9 @@ class Album(ObjectBase, GroupableMixin): self.photodb.commit() def edit(self, title=None, description=None, *, commit=True): + ''' + Change the title or description. Leave None to keep current value. + ''' if title is None: title = self.title if description is None: @@ -467,6 +478,9 @@ class Photo(ObjectBase): return bytestring.bytestring(self.bytes) 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(): self.add_tag(tag) diff --git a/etiquette/photodb.py b/etiquette/photodb.py index 5a6f123..988c868 100644 --- a/etiquette/photodb.py +++ b/etiquette/photodb.py @@ -145,33 +145,6 @@ def _helper_filenamefilter(subject, terms): basename = subject.lower() 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): 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')