diff --git a/etiquette/objects.py b/etiquette/objects.py
index 3904782..d7a3b65 100644
--- a/etiquette/objects.py
+++ b/etiquette/objects.py
@@ -357,7 +357,10 @@ class Bookmark(ObjectBase):
self.url = url
cur = self.photodb.sql.cursor()
- cur.execute('UPDATE bookmarks SET title = ?, url = ? WHERE id == ?', [self.title, self.url, self.id])
+ cur.execute(
+ 'UPDATE bookmarks SET title = ?, url = ? WHERE id == ?',
+ [self.title, self.url, self.id]
+ )
if commit:
self.photodb.log.debug('Committing - edit bookmark')
self.photodb.sql.commit()
@@ -422,15 +425,15 @@ class Photo(ObjectBase):
if self.has_tag(tag, check_children=False):
return
- # If the tag is above one we already have, keep our current one.
+ # If the new tag is less specific than one we already have,
+ # keep our current one.
existing = self.has_tag(tag, check_children=True)
if existing:
message = 'Preferring existing {exi:s} over {tag:s}'.format(exi=existing, tag=tag)
self.photodb.log.debug(message)
return
- # If the tag is beneath one we already have, remove our current one
- # in favor of the new, more specific tag.
+ # If the new tag is more specific, remove our current one for it.
for parent in tag.walk_parents():
if self.has_tag(parent, check_children=False):
self.photodb.log.debug('Preferring new {tag:s} over {par:s}'.format(tag=tag, par=parent))
@@ -585,10 +588,11 @@ class Photo(ObjectBase):
def has_tag(self, tag, *, check_children=True):
'''
- Return the Tag object if this photo contains that tag. Otherwise return False.
+ Return the Tag object if this photo contains that tag.
+ Otherwise return False.
check_children:
- If True, children of the requested tag are counted
+ If True, children of the requested tag are accepted.
'''
tag = self.photodb.get_tag(tag)
@@ -609,6 +613,9 @@ class Photo(ObjectBase):
return False
def make_thumbnail_filepath(self):
+ '''
+ Create the filepath that should be the location of our thumbnail.
+ '''
chunked_id = helpers.chunk_sequence(self.id, 3)
basename = chunked_id[-1]
folder = chunked_id[:-1]
@@ -695,8 +702,10 @@ class Photo(ObjectBase):
def rename_file(self, new_filename, *, move=False, commit=True):
'''
Rename the file on the disk as well as in the database.
- If `move` is True, allow this operation to move the file.
- Otherwise, slashes will be considered an error.
+
+ move:
+ If True, allow the file to be moved into another directory.
+ Otherwise, the rename must be local.
'''
old_path = self.real_path
old_path.correct_case()
@@ -856,11 +865,15 @@ class Tag(ObjectBase, GroupableMixin):
)
for relationship in generator:
photoid = relationship[constants.SQL_PHOTOTAG['photoid']]
- query = 'SELECT * FROM photo_tag_rel WHERE photoid == ? AND tagid == ?'
- cur.execute(query, [photoid, mastertag.id])
+ cur.execute(
+ 'SELECT * FROM photo_tag_rel WHERE photoid == ? AND tagid == ?',
+ [photoid, mastertag.id]
+ )
if cur.fetchone() is None:
- query = 'INSERT INTO photo_tag_rel VALUES(?, ?)'
- cur.execute(query, [photoid, mastertag.id])
+ cur.execute(
+ 'INSERT INTO photo_tag_rel VALUES(?, ?)',
+ [photoid, mastertag.id]
+ )
# Then delete the relationships with the old tag
self.delete()
@@ -906,7 +919,10 @@ class Tag(ObjectBase, GroupableMixin):
raise exceptions.NoSuchSynonym(synname)
cur = self.photodb.sql.cursor()
- cur.execute('SELECT * FROM tag_synonyms WHERE mastername == ? AND name == ?', [self.name, synname])
+ cur.execute(
+ 'SELECT * FROM tag_synonyms WHERE mastername == ? AND name == ?',
+ [self.name, synname]
+ )
fetch = cur.fetchone()
if fetch is None:
raise exceptions.NoSuchSynonym(synname)
diff --git a/etiquette/photodb.py b/etiquette/photodb.py
index 57c6464..36c371a 100644
--- a/etiquette/photodb.py
+++ b/etiquette/photodb.py
@@ -884,6 +884,7 @@ class PDBTagMixin:
if isinstance(tagname, objects.Tag):
tagname = tagname.name
+ tagname = tagname.strip('.+')
tagname = tagname.split('.')[-1].split('+')[0]
tagname = self.normalize_tagname(tagname)
diff --git a/templates/photo.html b/templates/photo.html
index 33dc76b..3c7c89b 100644
--- a/templates/photo.html
+++ b/templates/photo.html
@@ -124,6 +124,10 @@
Tags
diff --git a/test_phototagger.py b/test_phototagger.py
index 541bf74..02373ea 100644
--- a/test_phototagger.py
+++ b/test_phototagger.py
@@ -1,215 +1,35 @@
-import os
-import phototagger
import unittest
import random
-class PhotoDBTest(unittest.TestCase):
+class EtiquetteTest(unittest.TestCase):
def setUp(self):
self.P = phototagger.PhotoDB(':memory:')
-
-class AlbumTest(PhotoDBTest):
- '''
- Test the creation and properties of albums
- '''
- def test_create_album(self):
- album = self.P.new_album()
- test = self.P.get_album(album.id)
- self.assertEqual(album, test)
-
- album = self.P.new_album(title='test1', description='test2')
- self.assertEqual(album.title, 'test1')
- self.assertEqual(album.description, 'test2')
-
- def test_delete_album_nonrecursive(self):
- album = self.P.new_album()
- album.delete()
- self.assertRaises(phototagger.NoSuchAlbum, self.P.get_album, album.id)
-
- def test_edit_album(self):
- album = self.P.new_album(title='t1', description='d1')
- album.edit(title='t2')
- self.assertEqual(album.title, 't2')
- self.assertEqual(album.description, 'd1')
-
- album.edit(title='t3', description='d2')
- self.assertEqual(album.title, 't3')
- self.assertEqual(album.description, 'd2')
-
- album.edit(description='d3')
- album = self.P.get_album(album.id)
- self.assertEqual(album.title, 't3')
- self.assertEqual(album.description, 'd3')
+class AlbumTest(EtiquetteTest):
+ pass
-class PhotoTest(PhotoDBTest):
- '''
- Test the creation and properties of photos
- '''
- def test_create_photo(self):
- photo = self.P.new_photo('samples\\bolts.jpg')
- self.assertGreater(photo.area, 1)
-
- def test_delete_photo(self):
- pass
-
- def test_reload_metadata(self):
- pass
+class BookmarkTest(EtiquetteTest):
+ pass
-class TagTest(PhotoDBTest):
- '''
- Test the creation and properties of tags
- '''
- def test_normalize_tagname(self):
- tag = self.P.new_tag('test normalize')
- self.assertEqual(tag.name, 'test_normalize')
-
- tag = self.P.new_tag('TEST!!NORMALIZE')
- self.assertEqual(tag.name, 'testnormalize')
-
- self.assertRaises(phototagger.TagTooShort, self.P.new_tag, '')
- self.assertRaises(phototagger.TagTooShort, self.P.new_tag, '!??*&')
- self.assertRaises(phototagger.TagTooLong, self.P.new_tag, 'a'*(phototagger.MAX_TAG_NAME_LENGTH+1))
-
- def test_create_tag(self):
- tag = self.P.new_tag('test create tag')
- self.assertEqual(tag.name, 'test_create_tag')
- self.assertRaises(phototagger.TagExists, self.P.new_tag, 'test create tag')
-
- def test_delete_tag_nonrecursive(self):
- tag = self.P.new_tag('test delete tag non')
- tag.delete()
- self.assertRaises(phototagger.NoSuchTag, self.P.get_tag, tag.name)
-
- def test_rename_tag(self):
- tag = self.P.new_tag('test rename pre')
- self.assertEqual(tag.name, 'test_rename_pre')
- tag.rename('test rename post')
- self.assertEqual(self.P.get_tag('test rename post'), tag)
- self.assertRaises(phototagger.NoSuchTag, self.P.get_tag, 'test rename pre')
- self.assertRaises(phototagger.TagTooShort, tag.rename, '??')
- tag.rename(tag.name) # does nothing
+class PhotoTest(EtiquetteTest):
+ pass
-class SearchTest(PhotoDBTest):
- def search_extension(self):
- pass
- def search_minmaxers(self):
- pass
- def search_notags(self):
- pass
- def search_tags(self):
- pass
+class PhotoDBTest(EtiquetteTest):
+ pass
-class SynonymTest(PhotoDBTest):
- '''
- Test the creation and management of synonyms
- '''
- def test_create_synonym(self):
- tag = self.P.new_tag('test create syn')
- tag2 = self.P.new_tag('getting in the way')
- tag.add_synonym('test make syn')
-
- test = self.P.get_tag('test make syn')
- self.assertEqual(test, tag)
- self.assertTrue('test_make_syn' in tag.synonyms())
-
- self.assertRaises(phototagger.TagExists, tag.add_synonym, 'test make syn')
-
- def test_delete_synonym(self):
- tag = self.P.new_tag('test del syn')
- tag.add_synonym('test rem syn')
- tag.remove_synonym('test rem syn')
- self.assertRaises(phototagger.NoSuchSynonym, tag.remove_synonym, 'test rem syn')
-
- def test_convert_tag_to_synonym(self):
- tag1 = self.P.new_tag('convert 1')
- tag2 = self.P.new_tag('convert 2')
- tag2.convert_to_synonym(tag1)
-
- test = self.P.get_tag(tag2)
- self.assertEqual(test, tag1)
- self.assertTrue('convert_2' in tag1.synonyms())
-
- def test_get_synonyms(self):
- tag = self.P.new_tag('test get syns')
- tag.add_synonym('test get syns1')
- tag.add_synonym('test get syns2')
- tag.add_synonym('test get syns3')
- self.assertEqual(len(tag.synonyms()), 3)
+class SearchTest(EtiquetteTest):
+ pass
-class AlbumGroupTest(PhotoDBTest):
- '''
- Test the relationships between albums as they form and leave groups
- '''
- def test_delete_album_recursive(self):
- pass
-
- def test_join_album(self):
- pass
-
- def test_leave_album(self):
- pass
-
- def test_album_children(self):
- pass
-
- def test_album_parents(self):
- pass
+class TagTest(EtiquetteTest):
+ pass
-class TagGroupTest(PhotoDBTest):
- '''
- Test the relationships between tags as they form and leave groups
- '''
- def test_delete_tag_recursive(self):
- pass
-
- def test_join_tag(self):
- pass
-
- def test_leave_tag(self):
- pass
-
- def test_tag_children(self):
- pass
-
- def test_tag_parents(self):
- pass
-
- def test_tag_qualified_name(self):
- pass
+class UserTest(EtiquetteTest):
+ pass
-class AlbumPhotoTest(PhotoDBTest):
- '''
- Test the relationships between albums and photos
- '''
- def test_add_photo(self):
- pass
-
- def test_remove_photo(self):
- pass
-
-
-class PhotoTagTest(PhotoDBTest):
- '''
- Test the relationships between photos and tags
- '''
- def test_photo_has_tag(self):
- pass
-
- def test_add_tag(self):
- pass
-
- def test_remove_tag(self):
- pass
-
-
-
-
-if __name__ == '__main__':
- unittest.main()