Mercurial > wikked
changeset 456:b1f899f5136d
wiki: Add support for builtin/readonly endpoints.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Wed, 10 Jan 2018 21:23:00 -0800 |
parents | b478eb51c4d5 |
children | 038b22935250 |
files | wikked/endpoint.py wikked/fs.py wikked/resources/defaults.cfg wikked/resources/special/User.md wikked/views/__init__.py wikked/webimpl/__init__.py wikked/webimpl/read.py wikked/wiki.py |
diffstat | 8 files changed, 112 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wikked/endpoint.py Wed Jan 10 21:23:00 2018 -0800 @@ -0,0 +1,29 @@ +import os.path + + +class EndpointInfo(object): + def __init__(self, name): + self.name = name + self.query = True + self.readonly = False + self.builtin = False + self.default = None + self.root_dir = None + + +_resources_root_dir = os.path.join(os.path.dirname(__file__), 'resources') + + +def create_endpoint_infos(config): + endpoints = {} + sections = [s for s in config.sections() if s.startswith('endpoint:')] + for s in sections: + ep = EndpointInfo(s[9:]) # 9 = len('endpoint:') + ep.query = config.getboolean(s, 'query', fallback=True) + ep.readonly = config.getboolean(s, 'readonly', fallback=False) + ep.default = config.get(s, 'default', fallback=None) + if config.get(s, '__is_builtin', fallback=False): + ep.builtin = True + ep.root_dir = os.path.join(_resources_root_dir, ep.name) + endpoints[ep.name] = ep + return endpoints
--- a/wikked/fs.py Wed Jan 10 21:21:25 2018 -0800 +++ b/wikked/fs.py Wed Jan 10 21:23:00 2018 -0800 @@ -15,9 +15,6 @@ valid_filename_pattern = re.compile('^[\w \.\-\(\)\[\]\\/]+$', re.UNICODE) -builtin_namespace_help = os.path.join(os.path.dirname(__file__), - 'resources', 'help') - class PageInfo(object): def __init__(self, url, path): @@ -40,12 +37,14 @@ """ def __init__(self, root, config): self.root = root + self.wiki = None self.excluded = None self.page_extensions = None self.default_extension = config.get('wiki', 'default_extension') - self.include_builtin_namespaces = True + self.include_builtin_endpoints = True def start(self, wiki): + self.wiki = wiki self.page_extensions = list(set( itertools.chain(*wiki.formatters.values()))) @@ -67,8 +66,9 @@ yield from self._getPageInfos(basepath) - if subdir is None and self.include_builtin_namespaces: - yield from self._getPageInfos(builtin_namespace_help) + if subdir is None and self.include_builtin_endpoints: + for ep in self.wiki.getBuiltinEndpoints(): + yield from self._getPageInfos(ep.root_dir) def getPageInfo(self, path): logger.debug("Reading page info from: %s" % path) @@ -131,9 +131,12 @@ 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:] + elif self.include_builtin_endpoints: + for ep in self.wiki.getBuiltinEndpoints(): + if abs_path.startswith(ep.root_dir): + meta = ep.name + rel_path = abs_path[len(ep.root_dir) + 1:] + break rel_path_split = os.path.splitext(rel_path) ext = rel_path_split[1].lstrip('.') name = rel_path_split[0].replace(os.sep, '/') @@ -159,7 +162,11 @@ # page file. root = self.root if endpoint: - root = os.path.join(self.root, META_ENDPOINT, endpoint) + ep_info = self.wiki.getEndpoint(endpoint) + if ep_info is None or not ep_info.builtin: + root = os.path.join(self.root, META_ENDPOINT, endpoint) + else: + root = ep_info.root_dir # Make the URL into a relative file-system path. url_path = url[1:].replace('/', os.sep)
--- a/wikked/resources/defaults.cfg Wed Jan 10 21:21:25 2018 -0800 +++ b/wikked/resources/defaults.cfg Wed Jan 10 21:23:00 2018 -0800 @@ -8,13 +8,19 @@ database=sql database_url=sqlite:///%(root)s/.wiki/wiki.db -[endpoint:special] -query=False - [endpoint:templates] query=False [endpoint:user] query=False -default=special:User +default=special:/User + +[endpoint:special] +query=False +__is_builtin=True +[endpoint:help] +query=False +readonly=True +__is_builtin=True +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wikked/resources/special/User.md Wed Jan 10 21:23:00 2018 -0800 @@ -0,0 +1,5 @@ + +This is your personal wiki page. You can write whatever you want here, +although it's customary to start with a short presentation and some contact +information. +
--- a/wikked/views/__init__.py Wed Jan 10 21:21:25 2018 -0800 +++ b/wikked/views/__init__.py Wed Jan 10 21:23:00 2018 -0800 @@ -1,7 +1,8 @@ import urllib.parse from flask import request, url_for from flask.ext.login import current_user -from wikked.utils import get_url_folder +from wikked.utils import get_url_folder, split_page_url +from wikked.web import get_wiki def add_auth_data(data): @@ -26,8 +27,13 @@ home=True, new_page=True, read=False, edit=False, history=False, inlinks=False, upload=False, raw_url=None, extras=None, footers=None): + is_readonly_endpoint = False if url is not None: url = url.lstrip('/') + endpoint, _ = split_page_url(url) + if endpoint: + epinfo = get_wiki().getEndpoint(endpoint) + is_readonly_endpoint = (epinfo is not None and epinfo.readonly) elif read or edit or history or inlinks: raise Exception("Default navigation entries require a valid URL.") @@ -38,14 +44,14 @@ if home: nav['url_home'] = '/' - if new_page: + if new_page and not is_readonly_endpoint: url_folder = get_url_folder(url).lstrip('/') nav['url_new'] = url_for('create_page', url_folder=url_folder) if read: nav['url_read'] = url_for('read', url=url) - if edit: + if edit and not is_readonly_endpoint: nav['url_edit'] = url_for('edit_page', url=url) - if history: + if history and not is_readonly_endpoint: nav['url_hist'] = url_for('page_history', url=url) if inlinks: @@ -55,7 +61,7 @@ 'icon': 'link' }) - if upload: + if upload and not is_readonly_endpoint: nav['extras'].append({ 'title': "Upload File", 'url': url_for('upload_file', p=url),
--- a/wikked/webimpl/__init__.py Wed Jan 10 21:21:25 2018 -0800 +++ b/wikked/webimpl/__init__.py Wed Jan 10 21:23:00 2018 -0800 @@ -214,14 +214,14 @@ return builder -def make_page_title(url): +def make_page_title(url, include_endpoint=False): endpoint, path = split_page_url(url) last_slash = path.rstrip('/').rfind('/') if last_slash < 0 or last_slash == 0: title = path.lstrip('/') else: title = path[last_slash + 1:] - if endpoint: + if include_endpoint and endpoint: return '%s: %s' % (endpoint, title) return title
--- a/wikked/webimpl/read.py Wed Jan 10 21:21:25 2018 -0800 +++ b/wikked/webimpl/read.py Wed Jan 10 21:23:00 2018 -0800 @@ -1,7 +1,8 @@ import os.path import urllib.parse from wikked.webimpl import ( - get_redirect_target, get_page_meta, get_page_or_raise) + get_redirect_target, get_page_meta, get_page_or_raise, + make_page_title) from wikked.utils import split_page_url, PageNotFoundError @@ -40,15 +41,17 @@ # found that's OK. info_page = None + info_page_is_default = False endpoint_info = wiki.endpoints.get(endpoint) - if endpoint_info is not None: - # We have some information about this endpoint... - if endpoint_info.default and info_page is None: - # Default page text. - info_page = get_page_or_raise( - wiki, endpoint_info.default, - fields=['url', 'path', 'title', 'text', 'meta'], - check_perms=(user, 'read')) + if (endpoint_info is not None and endpoint_info.default and + info_page is None): + # We have no actual page to show, but we have a default one + # that we can use for this endpoint. + info_page = get_page_or_raise( + wiki, endpoint_info.default, + fields=['url', 'path', 'title', 'text', 'meta'], + check_perms=(user, 'read')) + info_page_is_default = True ext = None if info_page is not None: @@ -64,6 +67,20 @@ 'text': info_page.text, 'page_title': info_page.title, 'format': ext} + + if info_page_is_default: + # If our page is actually the endpoint's default page + # because the real page didn't exist, we need to change + # the title to match the page that we wanted originally. + # We also fix the URL so navigation links to edit/create + # the page acts on the wanted page -- not the default info + # page. + wanted_page_title = make_page_title(meta_page_url) + result['page_title'] = wanted_page_title + result['meta']['title'] = wanted_page_title + result['meta']['url'] = urllib.parse.quote( + meta_page_url.encode('utf-8')) + result.update(additional_info) return result raise PageNotFoundError(url)
--- a/wikked/wiki.py Wed Jan 10 21:21:25 2018 -0800 +++ b/wikked/wiki.py Wed Jan 10 21:23:00 2018 -0800 @@ -6,6 +6,7 @@ import multiprocessing from configparser import SafeConfigParser, NoOptionError from wikked.db.base import DatabaseUpgradeRequired +from wikked.endpoint import create_endpoint_infos from wikked.fs import FileSystem from wikked.auth import UserManager from wikked.scheduler import ResolveScheduler @@ -204,13 +205,6 @@ "No such source control: " + scm_type) -class EndpointInfo(object): - def __init__(self, name): - self.name = name - self.query = True - self.default = None - - class Wiki(object): """ The wiki class! This is where the magic happens. """ @@ -233,7 +227,7 @@ self.templates_url = ( parameters.config.get('wiki', 'templates_endpoint') + ':/') - self.endpoints = self._createEndpointInfos(parameters.config) + self.endpoints = create_endpoint_infos(parameters.config) self.fs = parameters.fs_factory() self.index = parameters.index_factory() @@ -436,21 +430,16 @@ def getSpecialFilenames(self): return self.special_filenames - def _createEndpointInfos(self, config): - endpoints = {} - sections = [s for s in config.sections() if s.startswith('endpoint:')] - for s in sections: - ep = EndpointInfo(s[9:]) # 9 = len('endpoint:') - if config.has_option(s, 'query'): - ep.query = config.getboolean(s, 'query') - 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 + def getEndpoints(self): + return self.endpoints.values() + + def getEndpoint(self, name): + return self.endpoints.get(name) + + def getBuiltinEndpoints(self): + for ep in self.endpoints.values(): + if ep.builtin: + yield ep def reloader_stat_loop(wiki, interval=1):