changeset 256:da5e6e00fb41

bake/serve: Make previewed and baked URLs consistent. The preview server now handles the `pretty_urls` setting correctly instead of forcing it. The `trailing_slash` and `pagination_suffix` setting are also doing the same between the 2 systems.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 22 Feb 2015 22:01:58 -0800
parents 311447fe3dd0
children e6ae65212c32
files piecrust/app.py piecrust/baking/single.py piecrust/data/base.py piecrust/routing.py piecrust/serving.py
diffstat 5 files changed, 72 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/piecrust/app.py	Fri Feb 20 23:44:23 2015 -0800
+++ b/piecrust/app.py	Sun Feb 22 22:01:58 2015 -0800
@@ -108,9 +108,7 @@
                 'default_template_engine': DEFAULT_TEMPLATE_ENGINE,
                 'enable_gzip': True,
                 'pretty_urls': False,
-                'slugify': 'transliterate|lowercase',
-                'timezone': False,
-                'locale': False,
+                'trailing_slash': False,
                 'date_format': DEFAULT_DATE_FORMAT,
                 'auto_formats': collections.OrderedDict([
                     ('html', ''),
@@ -121,7 +119,6 @@
                 'plugins_sources': [DEFAULT_PLUGIN_SOURCE],
                 'themes_sources': [DEFAULT_THEME_SOURCE],
                 'cache_time': 28800,
-                'display_errors': True,
                 'enable_debug_info': True,
                 'show_debug_info': False,
                 'use_default_content': True
@@ -149,10 +146,22 @@
         if sitec['default_auto_format'] not in sitec['auto_formats']:
             raise ConfigurationError("Default auto-format '%s' is not declared." % sitec['default_auto_format'])
 
-        # Cache pagination suffix regex.
-        pgn_suffix = re.escape(sitec['pagination_suffix'])
-        pgn_suffix = pgn_suffix.replace("\\%num\\%", "(?P<num>\\d+)") + '$'
-        cachec['pagination_suffix_re'] = pgn_suffix
+        # Cache pagination suffix regex and format.
+        pgn_suffix = sitec['pagination_suffix']
+        if len(pgn_suffix) == 0 or pgn_suffix[0] != '/':
+            raise ConfigurationError("The 'site/pagination_suffix' setting "
+                                     "must start with a slash.")
+        if '%num%' not in pgn_suffix:
+            raise ConfigurationError("The 'site/pagination_suffix' setting "
+                                     "must contain the '%num%' placeholder.")
+
+        pgn_suffix_fmt = pgn_suffix.replace('%num%', '%(num)d')
+        cachec['pagination_suffix_format'] = pgn_suffix_fmt
+
+        pgn_suffix_re = re.escape(pgn_suffix)
+        pgn_suffix_re = (pgn_suffix_re.replace("\\%num\\%", "(?P<num>\\d+)") +
+                         '$')
+        cachec['pagination_suffix_re'] = pgn_suffix_re
 
         # Make sure plugins and theme sources are lists.
         if not isinstance(sitec['plugins_sources'], list):
--- a/piecrust/baking/single.py	Fri Feb 20 23:44:23 2015 -0800
+++ b/piecrust/baking/single.py	Sun Feb 22 22:01:58 2015 -0800
@@ -33,34 +33,6 @@
         self.pretty_urls = app.config.get('site/pretty_urls')
         self.pagination_suffix = app.config.get('site/pagination_suffix')
 
-    def getOutputUri(self, uri, num):
-        suffix = self.pagination_suffix.replace('%num%', str(num))
-        if self.pretty_urls:
-            # Output will be:
-            # - `uri/name`
-            # - `uri/name/2`
-            # - `uri/name.ext`
-            # - `uri/name.ext/2`
-            if num <= 1:
-                return uri
-            return uri + suffix
-        else:
-            # Output will be:
-            # - `uri/name.html`
-            # - `uri/name/2.html`
-            # - `uri/name.ext`
-            # - `uri/name/2.ext`
-            if uri == '/':
-                if num <= 1:
-                    return '/'
-                return '/' + suffix.lstrip('/')
-            else:
-                if num <= 1:
-                    return uri
-                #TODO: watch out for tags with dots in them.
-                base_uri, ext = os.path.splitext(uri)
-                return base_uri + suffix + ext
-
     def getOutputPath(self, uri):
         bake_path = [self.out_dir]
         decoded_uri = urllib.parse.unquote(uri.lstrip('/'))
@@ -109,7 +81,8 @@
 
         # Generate the URL using the route.
         page = factory.buildPage()
-        uri = route.getUri(route_metadata, page, include_site_root=False)
+        uri = route.getUri(route_metadata, provider=page,
+                           include_site_root=False)
 
         override = self.record.getOverrideEntry(factory, uri)
         if override is not None:
@@ -161,7 +134,8 @@
                     invalidate_formatting = True
 
         while has_more_subs:
-            sub_uri = self.getOutputUri(uri, cur_sub)
+            sub_uri = route.getUri(route_metadata, sub_num=cur_sub,
+                                   provider=page, include_site_root=False)
             out_path = self.getOutputPath(sub_uri)
 
             # Check for up-to-date outputs.
--- a/piecrust/data/base.py	Fri Feb 20 23:44:23 2015 -0800
+++ b/piecrust/data/base.py	Sun Feb 22 22:01:58 2015 -0800
@@ -125,7 +125,7 @@
         route = page.app.getRoute(page.source.name, page.source_metadata)
         if route is None:
             raise Exception("Can't get route for page: %s" % page.path)
-        return route.getUri(page.source_metadata, page)
+        return route.getUri(page.source_metadata, provider=page)
 
     def _loadCustom(self):
         page_url = self._get_uri()
--- a/piecrust/routing.py	Fri Feb 20 23:44:23 2015 -0800
+++ b/piecrust/routing.py	Sun Feb 22 22:01:58 2015 -0800
@@ -1,4 +1,5 @@
 import re
+import os.path
 import logging
 
 
@@ -8,6 +9,7 @@
 route_re = re.compile(r'%((?P<qual>path):)?(?P<name>\w+)%')
 template_func_re = re.compile(r'^(?P<name>\w+)\((?P<first_arg>\w+)(?P<other_args>.*)\)\s*$')
 template_func_arg_re = re.compile(r',\s*(?P<arg>\w+)')
+ugly_url_cleaner = re.compile(r'\.html$')
 
 
 class IRouteMetadataProvider(object):
@@ -22,15 +24,22 @@
     """
     def __init__(self, app, cfg):
         self.app = app
+
+        self.pretty_urls = app.config.get('site/pretty_urls')
+        self.trailing_slash = app.config.get('site/trailing_slash')
+        self.pagination_suffix_format = app.config.get(
+                '__cache/pagination_suffix_format')
+        self.uri_root = app.config.get('site/root').rstrip('/') + '/'
+
         uri = cfg['url']
-        self.uri_root = app.config.get('site/root').rstrip('/') + '/'
         self.uri_pattern = uri.lstrip('/')
         self.uri_format = route_re.sub(self._uriFormatRepl, self.uri_pattern)
         if app.config.get('site/show_debug_info'):
             self.uri_format += '?!debug'
 
         # Get the straight-forward regex for matching this URI pattern.
-        p = route_re.sub(self._uriPatternRepl, self.uri_pattern) + '$'
+        re_suffix = '$'
+        p = route_re.sub(self._uriPatternRepl, self.uri_pattern) + re_suffix
         self.uri_re = re.compile(p)
 
         # If the URI pattern has a 'path'-type component, we'll need to match
@@ -76,6 +85,11 @@
         return self.required_source_metadata.issubset(source_metadata.keys())
 
     def matchUri(self, uri):
+        if not self.pretty_urls:
+            uri = ugly_url_cleaner.sub('', uri)
+        elif self.trailing_slash:
+            uri = uri.rstrip('/')
+
         m = self.uri_re.match(uri)
         if m:
             return m.groupdict()
@@ -85,17 +99,50 @@
                 return m.groupdict()
         return None
 
-    def getUri(self, source_metadata, provider=None, include_site_root=True):
+    def getUri(self, source_metadata, *, sub_num=1, provider=None,
+               include_site_root=True):
         if provider:
             source_metadata = dict(source_metadata)
             source_metadata.update(provider.getRouteMetadata())
+
         #TODO: fix this hard-coded shit
         for key in ['year', 'month', 'day']:
             if key in source_metadata and isinstance(source_metadata[key], str):
                 source_metadata[key] = int(source_metadata[key])
+
         uri = self.uri_format % source_metadata
+        suffix = None
+        if sub_num > 1:
+            # Note that we know the pagination suffix starts with a slash.
+            suffix = self.pagination_suffix_format % sub_num
+
+        if self.pretty_urls:
+            # Output will be:
+            # - `subdir/name`
+            # - `subdir/name/2`
+            # - `subdir/name.ext`
+            # - `subdir/name.ext/2`
+            if suffix:
+                uri = uri.rstrip('/') + suffix
+            if self.trailing_slash:
+                uri = uri.rstrip('/') + '/'
+        else:
+            # Output will be:
+            # - `subdir/name.html`
+            # - `subdir/name/2.html`
+            # - `subdir/name.ext`
+            # - `subdir/name/2.ext`
+            base_uri, ext = os.path.splitext(uri)
+            if not ext:
+                ext = '.html'
+            if suffix:
+                uri = base_uri + suffix + ext
+            else:
+                uri = base_uri + ext
+
         if include_site_root:
             uri = self.uri_root + uri
+
         return uri
 
     def _uriFormatRepl(self, m):
--- a/piecrust/serving.py	Fri Feb 20 23:44:23 2015 -0800
+++ b/piecrust/serving.py	Sun Feb 22 22:01:58 2015 -0800
@@ -130,7 +130,6 @@
         # Create the app for this request.
         app = PieCrust(root_dir=self.root_dir, debug=self.debug)
         app.config.set('site/root', '/')
-        app.config.set('site/pretty_urls', True)
         app.config.set('server/is_serving', True)
         if (app.config.get('site/enable_debug_info') and
                 '!debug' in request.args):