diff options
Diffstat (limited to 'meta/lib/oe/maketype.py')
-rw-r--r-- | meta/lib/oe/maketype.py | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/meta/lib/oe/maketype.py b/meta/lib/oe/maketype.py new file mode 100644 index 0000000000..139f333691 --- /dev/null +++ b/meta/lib/oe/maketype.py | |||
@@ -0,0 +1,99 @@ | |||
1 | """OpenEmbedded variable typing support | ||
2 | |||
3 | Types are defined in the metadata by name, using the 'type' flag on a | ||
4 | variable. Other flags may be utilized in the construction of the types. See | ||
5 | the arguments of the type's factory for details. | ||
6 | """ | ||
7 | |||
8 | import inspect | ||
9 | import types | ||
10 | |||
11 | available_types = {} | ||
12 | |||
13 | class MissingFlag(TypeError): | ||
14 | """A particular flag is required to construct the type, but has not been | ||
15 | provided.""" | ||
16 | def __init__(self, flag, type): | ||
17 | self.flag = flag | ||
18 | self.type = type | ||
19 | TypeError.__init__(self) | ||
20 | |||
21 | def __str__(self): | ||
22 | return "Type '%s' requires flag '%s'" % (self.type, self.flag) | ||
23 | |||
24 | def factory(var_type): | ||
25 | """Return the factory for a specified type.""" | ||
26 | if var_type is None: | ||
27 | raise TypeError("No type specified. Valid types: %s" % | ||
28 | ', '.join(available_types)) | ||
29 | try: | ||
30 | return available_types[var_type] | ||
31 | except KeyError: | ||
32 | raise TypeError("Invalid type '%s':\n Valid types: %s" % | ||
33 | (var_type, ', '.join(available_types))) | ||
34 | |||
35 | def create(value, var_type, **flags): | ||
36 | """Create an object of the specified type, given the specified flags and | ||
37 | string value.""" | ||
38 | obj = factory(var_type) | ||
39 | objflags = {} | ||
40 | for flag in obj.flags: | ||
41 | if flag not in flags: | ||
42 | if flag not in obj.optflags: | ||
43 | raise MissingFlag(flag, var_type) | ||
44 | else: | ||
45 | objflags[flag] = flags[flag] | ||
46 | |||
47 | return obj(value, **objflags) | ||
48 | |||
49 | def get_callable_args(obj): | ||
50 | """Grab all but the first argument of the specified callable, returning | ||
51 | the list, as well as a list of which of the arguments have default | ||
52 | values.""" | ||
53 | if type(obj) is type: | ||
54 | obj = obj.__init__ | ||
55 | |||
56 | args, varargs, keywords, defaults = inspect.getargspec(obj) | ||
57 | flaglist = [] | ||
58 | if args: | ||
59 | if len(args) > 1 and args[0] == 'self': | ||
60 | args = args[1:] | ||
61 | flaglist.extend(args) | ||
62 | |||
63 | optional = set() | ||
64 | if defaults: | ||
65 | optional |= set(flaglist[-len(defaults):]) | ||
66 | return flaglist, optional | ||
67 | |||
68 | def factory_setup(name, obj): | ||
69 | """Prepare a factory for use.""" | ||
70 | args, optional = get_callable_args(obj) | ||
71 | extra_args = args[1:] | ||
72 | if extra_args: | ||
73 | obj.flags, optional = extra_args, optional | ||
74 | obj.optflags = set(optional) | ||
75 | else: | ||
76 | obj.flags = obj.optflags = () | ||
77 | |||
78 | if not hasattr(obj, 'name'): | ||
79 | obj.name = name | ||
80 | |||
81 | def register(name, factory): | ||
82 | """Register a type, given its name and a factory callable. | ||
83 | |||
84 | Determines the required and optional flags from the factory's | ||
85 | arguments.""" | ||
86 | factory_setup(name, factory) | ||
87 | available_types[factory.name] = factory | ||
88 | |||
89 | |||
90 | # Register all our included types | ||
91 | for name in dir(types): | ||
92 | if name.startswith('_'): | ||
93 | continue | ||
94 | |||
95 | obj = getattr(types, name) | ||
96 | if not callable(obj): | ||
97 | continue | ||
98 | |||
99 | register(name, obj) | ||