lib/filesystem/map.py
branchsites
changeset 31 107062ebb6f9
child 32 be954df4f0e8
equal deleted inserted replaced
30:a86a25a9f75b 31:107062ebb6f9
       
     1 
       
     2 import os, os.path
       
     3 
       
     4 from lib import http, template, map
       
     5 
       
     6 import page, page_tree, menu
       
     7 
       
     8 class FilesystemMapper (map.Mapper) :
       
     9     """
       
    10         Translates requests to handlers based on a filesystem directory containing various kinds of files
       
    11     """
       
    12 
       
    13     # list of page handlers, by type
       
    14     PAGE_TYPES = [
       
    15         ('html',                    page.HTMLPage           ),
       
    16         (template.TEMPLATE_EXT,     page.TemplatePage       ),
       
    17     ]
       
    18 
       
    19     def __init__ (self, path) :
       
    20         """
       
    21             Create, path is where the pages are stored. The list of pages is loaded from $path/list
       
    22         """
       
    23         
       
    24         # store
       
    25         self.path = path
       
    26 
       
    27         # load the page tree
       
    28         self.tree = page_tree.PageTree(path + '/list')
       
    29     
       
    30     def _lookup_page_type (self, url, path, filename, basename, extension, tail) :
       
    31         """
       
    32             We found the file that we looked for, now get the correct type
       
    33         """
       
    34 
       
    35         # find appropriate handler
       
    36         for handler_ext, type in self.PAGE_TYPES :
       
    37             # match against file extension?
       
    38             if handler_ext == extension :
       
    39                 # found handler, return instance
       
    40                 return type(self, url, path, basename, tail)
       
    41 
       
    42         # no handler found
       
    43         raise PageError("No handler found for page %r of type %r" % (url, extension))
       
    44 
       
    45     def _lookup_page (self, name) :
       
    46         """
       
    47             Look up and return a Page object for the given page, or raise an error
       
    48         """
       
    49 
       
    50         # inital path
       
    51         path = self.path
       
    52         url_segments = []
       
    53 
       
    54         # name segments
       
    55         segments = name.split('/')
       
    56 
       
    57         # iterate through the parts of the page segments
       
    58         while True :
       
    59             segment = None
       
    60 
       
    61             # pop segment
       
    62             if segments :
       
    63                 segment = segments.pop(0)
       
    64 
       
    65                 url_segments.append(segment)
       
    66 
       
    67             # translate empty -> index
       
    68             if not segment :
       
    69                 segment = 'index'
       
    70 
       
    71             # look for it in the dir
       
    72             for filename in os.listdir(path) :
       
    73                 # build full file path
       
    74                 file_path = os.path.join(path, filename)
       
    75 
       
    76                 # stat, recurse into subdirectory?
       
    77                 if os.path.isdir(file_path) and filename == segment :
       
    78                     # use new dir
       
    79                     path = file_path
       
    80 
       
    81                     # break for-loop to look at next segment
       
    82                     break
       
    83      
       
    84                 # split into basename + extension
       
    85                 basename, extension = os.path.splitext(filename)
       
    86 
       
    87                 # ...remove that dot
       
    88                 extension = extension.lstrip('.')
       
    89                 
       
    90                 # match against requested page name?
       
    91                 if basename == segment :
       
    92                     # found the file we wanted
       
    93                     return self._lookup_page_type('/'.join(url_segments), file_path, filename, basename, extension, '/'.join(segments))
       
    94                 
       
    95                 else :
       
    96                     # inspect next file in dir
       
    97                     continue
       
    98 
       
    99             else :
       
   100                 # did not find any dir or file, break out of while loop
       
   101                 break
       
   102 
       
   103         # did not find the filename we were looking for in os.listdir
       
   104         raise PageError("Page not found: %s" % name, status='404 Not Found')
       
   105 
       
   106     def handle_request (self, request) :
       
   107         """
       
   108             Looks up the appropriate Page, and then renders it
       
   109         """
       
   110 
       
   111         # determine the page name
       
   112         page_name = request.get_page_name()
       
   113 
       
   114         # get the page handler
       
   115         p = self._lookup_page(page_name)
       
   116 
       
   117         # bind to request
       
   118         p.bind_request(request)
       
   119 
       
   120         # render the template
       
   121         response_data = template.render("layout",
       
   122             site_root_url   = request.get_script_dir(),
       
   123             site_page_url   = request.get_page_prefix(),
       
   124             page            = p,
       
   125             menu            = menu.Menu(self, p),
       
   126         )
       
   127         
       
   128         # return the response
       
   129         return http.Response(response_data)
       
   130 
       
   131