+28
-27
@@ -1,67 +1,68 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
import pathlib
|
||||
import tempfile
|
||||
import unittest
|
||||
import unittest.mock
|
||||
|
||||
from generator.practice.generate import generate_practice_scores
|
||||
from generator.arrange.generate import generate_performance_scores
|
||||
from generator.score import validate_generated_tree
|
||||
from generator.summary import validate_practice_parts
|
||||
from generator.parts import PART_TYPES
|
||||
from unittest.mock import patch
|
||||
from tests.test_musicxml import xml_note, xml_score
|
||||
import generator.arrange.generate
|
||||
import generator.parts
|
||||
import generator.practice.generate
|
||||
import generator.score
|
||||
import generator.summary
|
||||
import tests.rhythm_fixtures
|
||||
import tests.test_musicxml
|
||||
|
||||
class CatalogTests(unittest.TestCase):
|
||||
def test_every_numbered_source_is_wired_to_three_part_paths(self):
|
||||
source = Path('data/practice')
|
||||
source = pathlib.Path('data/practice')
|
||||
sources = sorted(source.glob('*.xml'))
|
||||
self.assertEqual([p.name for p in sources], [f'{i:04}.xml' for i in range(1, 367)])
|
||||
expected = {Path(path.stem) / (part + '.json') for path in sources for part in PART_TYPES}
|
||||
expected = {pathlib.Path(path.stem) / (part + '.json') for path in sources for part in generator.parts.PART_TYPES}
|
||||
self.assertEqual(len(expected), 1098)
|
||||
with tempfile.TemporaryDirectory() as temporary, patch('generator.practice.generate._practice_document', side_effect=lambda document, part: document):
|
||||
output = Path(temporary)
|
||||
self.assertEqual(generate_practice_scores(source, output), len(expected))
|
||||
with tempfile.TemporaryDirectory() as temporary, unittest.mock.patch('generator.practice.generate._practice_document', side_effect=lambda document, part, plan: document):
|
||||
output = pathlib.Path(temporary)
|
||||
self.assertEqual(generator.practice.generate.generate_practice_scores(source, output, rhythms=tests.rhythm_fixtures.library()), len(expected))
|
||||
self.assertEqual({p.relative_to(output) for p in output.rglob('*.json')}, expected)
|
||||
validate_practice_parts(output)
|
||||
validate_generated_tree(output)
|
||||
generator.summary.validate_practice_parts(output)
|
||||
generator.score.validate_generated_tree(output)
|
||||
def test_numbers_and_duplicate_titles_remain_distinct_and_songs_are_excluded(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
source, output = Path(temporary) / 'source', Path(temporary) / 'output'
|
||||
source, output = pathlib.Path(temporary) / 'source', pathlib.Path(temporary) / 'output'
|
||||
source.mkdir(parents=True)
|
||||
for name in ('1000.xml', '0000.xml', '0001.xml', '0999.xml', '0010.xml', '0366.xml'):
|
||||
(source / name).write_text(xml_score(xml_note()), encoding='utf-8')
|
||||
self.assertEqual(generate_practice_scores(source, output), 18)
|
||||
(source / name).write_text(tests.test_musicxml.xml_score(tests.test_musicxml.xml_note()), encoding='utf-8')
|
||||
self.assertEqual(generator.practice.generate.generate_practice_scores(source, output, rhythms=tests.rhythm_fixtures.library()), 18)
|
||||
self.assertEqual(sorted(p.name for p in output.iterdir()), ['0000', '0001', '0010', '0366', '0999', '1000'])
|
||||
for directory in output.iterdir():
|
||||
self.assertEqual({p.name for p in directory.glob('*.json')}, {(part + '.json') for part in PART_TYPES})
|
||||
self.assertEqual({p.name for p in directory.glob('*.json')}, {(part + '.json') for part in generator.parts.PART_TYPES})
|
||||
self.assertEqual(json.loads((directory / 'vocal.json').read_text())['metadata']['title'], 'Fixture')
|
||||
def test_invalid_names_and_legacy_nesting_preserve_output(self):
|
||||
for name in ('1.xml', '001.xml', '00001.xml', '\u0660\u0660\u0660\u0661.xml', '0001-copy.xml', '0001_copy.xml', 'chord/0001.xml', 'practice/melody/lesson/0001.xml'):
|
||||
with self.subTest(name=name), tempfile.TemporaryDirectory() as temporary:
|
||||
source, output = Path(temporary) / 'source', Path(temporary) / 'output'
|
||||
source, output = pathlib.Path(temporary) / 'source', pathlib.Path(temporary) / 'output'
|
||||
for relative in ('0002.xml', name):
|
||||
path = source / relative
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(xml_score(xml_note()), encoding='utf-8')
|
||||
path.write_text(tests.test_musicxml.xml_score(tests.test_musicxml.xml_note()), encoding='utf-8')
|
||||
output.mkdir()
|
||||
sentinel = output / 'existing'
|
||||
sentinel.write_text('unchanged')
|
||||
with self.assertRaisesRegex(ValueError, 'practice sources'):
|
||||
generate_practice_scores(source, output)
|
||||
generator.practice.generate.generate_practice_scores(source, output, rhythms=tests.rhythm_fixtures.library())
|
||||
self.assertEqual(list(output.iterdir()), [sentinel])
|
||||
self.assertEqual(sentinel.read_text(), 'unchanged')
|
||||
def test_empty_part_directory_fails(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
root = pathlib.Path(temporary)
|
||||
(root / '0001').mkdir()
|
||||
with self.assertRaisesRegex(ValueError, 'practice generator drift'):
|
||||
validate_practice_parts(root)
|
||||
generator.summary.validate_practice_parts(root)
|
||||
def test_songs_generate_only_authored_key_parts(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
source, output = Path(temporary) / 'songs', Path(temporary) / 'output'
|
||||
source, output = pathlib.Path(temporary) / 'songs', pathlib.Path(temporary) / 'output'
|
||||
source.mkdir()
|
||||
(source / 'song.xml').write_text(xml_score(xml_note('E', alter=-1), '<key><fifths>-3</fifths></key>'))
|
||||
self.assertEqual(generate_performance_scores(source, output), 3)
|
||||
(source / 'song.xml').write_text(tests.test_musicxml.xml_score(tests.test_musicxml.xml_note('E', alter=-1), '<key><fifths>-3</fifths></key>'))
|
||||
self.assertEqual(generator.arrange.generate.generate_performance_scores(source, output, rhythms=tests.rhythm_fixtures.library()), 3)
|
||||
self.assertEqual({p.name for p in output.iterdir()}, {'song-acoustic.json', 'song-electric.json', 'song-vocal.json'})
|
||||
for path in output.iterdir():
|
||||
metadata = json.loads(path.read_text())['metadata']
|
||||
|
||||
Reference in New Issue
Block a user