"""Cheap valid notes for renderer/packaging tests; never a production fallback. Learned decoding and authored-repertoire tests separately use the real path. """ import fractions import pathlib import unittest.mock import generator.production import generator.vocabulary import generator.harmonic_time import generator.solo.types import generator.solo.placement import generator.solo.profiles import generator.solo.learned import generator.solo.harmonic import dataclasses import generator.solo.expressions import generator.harmony def compose(analysis, measures, part, end, *, initial=None, start=fractions.Fraction(), **kwargs): spans = tuple(dataclasses.replace(s, start=s.start + start, end=s.end + start) for s in generator.harmonic_time.read({'measures': measures}, initial=initial)) h = generator.solo.harmonic.Harmony(spans) notes = [] for s in h.spans: a, b = max(start, s.start), min(end, s.end) if a >= b or s.chord == 'N.C.': continue number = next(n for n in range(55, 72) if n % 12 in s.roles.basic) chord = generator.solo.expressions.parsed_chord(s.chord) pitch = next(generator.solo.expressions.degree_pitch(chord, d, x, number) for d, x in generator.harmony.degrees(chord).items() if generator.solo.expressions.degree_pitch(chord, d, x, number).number() == number) notes.append(generator.solo.types.Note(a, b, pitch, event_id=str(a))) placed = generator.solo.placement.place(tuple(notes), analysis.tempo)[1] if notes else () return generator.solo.types.Solo(part, spans, (generator.solo.types.Phrase('fixture', start, end, placed, 'test', 'test', 'handoff'),), analysis.tempo, end, profile=generator.solo.profiles.for_part(part), start=start) def install(test): resources = generator.vocabulary.load() predictor = generator.solo.learned.Model.load(pathlib.Path(__file__).resolve().parents[1] / 'data/models/solo.json') tree = generator.production.generate_tree def serial(*args, **kwargs): kwargs['jobs'] = 1 return tree(*args, **kwargs) test.enterContext(unittest.mock.patch('generator.production.generate_tree', side_effect=serial)) test.enterContext(unittest.mock.patch('generator.vocabulary.load', return_value=resources)) test.enterContext(unittest.mock.patch('generator.solo.authored.lookup', return_value=None)) test.enterContext(unittest.mock.patch('generator.composition._solo_model', return_value=predictor)) test.enterContext(unittest.mock.patch('generator.composition._resource_key', return_value={'model': 'synthetic infrastructure fixture'})) test.enterContext(unittest.mock.patch('generator.solo.composer.compose', side_effect=compose))