def get_or_init(scope, name, template_cls, *args, **kwargs):
    """Gets an existing template from a scope if it exists; otherwise, it will
    be created and registered.

    If `scope` does not have the attribute `name`, then it will be created as
    `template_cls(name, *args, **kwargs)`.
    (`module_name=...` is also set, but should not be important).

    Args:
        scope: Scope that contains the template object (this may not
            necessarily be the scope of the instantiation).
        name: Name of the template object.
        template_cls: Class (either `TemplateBase` or a derivative).
        args, kwargs: Passed to the template class's constructor.

    Returns:
        The existing (or newly created) template object.
    """
    template = getattr(scope, name, None)
    if template is None:
        template = template_cls(name, *args, scope=scope, **kwargs)
        setattr(scope, name, template)
    return template