|
1 # |
|
2 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of the License "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 # raptor_api module |
|
17 # |
|
18 # Python API for Raptor. External code should interact with Raptor via this |
|
19 # module only, as it is the only programatic interface considered public. The |
|
20 # command line --query option is also implemented using this module. |
|
21 |
|
22 # constants |
|
23 ALL = 1 |
|
24 |
|
25 # objects |
|
26 |
|
27 class Reply(object): |
|
28 """object to return values from API calls. |
|
29 """ |
|
30 def __init__(self, text=""): |
|
31 self.text = text |
|
32 |
|
33 def __str__(self): |
|
34 name = type(self).__name__.lower() |
|
35 |
|
36 string = "<" + name |
|
37 children = [] |
|
38 longend = False |
|
39 |
|
40 for attribute,value in self.__dict__.items(): |
|
41 if attribute != "text": |
|
42 if isinstance(value, Reply): |
|
43 children.append(value) |
|
44 else: |
|
45 string += " %s='%s'" % (attribute, value) |
|
46 |
|
47 if children or self.text: |
|
48 string += ">" |
|
49 longend = True |
|
50 |
|
51 if self.text: |
|
52 string += self.text |
|
53 |
|
54 if children: |
|
55 string += "\n" |
|
56 |
|
57 for c in children: |
|
58 string += str(c) |
|
59 |
|
60 if longend: |
|
61 string += "</%s>\n" % name |
|
62 else: |
|
63 string += "/>\n" |
|
64 |
|
65 return string |
|
66 |
|
67 class Alias(Reply): |
|
68 def __init__(self, name, meaning): |
|
69 super(Alias,self).__init__() |
|
70 self.name = name |
|
71 self.meaning = meaning |
|
72 |
|
73 class Config(Reply): |
|
74 def __init__(self, fullname, outputpath): |
|
75 super(Config,self).__init__() |
|
76 self.fullname = fullname |
|
77 self.outputpath = outputpath |
|
78 |
|
79 class Product(Reply): |
|
80 def __init__(self, name): |
|
81 super(Product,self).__init__() |
|
82 self.name = name |
|
83 |
|
84 import generic_path |
|
85 import raptor |
|
86 import raptor_data |
|
87 import re |
|
88 |
|
89 class Context(object): |
|
90 """object to contain state information for API calls. |
|
91 |
|
92 For example, |
|
93 |
|
94 api = raptor_api.Context() |
|
95 val = api.getaliases("X") |
|
96 """ |
|
97 def __init__(self, initialiser=None): |
|
98 # this object has a private Raptor object that can either be |
|
99 # passed in or created internally. |
|
100 |
|
101 if initialiser == None: |
|
102 self.__raptor = raptor.Raptor() |
|
103 else: |
|
104 self.__raptor = initialiser |
|
105 |
|
106 def stringquery(self, query): |
|
107 """turn a string into an API call and execute it. |
|
108 |
|
109 This is a convenience method for "lazy" callers. |
|
110 |
|
111 The return value is also converted into a well-formed XML string. |
|
112 """ |
|
113 |
|
114 if query == "aliases": |
|
115 aliases = self.getaliases() |
|
116 return "".join(map(str, aliases)).strip() |
|
117 |
|
118 elif query == "products": |
|
119 variants = self.getproducts() |
|
120 return "".join(map(str, variants)).strip() |
|
121 |
|
122 elif query.startswith("config"): |
|
123 match = re.match("config\[(.*)\]", query) |
|
124 if match: |
|
125 config = self.getconfig(match.group(1)) |
|
126 return str(config).strip() |
|
127 else: |
|
128 raise BadQuery("syntax error") |
|
129 |
|
130 raise BadQuery("unknown query") |
|
131 |
|
132 def getaliases(self, type=""): |
|
133 """extract all aliases of a given type. |
|
134 |
|
135 the default type is "". |
|
136 to get all aliases pass type=ALL |
|
137 """ |
|
138 aliases = [] |
|
139 |
|
140 for a in self.__raptor.cache.aliases.values(): |
|
141 if type == ALL or a.type == type: |
|
142 # copy the members we want to expose |
|
143 aliases.append( Alias(a.name, a.meaning) ) |
|
144 |
|
145 return aliases |
|
146 |
|
147 def getconfig(self, name): |
|
148 """extract the values for a given configuration. |
|
149 |
|
150 'name' should be an alias or variant followed optionally by a |
|
151 dot-separated list of variants. For example "armv5_urel" or |
|
152 "armv5_urel.savespace.vasco". |
|
153 """ |
|
154 names = name.split(".") |
|
155 if names[0] in self.__raptor.cache.aliases: |
|
156 x = self.__raptor.cache.FindNamedAlias(names[0]) |
|
157 |
|
158 if len(names) > 1: |
|
159 fullname = x.meaning + "." + ".".join(names[1:]) |
|
160 else: |
|
161 fullname = x.meaning |
|
162 |
|
163 elif names[0] in self.__raptor.cache.variants: |
|
164 fullname = name |
|
165 |
|
166 else: |
|
167 raise BadQuery("'%s' is not an alias or a variant" % names[0]) |
|
168 |
|
169 # create an evaluator for the named configuration |
|
170 tmp = raptor_data.Alias("tmp") |
|
171 tmp.SetProperty("meaning", fullname) |
|
172 |
|
173 units = tmp.GenerateBuildUnits(self.__raptor.cache) |
|
174 evaluator = self.__raptor.GetEvaluator(None, units[0]) |
|
175 |
|
176 # get the outputpath |
|
177 # this is messy as some configs construct the path inside the FLM |
|
178 # rather than talking it from the XML: usually because of some |
|
179 # conditional logic... but maybe some refactoring could avoid that. |
|
180 releasepath = evaluator.Get("RELEASEPATH") |
|
181 if not releasepath: |
|
182 raise BadQuery("could not get RELEASEPATH for config '%s'" % name) |
|
183 |
|
184 variantplatform = evaluator.Get("VARIANTPLATFORM") |
|
185 varianttype = evaluator.Get("VARIANTTYPE") |
|
186 featurevariantname = evaluator.Get("FEATUREVARIANTNAME") |
|
187 |
|
188 platform = evaluator.Get("TRADITIONAL_PLATFORM") |
|
189 |
|
190 if platform == "TOOLS2": |
|
191 outputpath = releasepath |
|
192 else: |
|
193 if not variantplatform: |
|
194 raise BadQuery("could not get VARIANTPLATFORM for config '%s'" % name) |
|
195 |
|
196 if featurevariantname: |
|
197 variantplatform += featurevariantname |
|
198 |
|
199 if not varianttype: |
|
200 raise BadQuery("could not get VARIANTTYPE for config '%s'" % name) |
|
201 |
|
202 outputpath = str(generic_path.Join(releasepath, variantplatform, varianttype)) |
|
203 |
|
204 return Config(fullname, outputpath) |
|
205 |
|
206 def getproducts(self): |
|
207 """extract all product variants.""" |
|
208 |
|
209 variants = [] |
|
210 |
|
211 for v in self.__raptor.cache.variants.values(): |
|
212 if v.type == "product": |
|
213 # copy the members we want to expose |
|
214 variants.append( Product(v.name) ) |
|
215 |
|
216 return variants |
|
217 |
|
218 class BadQuery(Exception): |
|
219 pass |
|
220 |
|
221 # end of the raptor_api module |