changeset 448:c78eaebced8b

fs: Add support for builtin namespaces. Add stub page for a `help` namespace.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 07 Jan 2018 11:05:55 -0800
parents 8ca8c2713c92
children ecc1c1e3e04c
files tests/mock.py wikked/fs.py wikked/resources/help/Help Contents.md wikked/wiki.py
diffstat 4 files changed, 53 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/tests/mock.py	Wed Jan 03 01:04:53 2018 -0800
+++ b/tests/mock.py	Sun Jan 07 11:05:55 2018 -0800
@@ -91,6 +91,7 @@
 class MockFileSystem(FileSystem):
     def __init__(self, root, config, structure=None):
         super(MockFileSystem, self).__init__(root, config)
+        self.include_builtin_namespaces = False
         if not structure:
             self.structure = {}
         else:
@@ -99,6 +100,8 @@
     def getPageInfos(self, subdir=None):
         def tmp_walk(path):
             node = self._getNode(path)
+            if node is None:
+                raise Exception("No node at %s" % path)
             return mock_os_walk(path, node)
 
         orig_walk = os.walk
@@ -134,6 +137,8 @@
     def _getPhysicalPath(self, url, is_file=True, make_new=False):
         def tmp_walk(path):
             node = self._getNode(path)
+            if node is None:
+                raise Exception("No node at %s" % path)
             return mock_os_walk(path, node)
 
         orig_walk = os.walk
--- a/wikked/fs.py	Wed Jan 03 01:04:53 2018 -0800
+++ b/wikked/fs.py	Sun Jan 07 11:05:55 2018 -0800
@@ -6,16 +6,17 @@
 import logging
 import itertools
 from .utils import (PageNotFoundError, NamespaceNotFoundError,
-        split_page_url)
+                    split_page_url)
 
 
 META_ENDPOINT = '_meta'
 
-
 logger = logging.getLogger(__name__)
 
+valid_filename_pattern = re.compile('^[\w \.\-\(\)\[\]\\/]+$', re.UNICODE)
 
-valid_filename_pattern = re.compile('^[\w \.\-\(\)\[\]\\/]+$', re.UNICODE)
+builtin_namespace_help = os.path.join(os.path.dirname(__file__),
+                                      'resources', 'help')
 
 
 class PageInfo(object):
@@ -39,10 +40,10 @@
     """
     def __init__(self, root, config):
         self.root = root
-
         self.excluded = None
         self.page_extensions = None
         self.default_extension = config.get('wiki', 'default_extension')
+        self.include_builtin_namespaces = True
 
     def start(self, wiki):
         self.page_extensions = list(set(
@@ -64,22 +65,10 @@
         if subdir is not None:
             basepath = self.getPhysicalNamespacePath(subdir)
 
-        logger.debug("Scanning for pages in: %s" % basepath)
-        for dirpath, dirnames, filenames in os.walk(basepath):
-            incl_dirnames = []
-            for d in dirnames:
-                full_d = os.path.join(dirpath, d)
-                for e in self.excluded:
-                    if fnmatch.fnmatch(full_d, e):
-                        break
-                else:
-                    incl_dirnames.append(d)
-            dirnames[:] = incl_dirnames
-            for filename in filenames:
-                path = os.path.join(dirpath, filename)
-                page_info = self.getPageInfo(path)
-                if page_info is not None:
-                    yield page_info
+        yield from self._getPageInfos(basepath)
+
+        if subdir is None and self.include_builtin_namespaces:
+            yield from self._getPageInfos(builtin_namespace_help)
 
     def getPageInfo(self, path):
         logger.debug("Reading page info from: %s" % path)
@@ -117,6 +106,24 @@
     def getPhysicalNamespacePath(self, url, make_new=False):
         return self._getPhysicalPath(url, is_file=False, make_new=make_new)
 
+    def _getPageInfos(self, root_dir):
+        logger.debug("Scanning for pages in: %s" % root_dir)
+        for dirpath, dirnames, filenames in os.walk(root_dir):
+            incl_dirnames = []
+            for d in dirnames:
+                full_d = os.path.join(dirpath, d)
+                for e in self.excluded:
+                    if fnmatch.fnmatch(full_d, e):
+                        break
+                else:
+                    incl_dirnames.append(d)
+            dirnames[:] = incl_dirnames
+            for filename in filenames:
+                path = os.path.join(dirpath, filename)
+                page_info = self.getPageInfo(path)
+                if page_info is not None:
+                    yield page_info
+
     def _getPageInfo(self, path):
         meta = None
         abs_path = os.path.abspath(path)
@@ -124,12 +131,16 @@
         if rel_path.startswith(META_ENDPOINT + os.sep):
             rel_path = rel_path[len(META_ENDPOINT) + 1:]
             meta, rel_path = rel_path.split(os.sep, 1)
+        elif abs_path.startswith(builtin_namespace_help):
+            meta = 'help'
+            rel_path = abs_path[len(builtin_namespace_help) + 1:]
         rel_path_split = os.path.splitext(rel_path)
         ext = rel_path_split[1].lstrip('.')
         name = rel_path_split[0].replace(os.sep, '/')
         if len(ext) == 0:
             return None
-        if self.page_extensions is not None and ext not in self.page_extensions:
+        if (self.page_extensions is not None and
+                ext not in self.page_extensions):
             return None
 
         url = '/' + name
@@ -154,7 +165,7 @@
         url_path = url[1:].replace('/', os.sep)
         if url_path[0] == os.sep:
             raise ValueError("Page URLs can only have one slash at the "
-                    "beginning. Got: %s" % url)
+                             "beginning. Got: %s" % url)
 
         # If we want a non-existing file's path, just build that.
         if make_new:
@@ -189,7 +200,8 @@
 
     def _throwNotFoundError(self, url, searched, is_file):
         if is_file:
-            raise PageNotFoundError("No such page '%s' in: %s" % (url, searched))
+            raise PageNotFoundError("No such page '%s' in: %s" %
+                                    (url, searched))
         else:
-            raise NamespaceNotFoundError("No such namespace '%s' in: %s" % (url, searched))
-
+            raise NamespaceNotFoundError("No such namespace '%s' in: %s" %
+                                         (url, searched))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wikked/resources/help/Help Contents.md	Sun Jan 07 11:05:55 2018 -0800
@@ -0,0 +1,7 @@
+
+Welcome to the [Wikked][] help. These pages provide information and guidance
+about how to use your wiki.
+
+
+[wikked]: https://bolt80.com/wikked/
+
--- a/wikked/wiki.py	Wed Jan 03 01:04:53 2018 -0800
+++ b/wikked/wiki.py	Sun Jan 07 11:05:55 2018 -0800
@@ -446,6 +446,10 @@
             if config.has_option(s, 'default'):
                 ep.default = config.get(s, 'default')
             endpoints[ep.name] = ep
+        # The 'help' endpoint is built-in and is always the same.
+        help_ep = EndpointInfo('help')
+        help_ep.query = False
+        endpoints['help'] = help_ep
         return endpoints