lib/loaders.py
changeset 6 5565d94da522
parent 5 9ed4c7d2bdd2
equal deleted inserted replaced
5:9ed4c7d2bdd2 6:5565d94da522
       
     1 
       
     2 from __future__ import with_statement
       
     3 
       
     4 # XXX: for _HTMLPage
       
     5 import page
       
     6 import templates
       
     7 
       
     8 from pages import error404
       
     9 
       
    10 import os.path
       
    11 import imp
       
    12 
       
    13 # the page dir
       
    14 PAGE_DIR_PATH = "pages/"
       
    15 
       
    16 def build_page_path (*bits) :
       
    17     # XXX: fix directory traversal...
       
    18     
       
    19     return os.path.join(PAGE_DIR_PATH, *bits)
       
    20 
       
    21 class PageLoader (object) :
       
    22     """
       
    23         Load Page objects from files under pages/
       
    24     """
       
    25     
       
    26     # file extension, e.g. '.html' or '.py'
       
    27     suffix = None
       
    28 
       
    29     def __init__ (self, suffix) :
       
    30         self.suffix = suffix
       
    31         
       
    32     def _build_path (self, page_path) :
       
    33         """
       
    34             Builds a path from base_path + page_path + suffix. Returns None if the path does not exist
       
    35         """
       
    36         
       
    37         path = build_page_path(page_path) + self.suffix
       
    38 
       
    39         if os.path.exists(path) :
       
    40             return path
       
    41 
       
    42         else :
       
    43             return None
       
    44 
       
    45     def load (self, page_path) :
       
    46         """
       
    47             Attempts to load the page at the given path, returns the class on success, None on failure
       
    48         """
       
    49         
       
    50         abstract
       
    51 
       
    52 class _HTMLPage (page.Page) :
       
    53     # the path to the .html file
       
    54     file_path = None
       
    55     
       
    56     # parent page
       
    57     # parent = None
       
    58 
       
    59     def __init__ (self, *args) :
       
    60         super(_HTMLPage, self).__init__(*args)
       
    61 
       
    62         # open the .html and read in the contents
       
    63         with open(self.file_path, "r") as fh :
       
    64             self.file_data = fh.read()
       
    65 
       
    66     def render_template (self) :
       
    67         tpl = self._build_template(templates.layout)
       
    68         
       
    69         tpl.page_content = self.file_data
       
    70         
       
    71         return tpl
       
    72 
       
    73 class HTMLLoader (PageLoader) :
       
    74     """
       
    75         Static .html files that are inserted into the layout template as-is
       
    76 
       
    77         Sub-pages are not supported...
       
    78     """
       
    79 
       
    80     def __init__ (self) :
       
    81         super(HTMLLoader, self).__init__(".html")
       
    82 
       
    83     def get_title (self, page_path) :
       
    84         head, tail = os.path.split(page_path)
       
    85 
       
    86         return tail.title() if tail else "Index"
       
    87 
       
    88     def load (self, _page_path) :
       
    89         _file_path = self._build_path(_page_path)
       
    90         
       
    91         # ignore if it doesn't exist
       
    92         if not _file_path :
       
    93             return
       
    94         
       
    95         # get page title
       
    96         _title = self.get_title(_page_path)
       
    97 
       
    98         # create a new class and return it
       
    99         class _html_page (_HTMLPage) :
       
   100             file_path = _file_path
       
   101             title = _title
       
   102             name = _title
       
   103             path = _page_path
       
   104             
       
   105         # return it
       
   106         return _html_page
       
   107 
       
   108 class PythonLoader (PageLoader) :
       
   109     """
       
   110         Dynamic .py files that define a Page class
       
   111     """
       
   112 
       
   113     def __init__ (self) :
       
   114         super(PythonLoader, self).__init__(".py")
       
   115     
       
   116     def load (self, page_path) :
       
   117         path = self._build_path(page_path)
       
   118 
       
   119         # ignore if not exists
       
   120         if not path :
       
   121             return
       
   122 
       
   123         # load the module dynamically
       
   124         module = imp.load_source("__dyn_%d" % id(path), path)
       
   125 
       
   126         # return the Page object
       
   127         return module.Page
       
   128 
       
   129 # our defined loaders
       
   130 loaders = [
       
   131     HTMLLoader(),
       
   132     PythonLoader(),
       
   133 ]
       
   134 
       
   135 def load_page (req) :
       
   136     """
       
   137         Returns an instance of a Page object corresponding to the given req
       
   138     """
       
   139 
       
   140     # page path is given in req
       
   141     page_path = req.page_path
       
   142 
       
   143     # if it's a dir, then add 'index'
       
   144     if os.path.isdir(build_page_path(page_path)) :
       
   145         page_path = os.path.join(page_path, "index")
       
   146 
       
   147     # try each loader in turn
       
   148     for loader in loaders :
       
   149         page = loader.load(req.page_path)
       
   150         
       
   151         # found?
       
   152         if page :
       
   153             break
       
   154 
       
   155     # 404 error...
       
   156     if not page :
       
   157         page = error404.Error404
       
   158         
       
   159     return page(req, req.page_path)
       
   160