Implement variable typing (sync from OE)
This implementation consists of two components:
- Type creation python modules, whose job it is to construct objects of the
defined type for a given variable in the metadata
- typecheck.bbclass, which iterates over all configuration variables with a
type defined and uses oe.types to check the validity of the values
This gives us a few benefits:
- Automatic sanity checking of all configuration variables with a defined type
- Avoid duplicating the "how do I make use of the value of this variable"
logic between its users. For variables like PATH, this is simply a split(),
for boolean variables, the duplication can result in confusing, or even
mismatched semantics (is this 0/1, empty/nonempty, what?)
- Make it easier to create a configuration UI, as the type information could
be used to provide a better interface than a text edit box (e.g checkbox for
'boolean', dropdown for 'choice')
This functionality is entirely opt-in right now. To enable the configuration
variable type checking, simply INHERIT += "typecheck". Example of a failing
type check:
BAZ = "foo"
BAZ[type] = "boolean"
$ bitbake -p
FATAL: BAZ: Invalid boolean value 'foo'
$
Examples of leveraging oe.types in a python snippet:
PACKAGES[type] = "list"
python () {
import oe.data
for pkg in oe.data.typed_value("PACKAGES", d):
bb.note("package: %s" % pkg)
}
LIBTOOL_HAS_SYSROOT = "yes"
LIBTOOL_HAS_SYSROOT[type] = "boolean"
python () {
import oe.data
assert(oe.data.typed_value("LIBTOOL_HAS_SYSROOT", d) == True)
}
(From OE-Core rev: a04ce490e933fc7534db33f635b025c25329c564)
Signed-off-by: Chris Larson <chris_larson@mentor.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2010-11-09 21:48:13 +00:00
|
|
|
"""OpenEmbedded variable typing support
|
|
|
|
|
|
|
|
Types are defined in the metadata by name, using the 'type' flag on a
|
|
|
|
variable. Other flags may be utilized in the construction of the types. See
|
|
|
|
the arguments of the type's factory for details.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import inspect
|
2016-05-20 10:57:44 +00:00
|
|
|
import oe.types as types
|
|
|
|
import collections
|
Implement variable typing (sync from OE)
This implementation consists of two components:
- Type creation python modules, whose job it is to construct objects of the
defined type for a given variable in the metadata
- typecheck.bbclass, which iterates over all configuration variables with a
type defined and uses oe.types to check the validity of the values
This gives us a few benefits:
- Automatic sanity checking of all configuration variables with a defined type
- Avoid duplicating the "how do I make use of the value of this variable"
logic between its users. For variables like PATH, this is simply a split(),
for boolean variables, the duplication can result in confusing, or even
mismatched semantics (is this 0/1, empty/nonempty, what?)
- Make it easier to create a configuration UI, as the type information could
be used to provide a better interface than a text edit box (e.g checkbox for
'boolean', dropdown for 'choice')
This functionality is entirely opt-in right now. To enable the configuration
variable type checking, simply INHERIT += "typecheck". Example of a failing
type check:
BAZ = "foo"
BAZ[type] = "boolean"
$ bitbake -p
FATAL: BAZ: Invalid boolean value 'foo'
$
Examples of leveraging oe.types in a python snippet:
PACKAGES[type] = "list"
python () {
import oe.data
for pkg in oe.data.typed_value("PACKAGES", d):
bb.note("package: %s" % pkg)
}
LIBTOOL_HAS_SYSROOT = "yes"
LIBTOOL_HAS_SYSROOT[type] = "boolean"
python () {
import oe.data
assert(oe.data.typed_value("LIBTOOL_HAS_SYSROOT", d) == True)
}
(From OE-Core rev: a04ce490e933fc7534db33f635b025c25329c564)
Signed-off-by: Chris Larson <chris_larson@mentor.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2010-11-09 21:48:13 +00:00
|
|
|
|
|
|
|
available_types = {}
|
|
|
|
|
|
|
|
class MissingFlag(TypeError):
|
|
|
|
"""A particular flag is required to construct the type, but has not been
|
|
|
|
provided."""
|
|
|
|
def __init__(self, flag, type):
|
|
|
|
self.flag = flag
|
|
|
|
self.type = type
|
|
|
|
TypeError.__init__(self)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "Type '%s' requires flag '%s'" % (self.type, self.flag)
|
|
|
|
|
|
|
|
def factory(var_type):
|
|
|
|
"""Return the factory for a specified type."""
|
|
|
|
if var_type is None:
|
|
|
|
raise TypeError("No type specified. Valid types: %s" %
|
|
|
|
', '.join(available_types))
|
|
|
|
try:
|
|
|
|
return available_types[var_type]
|
|
|
|
except KeyError:
|
|
|
|
raise TypeError("Invalid type '%s':\n Valid types: %s" %
|
|
|
|
(var_type, ', '.join(available_types)))
|
|
|
|
|
|
|
|
def create(value, var_type, **flags):
|
|
|
|
"""Create an object of the specified type, given the specified flags and
|
|
|
|
string value."""
|
|
|
|
obj = factory(var_type)
|
|
|
|
objflags = {}
|
|
|
|
for flag in obj.flags:
|
|
|
|
if flag not in flags:
|
|
|
|
if flag not in obj.optflags:
|
|
|
|
raise MissingFlag(flag, var_type)
|
|
|
|
else:
|
|
|
|
objflags[flag] = flags[flag]
|
|
|
|
|
|
|
|
return obj(value, **objflags)
|
|
|
|
|
|
|
|
def get_callable_args(obj):
|
|
|
|
"""Grab all but the first argument of the specified callable, returning
|
|
|
|
the list, as well as a list of which of the arguments have default
|
|
|
|
values."""
|
|
|
|
if type(obj) is type:
|
|
|
|
obj = obj.__init__
|
|
|
|
|
2016-05-20 10:57:44 +00:00
|
|
|
sig = inspect.signature(obj)
|
|
|
|
args = list(sig.parameters.keys())
|
|
|
|
defaults = list(s for s in sig.parameters.keys() if sig.parameters[s].default != inspect.Parameter.empty)
|
Implement variable typing (sync from OE)
This implementation consists of two components:
- Type creation python modules, whose job it is to construct objects of the
defined type for a given variable in the metadata
- typecheck.bbclass, which iterates over all configuration variables with a
type defined and uses oe.types to check the validity of the values
This gives us a few benefits:
- Automatic sanity checking of all configuration variables with a defined type
- Avoid duplicating the "how do I make use of the value of this variable"
logic between its users. For variables like PATH, this is simply a split(),
for boolean variables, the duplication can result in confusing, or even
mismatched semantics (is this 0/1, empty/nonempty, what?)
- Make it easier to create a configuration UI, as the type information could
be used to provide a better interface than a text edit box (e.g checkbox for
'boolean', dropdown for 'choice')
This functionality is entirely opt-in right now. To enable the configuration
variable type checking, simply INHERIT += "typecheck". Example of a failing
type check:
BAZ = "foo"
BAZ[type] = "boolean"
$ bitbake -p
FATAL: BAZ: Invalid boolean value 'foo'
$
Examples of leveraging oe.types in a python snippet:
PACKAGES[type] = "list"
python () {
import oe.data
for pkg in oe.data.typed_value("PACKAGES", d):
bb.note("package: %s" % pkg)
}
LIBTOOL_HAS_SYSROOT = "yes"
LIBTOOL_HAS_SYSROOT[type] = "boolean"
python () {
import oe.data
assert(oe.data.typed_value("LIBTOOL_HAS_SYSROOT", d) == True)
}
(From OE-Core rev: a04ce490e933fc7534db33f635b025c25329c564)
Signed-off-by: Chris Larson <chris_larson@mentor.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2010-11-09 21:48:13 +00:00
|
|
|
flaglist = []
|
|
|
|
if args:
|
|
|
|
if len(args) > 1 and args[0] == 'self':
|
|
|
|
args = args[1:]
|
|
|
|
flaglist.extend(args)
|
|
|
|
|
|
|
|
optional = set()
|
|
|
|
if defaults:
|
|
|
|
optional |= set(flaglist[-len(defaults):])
|
|
|
|
return flaglist, optional
|
|
|
|
|
|
|
|
def factory_setup(name, obj):
|
|
|
|
"""Prepare a factory for use."""
|
|
|
|
args, optional = get_callable_args(obj)
|
|
|
|
extra_args = args[1:]
|
|
|
|
if extra_args:
|
|
|
|
obj.flags, optional = extra_args, optional
|
|
|
|
obj.optflags = set(optional)
|
|
|
|
else:
|
|
|
|
obj.flags = obj.optflags = ()
|
|
|
|
|
|
|
|
if not hasattr(obj, 'name'):
|
|
|
|
obj.name = name
|
|
|
|
|
|
|
|
def register(name, factory):
|
|
|
|
"""Register a type, given its name and a factory callable.
|
|
|
|
|
|
|
|
Determines the required and optional flags from the factory's
|
|
|
|
arguments."""
|
|
|
|
factory_setup(name, factory)
|
|
|
|
available_types[factory.name] = factory
|
|
|
|
|
|
|
|
|
|
|
|
# Register all our included types
|
|
|
|
for name in dir(types):
|
|
|
|
if name.startswith('_'):
|
|
|
|
continue
|
|
|
|
|
|
|
|
obj = getattr(types, name)
|
2016-05-20 10:57:44 +00:00
|
|
|
if not isinstance(obj, collections.Callable):
|
Implement variable typing (sync from OE)
This implementation consists of two components:
- Type creation python modules, whose job it is to construct objects of the
defined type for a given variable in the metadata
- typecheck.bbclass, which iterates over all configuration variables with a
type defined and uses oe.types to check the validity of the values
This gives us a few benefits:
- Automatic sanity checking of all configuration variables with a defined type
- Avoid duplicating the "how do I make use of the value of this variable"
logic between its users. For variables like PATH, this is simply a split(),
for boolean variables, the duplication can result in confusing, or even
mismatched semantics (is this 0/1, empty/nonempty, what?)
- Make it easier to create a configuration UI, as the type information could
be used to provide a better interface than a text edit box (e.g checkbox for
'boolean', dropdown for 'choice')
This functionality is entirely opt-in right now. To enable the configuration
variable type checking, simply INHERIT += "typecheck". Example of a failing
type check:
BAZ = "foo"
BAZ[type] = "boolean"
$ bitbake -p
FATAL: BAZ: Invalid boolean value 'foo'
$
Examples of leveraging oe.types in a python snippet:
PACKAGES[type] = "list"
python () {
import oe.data
for pkg in oe.data.typed_value("PACKAGES", d):
bb.note("package: %s" % pkg)
}
LIBTOOL_HAS_SYSROOT = "yes"
LIBTOOL_HAS_SYSROOT[type] = "boolean"
python () {
import oe.data
assert(oe.data.typed_value("LIBTOOL_HAS_SYSROOT", d) == True)
}
(From OE-Core rev: a04ce490e933fc7534db33f635b025c25329c564)
Signed-off-by: Chris Larson <chris_larson@mentor.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2010-11-09 21:48:13 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
register(name, obj)
|