Chromium Code Reviews| Index: chrome/common/extensions/docs/server2/intro_data_source.py |
| diff --git a/chrome/common/extensions/docs/server2/intro_data_source.py b/chrome/common/extensions/docs/server2/intro_data_source.py |
| index 53034de158b96cc522a2abb5cde5c5cfb00ca76a..3b86bbbdaf8a29f8779f2236b339579c6dd04fbe 100644 |
| --- a/chrome/common/extensions/docs/server2/intro_data_source.py |
| +++ b/chrome/common/extensions/docs/server2/intro_data_source.py |
| @@ -3,13 +3,13 @@ |
| # found in the LICENSE file. |
| from HTMLParser import HTMLParser |
| +import functools |
|
not at google - send to devlin
2013/05/03 15:56:25
f < H
jshumway
2013/05/10 02:08:36
Done.
|
| import logging |
| import os |
| import re |
| from docs_server_utils import FormatKey |
| from file_system import FileNotFoundError |
| -import compiled_file_system as compiled_fs |
| from third_party.handlebar import Handlebar |
| # TODO(kalman): rename this HTMLDataSource or other, then have separate intro |
| @@ -59,61 +59,85 @@ class _IntroParser(HTMLParser): |
| elif self._recent_tag in ['h2', 'h3']: |
| self._current_heading['title'] += data |
| +def _MakeIntroDict(ref_resolver, intro_path, intro): |
| + # Guess the name of the API from the path to the intro. |
| + api_name = os.path.splitext(intro_path.split('/')[-1])[0] |
| + intro_with_links = ref_resolver.ResolveAllLinks(intro, namespace=api_name) |
| + apps_parser = _IntroParser() |
| + apps_parser.feed(Handlebar(intro_with_links).render({ 'is_apps': True }).text) |
| + extensions_parser = _IntroParser() |
| + extensions_parser.feed(Handlebar(intro_with_links).render( |
| + { 'is_apps': False }).text) |
| + # TODO(cduvall): Use the normal template rendering system, so we can check |
| + # errors. |
| + if extensions_parser.page_title != apps_parser.page_title: |
| + logging.error( |
| + 'Title differs for apps and extensions: Apps: %s, Extensions: %s.' % |
| + (extensions_parser.page_title, apps_parser.page_title)) |
| + # The templates will render the heading themselves, so remove it from the |
| + # HTML content. |
| + intro_with_links = re.sub(_H1_REGEX, '', intro_with_links, count=1) |
| + return { |
| + 'intro': Handlebar(intro_with_links), |
| + 'title': apps_parser.page_title, |
| + 'apps_toc': apps_parser.toc, |
| + 'extensions_toc': extensions_parser.toc, |
| + } |
| + |
| class IntroDataSource(object): |
| - """This class fetches the intros for a given API. From this intro, a table |
| - of contents dictionary is created, which contains the headings in the intro. |
| + """ Allows a template to access the contents of a directory or one of its |
| + subdirectories. |
| + |
| + Each IntroDataSource has a dictionary of sub IntroDataSources that are used to |
| + access files in subdirectories. Each child IDS shares a cache and identity_fs |
| + with its parent. If subdirectory paths were added to base_paths instead, |
| + lookup time would have really bad time complexity. |
| """ |
| class Factory(object): |
| def __init__(self, compiled_fs_factory, ref_resolver_factory, base_paths): |
| - self._cache = compiled_fs_factory.Create(self._MakeIntroDict, |
| - IntroDataSource) |
| - self._ref_resolver = ref_resolver_factory.Create() |
| + self._cache = compiled_fs_factory.Create( |
| + functools.partial(_MakeIntroDict, ref_resolver_factory.Create()), |
| + IntroDataSource) |
| self._base_paths = base_paths |
| - |
| - def _MakeIntroDict(self, intro_path, intro): |
| - # Guess the name of the API from the path to the intro. |
| - api_name = os.path.splitext(intro_path.split('/')[-1])[0] |
| - intro_with_links = self._ref_resolver.ResolveAllLinks(intro, |
| - namespace=api_name) |
| - apps_parser = _IntroParser() |
| - apps_parser.feed(Handlebar(intro_with_links).render( |
| - { 'is_apps': True }).text) |
| - extensions_parser = _IntroParser() |
| - extensions_parser.feed(Handlebar(intro_with_links).render( |
| - { 'is_apps': False }).text) |
| - # TODO(cduvall): Use the normal template rendering system, so we can check |
| - # errors. |
| - if extensions_parser.page_title != apps_parser.page_title: |
| - logging.error( |
| - 'Title differs for apps and extensions: Apps: %s, Extensions: %s.' % |
| - (extensions_parser.page_title, apps_parser.page_title)) |
| - # The templates will render the heading themselves, so remove it from the |
| - # HTML content. |
| - intro_with_links = re.sub(_H1_REGEX, '', intro_with_links, count=1) |
| - return { |
| - 'intro': Handlebar(intro_with_links), |
| - 'title': apps_parser.page_title, |
| - 'apps_toc': apps_parser.toc, |
| - 'extensions_toc': extensions_parser.toc, |
| - } |
| + self._identity_fs = compiled_fs_factory.CreateIdentity(IntroDataSource) |
|
not at google - send to devlin
2013/05/03 15:56:25
hm ok, I don't think any of the changes to this fi
jshumway
2013/05/10 02:08:36
I reverted my changes to this file and everything
|
| def Create(self): |
| - return IntroDataSource(self._cache, self._base_paths) |
| + return IntroDataSource(self._cache, self._identity_fs, self._base_paths) |
| - def __init__(self, cache, base_paths): |
| + def __init__(self, cache, identity_fs, base_paths): |
| self._cache = cache |
| self._base_paths = base_paths |
| + self._identity_fs = identity_fs |
| + |
| + # Datasources for subdirectories. |
| + self._subIDS = {} |
| def get(self, key): |
| path = FormatKey(key) |
| + |
| def get_from_base_path(base_path): |
| - return self._cache.GetFromFile('%s/%s' % (base_path, path)) |
| + return self._cache.GetFromFile(os.path.join(base_path, path)) |
|
not at google - send to devlin
2013/05/03 15:56:25
caches always use '/' as a path separator, the cla
jshumway
2013/05/10 02:08:36
My bad
|
| + |
| for base_path in self._base_paths: |
| try: |
| return get_from_base_path(base_path) |
| except FileNotFoundError: |
| continue |
| + |
| + # File was not found, check if key is a subdirectory. |
| + for base_path in self._base_paths: |
| + subpath = os.path.join(base_path, key) |
| + try: |
| + subfiles = self._identity_fs.GetFromFileListing(subpath) |
| + except FileNotFoundError: |
| + continue |
| + |
| + if subfiles: |
| + self._subIDS[subpath] = IntroDataSource( |
| + self._cache, self._identity_fs, [subpath]) |
| + return self._subIDS[subpath] |
| + |
| # Not found. Do the first operation again so that we get a stack trace - we |
| # know that it'll fail. |
| get_from_base_path(self._base_paths[0]) |
| - raise AssertionError() |
| + raise AssertionError |