Improve Catalog
ci / checks (push) Successful in 46m42s

This commit is contained in:
khodowany
2026-09-27 11:03:43 -05:00
parent a416a80dd9
commit 142d843fac
418 changed files with 440 additions and 324488 deletions
+26 -25
View File
@@ -35,8 +35,6 @@ class CatalogTests(unittest.TestCase):
document = bundle('Song', 'F')
document['presentation']['title_image'] = '0123456789abcdef' * 4
write_score(self.root, 'songs/tune.json', document)
for part in ('Acoustic', 'Electric', 'Vocal'):
write_score(self.root, f'practice/0001/{part.lower()}.json', bundle('Exercise', 'Eb', part))
database = generator.catalog.build_catalog(self.root)
self.assertEqual(database, self.root / 'catalog.db')
song = self.rows('songs')[0]
@@ -44,22 +42,12 @@ class CatalogTests(unittest.TestCase):
self.assertEqual((song['id'], song['part'], song['source_path']), ('tune', 'Lead', 'songs/tune.json'))
self.assertEqual((song['measure_count'], song['total_pages']), (1, 1))
self.assertEqual(song['title_image'], document['presentation']['title_image'])
practice = self.rows('practice_exercises')
self.assertEqual([row['id'] for row in practice], ['0001-acoustic', '0001-electric', '0001-vocal'])
self.assertEqual(practice[0]['exercise_id'], '0001')
self.assertNotIn('practice_type_id', practice[0])
self.assertNotIn('lesson_group_id', practice[0])
self.assertEqual(practice[0]['key_signature'], 'Eb')
self.assertTrue(all(row['title_image'] == '0' * 64 for row in practice))
self.assertTrue(all(json.loads(row['source_json'])['presentation']['title_image'] == row['title_image'] for row in practice))
self.assertNotIn('authored_key_signature', practice[0])
with contextlib.closing(sqlite3.connect(database)) as connection:
self.assertEqual(connection.execute('PRAGMA application_id').fetchone()[0], generator.catalog.APPLICATION_ID)
self.assertEqual(connection.execute('PRAGMA integrity_check').fetchall(), [('ok',)])
self.assertEqual(connection.execute("SELECT name FROM sqlite_schema WHERE type='table' ORDER BY name").fetchall(), [('practice_exercises',), ('songs',)])
for table in ('songs', 'practice_exercises'):
columns = {row[1]: row for row in connection.execute(f'PRAGMA table_info({table})')}
self.assertEqual((columns['title_image'][2], columns['title_image'][3]), ('TEXT', 1))
self.assertEqual(connection.execute("SELECT name FROM sqlite_schema WHERE type='table' ORDER BY name").fetchall(), [('songs',)])
columns = {row[1]: row for row in connection.execute('PRAGMA table_info(songs)')}
self.assertEqual((columns['title_image'][2], columns['title_image'][3]), ('TEXT', 1))
self.assertFalse(pathlib.Path(str(database) + '-wal').exists())
self.assertFalse(pathlib.Path(str(database) + '-journal').exists())
def test_rebuild_is_deterministic_relocatable_and_replaces_deleted_rows(self):
@@ -88,14 +76,6 @@ class CatalogTests(unittest.TestCase):
generator.catalog.build_catalog(self.root)
self.assertEqual(database.read_bytes(), previous)
self.assertFalse(list(self.root.glob('.vamp-catalog-*')))
def test_missing_parts_and_metadata_disagreement_fail(self):
for part in ('Acoustic', 'Electric'):
write_score(self.root, f'practice/0001/{part.lower()}.json', bundle(part=part))
with self.assertRaisesRegex(ValueError, 'all three parts'):
generator.catalog.build_catalog(self.root)
write_score(self.root, 'practice/0001/vocal.json', bundle(key='F', part='Vocal'))
with self.assertRaisesRegex(ValueError, 'disagree'):
generator.catalog.build_catalog(self.root)
def test_missing_or_invalid_title_image_preserves_existing_database(self):
score = write_score(self.root, 'songs/tune.json')
database = generator.catalog.build_catalog(self.root)
@@ -113,9 +93,9 @@ class CatalogTests(unittest.TestCase):
self.assertFalse(list(self.root.glob('.vamp-catalog-*')))
def test_keyless_parts_preserve_their_original_key(self):
for part in ('Acoustic', 'Electric', 'Vocal'):
write_score(self.root, f'practice/0001/{part.lower()}.json', bundle(key='No key', part=part))
write_score(self.root, f'songs/{part.lower()}.json', bundle(key='No key', part=part))
generator.catalog.build_catalog(self.root)
self.assertTrue(all(row['key_signature'] == 'No key' for row in self.rows('practice_exercises')))
self.assertTrue(all(row['key_signature'] == 'No key' for row in self.rows('songs')))
def test_invalid_layout_and_escaping_source_fail(self):
with self.assertRaisesRegex(ValueError, 'directory not found'):
generator.catalog.build_catalog(self.root / 'missing')
@@ -140,3 +120,24 @@ class CatalogTests(unittest.TestCase):
self.assertEqual(pathlib.Path(config['database']['path']).name, 'catalog.db')
self.assertTrue((destination / 'songs/tune.png').exists())
self.assertFalse(list(destination.rglob('*.json')))
def test_menu_query_uses_index_and_preserves_binary_identity_order(self):
for name, title, composer, part in (('z', 'Same', 'Bea', 'Acoustic'), ('b', 'Same', 'Ada', 'Vocal'), ('a', 'Same', 'Ada', 'Acoustic'), ('c', 'same', 'Ada', 'Electric'), ('d', 'Same', 'Ada', 'Acoustic')):
document = bundle(title=title, part=part)
document['music']['metadata']['composer'] = composer
write_score(self.root, f'songs/{name}.json', document)
database = generator.catalog.build_catalog(self.root)
query = 'SELECT id, title, composer, part, source_path, measure_count, key_signature, total_pages, title_image FROM songs ORDER BY title, composer, part, id'
with contextlib.closing(sqlite3.connect(database)) as connection:
self.assertEqual([row[0] for row in connection.execute(query)], ['a', 'd', 'b', 'z', 'c'])
plan = ' '.join(row[3] for row in connection.execute('EXPLAIN QUERY PLAN ' + query))
self.assertIn('songs_menu', plan)
self.assertNotIn('TEMP B-TREE', plan)
def test_failed_population_rolls_back_schema_and_rows(self):
write_score(self.root, 'songs/a.json')
write_score(self.root, 'songs/b.json', bundle(title=''))
with contextlib.closing(sqlite3.connect(':memory:')) as connection:
with self.assertRaises(ValueError):
generator.catalog.populate(connection, self.root)
self.assertFalse(connection.in_transaction)
self.assertEqual(connection.execute("SELECT name FROM sqlite_schema").fetchall(), [])
self.assertEqual(connection.execute('PRAGMA application_id').fetchone()[0], 0)