lib/page.py
changeset 8 0ce1f471e9d7
parent 7 d6a8258bd90e
child 9 2a47b00f60b0
equal deleted inserted replaced
7:d6a8258bd90e 8:0ce1f471e9d7
     1 
     1 
     2 """
     2 """
     3     Handling page requests
     3     Handling page requests
     4 """
     4 """
     5 
     5 
     6 def handle_html (env) :
     6 # for filesystem ops
     7     return "A HTML page"
     7 import os, os.path
     8 
     8 
       
     9 # for ResponseError
       
    10 import http
       
    11 
       
    12 # for TemplatePage
       
    13 import template
       
    14 
       
    15 # path to directory containing the page heirarcy
       
    16 PAGE_DIR = "pages"
       
    17 
       
    18 class PageError (http.ResponseError) :
       
    19     """
       
    20         Error looking up/handling a page
       
    21     """
       
    22 
       
    23     pass
       
    24 
       
    25 class Page (object) :
       
    26     """
       
    27         This object represents the information about our attempt to render some specific page
       
    28     """
       
    29 
       
    30     def __init__ (self, url, path, basename, url_tail) :
       
    31         """
       
    32             Initialize the page at the given location
       
    33 
       
    34             @param url the URL leading to this page
       
    35             @param path the filesystem path to this page's file
       
    36             @param basename the filesystem name of this page's file, without the file extension
       
    37             @param url_trail trailing URL for this page
       
    38         """
       
    39         
       
    40         # store
       
    41         self.url = url
       
    42         self.path = path
       
    43         self.basename = basename
       
    44         self.url_tail = url_tail
       
    45 
       
    46         # sub-init
       
    47         self._init()
       
    48 
       
    49     def _init (self) :
       
    50         """
       
    51             Do initial data loading, etc
       
    52         """
       
    53         
       
    54         pass
       
    55 
       
    56     def get_title (self) :
       
    57         """
       
    58             Return the page's title
       
    59 
       
    60             Defaults to the Titlecase'd file basename
       
    61         """
       
    62 
       
    63         return self.basename.title()
       
    64 
       
    65     def get_content (self) :
       
    66         """
       
    67             Return the page content as a string
       
    68         """
       
    69 
       
    70         abstract
       
    71 
       
    72 class HTMLPage (Page) :
       
    73     """
       
    74         A simple .html page that's just passed through directly
       
    75     """
       
    76 
       
    77     def get_content (self) :
       
    78         """
       
    79             Opens the .html file, reads and returns contents
       
    80         """
       
    81 
       
    82         return open(self.path, 'rb').read()
       
    83 
       
    84 class TemplatePage (Page) :
       
    85     """
       
    86         A template that's rendered using our template library
       
    87     """
       
    88 
       
    89     def get_content (self) :
       
    90         """
       
    91             Loads the .tmpl file, and renders it
       
    92         """
       
    93 
       
    94         return template.render_file(self.path)
     9 
    95 
    10 # list of page handlers, by type
    96 # list of page handlers, by type
    11 type_handlers = [
    97 TYPE_HANDLERS = [
    12     ('.html',   handle_html),
    98     ('html',                    HTMLPage        ),
       
    99     (template.TEMPLATE_EXT,     TemplatePage    ),
    13 ]
   100 ]
    14 
   101 
    15 def lookup_handler (path) :
   102 def _lookup_handler (url, path, filename, basename, extension, tail) :
    16     """
   103     """
    17         Look up and return a handler for the given page, or raise an error
   104         We found the file that we looked for, now get its handler
    18     """
   105     """
    19 
   106 
    20     return handle_html
   107     # find appropriate handler
       
   108     for handler_ext, handler in TYPE_HANDLERS :
       
   109         # match against file extension?
       
   110         if handler_ext == extension :
       
   111             # found handler, return instance
       
   112             return handler(url, path, basename, tail)
    21 
   113 
       
   114     # no handler found
       
   115     raise PageError("No handler found for page %r of type %r" % (url, extension))
       
   116 
       
   117 def lookup (name) :
       
   118     """
       
   119         Look up and return a Page object for the given page, or raise an error
       
   120     """
       
   121 
       
   122     # inital path
       
   123     path = PAGE_DIR
       
   124     url_segments = []
       
   125 
       
   126     # name segments
       
   127     segments = name.split('/')
       
   128 
       
   129     # iterate through the parts of the page segments
       
   130     while segments :
       
   131         # pop segment
       
   132         segment = segments.pop(0)
       
   133 
       
   134         # add to page url
       
   135         url_segments.append(segment)
       
   136 
       
   137         # translate empty -> index
       
   138         if not segment :
       
   139             segment = 'index'
       
   140         
       
   141         # look for it in the dir
       
   142         for filename in os.listdir(path) :
       
   143             # build full file path
       
   144             file_path = os.path.join(path, filename)
       
   145 
       
   146             # stat, recurse into subdirectory?
       
   147             if os.path.isdir(file_path) and filename == segment :
       
   148                 # use new dir
       
   149                 path = file_path
       
   150 
       
   151                 # break for-loop to look at next segment
       
   152                 break
       
   153  
       
   154             # split into basename + extension
       
   155             basename, extension = os.path.splitext(filename)
       
   156 
       
   157             # ...remove that dot
       
   158             extension = extension.lstrip('.')
       
   159             
       
   160             # match against requested page name?
       
   161             if basename == segment :
       
   162                 # found the file we wanted
       
   163                 return _lookup_handler('/'.join(url_segments), file_path, filename, basename, extension, '/'.join(segments))
       
   164             
       
   165             else :
       
   166                 # inspect next file in dir
       
   167                 continue
       
   168 
       
   169     # did not find the filename we were looking for in os.listdir
       
   170     raise PageError("Page not found: %s" % name, status='404 Not Found')
       
   171