comparison piecrust/serving/util.py @ 852:4850f8c21b6e

core: Start of the big refactor for PieCrust 3.0. * Everything is a `ContentSource`, including assets directories. * Most content sources are subclasses of the base file-system source. * A source is processed by a "pipeline", and there are 2 built-in pipelines, one for assets and one for pages. The asset pipeline is vaguely functional, but the page pipeline is completely broken right now. * Rewrite the baking process as just running appropriate pipelines on each content item. This should allow for better parallelization.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 17 May 2017 00:11:48 -0700
parents 673979a5d548
children f070a4fc033c
comparison
equal deleted inserted replaced
851:2c7e57d80bba 852:4850f8c21b6e
3 import hashlib 3 import hashlib
4 import logging 4 import logging
5 import datetime 5 import datetime
6 from werkzeug.wrappers import Response 6 from werkzeug.wrappers import Response
7 from werkzeug.wsgi import wrap_file 7 from werkzeug.wsgi import wrap_file
8 from piecrust.app import PieCrust, apply_variant_and_values 8 from piecrust.page import QualifiedPage, PageNotFoundError
9 from piecrust.rendering import QualifiedPage
10 from piecrust.routing import RouteNotFoundError 9 from piecrust.routing import RouteNotFoundError
11 from piecrust.sources.base import MODE_PARSING
12 from piecrust.sources.pageref import PageNotFoundError
13 from piecrust.uriutil import split_sub_uri 10 from piecrust.uriutil import split_sub_uri
14 11
15 12
16 logger = logging.getLogger(__name__) 13 logger = logging.getLogger(__name__)
17 14
25 22
26 class RequestedPage(object): 23 class RequestedPage(object):
27 def __init__(self): 24 def __init__(self):
28 self.qualified_page = None 25 self.qualified_page = None
29 self.req_path = None 26 self.req_path = None
30 self.page_num = 1
31 self.not_found_errors = [] 27 self.not_found_errors = []
32 28
33 29
34 def find_routes(routes, uri, is_sub_page=False): 30 def find_routes(routes, uri, sub_num=1):
35 """ Returns routes matching the given URL, but puts generator routes 31 """ Returns routes matching the given URL.
36 at the end.
37 """ 32 """
38 res = [] 33 res = []
39 gen_res = []
40 for route in routes: 34 for route in routes:
41 metadata = route.matchUri(uri) 35 route_params = route.matchUri(uri)
42 if metadata is not None: 36 if route_params is not None:
43 if route.is_source_route: 37 res.append((route, route_params, sub_num))
44 res.append((route, metadata, is_sub_page)) 38 return res
45 else:
46 gen_res.append((route, metadata, is_sub_page))
47 return res + gen_res
48 39
49 40
50 def get_requested_page(app, req_path): 41 def get_requested_page(app, req_path):
51 # Remove the trailing slash to simplify how we parse URLs. 42 # Remove the trailing slash to simplify how we parse URLs.
52 root_url = app.config.get('site/root') 43 root_url = app.config.get('site/root')
58 49
59 # It could also be a sub-page (i.e. the URL ends with a page number), so 50 # It could also be a sub-page (i.e. the URL ends with a page number), so
60 # we try to also match the base URL (without the number). 51 # we try to also match the base URL (without the number).
61 req_path_no_num, page_num = split_sub_uri(app, req_path) 52 req_path_no_num, page_num = split_sub_uri(app, req_path)
62 if page_num > 1: 53 if page_num > 1:
63 routes += find_routes(app.routes, req_path_no_num, True) 54 routes += find_routes(app.routes, req_path_no_num, page_num)
64 55
65 if len(routes) == 0: 56 if len(routes) == 0:
66 raise RouteNotFoundError("Can't find route for: %s" % req_path) 57 raise RouteNotFoundError("Can't find route for: %s" % req_path)
67 58
68 req_page = RequestedPage() 59 req_page = RequestedPage()
69 for route, route_metadata, is_sub_page in routes: 60 for route, route_params, route_sub_num in routes:
70 try: 61 cur_req_path = req_path
71 cur_req_path = req_path 62 if route_sub_num > 1:
72 if is_sub_page: 63 cur_req_path = req_path_no_num
73 cur_req_path = req_path_no_num
74 64
75 qp = _get_requested_page_for_route( 65 qp = _get_requested_page_for_route(app, route, route_params,
76 app, route, route_metadata, cur_req_path) 66 route_sub_num)
77 if qp is not None: 67 if qp is not None:
78 req_page.qualified_page = qp 68 req_page.qualified_page = qp
79 req_page.req_path = cur_req_path 69 req_page.req_path = cur_req_path
80 if is_sub_page: 70 break
81 req_page.page_num = page_num 71
82 break 72 req_page.not_found_errors.append(PageNotFoundError(
83 except PageNotFoundError as nfe: 73 "No path found for '%s' in source '%s'." %
84 req_page.not_found_errors.append(nfe) 74 (cur_req_path, route.source_name)))
75
85 return req_page 76 return req_page
86 77
87 78
88 def _get_requested_page_for_route(app, route, route_metadata, req_path): 79 def _get_requested_page_for_route(app, route, route_params, sub_num):
89 if not route.is_generator_route: 80 source = app.getSource(route.source_name)
90 source = app.getSource(route.source_name) 81 item = source.findContent(route_params)
91 factory = source.findPageFactory(route_metadata, MODE_PARSING) 82 if item is None:
92 if factory is None: 83 return None
93 raise PageNotFoundError(
94 "No path found for '%s' in source '%s'." %
95 (req_path, source.name))
96 else:
97 factory = route.generator.getPageFactory(route_metadata)
98 if factory is None:
99 raise PageNotFoundError(
100 "No path found for '%s' in generator '%s'." %
101 (req_path, route.generator.name))
102 84
103 # Build the page. 85 # Build the page.
104 page = factory.buildPage() 86 page = app.getPage(item)
105 qp = QualifiedPage(page, route, route_metadata) 87 qp = QualifiedPage(page, route, route_params, sub_num)
106 return qp 88 return qp
107 89
108 90
109 def load_mimetype_map(): 91 def load_mimetype_map():
110 mimetype_map = {} 92 mimetype_map = {}