Skip to content

Runner state setting and getting #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
66 changes: 62 additions & 4 deletions tests/test_shortcuts.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import os
from .context import YarnRunner

compiled_yarn_f1 = open(os.path.join(os.path.dirname(
__file__), '../examples/yarn1/shortcuts.yarnc'), 'rb')
names_csv_f1 = open(os.path.join(os.path.dirname(
__file__), '../examples/yarn1/shortcuts.csv'), 'r')
compiled_yarn_fname1 = os.path.join(os.path.dirname(
__file__), '../examples/yarn1/shortcuts.yarnc')
compiled_yarn_f1 = open(compiled_yarn_fname1, 'rb')
names_csv_fname1 = os.path.join(os.path.dirname(
__file__), '../examples/yarn1/shortcuts.csv')
names_csv_f1 = open(names_csv_fname1, 'r')
compiled_yarn_f2 = open(os.path.join(os.path.dirname(
__file__), '../examples/yarn2/shortcuts.yarnc'), 'rb')
names_csv_f2 = open(os.path.join(os.path.dirname(
Expand Down Expand Up @@ -41,6 +43,62 @@ def test_shortcuts1():
assert runner1.current_node == 'Start'


def test_shortcuts2():
compiled_yarn_f3 = open(compiled_yarn_fname1, "rb")
names_csv_f3 = open(names_csv_fname1, "r")
runner3 = YarnRunner(compiled_yarn_f3, names_csv_f3)
assert "This is a test of shortcut functionality." == runner3.get_line()
assert not runner3.has_line()
assert not runner3.finished
runner3.choose(1)

assert "Option 2 selected." == runner3.get_line()
assert runner3.has_line()
assert "This is the last line." == runner3.get_line()
assert not runner3.has_line()
assert runner3.finished
assert runner3.current_node == 'Start'


def test_shortcuts_json():
compiled_yarn_f3 = open(compiled_yarn_fname1, "rb")
names_csv_f3 = open(names_csv_fname1, "r")
runner3 = YarnRunner(compiled_yarn_f3, names_csv_f3)
assert "This is a test of shortcut functionality." == runner3.get_line()
assert not runner3.has_line()
assert not runner3.finished

choices = runner3.get_choices()

assert len(choices) == 4
assert choices[0]["text"] == "Option 1"
assert choices[1]["text"] == "Option 2"
assert choices[2]["text"] == "Option 3"
assert choices[3]["text"] == "Option 4"

dump = runner3.save()
compiled_yarn_f4 = open(compiled_yarn_fname1, "rb")
names_csv_f4 = open(names_csv_fname1, "r")
runner4 = YarnRunner(compiled_yarn_f4, names_csv_f4)
runner4.load(dump)

choices = runner4.get_choices()

assert len(choices) == 4
assert choices[0]["text"] == "Option 1"
assert choices[1]["text"] == "Option 2"
assert choices[2]["text"] == "Option 3"
assert choices[3]["text"] == "Option 4"

runner4.choose(0)

assert "Option 1 selected." == runner4.get_line()
assert runner4.has_line()
assert "This is the last line." == runner4.get_line()
assert not runner4.has_line()
assert runner4.finished
assert runner4.current_node == 'Start'

def test_start_node_text2():
assert "This is a test of shortcut functionality." == runner2.get_line()
assert not runner2.has_line()
Expand Down
40 changes: 37 additions & 3 deletions yarnrunner_python/runner.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from typing import Any, Dict, List, Optional, Union

import csv
import re
import json
from warnings import warn
from google.protobuf import json_format
from .yarn_spinner_pb2 import Program as YarnProgram, Instruction
from .yarn_spinner_pb2 import Program as YarnProgram, Instruction # type: ignore
from .vm_std_lib import functions as std_lib_functions


Expand Down Expand Up @@ -33,6 +36,37 @@ def __init__(self, compiled_yarn_f, names_csv_f, autostart=True, enable_tracing=
if autostart:
self.resume()

def save(self) -> str:
dump = {
# "program_version": hash(self._compiled_yarn) + hash(self.string_lookup_table),
"visits": self.visits,
"variables": self.variables,
"current_node": self.current_node,
"line_buffer": self._line_buffer,
"option_buffer": self._option_buffer,
"vm_data_stack": self._vm_data_stack,
"vm_instruction_stack": [json.loads(json_format.MessageToJson(i)) for i in self._vm_instruction_stack],
"program_counter": self._program_counter,
"previous_instruction": json.loads(json_format.MessageToJson(self._previous_instruction)),
"finished": self.finished
}
return json.dumps(dump)

def load(self, data: str) -> None:
# if not data or "program_version" not in data or data["program_version"] != hash(self._compiled_yarn) + hash(self.string_lookup_table):
# raise ValueError("Mismatched yarn version")
dump = json.loads(data)
self.visits = dump["visits"]
self.variables = dump["variables"]
self.current_node = dump["current_node"]
self._line_buffer = dump["line_buffer"]
self._option_buffer = dump["option_buffer"]
self._vm_data_stack = dump["vm_data_stack"]
self._vm_instruction_stack = [json_format.Parse(json.dumps(i), Instruction()) for i in dump["vm_instruction_stack"]]
self._program_counter = dump["program_counter"]
self._previous_instruction = json_format.Parse(json.dumps(dump["previous_instruction"]), Instruction())
self.finished = dump["finished"]

def __construct_string_lookup_table(self):
self.string_lookup_table = dict()

Expand All @@ -48,7 +82,7 @@ def resume(self):
self.paused = False
self.__process_instruction()

def __lookup_string(self, string_key):
def __lookup_string(self, string_key) -> str:
if string_key not in self.string_lookup_table:
raise Exception(
f"{string_key} is not a key in the string lookup table.")
Expand Down Expand Up @@ -242,7 +276,7 @@ def sanitize_quotes(arg):
if type(ret) is str:
self._line_buffer.append(ret)

def __add_option(self, instruction):
def __add_option(self, instruction) -> None:
title_string_key = instruction.operands[0].string_value
choice_path = instruction.operands[1].string_value

Expand Down