Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 import hashlib | 5 import hashlib |
| 6 import json | 6 import json |
| 7 import logging | 7 import logging |
| 8 import re | 8 import re |
| 9 | 9 |
| 10 import compiled_file_system as compiled_fs | 10 import compiled_file_system as compiled_fs |
| 11 from file_system import FileNotFoundError | 11 from file_system import FileNotFoundError |
| 12 from reference_resolver import ReferenceResolver | |
| 12 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater | 13 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater |
| 13 import third_party.json_schema_compiler.model as model | 14 import third_party.json_schema_compiler.model as model |
| 14 import url_constants | 15 import url_constants |
| 15 | 16 |
| 16 DEFAULT_ICON_PATH = '/images/sample-default-icon.png' | 17 DEFAULT_ICON_PATH = '/images/sample-default-icon.png' |
| 17 | 18 |
| 18 def _MakeAPILink(prefix, item, api_list): | |
| 19 item = item.replace('chrome.', '') | |
| 20 parts = item.split('.') | |
| 21 api_name = [] | |
| 22 for i in range(1, len(parts) + 1): | |
| 23 if '.'.join(parts[:i]) in api_list: | |
| 24 return '%s.html#%s-%s' % ('.'.join(parts[:i]), | |
| 25 prefix, | |
| 26 '.'.join(parts[i:])) | |
| 27 return None | |
| 28 | |
| 29 class SamplesDataSource(object): | 19 class SamplesDataSource(object): |
| 30 """Constructs a list of samples and their respective files and api calls. | 20 """Constructs a list of samples and their respective files and api calls. |
| 31 """ | 21 """ |
| 32 | 22 |
| 33 class Factory(object): | 23 class Factory(object): |
| 34 """A factory to create SamplesDataSource instances bound to individual | 24 """A factory to create SamplesDataSource instances bound to individual |
| 35 Requests. | 25 Requests. |
| 36 """ | 26 """ |
| 37 def __init__(self, | 27 def __init__(self, |
| 38 channel, | 28 channel, |
| 39 file_system, | 29 file_system, |
| 40 github_file_system, | 30 github_file_system, |
| 41 cache_factory, | 31 cache_factory, |
| 42 github_cache_factory, | 32 github_cache_factory, |
| 33 api_data_source_factory, | |
| 43 api_list_data_source_factory, | 34 api_list_data_source_factory, |
| 44 samples_path): | 35 samples_path): |
| 45 self._file_system = file_system | 36 self._file_system = file_system |
| 46 self._github_file_system = github_file_system | 37 self._github_file_system = github_file_system |
| 47 self._static_path = ((('/' + channel) if channel != 'local' else '') + | 38 self._static_path = ((('/' + channel) if channel != 'local' else '') + |
| 48 '/static') | 39 '/static') |
| 49 self._extensions_cache = cache_factory.Create(self._MakeSamplesList, | 40 self._extensions_cache = cache_factory.Create(self._MakeSamplesList, |
| 50 compiled_fs.EXTENSIONS) | 41 compiled_fs.EXTENSIONS) |
| 51 self._apps_cache = github_cache_factory.Create( | 42 self._apps_cache = github_cache_factory.Create( |
| 52 lambda x: self._MakeSamplesList(x, is_apps=True), | 43 lambda x: self._MakeSamplesList(x, is_apps=True), |
| 53 compiled_fs.APPS) | 44 compiled_fs.APPS) |
| 54 self._api_list_data_source = api_list_data_source_factory.Create() | |
| 55 self._samples_path = samples_path | 45 self._samples_path = samples_path |
| 46 self._reference_resolver = ReferenceResolver( | |
| 47 api_data_source_factory.Create(None, | |
| 48 self.Create(None), | |
| 49 resolve_refs=False), | |
| 50 api_list_data_source_factory.Create()) | |
|
not at google - send to devlin
2012/11/02 17:26:48
A good clue for when you need to introduce a Facto
cduvall
2012/11/03 01:30:05
Cool, thanks for the architecture tips they're sup
| |
| 56 | 51 |
| 57 def Create(self, request): | 52 def Create(self, request): |
| 58 """Returns a new SamplesDataSource bound to |request|. | 53 """Returns a new SamplesDataSource bound to |request|. |
| 59 """ | 54 """ |
| 60 return SamplesDataSource(self._extensions_cache, | 55 return SamplesDataSource(self._extensions_cache, |
| 61 self._apps_cache, | 56 self._apps_cache, |
| 62 self._samples_path, | 57 self._samples_path, |
| 63 request) | 58 request) |
| 64 | 59 |
| 65 def _GetAllAPINames(self): | |
| 66 apis = [] | |
| 67 for k1 in ['apps', 'extensions']: | |
| 68 for k2 in ['chrome', 'experimental']: | |
| 69 apis.extend( | |
| 70 [api['name'] for api in self._api_list_data_source[k1][k2]]) | |
| 71 return apis | |
| 72 | |
| 73 def _GetAPIItems(self, js_file): | 60 def _GetAPIItems(self, js_file): |
| 74 return set(re.findall('(chrome\.[a-zA-Z0-9\.]+)', js_file)) | 61 return set(re.findall('(chrome\.[a-zA-Z0-9\.]+)', js_file)) |
| 75 | 62 |
| 76 def _GetDataFromManifest(self, path, file_system): | 63 def _GetDataFromManifest(self, path, file_system): |
| 77 manifest = file_system.ReadSingle(path + '/manifest.json') | 64 manifest = file_system.ReadSingle(path + '/manifest.json') |
| 78 try: | 65 try: |
| 79 manifest_json = json.loads(json_comment_eater.Nom(manifest)) | 66 manifest_json = json.loads(json_comment_eater.Nom(manifest)) |
| 80 except ValueError as e: | 67 except ValueError as e: |
| 81 logging.error('Error parsing manifest.json for %s: %s' % (path, e)) | 68 logging.error('Error parsing manifest.json for %s: %s' % (path, e)) |
| 82 return None | 69 return None |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 101 except ValueError as e: | 88 except ValueError as e: |
| 102 logging.error('Error parsing locales files for %s: %s' % (path, e)) | 89 logging.error('Error parsing locales files for %s: %s' % (path, e)) |
| 103 else: | 90 else: |
| 104 for path, json_ in locales_json: | 91 for path, json_ in locales_json: |
| 105 l10n_data['locales'][path[len(locales_path):].split('/')[0]] = json_ | 92 l10n_data['locales'][path[len(locales_path):].split('/')[0]] = json_ |
| 106 return l10n_data | 93 return l10n_data |
| 107 | 94 |
| 108 def _MakeSamplesList(self, files, is_apps=False): | 95 def _MakeSamplesList(self, files, is_apps=False): |
| 109 file_system = self._github_file_system if is_apps else self._file_system | 96 file_system = self._github_file_system if is_apps else self._file_system |
| 110 samples_list = [] | 97 samples_list = [] |
| 111 api_list = self._GetAllAPINames() | |
| 112 for filename in sorted(files): | 98 for filename in sorted(files): |
| 113 if filename.rsplit('/')[-1] != 'manifest.json': | 99 if filename.rsplit('/')[-1] != 'manifest.json': |
| 114 continue | 100 continue |
| 115 # This is a little hacky, but it makes a sample page. | 101 # This is a little hacky, but it makes a sample page. |
| 116 sample_path = filename.rsplit('/', 1)[-2] | 102 sample_path = filename.rsplit('/', 1)[-2] |
| 117 sample_files = [path for path in files | 103 sample_files = [path for path in files |
| 118 if path.startswith(sample_path + '/')] | 104 if path.startswith(sample_path + '/')] |
| 119 js_files = [path for path in sample_files if path.endswith('.js')] | 105 js_files = [path for path in sample_files if path.endswith('.js')] |
| 120 try: | 106 try: |
| 121 js_contents = file_system.Read(js_files).Get() | 107 js_contents = file_system.Read(js_files).Get() |
| 122 except FileNotFoundError as e: | 108 except FileNotFoundError as e: |
| 123 logging.warning('Error fetching samples files: %s. Was a file ' | 109 logging.warning('Error fetching samples files: %s. Was a file ' |
| 124 'deleted from a sample? This warning should go away ' | 110 'deleted from a sample? This warning should go away ' |
| 125 'in 5 minutes.' % e) | 111 'in 5 minutes.' % e) |
| 126 continue | 112 continue |
| 127 api_items = set() | 113 api_items = set() |
| 128 for js in js_contents.values(): | 114 for js in js_contents.values(): |
| 129 api_items.update(self._GetAPIItems(js)) | 115 api_items.update(self._GetAPIItems(js)) |
| 130 | 116 |
| 131 api_calls = [] | 117 api_calls = [] |
| 132 for item in api_items: | 118 for item in api_items: |
| 133 if len(item.split('.')) < 3: | 119 if len(item.split('.')) < 3: |
| 134 continue | 120 continue |
| 135 if item.endswith('.removeListener') or item.endswith('.hasListener'): | 121 if item.endswith('.removeListener') or item.endswith('.hasListener'): |
| 136 continue | 122 continue |
| 137 if item.endswith('.addListener'): | 123 if item.endswith('.addListener'): |
| 138 item = item[:-len('.addListener')] | 124 item = item[:-len('.addListener')] |
| 139 link = _MakeAPILink('event', item, api_list) | 125 if item.startswith('chrome.'): |
| 140 if link is None: | 126 item = item[len('chrome.'):] |
| 141 continue | 127 ref_data = self._reference_resolver.GetLinkToRefType('samples', item) |
| 142 api_calls.append({ | 128 if ref_data is None: |
| 143 'name': item, | 129 continue |
| 144 'link': link | 130 api_calls.append({ |
| 145 }) | 131 'name': ref_data['text'], |
| 146 else: | 132 'link': ref_data['href'] |
| 147 # TODO(cduvall): this might be a property or a type. | 133 }) |
| 148 link = _MakeAPILink('method', item, api_list) | |
| 149 if link is None: | |
| 150 continue | |
| 151 api_calls.append({ | |
| 152 'name': item, | |
| 153 'link': link | |
| 154 }) | |
| 155 try: | 134 try: |
| 156 manifest_data = self._GetDataFromManifest(sample_path, file_system) | 135 manifest_data = self._GetDataFromManifest(sample_path, file_system) |
| 157 except FileNotFoundError as e: | 136 except FileNotFoundError as e: |
| 158 logging.warning('Error getting data from samples manifest: %s. If ' | 137 logging.warning('Error getting data from samples manifest: %s. If ' |
| 159 'this file was deleted from a sample this message ' | 138 'this file was deleted from a sample this message ' |
| 160 'should go away in 5 minutes.' % e) | 139 'should go away in 5 minutes.' % e) |
| 161 continue | 140 continue |
| 162 if manifest_data is None: | 141 if manifest_data is None: |
| 163 continue | 142 continue |
| 164 | 143 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 return return_list | 235 return return_list |
| 257 | 236 |
| 258 def __getitem__(self, key): | 237 def __getitem__(self, key): |
| 259 return self.get(key) | 238 return self.get(key) |
| 260 | 239 |
| 261 def get(self, key): | 240 def get(self, key): |
| 262 return { | 241 return { |
| 263 'apps': lambda: self._CreateSamplesDict('apps'), | 242 'apps': lambda: self._CreateSamplesDict('apps'), |
| 264 'extensions': lambda: self._CreateSamplesDict('extensions') | 243 'extensions': lambda: self._CreateSamplesDict('extensions') |
| 265 }.get(key, lambda: {})() | 244 }.get(key, lambda: {})() |
| OLD | NEW |