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
3# found in the LICENSE file.
4
5import os
6
7from compiled_file_system import Unicode
8from data_source import DataSource
9from docs_server_utils import FormatKey
10from extensions_paths import INTROS_TEMPLATES, ARTICLES_TEMPLATES
11from file_system import FileNotFoundError
12from future import Future
13from third_party.handlebar import Handlebar
14
15
16
17# TODO(kalman): rename this HTMLDataSource or other, then have separate intro
18# article data sources created as instances of it.
19class IntroDataSource(DataSource):
20  '''This class fetches the intros for a given API. From this intro, a table
21  of contents dictionary is created, which contains the headings in the intro.
22  '''
23
24  def __init__(self, server_instance, request):
25    self._request = request
26    self._cache = server_instance.compiled_fs_factory.Create(
27        server_instance.host_file_system_provider.GetTrunk(),
28        self._MakeIntro,
29        IntroDataSource)
30    self._ref_resolver = server_instance.ref_resolver_factory.Create()
31
32  @Unicode
33  def _MakeIntro(self, intro_path, intro):
34    # Guess the name of the API from the path to the intro.
35    api_name = os.path.splitext(intro_path.split('/')[-1])[0]
36    return Handlebar(
37        self._ref_resolver.ResolveAllLinks(intro,
38                                           relative_to=self._request.path,
39                                           namespace=api_name),
40        name=intro_path)
41
42  def get(self, key):
43    path = FormatKey(key)
44    def get_from_base_path(base_path):
45      return self._cache.GetFromFile('%s/%s' % (base_path, path)).Get()
46    base_paths = (INTROS_TEMPLATES, ARTICLES_TEMPLATES)
47    for base_path in base_paths:
48      try:
49        return get_from_base_path(base_path)
50      except FileNotFoundError:
51        continue
52    # Not found. Do the first operation again so that we get a stack trace - we
53    # know that it'll fail.
54    get_from_base_path(base_paths[0])
55    raise AssertionError()
56
57  def Cron(self):
58    # TODO(kalman): Walk through the intros and articles directory.
59    return Future(value=())
60