1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
6 from tvcm import resource as resource_module
7 from tvcm import resource_loader
9 def _FindAllFilesRecursive(source_paths):
11 for source_path in source_paths:
12 for dirpath, dirnames, filenames in os.walk(source_path):
16 x = os.path.abspath(os.path.join(dirpath, f))
20 def _IsFilenameAModule(loader, x):
21 if x.endswith('.html'):
27 def _IsFilenameATest(loader, x):
28 if x.endswith('_test.js'):
31 if x.endswith('_test.html'):
34 if x.endswith('_unittest.js'):
37 if x.endswith('_unittest.html'):
40 # TODO(nduca): Add content test?
43 class AbsFilenameList(object):
44 def __init__(self, willDirtyCallback):
45 self._willDirtyCallback = willDirtyCallback
47 self._filenames_set = set()
49 def _WillBecomeDirty(self):
50 if self._willDirtyCallback:
51 self._willDirtyCallback()
53 def append(self, filename):
54 assert os.path.isabs(filename)
55 self._WillBecomeDirty()
56 self._filenames.append(filename)
57 self._filenames_set.add(filename)
59 def extend(self, iter):
60 self._WillBecomeDirty()
62 assert os.path.isabs(filename)
63 self._filenames.append(filename)
64 self._filenames_set.add(filename)
66 def appendRel(self, basedir, filename):
67 assert os.path.isabs(basedir)
68 self._WillBecomeDirty()
69 n = os.path.abspath(os.path.join(basedir, filename))
70 self._filenames.append(n)
71 self._filenames_set.add(n)
73 def extendRel(self, basedir, iter):
74 self._WillBecomeDirty()
75 assert os.path.isabs(basedir)
77 n = os.path.abspath(os.path.join(basedir, filename))
78 self._filenames.append(n)
79 self._filenames_set.add(n)
81 def __contains__(self, x):
82 return x in self._filenames_set
85 return self._filenames.__len__()
88 return iter(self._filenames)
91 return repr(self._filenames)
94 return str(self._filenames)
97 class Project(object):
98 tvcm_path = os.path.abspath(os.path.join(
99 os.path.dirname(__file__), '..'))
101 tvcm_src_path = os.path.abspath(os.path.join(
104 def __init__(self, source_paths=None, include_tvcm_paths=True, non_module_html_files=None):
106 source_paths: A list of top-level directories in which modules and raw scripts can be found.
107 Module paths are relative to these directories.
111 self.source_paths = AbsFilenameList(self._WillPartOfPathChange)
112 self.non_module_html_files = AbsFilenameList(self._WillPartOfPathChange)
114 if include_tvcm_paths:
115 self.source_paths.append(self.tvcm_src_path)
117 if source_paths != None:
118 self.source_paths.extend(source_paths)
120 if non_module_html_files != None:
121 self.non_module_html_files.extend(non_module_html_files)
126 def _WillPartOfPathChange(self):
128 raise Exception('The project is frozen. You cannot edit it now')
133 return Project(d['source_paths'],
134 include_tvcm_paths=False,
135 non_module_html_files=d.get('non_module_html_files', None))
139 'source_paths': list(self.source_paths),
140 'non_module_html_files': list(self.non_module_html_files)
144 return "Project(%s)" % repr(self.source_paths)
146 def AddSourcePath(self, path):
147 self.source_paths.append(path)
151 if self._loader == None:
152 self._loader = resource_loader.ResourceLoader(self)
155 def ResetLoader(self):
158 def _FindAllModuleFilenames(self, source_paths):
159 all_filenames = _FindAllFilesRecursive(source_paths)
160 return [x for x in all_filenames if
161 x not in self.non_module_html_files and
162 _IsFilenameAModule(self.loader, x)]
164 def _FindTestModuleFilenames(self, source_paths):
165 all_filenames = _FindAllFilesRecursive(source_paths)
166 return [x for x in all_filenames if
167 x not in self.non_module_html_files and
168 _IsFilenameATest(self.loader, x)]
170 def FindAllTestModuleResources(self, start_path=None):
171 if start_path == None:
172 test_module_filenames = self._FindTestModuleFilenames(self.source_paths)
174 test_module_filenames = self._FindTestModuleFilenames([start_path])
175 test_module_filenames.sort()
177 # Find the equivalent resources.
178 return [self.loader.FindResourceGivenAbsolutePath(x)
179 for x in test_module_filenames]
181 def FindAllModuleFilenames(self):
182 return self._FindAllModuleFilenames(self.source_paths)
184 def CalcLoadSequenceForAllModules(self):
185 filenames = self.FindAllModuleFilenames()
186 return self.CalcLoadSequenceForModuleFilenames(filenames)
188 def _Load(self, filenames):
189 return [self.loader.LoadModule(module_filename=filename) for
190 filename in filenames]
192 def CalcLoadSequenceForModuleFilenames(self, filenames):
193 modules = self._Load(filenames)
194 return self.CalcLoadSequenceForModules(modules)
196 def CalcLoadSequenceForModuleNames(self, module_names):
197 modules = [self.loader.LoadModule(module_name=name) for
198 name in module_names]
199 return self.CalcLoadSequenceForModules(modules)
201 def CalcLoadSequenceForModules(self, modules):
202 already_loaded_set = set()
205 m.ComputeLoadSequenceRecursive(load_sequence, already_loaded_set)