Source code for turberfield.dialogue.performer

#!/usr/bin/env python3
# encoding: UTF-8

# This file is part of turberfield.
#
# Turberfield is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Turberfield is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with turberfield.  If not, see <http://www.gnu.org/licenses/>.

from collections import defaultdict

from turberfield.dialogue.model import Model
from turberfield.dialogue.model import SceneScript


[docs]class Performer: @staticmethod def next(folders, ensemble, strict=True, roles=1): for folder in folders: scripts = SceneScript.scripts(**folder._asdict()) for script in scripts: with script as dialogue: selection = dialogue.select(ensemble, roles=roles) if all(selection.values()): return (script, selection) elif not strict and any(selection.values()): return (script, selection) else: return None @staticmethod def react(obj): if isinstance(obj, Model.Property): if obj.object is not None: setattr(obj.object, obj.attr, obj.val) return obj @property def stopped(self): """Is `True` when none of the folders can be cast, `False` otherwise.""" return not bool(self.next(self.folders, self.ensemble))
[docs] def __init__(self, folders, ensemble): """An object which can select actors for a scene and run a performance. :param folders: A sequence of :py:class:`~turberfield.dialogue.model.SceneScript.Folder` objects. :param ensemble: A sequence of Python objects. """ self.folders = folders self.ensemble = ensemble self.metadata = defaultdict(list) self.shots = [] self.script = None self.selection = None
[docs] def run(self, react=True, strict=True, roles=1): """Select a cast and perform the next scene. :param bool react: If `True`, then Property directives are executed at the point they are encountered. Pass `False` to skip them so they can be enacted later on. :param bool strict: Only fully-cast scripts to be performed. :param int roles: Maximum number of roles permitted each character. This method is a generator. It yields events from the performance. """ try: self.script, self.selection = self.next( self.folders, self.ensemble, strict=strict, roles=roles ) except TypeError: raise GeneratorExit with self.script as dialogue: model = dialogue.cast(self.selection).run() for shot, item in model: yield shot yield item if not self.shots or self.shots[-1][:2] != shot[:2]: self.shots.append(shot._replace(items=self.script.fP)) if react: self.react(item) for key, value in model.metadata: if value not in self.metadata[key]: self.metadata[key].append(value)