From 19dbe6d4a2b8bb349844500aaba94c7fc7fc543c Mon Sep 17 00:00:00 2001 From: Johannes Ammon Date: Sun, 26 Apr 2015 06:56:39 +0200 Subject: [PATCH 1/6] Build the list of pages only once --- cactus/site.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/cactus/site.py b/cactus/site.py index 052366a7..242fe033 100644 --- a/cactus/site.py +++ b/cactus/site.py @@ -340,24 +340,19 @@ def buildStatic(self): def pages(self): """ List of pages. + This routine is called from different places, + but builds the page list only once """ - if not hasattr(self, "_page_cache"): self._page_cache = {} - pages = [] - - for path in fileList(self.page_path, relative=True): - - if path.endswith("~"): - continue - - if not self._page_cache.has_key(path): + for path in fileList(self.page_path, relative=True): + # ignore backup files + if path.endswith("~"): + continue self._page_cache[path] = Page(self, path) - pages.append(self._page_cache[path]) - - return pages + return self._page_cache.values() def _rebuild_should_ignore(self, file_path): From e74626107bc5b9769b084bb4f7835d871f3f3746 Mon Sep 17 00:00:00 2001 From: Johannes Ammon Date: Sun, 26 Apr 2015 08:00:44 +0200 Subject: [PATCH 2/6] Renamed method for clarification and readability --- cactus/page.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cactus/page.py b/cactus/page.py index 7816e6b3..5fedb2bd 100644 --- a/cactus/page.py +++ b/cactus/page.py @@ -64,7 +64,7 @@ def full_source_path(self): def full_build_path(self): return os.path.join(self.site.build_path, self.build_path) - def data(self): + def read_data(self): with open(self.full_source_path, 'rU') as f: try: return f.read().decode('utf-8') @@ -80,7 +80,7 @@ def context(self, data=None, extra=None): context = {'__CACTUS_CURRENT_PAGE__': self,} - page_context, data = self.parse_context(data or self.data()) + page_context, data = self.parse_context(data or self.read_data()) context.update(self.site.context()) context.update(extra) @@ -93,7 +93,7 @@ def render(self): Takes the template data with context and renders it to the final output file. """ - data = self.data() + data = self.read_data() context = self.context(data=data) # This is not very nice, but we already used the header context in the From 561db5dc6cd8d80ea0907e5b47161e2e6c0fb5e7 Mon Sep 17 00:00:00 2001 From: Johannes Ammon Date: Sun, 26 Apr 2015 08:04:33 +0200 Subject: [PATCH 3/6] Simplifying code, adding to documentation --- README.md | 9 +++++++++ cactus/page.py | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6ea94d44..c682cb5a 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,15 @@ Cactus makes it easy to relatively link to pages and static assets inside your p Just use the URL you would normally use: don't forget the leading slash. +You can add extra context to your pages. Just insert it on the top of the file like this: + + name: koen + age: 29 + + {% extends "base.html" %} + … + +which will be converted to a dict: `{'name': 'koen', 'age': '29'}` and added to the context. ### Templates diff --git a/cactus/page.py b/cactus/page.py index 5fedb2bd..cebb2a79 100644 --- a/cactus/page.py +++ b/cactus/page.py @@ -149,8 +149,8 @@ def parse_context(self, data, splitChar=':'): continue elif splitChar in line: - line = line.split(splitChar) - values[line[0].strip()] = (splitChar.join(line[1:])).strip() + line = line.split(splitChar, 1) + values[line[0].strip()] = line[1].strip() else: break From f8c8227a30f578604c468e952e916d3b5adfd45e Mon Sep 17 00:00:00 2001 From: Johannes Ammon Date: Sun, 26 Apr 2015 08:36:58 +0200 Subject: [PATCH 4/6] Changed methods to properties which are set in __init__ --- cactus/page.py | 19 ++++++++----------- cactus/site.py | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/cactus/page.py b/cactus/page.py index cebb2a79..738444a1 100644 --- a/cactus/page.py +++ b/cactus/page.py @@ -24,10 +24,13 @@ def __init__(self, site, source_path): # The URL where this element should be linked in "base" pages self.link_url = '/{0}'.format(self.source_path) + self.is_html = urlparse.urlparse(self.source_path).path.endswith('.html') + self.is_index = urlparse.urlparse(self.source_path).path.endswith('index.html') + if self.site.prettify_urls: # The URL where this element should be linked in "built" pages - if self.is_html(): - if self.is_index(): + if self.is_html: + if self.is_index: self.final_url = self.link_url.rsplit('index.html', 1)[0] else: self.final_url = '{0}/'.format(self.link_url.rsplit('.html', 1)[0]) @@ -35,7 +38,7 @@ def __init__(self, site, source_path): self.final_url = self.link_url # The path where this element should be built to - if not self.is_html() or self.source_path.endswith('index.html'): + if not self.is_html or self.source_path.endswith('index.html'): self.build_path = self.source_path else: self.build_path = '{0}/{1}'.format(self.source_path.rsplit('.html', 1)[0], 'index.html') @@ -43,12 +46,6 @@ def __init__(self, site, source_path): self.final_url = self.link_url self.build_path = self.source_path - def is_html(self): - return urlparse.urlparse(self.source_path).path.endswith('.html') - - def is_index(self): - return urlparse.urlparse(self.source_path).path.endswith('index.html') - @property def absolute_final_url(self): """ @@ -135,8 +132,8 @@ def parse_context(self, data, splitChar=':'): will be converted in a dict: {'name': 'koen', 'age': '29'} """ - if not self.is_html(): - return {}, data + if not self.is_html: + return {} values = {} lines = data.splitlines() diff --git a/cactus/site.py b/cactus/site.py index 242fe033..de755cef 100644 --- a/cactus/site.py +++ b/cactus/site.py @@ -175,7 +175,7 @@ def context(self): """ ctx = { 'CACTUS': { - 'pages': [p for p in self.pages() if p.is_html()], + 'pages': [p for p in self.pages() if p.is_html], 'static': [p for p in self.static()] }, '__CACTUS_SITE__': self, From 5d00d694cfa6970db5809b94a938d68044497ab3 Mon Sep 17 00:00:00 2001 From: Johannes Ammon Date: Sun, 26 Apr 2015 08:59:56 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=E2=80=9Adata=E2=80=98=20should=20be=20a=20?= =?UTF-8?q?property=20of=20Page=20and=20should=20not=20be=20passed=20aroun?= =?UTF-8?q?d=20as=20parameter=20(tests=20failing!)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cactus/page.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/cactus/page.py b/cactus/page.py index 738444a1..eceab8c8 100644 --- a/cactus/page.py +++ b/cactus/page.py @@ -46,6 +46,8 @@ def __init__(self, site, source_path): self.final_url = self.link_url self.build_path = self.source_path + self.data = self.read_data() + @property def absolute_final_url(self): """ @@ -68,7 +70,7 @@ def read_data(self): except: logger.warning("Template engine could not process page: %s", self.path) - def context(self, data=None, extra=None): + def context(self, extra=None): """ The page context. """ @@ -76,8 +78,8 @@ def context(self, data=None, extra=None): extra = {} context = {'__CACTUS_CURRENT_PAGE__': self,} - - page_context, data = self.parse_context(data or self.read_data()) + + page_context = self.parse_context() context.update(self.site.context()) context.update(extra) @@ -90,15 +92,10 @@ def render(self): Takes the template data with context and renders it to the final output file. """ - data = self.read_data() - context = self.context(data=data) - - # This is not very nice, but we already used the header context in the - # page context, so we don't need it anymore. - page_context, data = self.parse_context(data) + context = self.context() context, data = self.site.plugin_manager.preBuildPage( - self.site, self, context, data) + self.site, self, context, self.data) return Template(data).render(context) @@ -122,23 +119,27 @@ def build(self): self.site.plugin_manager.postBuildPage(self) - def parse_context(self, data, splitChar=':'): + def parse_context(self, splitChar=':'): """ Values like name: koen age: 29 - will be converted in a dict: {'name': 'koen', 'age': '29'} + from the top of the input file will be converted into a dict: + + {'name': 'koen', 'age': '29'} + + and these lines are deleted from 'self.data' """ if not self.is_html: return {} values = {} - lines = data.splitlines() + lines = self.data.splitlines() if not lines: - return {}, '' + return {} for i, line in enumerate(lines): @@ -152,7 +153,8 @@ def parse_context(self, data, splitChar=':'): else: break - return values, '\n'.join(lines[i:]) + self.data = '\n'.join(lines[i:]) + return values def __repr__(self): return ''.format(self.source_path) From 54105440081873308ef58996709ff55ca28dca1f Mon Sep 17 00:00:00 2001 From: Johannes Ammon Date: Sun, 26 Apr 2015 09:58:26 +0200 Subject: [PATCH 6/6] Pages must be read for each built newly (fixes failing test introduced in the last commit) --- cactus/site.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/cactus/site.py b/cactus/site.py index de755cef..6cd4f999 100644 --- a/cactus/site.py +++ b/cactus/site.py @@ -267,6 +267,9 @@ def build(self): else: os.remove(path) + # read pages for each built + self._read_pages() + # Render the pages to their output files mapper = map if self._parallel >= PARALLEL_AGGRESSIVE: @@ -344,16 +347,20 @@ def pages(self): but builds the page list only once """ if not hasattr(self, "_page_cache"): - self._page_cache = {} - - for path in fileList(self.page_path, relative=True): - # ignore backup files - if path.endswith("~"): - continue - self._page_cache[path] = Page(self, path) - + self._read_pages() return self._page_cache.values() + def _read_pages(self): + """ + Read the pages into self._page_cache + """ + self._page_cache = {} + for path in fileList(self.page_path, relative=True): + # ignore backup files + if path.endswith("~"): + continue + self._page_cache[path] = Page(self, path) + def _rebuild_should_ignore(self, file_path): file_relative_path = os.path.relpath(file_path, self.path)