domain, collection, template

A template is always part of a collection
in a domain.

The implications of this are that those related objects are always
created, even if we are still free to create them
explicitly in any order we prefer.
Another implication is consistency and simplicity of the
implementation, reducing the need to handle other scenarios.

The preferred usage is to first explicitly create the Domain instance,
that will by default create the default empty string named


class Domain(object):
    """ A registry of collections """
    def __init__(self, default_dir, 
            restricted=False, errors=3, log=get_log(),
            # defaults for Collections
            cache_size=0, auto_reload=60, slurpy_directives=True, 
            # defaults for Collections (and Templates)
            quoting="xml", input_encoding="utf_8", filters=[]):
        default_dir: either(str, Collection)
            abs path, or actual default collection instance
        restricted: bool
            restricted evaluation namespace
        errors: int
            ["silent", "zero", "name", "render", "raise"]
        log: the logging.getLogger("evoque") logger; may be pre-initialized 
            and passed in, or adjusted as needed after initialization. 
            Default settings (via loggin.basicConfig()) are:
                format="%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s"
        # Defaults for Collections
        cache_size: int
            max number loaded templates in collection
            0 means unlimited loaded templates
        auto_reload: int
            min seconds to wait to check if needs reloading
            0 means check on every rendering
        slurpy_directives: bool
            consume all whitespace trailing a directive

        # Defaults for Collections (and Templates)

        quoting: either("xml", "str", type)
            "xml" -> qpy.xml, "str" -> unicode
        input_encoding: str
            hint for how to decode template source
        filters: [callable]
            list of template post-evaluation filter functions
""" domain public methods """

set_on_globals(name: str, value: any) -> None
set_namespace_on_globals(name: either(str, None), obj: any, 
        no_underscored: bool = True
    ) -> None

get_collection(name: either(None, str, Collection) = None
    ) -> Collection
set_collection(name: str, dir: str, 
        cache_size: int = None, 
        auto_reload: int = None, 
        slurpy_directives: bool = None, 
        quoting: either(str, type) = None, 
        input_encoding: str = None, 
        filters:[callable] = None
    ) -> None
has_collection(name: str) -> bool

""" methods wrapping collection.*_template() """"

        src=None, collection=None, raw=None, data=None, 
        quoting=None, input_encoding=None, filters=None
    ) -> Template
        src=None, collection=None, raw=None, data=None, 
        quoting=None, input_encoding=None, filters=None
    ) -> None
has_template(name, collection=None) -> bool


class Collection(object):
    """ A collection of templates, rooted at a directory """
    def __init__(self, domain, name, path, 
            # defaults from Domain
            cache_size=None, auto_reload=None, slurpy_directives=None, 
            # defaults (from Domain) for Templates
            quoting=None, input_encoding=None, filters=None):
        domain: either(None, Domain)
        name: str, name by which to retrieve the collection
        path: str, abs path for root folder for the collection
        For more on defaults from Domain init parameters, see the 
        docstring in domain.Domain.__init__().
        Preferred way to create a new collection: 
""" collection public methods """

get_template(name="", src=None, raw=None, data=None, 
        quoting=None, input_encoding=None, filters=None
    ) -> Template
    """ get / load (if file-based) a template """

set_template(name, src, raw=None, data=None, from_string=True, 
        quoting=None, input_encoding=None, filters=None
    ) -> None
    """ typically used to set a template from a string """

has_template(name) -> bool

""" collection (read-only) attributes """

domain: Domain


class Template(object):
    """ An Evoque template 
    def __init__(self, domain, name, src=None, collection=None, 
            raw=None, data=None, from_string=False, 
            # defaults from Collection
            quoting=None, input_encoding=None, filters=None):
        domain: either(str, Domain)
            abs path, or actual domain instance
        name: str
            if no src this is collection-root-relative locator
        src: either(None, str)
            (file-based) collection-root-relative locator
            (from_string=True) template source string
        collection: either(None, str, Collection)
            None implies default collection, else 
            str/Collection refer to an existing collection
        raw: bool 
            if raw, do not compile the template source 
        data: either(None, dict) 
            default data for template evaluation 
        from_string: bool
            when True src must specify the template source
        For more on defaults from Collection init parameters, see the 
        docstring in collection.Collection.__init__().
        Preferred way to create a new template:
            domain.{get_template(), set_template()}
""" template public methods """

evoque(locals: dict = None, 
    raw: bool = None, 
    quoting: either(str, type) = None 
    **kw) -> qsclass
    Render template, as an instance of `qsclass` (derived from `quoting` or 
    from `template.qsclass`). If `locals` is None, use a copy of "own" locals.
    If `raw` or `template.raw` is True, return raw string without evaluation.
    Any `kw args` are set onto `locals` before evaluation.

test() -> either(None, [qsclass])
    """ Return a rendering per test directive """

unload() -> None
    """ Unloads self from collection """

""" template (read-only) attributes """

name: str
collection: Collection
raw: bool
data: either(None, dict)
    # default data for template evaluation 
qsclass: either(unicode, qpy.xml, type)
    # quoted-no-more string class, determined from quoting init param
input_encoding: str
    # encoding hint, default from collection
filters: [callable]
    # post-evaluation filters, default from collection

Note there are no instance attributes that correspond
directly to the src, from_string and
quoting init parameters.