[oe] [RFC] [PATCH 1/2] Implement variable typing
Chris Larson
kergoth at gmail.com
Tue Nov 9 23:18:27 UTC 2010
From: Chris Larson <chris_larson at mentor.com>
This implementation consists of two components:
- oe.types python module, 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.types
for pkg in oe.types.value("PACKAGES", d):
bb.note("package: %s" % pkg)
}
LIBTOOL_HAS_SYSROOT = "yes"
LIBTOOL_HAS_SYSROOT[type] = "boolean"
python () {
import oe.types
assert(oe.types.value("LIBTOOL_HAS_SYSROOT", d) == True)
}
Signed-off-by: Chris Larson <chris_larson at mentor.com>
---
classes/typecheck.bbclass | 12 +++++++
lib/oe/types.py | 77 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+), 0 deletions(-)
create mode 100644 classes/typecheck.bbclass
create mode 100644 lib/oe/types.py
diff --git a/classes/typecheck.bbclass b/classes/typecheck.bbclass
new file mode 100644
index 0000000..646cd4e
--- /dev/null
+++ b/classes/typecheck.bbclass
@@ -0,0 +1,12 @@
+# Check types of bitbake configuration variables
+#
+# See oe.types for details.
+
+python check_types() {
+ import oe.types
+ if isinstance(e, bb.event.ConfigParsed):
+ for key in e.data.keys():
+ if e.data.getVarFlag(key, "type"):
+ oe.types.value(key, e.data)
+}
+addhandler check_types
diff --git a/lib/oe/types.py b/lib/oe/types.py
new file mode 100644
index 0000000..df6785f
--- /dev/null
+++ b/lib/oe/types.py
@@ -0,0 +1,77 @@
+# Constructs objects of the specified type for a given variable in the
+# metadata. The 'type' flag of the variable defines which of the factory
+# functions in this module will be called.
+#
+# If no type is defined, the value() function will simply return the expanded
+# string value as is.
+
+class OEList(list):
+ def __init__(self, value, separator):
+ self.separator = separator
+ __builtins__["list"].__init__(self, value)
+
+ def __str__(self):
+ return self.separator.join(self)
+
+def boolean(key, metadata):
+ value = metadata.getVar(key, True)
+ strvalue = str(value).lower()
+ if strvalue in ('yes', 'y', 'true', 't', '1'):
+ return True
+ elif strvalue in ('no', 'n', 'false', 'f', '0'):
+ return False
+ raise ValueError("Invalid boolean value '%s'" % strvalue)
+
+def list(key, metadata):
+ value = metadata.getVar(key, True)
+ separator = metadata.getVarFlag(key, "separator") or " "
+ return OEList(value.split(separator), separator)
+
+def integer(key, metadata):
+ return int(metadata.getVar(key, True))
+
+def choice(key, metadata):
+ value = metadata.getVar(key, True).upper()
+ choices = metadata.getVarFlag(key, "choices")
+ if not choices:
+ raise ValueError("No 'choices' flag set for variable '%s'" % key)
+
+ for choice in choices.split():
+ if choice.upper() == value:
+ break
+ else:
+ raise ValueError("Invalid choice '%s' for '%s'. Valid choices: %s" %
+ (value, key, choices))
+ return value
+
+def regex(key, metadata):
+ import re
+ value = metadata.getVar(key, True)
+ flagval = 0
+ flags = metadata.getVarFlag(key, "regexflags")
+ if flags:
+ for flag in flags.split():
+ flag = flag.upper()
+ try:
+ flagval |= getattr(re, flag)
+ except AttributeError:
+ raise ValueError("Invalid regex flag '%s'" % flag)
+ try:
+ return re.compile(value, flagval)
+ except Exception, exc:
+ raise ValueError("Invalid value '%s' for regex(): %s" % (value, exc))
+
+def value(key, d):
+ import bb
+ var_type = d.getVarFlag(key, "type")
+ if var_type:
+ try:
+ func = globals()[var_type]
+ except KeyError:
+ raise TypeError("Invalid variable type: %s" % var_type)
+ try:
+ return func(key, d)
+ except ValueError, exc:
+ bb.fatal("%s: %s" % (key, str(exc)))
+ else:
+ return d.getVar(key, True)
--
1.7.2.3
More information about the Openembedded-devel
mailing list