'Decorator for Spack directives.
Spack directives allow you to modify a package while it is being
defined, e.g. to add version or dependency information.  Directives
are one of the key pieces of Spack\'s package "language", which is
embedded in python.
Here\'s an example directive:
@directive(dicts=\'versions\')
version(pkg, ...):
This directive allows you write:
class Foo(Package):
version(...)
The ``@directive`` decorator handles a couple things for you:
1. Adds the class scope (pkg) as an initial parameter when
called, like a class method would.  This allows you to modify
a package from within a directive, while the package is still
being defined.
2. It automatically adds a dictionary called "versions" to the
package so that you can refer to pkg.versions.
The ``(dicts=\'versions\')`` part ensures that ALL packages in Spack
will have a ``versions`` attribute after they\'re constructed, and
that if no directive actually modified it, it will just be an
empty dict.
This is just a modular way to add storage attributes to the
Package class, and it\'s how Spack gets information from the
packages to the core.'

@staticmethod
def directive(dicts=None):

    global __all__
    if isinstance(dicts, string_types):
        dicts = (dicts,)
    if (not isinstance(dicts, collections.Sequence)):
        message = 'dicts    arg    must    be    list,    tuple,    or    string.    Found    {0}'
        raise TypeError(message.format(type(dicts)))
    DirectiveMetaMixin._directive_names |= set(dicts)
    def _decorator(decorated_function):
        __all__.append(decorated_function.__name__)
        @functools.wraps(decorated_function)
        def _wrapper(*args, **kwargs):
            values = decorated_function(*args, **kwargs)
            if (not isinstance(values, collections.Sequence)):
                values = (values,)
            DirectiveMetaMixin._directives_to_be_executed.extend(values)
        return _wrapper
    return _decorator
