From 5dc21ef69f6d72bdfb796a7a75dcd185d4cb997f Mon Sep 17 00:00:00 2001 From: Ben Connors Date: Sun, 1 Dec 2019 14:30:52 -0500 Subject: Some library commenting --- blc2/__init__.py | 12 +++++++++++- blc2/exceptions.py | 2 +- blc2/functions/__init__.py | 31 +++++++++++++++++++++++++++++-- blc2/functions/join.py | 29 +++++++++++++++++++++++++++-- blc2/interfaces.py | 3 ++- 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/blc2/__init__.py b/blc2/__init__.py index 24a8009..6ca795f 100644 --- a/blc2/__init__.py +++ b/blc2/__init__.py @@ -1,4 +1,14 @@ +"""BLC2 library. + +This library implements a relatively basic lighting design and rendering system. It is +inspired by QLC+, but extends functions to make them simpler, more featureful, and more +oriented to theatrical productions. + +Note that this library currently permits creating circular references, but these have no +physical meaning and cannot be saved or loaded from the disk. Do not make them. +""" + from .workspace import Workspace from .topology import Fixture -__version__ = "v0.0.1" +__version__ = "v0.0.2" diff --git a/blc2/exceptions.py b/blc2/exceptions.py index 1b950e8..4434ebd 100644 --- a/blc2/exceptions.py +++ b/blc2/exceptions.py @@ -1,4 +1,4 @@ """Module containing common exceptions.""" class LoadError(Exception): - pass + """Exception for errors in loading a workspace.""" diff --git a/blc2/functions/__init__.py b/blc2/functions/__init__.py index 921a6b0..8b84835 100644 --- a/blc2/functions/__init__.py +++ b/blc2/functions/__init__.py @@ -1,7 +1,34 @@ -from .audio import Audio +"""Function sub-module. + +This module provides an interface for and implementation of the basic lighting functions. + +`Function` provides the interface that all functions must implement as well as some +convenience functions and implementations to simplify writing implementations. + +Two "primitive" functions are provided: + +`Audio` provides the primitive function for audio cues, each capable of representing a +single audio file. + +`Scene` provides the primitive function for lighting cues, each capable of representing a +single static lighting cue. + +Two "composite" functions are provided: + +`Chaser` provides the ability to construct sequences of functions to be run in turn. + +`Join` provides the ability to "join" functions together and run them simultaneously, e.g. +for running cues where the lighting and sound cues must be fired simultaneously. + +These composite functions may be nested, i.e. a `Chaser` may have another `Chaser` as one +of its steps. +""" + from .function import Function +from .audio import Audio from .scene import Scene from .chaser import Chaser from .chaserstep import ChaserStep +from .join import Join -__all__ = ["Audio", "Function", "Scene", "Chaser", "ChaserStep"] +__all__ = ["Audio", "Function", "Scene", "Chaser", "ChaserStep", "Join"] diff --git a/blc2/functions/join.py b/blc2/functions/join.py index 8c911bf..3d23480 100644 --- a/blc2/functions/join.py +++ b/blc2/functions/join.py @@ -2,14 +2,19 @@ import xml.etree.ElementTree as et -from ..constants import JOIN, INFTY, BXW +from ..constants import JOIN, BXW from .function import Function from ..exceptions import LoadError class Join(Function): """Class for joins. - Joins merge multiple functions into one (e.g. audio and lighting). + Joins merge multiple functions into one (e.g. audio and lighting). It takes the + duration and actual duration of the longest function (it may be a different function + in the two cases). + + For convenience, Join's interface is very similar to that of Chaser, with only some + functions missing. """ type = JOIN @@ -60,6 +65,12 @@ class Join(Function): self._recalculate() def get_data(self, params=None): + """Get the data for the functions. + + :param params: parameters to pass to the composite get_data functions. Must be + either `None` or provide a value for each composite function, which will be starred + when passed to the functions + """ if params is not None: if len(params) != len(self._steps): raise ValueError("Must have same number of parameters as steps!") @@ -71,9 +82,16 @@ class Join(Function): @property def steps(self): + """Return a tuple of the Join's steps.""" return tuple(self._steps) def add_step(self, s): + """Add the given step to the Join. + + :param s: the step to add, either a Function or an integer. + """ + if isinstance(s, int): + s = self.w.functions[s] if s.id in (i.id for i in self._steps): raise ValueError("Already added") self._steps.append(s) @@ -83,6 +101,11 @@ class Join(Function): self.w.register_function_delete_callback(s, self._recalculate, self) def delete_step(self, s, index=False): + """Delete a step from the Join. + + :param s: the step to delete, either a Function or an integer. + :param index: whether or not `s` is an index of self.steps or a Function/ID. + """ if index: s = self._steps[s] elif isinstance(s, int): @@ -100,11 +123,13 @@ class Join(Function): lc = {c: 0 for c in self._scope} ac = [] + ## Render and mix the composite renders for i, s in enumerate(self.steps): lcs, acs, data[i] = s.render(t, data=data[i]) for c, v in lcs: if v > lc[c]: lc[c] = v + ## Convolute the audio hash ac.extend(((hash((self._id, aid)), *others) for aid, *others in acs)) return tuple(lc.items()), tuple(ac), data diff --git a/blc2/interfaces.py b/blc2/interfaces.py index e0a904a..a4af83c 100644 --- a/blc2/interfaces.py +++ b/blc2/interfaces.py @@ -7,6 +7,7 @@ class XMLSerializable(metaclass=ABCMeta): """Interface for XML-serializable Workspace components.""" @staticmethod def int_or_none(v): + """Convert the argument to an int if possible; otherwise return `None`.""" if v is None: return None @@ -21,7 +22,7 @@ class XMLSerializable(metaclass=ABCMeta): def indent(elem, indent=4, level=0): """Pretty-indent the XML tree.""" i = "\n" + level*(indent*' ') - if len(elem) > 0: + if elem: if not elem.text or not elem.text.strip(): elem.text = i + (' '*indent) if not elem.tail or not elem.tail.strip(): -- cgit v1.2.3