123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- #
- # SPDX-License-Identifier: GPL-2.0-only
- #
- """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
- import oe.types as types
- try:
- # Python 3.7+
- from collections.abc import Callable
- except ImportError:
- # Python < 3.7
- from collections import Callable
- 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__
- 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)
- 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)
- if not isinstance(obj, Callable):
- continue
- register(name, obj)
|