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

Side by Side Diff: third_party/closure_compiler/processor.py

Issue 476453002: Python readability review for dbeam@. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove space Created 5 years, 9 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 | « third_party/closure_compiler/compiler_customization_test.py ('k') | 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 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Process Chrome resources (HTML/CSS/JS) to handle <include> and <if> tags.""" 5 """Process Chrome resources (HTML/CSS/JS) to handle <include> and <if> tags."""
6 6
7 from collections import defaultdict 7 from collections import defaultdict
8 import re 8 import re
9 import os 9 import os
10 10
11 11
12 class LineNumber(object): 12 class LineNumber(object):
13 """A simple wrapper to hold line information (e.g. file.js:32). 13 """A simple wrapper to hold line information (e.g. file.js:32)."""
14
15 Args:
16 source_file: A file path.
17 line_number: The line in |file|.
18 """
19 def __init__(self, source_file, line_number): 14 def __init__(self, source_file, line_number):
15 """
16 Args:
17 source_file: A file path (as a string).
18 line_number: The line in |file| (as an integer).
19 """
20 self.file = source_file 20 self.file = source_file
21 self.line_number = int(line_number) 21 self.line_number = int(line_number)
22 22
23 23
24 class FileCache(object): 24 class FileCache(object):
25 """An in-memory cache to speed up reading the same files over and over. 25 """An in-memory cache to speed up reading the same files over and over.
26 26
27 Usage: 27 Usage:
28 FileCache.read(path_to_file) 28 FileCache.read(path_to_file)
29 """ 29 """
30 30
31 _cache = defaultdict(str) 31 _cache = defaultdict(str)
32 32
33 @classmethod 33 @classmethod
34 def read(self, source_file): 34 def read(self, source_file):
35 """Read a file and return it as a string. 35 """Read a file and return it as a string.
36 36
37 Args: 37 Args:
38 source_file: a file to read and return the contents of. 38 source_file: a file path (as a string) to read and return the contents.
39 39
40 Returns: 40 Returns:
41 |file| as a string. 41 The contents of |source_file| (as a string).
42 """ 42 """
43 abs_file = os.path.abspath(source_file) 43 abs_file = os.path.abspath(source_file)
44 self._cache[abs_file] = self._cache[abs_file] or open(abs_file, "r").read() 44 self._cache[abs_file] = self._cache[abs_file] or open(abs_file, "r").read()
45 return self._cache[abs_file] 45 return self._cache[abs_file]
46 46
47 47
48 class Processor(object): 48 class Processor(object):
49 """Processes resource files, inlining the contents of <include> tags, removing 49 """Processes resource files, inlining the contents of <include> tags, removing
50 <if> tags, and retaining original line info. 50 <if> tags, and retaining original line info.
51 51
52 For example 52 For example
53 53
54 1: /* blah.js */ 54 1: /* blah.js */
55 2: <if expr="is_win"> 55 2: <if expr="is_win">
56 3: <include src="win.js"> 56 3: <include src="win.js">
57 4: </if> 57 4: </if>
58 58
59 would be turned into: 59 would be turned into:
60 60
61 1: /* blah.js */ 61 1: /* blah.js */
62 2: 62 2:
63 3: /* win.js */ 63 3: /* win.js */
64 4: alert('Ew; Windows.'); 64 4: alert('Ew; Windows.');
65 5: 65 5:
66
67 Args:
68 source_file: A file to process.
69
70 Attributes:
71 contents: Expanded contents after inlining <include>s and stripping <if>s.
72 included_files: A list of files that were inlined via <include>.
73 """ 66 """
74 67
75 _IF_TAGS_REG = "</?if[^>]*?>" 68 _IF_TAGS_REG = "</?if[^>]*?>"
76 _INCLUDE_REG = "<include[^>]+src=['\"]([^>]*)['\"]>" 69 _INCLUDE_REG = "<include[^>]+src=['\"]([^>]*)['\"]>"
77 70
78 def __init__(self, source_file): 71 def __init__(self, source_file):
79 self._included_files = set() 72 """
73 Args:
74 source_file: A file path to process (as a string).
75 """
76 self.included_files = set()
80 self._index = 0 77 self._index = 0
81 self._lines = self._get_file(source_file) 78 self._lines = self._get_file(source_file)
82 79
80 # Can't enumerate(self._lines) here because some lines are re-processed.
83 while self._index < len(self._lines): 81 while self._index < len(self._lines):
84 current_line = self._lines[self._index] 82 current_line = self._lines[self._index]
85 match = re.search(self._INCLUDE_REG, current_line[2]) 83 match = re.search(self._INCLUDE_REG, current_line[2])
86 if match: 84 if match:
87 file_dir = os.path.dirname(current_line[0]) 85 file_dir = os.path.dirname(current_line[0])
88 file_name = os.path.abspath(os.path.join(file_dir, match.group(1))) 86 file_name = os.path.abspath(os.path.join(file_dir, match.group(1)))
89 if file_name not in self._included_files: 87 if file_name not in self.included_files:
90 self._include_file(file_name) 88 self._include_file(file_name)
91 continue # Stay on the same line. 89 continue # Stay on the same line.
92 else: 90 else:
93 # Found a duplicate <include>. Ignore and insert a blank line to 91 # Found a duplicate <include>. Ignore and insert a blank line to
94 # preserve line numbers. 92 # preserve line numbers.
95 self._lines[self._index] = self._lines[self._index][:2] + ("",) 93 self._lines[self._index] = self._lines[self._index][:2] + ("",)
96 self._index += 1 94 self._index += 1
97 95
98 for i, line in enumerate(self._lines): 96 for i, line in enumerate(self._lines):
99 self._lines[i] = line[:2] + (re.sub(self._IF_TAGS_REG, "", line[2]),) 97 self._lines[i] = line[:2] + (re.sub(self._IF_TAGS_REG, "", line[2]),)
100 98
101 self.contents = "\n".join(l[2] for l in self._lines) 99 self.contents = "\n".join(l[2] for l in self._lines)
102 100
103 # Returns a list of tuples in the format: (file, line number, line contents). 101 # Returns a list of tuples in the format: (file, line number, line contents).
104 def _get_file(self, source_file): 102 def _get_file(self, source_file):
105 lines = FileCache.read(source_file).splitlines() 103 lines = FileCache.read(source_file).splitlines()
106 return [(source_file, lnum + 1, line) for lnum, line in enumerate(lines)] 104 return [(source_file, lnum + 1, line) for lnum, line in enumerate(lines)]
107 105
108 def _include_file(self, source_file): 106 def _include_file(self, source_file):
109 self._included_files.add(source_file) 107 self.included_files.add(source_file)
110 f = self._get_file(source_file) 108 f = self._get_file(source_file)
111 self._lines = self._lines[:self._index] + f + self._lines[self._index + 1:] 109 self._lines = self._lines[:self._index] + f + self._lines[self._index + 1:]
112 110
113 def get_file_from_line(self, line_number): 111 def get_file_from_line(self, line_number):
114 """Get the original file and line number for an expanded file's line number. 112 """Get the original file and line number for an expanded file's line number.
115 113
116 Args: 114 Args:
117 line_number: A processed file's line number. 115 line_number: A processed file's line number (as an integer or string).
118 """ 116 """
119 line_number = int(line_number) - 1 117 line_number = int(line_number) - 1
120 return LineNumber(self._lines[line_number][0], self._lines[line_number][1]) 118 return LineNumber(self._lines[line_number][0], self._lines[line_number][1])
121
122 @property
123 def included_files(self):
124 """A list of files that were inlined via <include>."""
125 return self._included_files
OLDNEW
« no previous file with comments | « third_party/closure_compiler/compiler_customization_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698