def test_speaker_reset_by_dedent(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ One --- [P]_ I'm speaking. Still speaking. Not any more. """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([self.personae[0]])) model = script.run() one, two, three = list(model) self.assertTrue(one[1].persona) self.assertTrue(two[1].persona) self.assertIsNone(three[1].persona, three)
def test_fx_bad_substitution(self): content = textwrap.dedent(""" Scene ~~~~~ Shot ---- .. fx:: turberfield.dialogue.sequences.battle_royal barks/|P_NONE|/surprise.wav :offset: 0 :duration: 3000 :loop: 1 """) ensemble = copy.deepcopy(PropertyDirectiveTests.personae) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([ensemble[0]])) model = script.run() shot, cue = next(iter(model)) self.assertEqual("turberfield.dialogue.sequences.battle_royal", cue.package) self.assertEqual("barks//surprise.wav", cue.resource) self.assertEqual(0, cue.offset) self.assertEqual(3000, cue.duration) self.assertEqual(1, cue.loop)
def test_property_getter_indent(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- [P]_ Hi, I'm |P_FIRSTNAME|. |P_SURNAME|. .. |P_FIRSTNAME| property:: P.name.firstname .. |P_SURNAME| property:: P.name.surname """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([self.personae[0]])) model = iter(script.run()) shot, line = next(model) self.assertEqual("scene", shot.scene) self.assertEqual("shot", shot.name) self.assertEqual("Hi, I'm William.", line.text) self.assertTrue(line.persona) shot, line = next(model) self.assertTrue(line.persona, line)
def test_fx_label_substitution(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- .. fx:: turberfield.dialogue.sequences.battle_royal faces/|P_NAME|/surprise.png :offset: 0 :duration: 3000 :label: |P_NAME| looks surprised .. |P_NAME| property:: P.name.firstname """) ensemble = copy.deepcopy(PropertyDirectiveTests.personae) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([ensemble[0]])) model = script.run() shot, cue = next(iter(model)) self.assertEqual("turberfield.dialogue.sequences.battle_royal", cue.package) self.assertEqual("faces/William/surprise.png", cue.resource) self.assertEqual(0, cue.offset) self.assertEqual(3000, cue.duration) self.assertEqual("William looks surprised", cue.label)
def test_single_fx_splits_frame(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- [P]_ |P_FIRSTNAME| says, "{0}". .. fx:: logic slapwhack.wav :offset: 0 :duration: 3000 :loop: 1 [P]_ |P_FIRSTNAME| says, "{0}". .. |P_FIRSTNAME| property:: P.name.firstname """.format("Hello")) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select(self.ensemble)) rv = list( Handler.frames(None, HandlerTests.dialogue(script.run()), dwell=0.3, pause=1)) self.assertEqual(2, len(rv)) self.assertTrue(all(i for i in rv)) self.assertIsInstance(rv[1][0].dialogue, Model.Audio)
def test_shot_duplicates_scene(self): content = textwrap.dedent( """ Scene 1 ======= Shot 1 ------ Text Scene 2 ======= Scene 1 ------- Text """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([])) model = list(script.run()) shot, line = next(iter(model)) self.assertEqual("scene 1", shot.scene) self.assertEqual("shot 1", shot.name)
def test_exact_matching(self): content = textwrap.dedent(""" .. entity:: WHATEVER Test exact ~~~~~~~~~~ One --- .. condition:: WHATEVER.value 1 One. Two --- .. condition:: WHATEVER.value 2 Two. """) script = SceneScript("inline", doc=SceneScript.read(content)) selection = script.select([DataObject(value=1)]) self.assertTrue(all(selection.values())) script.cast(selection) model = script.run() conditions = [l for s, l in model if isinstance(l, Model.Condition)] self.assertEqual(2, len(conditions)) self.assertTrue(Performer.allows(conditions[0])) self.assertFalse(Performer.allows(conditions[1]))
def test_set_refresh_enabled(self): text = textwrap.dedent(""" .. entity:: THEME_SETTINGS Scene ===== one --- .. property:: THEME_SETTINGS.punchline-states-refresh none two --- .. property:: THEME_SETTINGS.punchline-states-refresh inherit """) theme = Theme() script = SceneScript("inline", doc=SceneScript.read(text)) script.cast(script.select([theme.settings])) model = ModelAssignsStrings(script.fP, script.doc) script.doc.walkabout(model) presenter = Presenter(model) self.assertEqual(2, len(presenter.frames)) presenter.animate(presenter.frames[0]) self.assertEqual("none", theme.refresh_target) presenter.animate(presenter.frames[1]) self.assertEqual("inherit", theme.refresh_target)
def test_property_getter_fields(self): content = textwrap.dedent(""" .. |VERSION| property:: turberfield.dialogue.__version__ :copyright: 2017 :version: |VERSION| """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([self.personae[0]])) model = script.run() metadata = dict(model.metadata) self.assertIn("copyright", metadata) self.assertIn("version", metadata) self.assertEqual(2, metadata["version"].count("."), metadata)
def test_missing_citations(self): content = textwrap.dedent(""" [NARRATOR]_ And they lived happily ever after. """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([])) model = list(script.run()) items = list(model) self.assertEqual(1, len(items), items) shot, line = items[0] self.assertIs(None, shot.scene) self.assertIs(None, shot.name) self.assertEqual("narrator", line.persona)
def test_dialogue_at_level_1(self): content = textwrap.dedent(""" .. entity:: P Scene ===== [P]_ You can call me |P_NICKNAME|. .. |P_NICKNAME| property:: P.nickname """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([self.personae[0]])) model = list(script.run()) self.assertFalse(model)
def build_model(text, theme, uid=None, path: pathlib.Path = None, model_type=ModelAssignsStrings): theme.settings.id = uid or theme.settings.id path = path or pathlib.Path(".") SceneScript.settings.raw_enabled = True SceneScript.settings.file_insertion_enabled = True SceneScript.settings.input_encoding = "utf-8" SceneScript.settings.input_encoding_error_handler = "replace" script = SceneScript(path, doc=SceneScript.read(text)) ensemble = list(Eponymous.create(script)) + [theme.settings] script.cast(script.select(ensemble)) model = model_type(script.fP, script.doc) script.doc.walkabout(model) return model
def test_dialogue_at_level_0(self): content = textwrap.dedent(""" .. entity:: P [P]_ You can call me |P_NICKNAME|. .. |P_NICKNAME| property:: P.nickname """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([self.personae[0]])) model = list(script.run()) shot, line = next(iter(model)) self.assertIs(None, shot.scene) self.assertIs(None, shot.name) self.assertIn(line.text, ("You can call me Fuzzer.", "You can call me Q.A."))
def test_property_setter_bad_substitution(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- .. property:: P.state |S_ID| """) ensemble = copy.deepcopy(PropertyDirectiveTests.personae) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([ensemble[0]])) model = script.run() p = next(l for s, l in model if isinstance(l, Model.Property)) self.assertEqual("state", p.attr) self.assertIs(None, p.val)
def test_frame_from_dialogue(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- [P]_ |P_FIRSTNAME| says, "{0}". .. |P_FIRSTNAME| property:: P.name.firstname """.format("Hello")) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select(self.ensemble)) rv = Frame.items(FrameTests.dialogue(script.run()), dwell=0.3, pause=1) self.fail(list(rv))
def test_property_setter_enum(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- .. property:: P.state turberfield.dialogue.test.test_model.SelectTests.Aggression.calm """) ensemble = copy.deepcopy(PropertyDirectiveTests.personae) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([ensemble[0]])) model = script.run() p = next(l for s, l in model if isinstance(l, Model.Property)) self.assertEqual("state", p.attr) self.assertEqual(str(SelectTests.Aggression.calm), str(p.val)) setattr(p.object, p.attr, p.val)
def test_condition_evaluation_two(self): effects = [ ConditionDirectiveTests.Rain().set_state( ConditionDirectiveTests.Weather.quiet), ConditionDirectiveTests.Sleet().set_state( ConditionDirectiveTests.Weather.stormy), ConditionDirectiveTests.Snow().set_state( ConditionDirectiveTests.Weather.stormy), ] script = SceneScript("inline", doc=SceneScript.read(self.content)) selection = script.select(effects) self.assertTrue(all(selection.values())) script.cast(selection) model = script.run() conditions = [l for s, l in model if isinstance(l, Model.Condition)] self.assertEqual(4, len(conditions)) self.assertTrue(Performer.allows(conditions[0])) self.assertFalse(Performer.allows(conditions[1])) self.assertTrue(Performer.allows(conditions[2])) self.assertFalse(Performer.allows(conditions[3]))
def test_property_setter_object(self): content = textwrap.dedent(""" .. entity:: P .. entity:: S Scene ~~~~~ Shot ---- .. property:: P.id S.id """) ensemble = copy.deepcopy(PropertyDirectiveTests.personae) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select(ensemble)) model = script.run() p = [l for s, l in model if isinstance(l, Model.Property)][-1] self.assertEqual(ensemble[0], p.object) self.assertEqual("id", p.attr) self.assertIsInstance(p.val, uuid.UUID) self.assertEqual(p.val, ensemble[1].id)
def test_property_setter_good_substitution(self): content = textwrap.dedent(""" .. entity:: P .. entity:: S .. |S_ID| property:: S.id.int Scene ~~~~~ Shot ---- .. property:: P.state |S_ID| """) ensemble = copy.deepcopy(PropertyDirectiveTests.personae) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select(ensemble)) model = script.run() p = [l for s, l in model if isinstance(l, Model.Property)][-1] self.assertEqual("state", p.attr) self.assertIsInstance(p.val, int)
def test_regex_matching_state(self): content = textwrap.dedent(""" .. entity:: WHATEVER Test exact ~~~~~~~~~~ Even ---- .. condition:: WHATEVER.state ([02468]) Even. Odd --- .. condition:: WHATEVER.state ([13579]) Odd. """) obj = Stateful() script = SceneScript("inline", doc=SceneScript.read(content)) selection = script.select([obj]) self.assertTrue(all(selection.values())) script.cast(selection) model = script.run() conditions = [l for s, l in model if isinstance(l, Model.Condition)] self.assertEqual(2, len(conditions)) self.assertTrue(Performer.allows(conditions[0]), conditions[0]) self.assertFalse(Performer.allows(conditions[1])) obj.state = 1 self.assertFalse(Performer.allows(conditions[0]), conditions[0]) self.assertTrue(Performer.allows(conditions[1]))
def test_init_from_setter(self): text = textwrap.dedent(""" .. entity:: THEME_SETTINGS Scene ===== Shot ---- .. property:: THEME_SETTINGS.midtone hsl(86, 93%, 12%, 0.7) """) uid = uuid.uuid4() theme = type("Fake", (), {})() theme.settings = Settings(id=uid) script = SceneScript("inline", doc=SceneScript.read(text)) script.cast(script.select([theme.settings])) model = ModelAssignsStrings(script.fP, script.doc) script.doc.walkabout(model) self.assertEqual(1, len(model.shots)) shot = model.shots[0] self.assertEqual(1, len(shot.items)) setter = shot.items[0] self.assertIsInstance(setter, Model.Property)
def test_frame_from_dialogue(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- [P]_ |P_FIRSTNAME| says, "{0}". .. |P_FIRSTNAME| property:: P.name.firstname """.format("Hello")) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select(self.ensemble)) rv = list( Handler.frames(None, HandlerTests.dialogue(script.run()), dwell=0.3, pause=1)) self.assertEqual(1, len(rv))
def test_nickname_getter(self): content = textwrap.dedent(""" .. entity:: P Scene ~~~~~ Shot ---- [P]_ You can call me |P_NICKNAME|. .. |P_NICKNAME| property:: P.nickname """) script = SceneScript("inline", doc=SceneScript.read(content)) script.cast(script.select([self.personae[0]])) model = list(script.run()) shot, line = next(iter(model)) self.assertEqual("scene", shot.scene) self.assertEqual("shot", shot.name) self.assertIn(line.text, ("You can call me Fuzzer.", "You can call me Q.A."))
def test_resource_activation(self): references = [ ResourceTests.Resource(uuid.uuid4(), p, "phrases/{0}".format(n + 1)) for n, p in enumerate(ResourceTests.phrases) ] references.extend([ ResourceTests.Guru(name="Mr Tim Peters"), Player(name="tundish"), ResourceTests.Session() ]) content = textwrap.dedent(""" .. entity:: GURU :types: turberfield.dialogue.test.test_resource.ResourceTests.Guru .. entity:: SESSION :types: turberfield.dialogue.test.test_resource.ResourceTests.Session .. entity:: STUDENT :types: turberfield.dialogue.test.test_resource.ResourceTests.Player .. entity:: PHRASE :types: turberfield.dialogue.test.test_resource.ResourceTests.Resource Scene ~~~~~ Shot ---- [GURU]_ Remember, |S_FIRSTNAME|. |PHRASE_LABEL|. .. Property attributes accept only integers and importable objects .. property:: SESSION.addition |PHRASE_ID| .. Use a Memory directive to generate an event containing formatted strings. .. Here, an integer state is used for 'learned'. A 0 could signify 'forgot'. .. memory:: 1 :subject: SESSION :object: PHRASE |S_FIRSTNAME| learned phrase /|SESSION_ID|/|PHRASE_PATH| (|PHRASE_LABEL|). .. |S_FIRSTNAME| property:: STUDENT.name.firstname .. |SESSION_ID| property:: SESSION.id.hex .. |PHRASE_ID| property:: PHRASE.id.int .. |PHRASE_LABEL| property:: PHRASE.label .. |PHRASE_PATH| property:: PHRASE.path """) script = SceneScript("inline", doc=SceneScript.read(content)) cast = script.select(references, relative=True) self.assertTrue(all(cast.values())) script.cast(cast) model = script.run() items = list(model) p = [l for s, l in model if isinstance(l, Model.Property)][-1] self.assertEqual(references[0].id.int, p.val)
def test_handler_frames_conditional_dialogue(self): content = textwrap.dedent(""" .. entity:: PLAYER :types: carmen.logic.Player .. entity:: NARRATOR :types: carmen.logic.Narrator Feels ~~~~~ Hungry ------ .. condition:: PLAYER.state carmen.types.Time.day_lunch [NARRATOR]_ You're hungry. [NARRATOR]_ Nom nom nom. Tired ----- .. condition:: PLAYER.state carmen.types.Time.eve [NARRATOR]_ You're tired. [NARRATOR]_ ZZZZZZZZ. """) script = SceneScript("inline", doc=SceneScript.read(content)) ensemble = [Player(name="test").set_state(Time.day_lunch), Narrator()] script.cast(script.select(ensemble)) scene = list(HandlerTests.dialogue(script.run())) conditions = [i for i in scene if isinstance(i, Model.Condition)] self.assertEqual(2, len(conditions)) self.assertTrue(Performer.allows(conditions[0])) self.assertFalse(Performer.allows(conditions[1])) rv = list(Handler.frames(None, scene, dwell=0.3, pause=1)) self.assertEqual(2, len(rv), rv) self.assertIsInstance(rv[0][0].dialogue, Model.Line) self.assertEqual(0, rv[0][0].offset) self.assertEqual(1.3, rv[0][0].duration) self.assertEqual(1.3, rv[0][1].offset) self.assertEqual(1.6, rv[0][1].duration) self.assertAlmostEqual(2.9, Handler.refresh(rv[0], min_val=0)) self.assertIsInstance(rv[1][0].dialogue, Model.Line) self.assertEqual(0, rv[1][0].offset) self.assertEqual(1.3, rv[1][0].duration) self.assertEqual(1.3, rv[1][1].offset) self.assertEqual(1.0, rv[1][1].duration) self.assertAlmostEqual(2.3, Handler.refresh(rv[1], min_val=0)) # A reminder that conditions require exact matches, unlike the # prefix-based casting by state ensemble[0].set_state(Time.eve_midnight) scene = list(HandlerTests.dialogue(script.run())) conditions = [i for i in scene if isinstance(i, Model.Condition)] self.assertEqual(2, len(conditions)) self.assertFalse(Performer.allows(conditions[0])) self.assertFalse(Performer.allows(conditions[1]))