def _add_tween(self, tween_factory, under=None, over=None, explicit=False): if not isinstance(tween_factory, str): raise ConfigurationError( 'The "tween_factory" argument to add_tween must be a ' 'dotted name to a globally importable object, not %r' % tween_factory ) name = tween_factory if name in (MAIN, INGRESS): raise ConfigurationError('%s is a reserved tween name' % name) tween_factory = self.maybe_dotted(tween_factory) for t, p in [('over', over), ('under', under)]: if p is not None: if not is_string_or_iterable(p): raise ConfigurationError( '"%s" must be a string or iterable, not %s' % (t, p) ) if over is INGRESS or is_nonstr_iter(over) and INGRESS in over: raise ConfigurationError('%s cannot be over INGRESS' % name) if under is MAIN or is_nonstr_iter(under) and MAIN in under: raise ConfigurationError('%s cannot be under MAIN' % name) registry = self.registry introspectables = [] tweens = registry.queryUtility(ITweens) if tweens is None: tweens = Tweens() registry.registerUtility(tweens, ITweens) def register(): if explicit: tweens.add_explicit(name, tween_factory) else: tweens.add_implicit( name, tween_factory, under=under, over=over ) discriminator = ('tween', name, explicit) tween_type = explicit and 'explicit' or 'implicit' intr = self.introspectable( 'tweens', discriminator, name, '%s tween' % tween_type ) intr['name'] = name intr['factory'] = tween_factory intr['type'] = tween_type intr['under'] = under intr['over'] = over introspectables.append(intr) self.action(discriminator, register, introspectables=introspectables)