summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blc2/__init__.py2
-rw-r--r--blc2/functions/__init__.py7
-rw-r--r--blc2/functions/audio.py11
-rw-r--r--examples/workspace.xml4
-rw-r--r--tests/conftest.py22
-rw-r--r--tests/test_functions_audio.py17
-rw-r--r--tests/test_functions_scene.py43
7 files changed, 84 insertions, 22 deletions
diff --git a/blc2/__init__.py b/blc2/__init__.py
index e69de29..72a362d 100644
--- a/blc2/__init__.py
+++ b/blc2/__init__.py
@@ -0,0 +1,2 @@
+from .workspace import Workspace
+from .topology import Fixture
diff --git a/blc2/functions/__init__.py b/blc2/functions/__init__.py
index e69de29..921a6b0 100644
--- a/blc2/functions/__init__.py
+++ b/blc2/functions/__init__.py
@@ -0,0 +1,7 @@
+from .audio import Audio
+from .function import Function
+from .scene import Scene
+from .chaser import Chaser
+from .chaserstep import ChaserStep
+
+__all__ = ["Audio", "Function", "Scene", "Chaser", "ChaserStep"]
diff --git a/blc2/functions/audio.py b/blc2/functions/audio.py
index 9b22ba9..c30f279 100644
--- a/blc2/functions/audio.py
+++ b/blc2/functions/audio.py
@@ -139,8 +139,7 @@ class Audio(Function):
e.set("fade-in", str(self.fade_in))
e.set("fade-out", str(self.fade_out))
if self.filename is not None:
- filename = et.SubElement(e, BXW+"filename")
- filename.text = self.filename
+ e.set("filename", self.filename)
return e
@@ -169,13 +168,7 @@ class Audio(Function):
except ValueError:
raise LoadError("Invalid fade out")
- if len(e) > 1:
- raise LoadError("Audio tag can have at most one filename")
- elif len(e) == 1:
- filename, = e
- filename = filename.text
- else:
- filename = None
+ filename = e.get("filename")
return cls(w=w, id_=id_, name=name, filename=filename, fade_in=fade_in,
fade_out=fade_out)
diff --git a/examples/workspace.xml b/examples/workspace.xml
index 3fa2d70..c30e8ef 100644
--- a/examples/workspace.xml
+++ b/examples/workspace.xml
@@ -31,9 +31,7 @@
<value fixture="0" channel="2">127</value>
</function>
- <function type="Audio" id="1" name="Intro" fade-in="0" fade-out="0">
- <filename>tests/silence.m4a</filename>
- </function>
+ <function type="Audio" id="1" name="Intro" fade-in="0" fade-out="0" filename="tests/silence.m4a"/>
<function type="Chaser" id="2" name="Chaser 1" advance-mode="Loop">
<step id="3" name="Step 1" fade-in="10" fade-out="100" duration-mode="Manual" duration="infty" function="0"/>
diff --git a/tests/conftest.py b/tests/conftest.py
index 1a9af58..896a2ba 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -19,15 +19,27 @@ def aws():
return w
def elements_equal(e1, e2):
- if e1.tag != e2.tag: return False
- if e1.text != e2.text: return False
- if e1.tail.strip() != e2.tail.strip(): return False
- if e1.attrib != e2.attrib: return False
- if len(e1) != len(e2): return False
+ """Determine if two XML elements are equal."""
+ if e1.tag != e2.tag:
+ print("tag", e1.tag, e2.tag)
+ return False
+ if ("" if e1.text is None else e1.text).strip("\r\n\t ") != ("" if e2.text is None else e2.text).strip("\r\n\t "):
+ print("text", repr(e1.text), repr(e2.text))
+ return False
+ if ("" if e1.tail is None else e1.tail).strip("\r\n\t ") != ("" if e2.tail is None else e2.tail).strip("\r\n\t "):
+ print("tail", repr(e1.tail), repr(e2.tail))
+ return False
+ if e1.attrib != e2.attrib:
+ print("attrib", repr(e1.attrib), repr(e2.attrib))
+ return False
+ if len(e1) != len(e2):
+ print("len", len(e1), len(e2))
+ return False
return all(elements_equal(c1, c2) for c1, c2 in zip(e1, e2))
@pytest.fixture
def test_xml_eq():
+ """Use for testing serialization functions."""
def inner(e: et.Element, s: str):
return elements_equal(e, et.fromstring(s))
return inner
diff --git a/tests/test_functions_audio.py b/tests/test_functions_audio.py
index 35d548a..5aaec5a 100644
--- a/tests/test_functions_audio.py
+++ b/tests/test_functions_audio.py
@@ -3,11 +3,14 @@
import pytest
from blc2.functions.audio import Audio
+from blc2.constants import BXW
def test_audio(aws):
a = Audio(aws)
a.fade_out = 1000
+ a.fade_out = 1000
+ a.fade_in = 1000
a.fade_in = 1000
a.filename = "nonexistant"
@@ -59,3 +62,17 @@ def test_audio(aws):
a.filename = None
assert a.duration == 0
assert a.actual_duration == 0
+
+def test_audio_serialize(aws, test_xml_eq):
+ a1 = Audio(aws, id_=123, name="Test Audio 1", fade_out=100, filename="test.wav")
+ a2 = Audio(aws, id_=124, name="Test Audio 2", filename=None)
+
+ test = (a1, a2)
+ success = [
+"""<function type="Audio" xmlns="{}" id="123" name="Test Audio 1" fade-in="0" fade-out="100" filename="test.wav"/>""",
+"""<function type="Audio" xmlns="{}" id="124" name="Test Audio 2" fade-in="0" fade-out="0"/>"""
+ ]
+
+ for case, s in zip(test, success):
+ s = s.replace('\n', "").format(BXW.strip("{}"))
+ assert test_xml_eq(case.serialize(), s)
diff --git a/tests/test_functions_scene.py b/tests/test_functions_scene.py
index 77b2d6f..4ce328a 100644
--- a/tests/test_functions_scene.py
+++ b/tests/test_functions_scene.py
@@ -1,9 +1,12 @@
-import pytest
+"""Tests for scene primitive."""
import xml.etree.ElementTree as et
+import pytest
+
from blc2.functions.scene import Scene
from blc2.constants import INFTY, BXW
+from blc2.exceptions import LoadError
def test_scene(aws):
"""Test creation and modification of scenes."""
@@ -85,11 +88,12 @@ def test_scene(aws):
s1[c1] = -256
assert s1[c1] == 10
+ assert s1.copy_data(None) is None
+
del s1[c4]
del s1[c4]
def test_scene_serialize(aws, test_xml_eq):
- return
c1, c2, c3, c4 = aws.fixtures[0].channels
s = Scene(aws, id_=123, name="Test Scene", values={c1: 1, c2: 2, c3: 3, c4: 4})
@@ -103,10 +107,39 @@ def test_scene_serialize(aws, test_xml_eq):
<value fixture="{f3}" channel="{i3}">3</value>
<value fixture="{f4}" channel="{i4}">4</value>
</function>
-""".format(bxw=BXW.strip("{}"), f1=f1, f2=f2, f3=f3, f4=f4, i1=i1,i2=i2,i3=i3,i4=i4)
+""".format(bxw=BXW.strip("{}"), f1=f1, f2=f2, f3=f3, f4=f4, i1=i1,i2=i2,i3=i3,i4=i4).replace("\n", "")
et.register_namespace("", BXW)
- print(et.tostring(e, encoding="utf-8"))
- print(expected)
assert test_xml_eq(e, expected)
+
+def test_scene_deserialize(aws, test_xml_eq):
+ fail = [
+ """<function xmlns={} type="asdf"/>""",
+ """<asdf/>""",
+ """<function xmlns={} type="Scene" id="asdf"/>""",
+ """<function xmlns={} type="Scene" id="123" name="Test Scene">
+ <asdf/></function>""",
+ """<function xmlns={} type="Scene" id="123" name="Test Scene">
+ <value/></function>""",
+ """<function xmlns={} type="Scene" id="123" name="Test Scene">
+ <value fixture="10" channel="45"/></function>""",
+ """<function xmlns={} type="Scene" id="123" name="Test Scene">
+ <value fixture="0" channel="10"/></function>""",
+ """<function xmlns={} type="Scene" id="123" name="Test Scene">
+ <value fixture="0" channel="1"/></function>""",
+ ]
+
+ for case in fail:
+ case = case.format('"'+BXW.strip("{}")+'"')
+ with pytest.raises(LoadError):
+ Scene.deserialize(aws, et.fromstring(case))
+
+
+ case = """<function xmlns={} type="Scene" id="123" name="Test Scene">
+ <value fixture="0" channel="0">123</value></function>"""
+ case = case.format('"'+BXW.strip("{}")+'"').replace('\n', "")
+
+ s = Scene.deserialize(aws, et.fromstring(case))
+
+ assert test_xml_eq(s.serialize(), case)