Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: build/android/gyp/generate_v14_resources.py

Issue 14969022: [Android] Warning if Left/Right attributes are used in layout and style xmls. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2013 The Chromium Authors. All rights reserved. 3 # Copyright 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Convert Android xml resources to API 14 compatible. 7 """Convert Android xml resources to API 14 compatible.
8 8
9 There are two reasons that we cannot just use API attributes, 9 There are two reasons that we cannot just use API attributes,
10 so we are generating another set of resources by this script. 10 so we are generating another set of resources by this script.
11 11
12 1. paddingStart attribute can cause a crash on Galaxy Tab 2. 12 1. paddingStart attribute can cause a crash on Galaxy Tab 2.
13 2. There is a bug that paddingStart does not override paddingLeft on 13 2. There is a bug that paddingStart does not override paddingLeft on
14 JB-MR1. This is fixed on JB-MR2. 14 JB-MR1. This is fixed on JB-MR2.
15 15
16 Therefore, this resource generation script can be removed when 16 Therefore, this resource generation script can be removed when
17 we drop the support for JB-MR1. 17 we drop the support for JB-MR1.
18 18
19 Please refer to http://crbug.com/235118 for the details. 19 Please refer to http://crbug.com/235118 for the details.
20 """ 20 """
21 21
22 import optparse 22 import optparse
23 import os 23 import os
24 import re 24 import re
25 import sys 25 import sys
26 import xml.dom.minidom as minidom 26 import xml.dom.minidom as minidom
27 27
28 from util import build_utils 28 from util import build_utils
29 29
30 # Note that we are assumping 'android:' is an alias of
newt (away) 2013/05/10 01:15:49 "assuming"
Kibeom Kim (inactive) 2013/05/10 02:14:27 Done.
31 # the namespace 'http://schemas.android.com/apk/res/android'.
30 32
31 ATTRIBUTE_NAMESPACE = 'http://schemas.android.com/apk/res/android' 33 GRAVITY_ATTRIBUTES = ('android:gravity', 'android:layout_gravity')
32 34
33 # Almost all the attributes that has "Start" or "End" in 35 # Almost all the attributes that has "Start" or "End" in
34 # its name should be mapped. 36 # its name should be mapped.
35 ATTRIBUTES_TO_MAP = {'paddingStart' : 'paddingLeft', 37 ATTRIBUTES_TO_MAP = {'paddingStart' : 'paddingLeft',
36 'drawableStart' : 'drawableLeft', 38 'drawableStart' : 'drawableLeft',
37 'layout_alignStart' : 'layout_alignLeft', 39 'layout_alignStart' : 'layout_alignLeft',
38 'layout_marginStart' : 'layout_marginLeft', 40 'layout_marginStart' : 'layout_marginLeft',
39 'layout_alignParentStart' : 'layout_alignParentLeft', 41 'layout_alignParentStart' : 'layout_alignParentLeft',
40 'layout_toStartOf' : 'layout_toLeftOf', 42 'layout_toStartOf' : 'layout_toLeftOf',
41 'paddingEnd' : 'paddingRight', 43 'paddingEnd' : 'paddingRight',
42 'drawableEnd' : 'drawableRight', 44 'drawableEnd' : 'drawableRight',
43 'layout_alignEnd' : 'layout_alignRight', 45 'layout_alignEnd' : 'layout_alignRight',
44 'layout_marginEnd' : 'layout_marginRight', 46 'layout_marginEnd' : 'layout_marginRight',
45 'layout_alignParentEnd' : 'layout_alignParentRight', 47 'layout_alignParentEnd' : 'layout_alignParentRight',
46 'layout_toEndOf' : 'layout_toRightOf'} 48 'layout_toEndOf' : 'layout_toRightOf'}
47 49
48 ATTRIBUTES_TO_MAP_NS = {} 50 ATTRIBUTES_TO_MAP = dict(['android:' + k, 'android:' + v] for k, v
51 in ATTRIBUTES_TO_MAP.iteritems())
49 52
50 for k, v in ATTRIBUTES_TO_MAP.items(): 53 ATTRIBUTES_TO_MAP_REVERSED = dict([v,k] for k, v
51 ATTRIBUTES_TO_MAP_NS[(ATTRIBUTE_NAMESPACE, k)] = (ATTRIBUTE_NAMESPACE, v) 54 in ATTRIBUTES_TO_MAP.iteritems())
52
53 ATTRIBUTES_TO_MAP_NS_VALUES = set(ATTRIBUTES_TO_MAP_NS.values())
54 55
55 56
56 def IterateXmlElements(node): 57 def IterateXmlElements(node):
57 """minidom helper function that iterates all the element nodes. 58 """minidom helper function that iterates all the element nodes.
58 Iteration order is pre-order depth-first.""" 59 Iteration order is pre-order depth-first."""
59 if node.nodeType == node.ELEMENT_NODE: 60 if node.nodeType == node.ELEMENT_NODE:
60 yield node 61 yield node
61 for child_node in node.childNodes: 62 for child_node in node.childNodes:
62 for child_node_element in IterateXmlElements(child_node): 63 for child_node_element in IterateXmlElements(child_node):
63 yield child_node_element 64 yield child_node_element
64 65
65 66
66 def GenerateV14StyleResource(dom, output_file): 67 def WarnDeprecatedAttribute(name, value, file):
newt (away) 2013/05/10 01:16:43 also: it's better to use filename instead of file,
Kibeom Kim (inactive) 2013/05/10 02:14:27 Done.
68 if name in ATTRIBUTES_TO_MAP_REVERSED:
69 print >> sys.stderr, ('warning: ' +file + ' should use ' +
newt (away) 2013/05/10 01:15:49 nit: space before "file"
Kibeom Kim (inactive) 2013/05/10 02:14:27 Done.
70 ATTRIBUTES_TO_MAP_REVERSED[name] +
71 ' instead of ' + name)
72 elif name in GRAVITY_ATTRIBUTES and ('left' in value or 'right' in value):
newt (away) 2013/05/10 01:15:49 elif name in GRAVITY_ATTRIBUTES and value in ('lef
Kibeom Kim (inactive) 2013/05/10 02:14:27 But what if value == 'left|top' ?
newt (away) 2013/05/10 06:13:50 ah, good point. looks good as is.
73 print >> sys.stderr, ('warning: ' + file +
74 ' should use start/end instead of left/right for ' +
75 name)
76
77
78 def GenerateV14StyleResource(input_file, output_file):
67 """Convert style resource to API 14 compatible style resource. 79 """Convert style resource to API 14 compatible style resource.
68 80
69 It's mostly a simple replacement, s/Start/Left s/End/Right, 81 It's mostly a simple replacement, s/Start/Left s/End/Right,
70 on the attribute names specified by <item> element. 82 on the attribute names specified by <item> element.
71 """ 83 """
84 dom = minidom.parse(input_file)
85
72 for style_element in dom.getElementsByTagName('style'): 86 for style_element in dom.getElementsByTagName('style'):
73 for item_element in style_element.getElementsByTagName('item'): 87 for item_element in style_element.getElementsByTagName('item'):
74 namespace, name = item_element.attributes['name'].value.split(':') 88 name = item_element.attributes['name']
newt (away) 2013/05/10 01:15:49 add ".value" to the end of the line?
Kibeom Kim (inactive) 2013/05/10 02:14:27 Done. Thanks for catching this!
75 # Note: namespace == 'android' is not precise because 89 value = item_element.childNodes[0].nodeValue
76 # we are looking for 'http://schemas.android.com/apk/res/android' and 90 if name in ATTRIBUTES_TO_MAP:
77 # 'android' can be aliased to another name in layout xml files where 91 item_element.attributes['name'] = ATTRIBUTES_TO_MAP[name]
78 # this style is used. e.g. xmlns:android="http://crbug.com/". 92 else:
79 if namespace == 'android' and name in ATTRIBUTES_TO_MAP: 93 WarnDeprecatedAttribute(name, value, 'xxx')
Kibeom Kim (inactive) 2013/05/10 00:31:39 oops, 'xxx' to file
newt (away) 2013/05/10 01:15:49 'xxx' -> input_file
Kibeom Kim (inactive) 2013/05/10 02:14:27 Done.
Kibeom Kim (inactive) 2013/05/10 02:14:27 Done.
80 mapped_name = ATTRIBUTES_TO_MAP[name]
81 item_element.attributes['name'] = namespace + ':' + mapped_name
82 94
83 build_utils.MakeDirectory(os.path.dirname(output_file)) 95 build_utils.MakeDirectory(os.path.dirname(output_file))
84 with open(output_file, 'w') as f: 96 with open(output_file, 'w') as f:
85 dom.writexml(f, '', ' ', '\n', encoding='utf-8') 97 dom.writexml(f, '', ' ', '\n', encoding='utf-8')
86 98
87 99
88 def GenerateV14LayoutResource(input_file, output_file): 100 def GenerateV14LayoutResource(input_file, output_file):
89 """Convert layout resource to API 14 compatible layout resource. 101 """Convert layout resource to API 14 compatible layout resource.
90 102
91 It's mostly a simple replacement, s/Start/Left s/End/Right, 103 It's mostly a simple replacement, s/Start/Left s/End/Right,
92 on the attribute names. 104 on the attribute names.
93 """ 105 """
94 dom = minidom.parse(input_file) 106 dom = minidom.parse(input_file)
newt (away) 2013/05/10 01:15:49 you could use ElementTree and xpath here: tre
Kibeom Kim (inactive) 2013/05/10 02:14:27 Actually, I used cElementTree before because it's
newt (away) 2013/05/10 06:13:50 ah. looks like there's a solution in python 2.6: l
95 107
108 # Iterate all the elements' attributes to find attributes to convert.
96 for element in IterateXmlElements(dom): 109 for element in IterateXmlElements(dom):
97 all_names = element.attributes.keysNS() 110 for name, value in list(element.attributes.items()):
98 111 # Convert any other API 17 Start/End attributes to Left/Right attributes.
99 # Iterate all the attributes to find attributes to convert. 112 # For example, from paddingStart="10dp" to paddingLeft="10dp"
100 # Note that name variable is actually a tuple that has namespace and name.
101 # For example,
102 # name == ('http://schemas.android.com/apk/res/android', 'paddingStart')
103 for name, value in list(element.attributes.itemsNS()):
104 # Note: gravity attributes are not necessary to convert because 113 # Note: gravity attributes are not necessary to convert because
105 # start/end values are backward-compatible. Explained at 114 # start/end values are backward-compatible. Explained at
106 # https://plus.sandbox.google.com/+RomanNurik/posts/huuJd8iVVXY?e=Showroom 115 # https://plus.sandbox.google.com/+RomanNurik/posts/huuJd8iVVXY?e=Showroom
107 116 if name in ATTRIBUTES_TO_MAP:
108 # Convert any other API 17 Start/End attributes to Left/Right attributes. 117 element.setAttribute(ATTRIBUTES_TO_MAP[name], value)
109 # For example, from paddingStart="10dp" to paddingLeft="10dp"
110 if name in ATTRIBUTES_TO_MAP_NS:
111 mapped_name = ATTRIBUTES_TO_MAP_NS[name]
112
113 # Add the new mapped attribute and remove the original attribute.
114 # For example, add paddingLeft and remove paddingStart.
115 # Note that instead of element.setAttribute(...), this is more correct.
116 # element.setAttributeNS(mapped_name[0], mapped_name[1], value)
117 # However, there is a minidom bug that doesn't print namespace set by
118 # setAttributeNS. Hence this workaround.
119 # This is a similar bug discussion about minidom namespace normalizing.
120 # http://stackoverflow.com/questions/863774/how-to-generate-xml-document s-with-namespaces-in-python
121 element.setAttribute('android:' + mapped_name[1], value)
122 del element.attributes[name] 118 del element.attributes[name]
123 elif name in ATTRIBUTES_TO_MAP_NS_VALUES: 119 else:
124 # TODO(kkimlabs): Enable warning once layouts have been converted 120 WarnDeprecatedAttribute(name, value, input_file)
125 # print >> sys.stderror, 'Warning: layout should use xxx instead of yyy'
126 pass
127 121
128 build_utils.MakeDirectory(os.path.dirname(output_file)) 122 build_utils.MakeDirectory(os.path.dirname(output_file))
129 with open(output_file, 'w') as f: 123 with open(output_file, 'w') as f:
130 dom.writexml(f, '', ' ', '\n', encoding='utf-8') 124 dom.writexml(f, '', ' ', '\n', encoding='utf-8')
131 125
132 126
133 def GenerateV14XmlResourcesInDir(input_dir, output_dir, only_styles=False): 127 def GenerateV14XmlResourcesInDir(input_dir, output_dir, only_styles=False):
134 """Convert resources to API 14 compatible XML resources in the directory.""" 128 """Convert resources to API 14 compatible XML resources in the directory."""
135 for input_file in build_utils.FindInDirectory(input_dir, '*.xml'): 129 for input_file in build_utils.FindInDirectory(input_dir, '*.xml'):
136 output_file = os.path.join(output_dir, 130 output_file = os.path.join(output_dir,
137 os.path.relpath(input_file, input_dir)) 131 os.path.relpath(input_file, input_dir))
138 if only_styles: 132 if only_styles:
139 dom = minidom.parse(input_file) 133 dom = minidom.parse(input_file)
newt (away) 2013/05/10 01:15:49 instead of parsing input_file twice, I'd remove th
Kibeom Kim (inactive) 2013/05/10 02:14:27 Done.
140 if not dom.getElementsByTagName('style'): 134 if not dom.getElementsByTagName('style'):
141 continue 135 continue
142 GenerateV14StyleResource(dom, output_file) 136 GenerateV14StyleResource(input_file, output_file)
143 else: 137 else:
144 GenerateV14LayoutResource(input_file, output_file) 138 GenerateV14LayoutResource(input_file, output_file)
145 139
146 140
147 def ParseArgs(): 141 def ParseArgs():
148 """Parses command line options. 142 """Parses command line options.
149 143
150 Returns: 144 Returns:
151 An options object as from optparse.OptionsParser.parse_args() 145 An options object as from optparse.OptionsParser.parse_args()
152 """ 146 """
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 GenerateV14XmlResourcesInDir(input_dir, output_dir) 193 GenerateV14XmlResourcesInDir(input_dir, output_dir)
200 elif resource_type in ('values'): 194 elif resource_type in ('values'):
201 GenerateV14XmlResourcesInDir(input_dir, output_dir, only_styles=True) 195 GenerateV14XmlResourcesInDir(input_dir, output_dir, only_styles=True)
202 196
203 if options.stamp: 197 if options.stamp:
204 build_utils.Touch(options.stamp) 198 build_utils.Touch(options.stamp)
205 199
206 if __name__ == '__main__': 200 if __name__ == '__main__':
207 sys.exit(main(sys.argv)) 201 sys.exit(main(sys.argv))
208 202
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698