Plain is headed towards 1.0! Subscribe for development updates →

 1import os
 2
 3from plain.internal import internalcode
 4from plain.urls import path
 5
 6from .exceptions import PageNotFoundError
 7from .pages import Page
 8
 9
10@internalcode
11class PagesRegistry:
12    """
13    The registry loads up all the pages at once, so we only have to do a
14    dict key lookup at runtime to get a page.
15    """
16
17    def __init__(self):
18        # url path -> file path
19        self.registered_pages = {}
20
21    def get_page_urls(self):
22        """
23        Generate a list of real urls based on the files that exist.
24        This way, you get a concrete url reversingerror if you try
25        to refer to a page/url that isn't going to work.
26        """
27        paths = []
28
29        for url_name in self.registered_pages.keys():
30            page = self.get_page(url_name)
31            url = page.get_url_path()
32            view_class = page.get_view_class()
33
34            paths.append(
35                path(
36                    url,
37                    view_class,
38                    name=url_name,
39                )
40            )
41
42        return paths
43
44    def discover_pages(self, pages_dir):
45        for root, _, files in os.walk(pages_dir):
46            for file in files:
47                relative_path = os.path.relpath(os.path.join(root, file), pages_dir)
48                absolute_path = os.path.join(root, file)
49
50                page_args = (relative_path, absolute_path)
51                url_name = Page(*page_args).get_url_name()
52
53                # Some pages don't get a url (like templates)
54                if url_name is None:
55                    continue
56
57                self.registered_pages[url_name] = page_args
58
59    def get_page(self, url_name):
60        try:
61            page_args = self.registered_pages[url_name]
62            # Instantiate the page here, so we don't store a ton of cached data over time
63            # as we render all the pages
64            return Page(*page_args)
65        except KeyError:
66            raise PageNotFoundError(f"Could not find a page for {url_name}")
67
68
69pages_registry = PagesRegistry()