qmsk_www_pages/pages.py
changeset 205 f1adf52f485a
parent 202 da5de3a97efb
child 69 4b8814ff6d6d
equal deleted inserted replaced
204:99f9e50030ae 205:f1adf52f485a
     2 
     2 
     3 import codecs
     3 import codecs
     4 import datetime
     4 import datetime
     5 import logging; log = logging.getLogger('qmsk_www_pages.pages')
     5 import logging; log = logging.getLogger('qmsk_www_pages.pages')
     6 import os, os.path
     6 import os, os.path
       
     7 
       
     8 class NotFound (Exception):
       
     9     pass
     7 
    10 
     8 class Site (object):
    11 class Site (object):
     9     @classmethod
    12     @classmethod
    10     def lookup (cls):
    13     def lookup (cls):
    11         return cls(
    14         return cls(
    20 class Tree (object):
    23 class Tree (object):
    21     INDEX = 'index'
    24     INDEX = 'index'
    22 
    25 
    23     @classmethod
    26     @classmethod
    24     def lookup (cls, site, parts):
    27     def lookup (cls, site, parts):
    25         path = site.root
    28         """
    26 
    29             Returns Tree
    27         for part in parts:
    30 
    28             if part.startswith('.'):
    31             Raises NotFound
       
    32         """
       
    33 
       
    34         parents = ( )
       
    35         tree = cls(site.root, None, parents, site,
       
    36                 title       = site.name,
       
    37         )
       
    38 
       
    39         for name in parts:
       
    40             if name.startswith('.'):
    29                 # evil
    41                 # evil
    30                 return None
    42                 raise NotFound()
    31             
    43             
    32             if not part:
    44             if not name:
    33                 continue
    45                 continue
    34         
    46         
    35             path = os.path.join(path, part)
    47             path = os.path.join(tree.path, name)
    36 
    48 
    37             if not os.path.exists(path):
    49             if not os.path.exists(path):
    38                 return None
    50                 raise NotFound()
    39             
    51             
    40             if not os.path.isdir(path):
    52             if not os.path.isdir(path):
    41                 return None
    53                 raise NotFound()
    42         
    54 
    43         return cls(path, parts, site)
    55             parents += (tree, )
    44 
    56             tree = cls(path, name, parents, site)
    45     def __init__ (self, path, parts, site):
    57 
       
    58         return tree
       
    59 
       
    60     def __init__ (self, path, name, parents, site,
       
    61             title   = None,
       
    62     ):
       
    63         """
       
    64             path:       filesystem path
       
    65             name:       subtree name, or None for root
       
    66             parents:    (Tree)
       
    67             site:       Site
       
    68         """
       
    69 
    46         self.path = path
    70         self.path = path
    47         self.parts = parts
    71         self.name = name
       
    72         self.parents = parents
    48         self.site = site
    73         self.site = site
    49 
    74 
       
    75         self.title = title or name
       
    76 
       
    77     def hierarchy (self):
       
    78         """
       
    79             Yield Tree.
       
    80         """
       
    81 
       
    82         for tree in self.parents:
       
    83             yield tree
       
    84 
       
    85         yield self
       
    86 
    50     def url (self, tree=None, page=None):
    87     def url (self, tree=None, page=None):
    51         path = '/'.join(self.parts)
    88         path = '/'.join(tree.name for tree in self.hierarchy() if tree.name is not None)
    52 
    89 
    53         if path:
    90         if path:
    54             path += '/'
    91             path += '/'
    55 
    92 
    56         if tree:
    93         if tree:
    58 
    95 
    59         if page:
    96         if page:
    60             path += page
    97             path += page
    61 
    98 
    62         return path
    99         return path
    63 
       
    64     def breadcrumb (self):
       
    65         path = []
       
    66 
       
    67         yield '', self.site.name
       
    68 
       
    69         for part in self.parts:
       
    70             path.append(part)
       
    71 
       
    72             yield '/'.join(path) + '/', part
       
    73 
   100 
    74     def scan (self):
   101     def scan (self):
    75         """
   102         """
    76             Scan for files in tree.
   103             Scan for files in tree.
    77         """
   104         """
   117 
   144 
   118     def page (self, name):
   145     def page (self, name):
   119         """
   146         """
   120             Scans through tree looking for a matching page.
   147             Scans through tree looking for a matching page.
   121             
   148             
   122             Returns Page.
   149             Returns Page or None.
   123         """
   150         """
   124         
   151         
   125         if not name:
   152         if not name:
   126             name = self.INDEX
   153             name = self.INDEX
   127 
   154 
   142             # out
   169             # out
   143             return page_type(
   170             return page_type(
   144                 path    = path,
   171                 path    = path,
   145                 name    = name,
   172                 name    = name,
   146                 tree    = self,
   173                 tree    = self,
       
   174                 parents = self.parents + (self, ),
   147             )
   175             )
   148 
   176 
   149 class Page (object):
   177 class Page (object):
   150     ENCODING = 'utf-8'
   178     ENCODING = 'utf-8'
   151 
   179 
   152     @classmethod
   180     @classmethod
   153     def lookup (cls, site, page):
   181     def lookup (cls, site, page):
   154         """
   182         """
   155             Lookup a Page from disk.
   183             Returns Page.
   156 
   184             
   157             Returns None if there is no such page.
   185             Raises NotFound
   158         """
   186         """
   159         
   187         
   160         log.info("page=%r", page)
   188         log.info("page=%r", page)
   161 
   189 
   162         if page:
   190         if page:
   172             tree_parts = []
   200             tree_parts = []
   173 
   201 
   174         # scan dir
   202         # scan dir
   175         tree = Tree.lookup(site, tree_parts)
   203         tree = Tree.lookup(site, tree_parts)
   176 
   204 
   177         if not tree:
       
   178             return None
       
   179 
       
   180         # scan page
   205         # scan page
   181         page = tree.page(page_name)
   206         page = tree.page(page_name)
   182 
   207 
   183         if not page:
   208         if not page:
   184             return None
   209             raise NotFound()
   185 
   210 
   186         return page
   211         return page
   187 
   212 
   188     def __init__ (self, path, name, tree, encoding=ENCODING):
   213     def __init__ (self, path, name, tree, parents=(), encoding=ENCODING, title=None):
   189         self.path = path
   214         self.path = path
   190         self.name = name
   215         self.name = name
   191         self.tree = tree
   216         self.tree = tree
       
   217         self.parents = parents
       
   218 
   192         self.encoding = encoding
   219         self.encoding = encoding
       
   220         self.title = title or name
   193 
   221 
   194     def url (self):
   222     def url (self):
   195         return self.tree.url(page=self.name)
   223         return self.tree.url(page=self.name)
   196 
   224 
   197     def open (self):
   225     def open (self):
   199 
   227 
   200     def stat (self):
   228     def stat (self):
   201         return os.stat(self.path)
   229         return os.stat(self.path)
   202 
   230 
   203     def breadcrumb (self):
   231     def breadcrumb (self):
   204         for path, name in self.tree.breadcrumb():
   232         for tree in self.tree.hierarchy():
   205             yield path, name
   233             yield tree.url(), tree.title
   206         
   234         
   207         if self.name != self.tree.INDEX:
   235         if self.name != self.tree.INDEX:
   208             yield self.url(), self.name
   236             yield self.url(), self.title
   209 
   237 
   210     def modified (self):
   238     def modified (self):
   211         return datetime.datetime.utcfromtimestamp(self.stat().st_mtime)
   239         return datetime.datetime.utcfromtimestamp(self.stat().st_mtime)
   212 
   240 
   213     def render (self, request):
   241     def render (self, request):