def run(self): """ Main loop for pyblosxom. This should be called _after_ initialization. This method will run the handle callback to allow registered handlers to handle the request. If nothing handles the request, then we use the default_blosxom_handler. """ self.initialize() # run the start callback tools.run_callback("start", {'request': self._request}) data = self._request.getData() pyhttp = self._request.getHttp() config = self._request.getConfiguration() # allow anyone else to handle the request at this point handled = tools.run_callback("handle", {'request': self._request}, mappingfunc=lambda x, y: x, donefunc=lambda x: x) if not handled == 1: blosxom_handler(self._request) # do end callback tools.run_callback("end", {'request': self._request})
def _entryparser(request): """Applies: - cb_preformat - cb_format - cb_postformat""" entry = request['entry'] config = request['config'] log.debug('cb_preformat: "%s"' % entry.title) entry = tools.run_callback( 'preformat', {'entry': entry, 'config': config}, defaultfunc=_preformat)['entry'] log.debug('cb_format: "%s"' % entry.title) entry = tools.run_callback( 'format', {'entry': entry, 'config': config}, defaultfunc=_format)['entry'] log.debug('cb_postformat: "%s"' % entry.title) entry = tools.run_callback( 'postformat', {'entry': entry, 'config': config}, defaultfunc=lambda x: x)['entry'] return entry
def run(self): """ Main loop for pyblosxom. This should be called _after_ initialization. This method will run the handle callback to allow registered handlers to handle the request. If nothing handles the request, then we use the default_blosxom_handler. """ self.initialize() # run the start callback tools.run_callback("start", {'request': self._request}) data = self._request.getData() pyhttp = self._request.getHttp() config = self._request.getConfiguration() # allow anyone else to handle the request at this point handled = tools.run_callback("handle", {'request': self._request}, mappingfunc=lambda x,y:x, donefunc=lambda x:x) if not handled == 1: blosxom_handler(self._request) # do end callback tools.run_callback("end", {'request': self._request})
def blosxom_entry_parser(filename, request): """ Open up a *.txt file and read its contents. The first line becomes the title of the entry. The other lines are the body of the entry. @param filename: A filename to extract data and metadata from @type filename: string @param request: A standard request object @type request: L{Pyblosxom.pyblosxom.Request} object @returns: A dict containing parsed data and meta data with the particular file (and plugin) @rtype: dict """ config = request.getConfiguration() entryData = {} try: story = open(filename).readlines() except IOError: raise IOError if len(story) > 0: entryData['title'] = story.pop(0).strip() # this handles properties of the entry that are between # the title and the body and start with a # while len(story) > 0: match = re.match(r'^#(\w+)\s+(.*)', story[0]) if match: story.pop(0) entryData[match.groups()[0]] = match.groups()[1].strip() else: break # Call the preformat function entryData['body'] = tools.run_callback( 'preformat', { 'parser': (entryData.get('parser', '') or config.get('parser', 'plain')), 'story': story, 'request': request }, donefunc=lambda x: x != None, defaultfunc=lambda x: ''.join(x['story'])) # Call the postformat callbacks tools.run_callback('postformat', { 'request': request, 'entry_data': entryData }) return entryData
def blosxom_entry_parser(filename, request): """ Open up a *.txt file and read its contents. The first line becomes the title of the entry. The other lines are the body of the entry. @param filename: A filename to extract data and metadata from @type filename: string @param request: A standard request object @type request: L{Pyblosxom.pyblosxom.Request} object @returns: A dict containing parsed data and meta data with the particular file (and plugin) @rtype: dict """ config = request.getConfiguration() entryData = {} try: story = open(filename).readlines() except IOError: raise IOError if len(story) > 0: entryData['title'] = story.pop(0).strip() # this handles properties of the entry that are between # the title and the body and start with a # while len(story) > 0: match = re.match(r'^#(\w+)\s+(.*)', story[0]) if match: story.pop(0) entryData[match.groups()[0]] = match.groups()[1].strip() else: break # Call the preformat function entryData['body'] = tools.run_callback('preformat', {'parser': (entryData.get('parser', '') or config.get('parser', 'plain')), 'story': story, 'request': request}, donefunc = lambda x:x != None, defaultfunc = lambda x: ''.join(x['story'])) # Call the postformat callbacks tools.run_callback('postformat', {'request': request, 'entry_data': entryData}) return entryData
def initialize(self): """ The initialize step further initializes the Request by setting additional information in the _data dict, registering plugins, and entryparsers. """ global VERSION_DATE data = self._request.getData() pyhttp = self._request.getHttp() config = self._request.getConfiguration() data["pyblosxom_version"] = VERSION_DATE data['pi_bl'] = '' # Get our URL and configure the base_url param if pyhttp.has_key('SCRIPT_NAME'): if not config.has_key('base_url'): config['base_url'] = 'http://%s%s' % (pyhttp['HTTP_HOST'], pyhttp['SCRIPT_NAME']) else: config['base_url'] = config.get('base_url', '') if config["datadir"].endswith("\\") or config["datadir"].endswith("/"): config['datadir'] = config['datadir'][:-1] # import and initialize plugins import plugin_utils plugin_utils.initialize_plugins(config.get("plugin_dirs", []), config.get("load_plugins", None)) # entryparser callback is run here first to allow other plugins # register what file extensions can be used data['extensions'] = tools.run_callback("entryparser", {'txt': blosxom_entry_parser}, mappingfunc=lambda x,y:y, defaultfunc=lambda x:x)
def cb_end(request): """Generates a overview of all articles.""" request = deepcopy(request) request = tools.run_callback('prepare', request) # needed for entry's url config = request._config data = request._data layout = os.path.join(config.get('layout_dir', 'layouts'), 'articles.html') tt_articles = Template(convert_text(open(layout).read())) articles = defaultdict(list) for entry in sorted(data['entry_list'], key=lambda k: k.date, reverse=True): url, title, year = entry['url'], entry['title'], entry.date.year articles[year].append((entry.date, url, title)) articlesdict = config.copy() articlesdict.update({'articles': articles, 'num_entries': len(data['entry_list'])}) html = tt_articles.render(articlesdict) path = os.path.join(config.get('output_dir', 'out'), 'articles', 'index.html') tools.mk_file(html, {'title': 'articles/index.html'}, path) return request
def runCallback(self, callback="help"): """ Generic method to run the engine for a specific callback """ self.initialize() # run the start callback tools.run_callback("start", {'request': self._request}) config = self._request.getConfig() data = self._request.getData() # invoke all callbacks for the 'callback' handled = tools.run_callback(callback, {'request': self._request}, mappingfunc=lambda x, y: x, donefunc=lambda x: x) # do end callback tools.run_callback("end", {'request': request})
def runCallback(self, callback="help"): """ Generic method to run the engine for a specific callback """ self.initialize() # run the start callback tools.run_callback("start", {'request': self._request}) config = self._request.getConfig() data = self._request.getData() # invoke all callbacks for the 'callback' handled = tools.run_callback(callback, {'request': self._request}, mappingfunc=lambda x,y:x, donefunc=lambda x:x) # do end callback tools.run_callback("end", {'request': request})
def run(self): """This is the main loop for lilith. This method will run the handle callback to allow registered handlers to handle the request. If nothing handles the request, then we use the ``_lilith_handler``. """ self.initialize() # run the start callback log.debug('cb_start') request = tools.run_callback('start', self.request) # run the default handler log.debug('cb_handle') request = tools.run_callback("handle", request, mapping=lambda x,y:x, defaultfunc=_lilith_handler) # do end callback tools.run_callback('end', request)
def cb_end(request): tt_atom_entry = Template(convert_text(ATOM_ENTRY)) tt_atom_body = Template(convert_text(ATOM_BODY)) tt_rss_entry = Template(convert_text(RSS_ENTRY)) tt_rss_body = Template(convert_text(RSS_BODY)) config = request._config data = request._data data['type'] = 'feed' count = 25 # last preparations request = tools.run_callback( 'prepare', request) dict = request._config rss_list = [] atom_list = [] for entry in data['entry_list'][:25]: entry['body'] = cgi.escape(entry['body'].replace('­', '')) entrydict = dict.copy() entrydict.update(entry) atom_list.append(tt_atom_entry.render( entrydict )) rss_list.append(tt_rss_entry.render( entrydict )) # atom dict.update( {'entry_list': '\n'.join(atom_list), 'date': data['entry_list'][0].date } ) xml = tt_atom_body.render( dict ) directory = os.path.join(config.get('output_dir', 'out'), 'atom') path = os.path.join(directory, 'index.xml') tools.mk_file(xml, {'title': 'atom/index.xml'}, path) # rss dict.update( {'entry_list': '\n'.join(rss_list), 'date': data['entry_list'][0].date } ) xml = tt_rss_body.render( dict ) directory = os.path.join(config.get('output_dir', 'out'), 'rss') path = os.path.join(directory, 'index.xml') tools.mk_file(xml, {'title': 'rss/index.xml'}, path) return request
def cb_page(request): """mostly identical to lilith._cb_page except of not displaying content which has translations and is not in default language.""" config = request._config data = request._data data['type'] = 'page' ipp = config.get('items_per_page', 6) # last preparations request = tools.run_callback( 'prepare', request) layout = config.get('layout_dir', 'layouts') tt_entry = Template(open(os.path.join(layout, 'entry.html')).read()) tt_main = Template(open(os.path.join(layout, 'main.html')).read()) dict = request._config entry_list = [] for entry in data['entry_list']: if entry.get('identifier', False) and entry['lang'] != config['lang'][:2]: continue translations = filter(lambda e: e != entry and \ e.get('identifier', '') == entry.get('identifier', False), data['entry_list']) entry['translations'] = translations entrydict = dict.copy() entrydict.update(entry) entry_list.append(tt_entry.render(entrydict)) for i, mem in enumerate([entry_list[x*ipp:(x+1)*ipp] for x in range(len(entry_list)/ipp+1)]): dict.update( {'entry_list': '\n'.join(mem), 'page': i+1, 'num_entries': len(entry_list)} ) html = tt_main.render( dict ) directory = os.path.join(config.get('output_dir', 'out'), '' if i == 0 else 'page/%s' % (i+1)) path = os.path.join(directory, 'index.html') tools.mk_file(html, {'title': 'page/%s' % (i+1)}, path) return request
def cb_item(request): """Creates single full-length entry. Looks like http://domain.tld/year/$lang/title/(index.html). required: entry.html -- layout of Post's entry main.html -- layout of the website """ config = request._config data = request._data data['type'] = 'item' layout = config.get('layout_dir', 'layouts') tt_entry = Template(open(os.path.join(layout, 'entry.html')).read()) tt_main = Template(open(os.path.join(layout, 'main.html')).read()) # last preparations request = tools.run_callback( 'prepare', request) dict = request._config for entry in data['entry_list']: translations = filter(lambda e: e != entry and \ e.get('identifier', '') == entry.get('identifier', False), data['entry_list']) log.debug("%s's translations: %s" % (entry.title, repr(translations))) entry['translations'] = translations entrydict = dict.copy() entrydict.update(entry) dict.update({'entry_list': tt_entry.render(entrydict) }) html = tt_main.render( dict ) directory = os.path.join(config.get('output_dir', 'out'), str(entry.date.year), entry['lang_dir'], entry.safe_title) path = os.path.join(directory, 'index.html') tools.mk_file(html, entry, path) return request
def _page(request): """Creates nicely paged listing of your posts. First “Page” is the index.hml used to have this nice url: http://yourblog.com/ with a recent list of your (e.g. summarized) Posts. Other pages are enumerated to /page/n+1 required: items_per_page -- posts displayed per page (defaults to 6) entry.html -- layout of Post's entry main.html -- layout of the website """ config = request._config data = request._data data['type'] = 'page' ipp = config.get('items_per_page', 6) # last preparations request = tools.run_callback( 'prepare', request) layout = config.get('layout_dir', 'layouts') tt_entry = Template(open(os.path.join(layout, 'entry.html')).read()) tt_main = Template(open(os.path.join(layout, 'main.html')).read()) dict = request._config entry_list = [] for entry in data['entry_list']: entrydict = dict.copy() entrydict.update(entry) entry_list.append(tt_entry.render(entrydict)) for i, mem in enumerate([entry_list[x*ipp:(x+1)*ipp] for x in range(len(entry_list)/ipp+1)]): dict.update( {'entry_list': '\n'.join(mem), 'page': i+1, 'num_entries': len(entry_list)} ) html = tt_main.render( dict ) directory = os.path.join(config.get('output_dir', 'out'), '' if i == 0 else 'page/%s' % (i+1)) path = os.path.join(directory, 'index.html') tools.mk_file(html, {'title': 'page/%s' % (i+1)}, path) return request
def _item(request): """Creates single full-length entry. Looks like http://yourblog.org/year/title/(index.html). required: entry.html -- layout of Post's entry main.html -- layout of the website """ config = request._config data = request._data data['type'] = 'item' layout = config.get('layout_dir', 'layouts') tt_entry = Template(open(os.path.join(layout, 'entry.html')).read()) tt_main = Template(open(os.path.join(layout, 'main.html')).read()) # last preparations request = tools.run_callback( 'prepare', request) dict = request._config entry_list = [] for entry in data['entry_list']: entrydict = dict.copy() entrydict.update(entry) dict.update({'entry_list':tt_entry.render(entrydict) }) html = tt_main.render( dict ) directory = os.path.join(config.get('output_dir', 'out'), str(entry.date.year), entry.safe_title) path = os.path.join(directory, 'index.html') tools.mk_file(html, entry, path) return request
def initialize(self): """ The initialize step further initializes the Request by setting additional information in the _data dict, registering plugins, and entryparsers. """ global VERSION_DATE data = self._request.getData() pyhttp = self._request.getHttp() config = self._request.getConfiguration() data["pyblosxom_version"] = VERSION_DATE data['pi_bl'] = '' # Get our URL and configure the base_url param if pyhttp.has_key('SCRIPT_NAME'): if not config.has_key('base_url'): config['base_url'] = 'http://%s%s' % (pyhttp['HTTP_HOST'], pyhttp['SCRIPT_NAME']) else: config['base_url'] = config.get('base_url', '') if config["datadir"].endswith("\\") or config["datadir"].endswith("/"): config['datadir'] = config['datadir'][:-1] # import and initialize plugins import plugin_utils plugin_utils.initialize_plugins(config.get("plugin_dirs", []), config.get("load_plugins", None)) # entryparser callback is run here first to allow other plugins # register what file extensions can be used data['extensions'] = tools.run_callback("entryparser", {'txt': blosxom_entry_parser}, mappingfunc=lambda x, y: y, defaultfunc=lambda x: x)
def run(self): """ Main loop for pyblosxom. """ config = self._request.getConfiguration() data = self._request.getData() # import and initialize plugins import plugin_utils plugin_utils.initialize_plugins(config) # inject our own startup into the callback thing plugin_utils.callbacks.setdefault("startup", []).append(self.startup) # get the renderer we want to use r = config.get("renderer", "blosxom") # import the renderer r = tools.importName("Pyblosxom.renderers", r) # get the renderer object r = r.Renderer(self._request, config.get("stdoutput", sys.stdout)) # go through the renderer callback to see if anyone else # wants to render. the default is the renderer object we # figured out from above. this renderer gets stored in # the data dict for downstream processing. data['renderer'] = tools.run_callback('renderer', {'request': self._request}, donefunc = lambda x: x != None, defaultfunc = lambda x: r) # do start callback tools.run_callback("start", {'request': self._request}) # entryparser callback is runned first here to allow other plugins # register what file extensions can be used data['extensions'] = tools.run_callback("entryparser", {'txt': self.defaultEntryParser}, mappingfunc=lambda x,y:y, defaultfunc=lambda x:x) # process the path info to determine what kind of blog entry(ies) # this is tools.run_callback("pathinfo", {"request": self._request}, donefunc=lambda x:x != None, defaultfunc=self.processPathInfo) # call the filelist callback to generate a list of entries data["entry_list"] = tools.run_callback("filelist", {"request": self._request}, donefunc=lambda x:x != None, defaultfunc=self.defaultFileListHandler) # we pass the request with the entry_list through the prepare callback # giving everyone a chance to transform the data. the request is # modified in place. tools.run_callback("prepare", {"request": self._request}) # now we pass the entry_list through the renderer entry_list = data["entry_list"] renderer = data['renderer'] if renderer and not renderer.rendered: if entry_list: renderer.setContent(entry_list) # Log it as success tools.run_callback("logrequest", {'filename':config.get('logfile',''), 'return_code': '200', 'request': self._request}) else: renderer.addHeader('Status', '404 Not Found') renderer.setContent( {'title': 'The page you are looking for is not available', 'body': 'Somehow I cannot find the page you want. ' + 'Go Back to <a href="%s">%s</a>?' % (config["base_url"], config["blog_title"])}) # Log it as failure tools.run_callback("logrequest", {'filename':config.get('logfile',''), 'return_code': '404', 'request': self._request}) renderer.render() # do end callback tools.run_callback("end", {'request':self._request}) elif not renderer: output = config.get('stdoutput', sys.stdout) output.write("Content-Type: text/plain\n\nThere is something wrong with your setup.\n Check your config files and verify that your configuration is correct.\n")
def runStaticRenderer(self, incremental=0): """ This will go through all possible things in the blog and statically render everything to the "static_dir" specified in the config file. This figures out all the possible path_info settings and calls self.run() a bazillion times saving each file. @param incremental: whether (1) or not (0) to incrementally render the pages. if we're incrementally rendering pages, then we render only the ones that have changed. @type incremental: boolean """ self.initialize() config = self._request.getConfiguration() data = self._request.getData() print "Performing static rendering." if incremental: print "Incremental is set." staticdir = config.get("static_dir", "") datadir = config["datadir"] if not staticdir: raise Exception("You must set static_dir in your config file.") flavours = config.get("static_flavours", ["html"]) renderme = [] monthnames = config.get("static_monthnames", 1) monthnumbers = config.get("static_monthnumbers", 0) dates = {} categories = {} # first we handle entries and categories listing = tools.Walk(self._request, datadir) for mem in listing: # skip the ones that have bad extensions ext = mem[mem.rfind(".")+1:] if not ext in data["extensions"].keys(): continue # grab the mtime of the entry file mtime = time.mktime(tools.filestat(self._request, mem)) # remove the datadir from the front and the bit at the end mem = mem[len(datadir):mem.rfind(".")] # this is the static filename fn = os.path.normpath(staticdir + mem) # grab the mtime of one of the statically rendered file try: smtime = os.stat(fn + "." + flavours[0])[8] except: smtime = 0 # if the entry is more recent than the static, we want to re-render if smtime < mtime or not incremental: # grab the categories temp = os.path.dirname(mem).split(os.sep) for i in range(len(temp)+1): p = os.sep.join(temp[0:i]) categories[p] = 0 # grab the date mtime = time.localtime(mtime) year = time.strftime("%Y", mtime) month = time.strftime("%m", mtime) # monthname = tools.num2month[month] day = time.strftime("%d", mtime) dates[year] = 1 if monthnumbers: dates[year + "/" + month] = 1 dates[year + "/" + month + "/" + day] = 1 if monthnames: dates[year + "/" + monthname] = 1 dates[year + "/" + monthname + "/" + day] = 1 # toss in the render queue for f in flavours: renderme.append( (mem + "." + f, "") ) print "rendering %d entries." % len(renderme) # handle categories categories = categories.keys() categories.sort() print "rendering %d category indexes." % len(categories) for mem in categories: mem = os.path.normpath( mem + "/index." ) for f in flavours: renderme.append( (mem + f, "") ) # now we handle dates dates = dates.keys() dates.sort() print "rendering %d date indexes." % len(dates) for mem in dates: mem = os.path.normpath( mem + "/index." ) for f in flavours: renderme.append( (mem + f, "") ) # now we handle arbitrary urls additional_stuff = config.get("static_urls", []) print "rendering %d arbitrary urls." % len(additional_stuff) for mem in additional_stuff: if mem.find("?") != -1: url = mem[:mem.find("?")] query = mem[mem.find("?")+1:] else: url = mem query = "" renderme.append( (url, query) ) # now we pass the complete render list to all the plugins # via cb_staticrender_filelist and they can add to the filelist # any ( url, query ) tuples they want rendered. print "(before) building %s files." % len(renderme) handled = tools.run_callback("staticrender_filelist", {'request': self._request, 'filelist': renderme, 'flavours': flavours}) print "building %s files." % len(renderme) for url, q in renderme: print "rendering '%s' ..." % url tools.render_url(config, url, q)
def blosxom_handler(request): """ This is the default blosxom handler. """ import cgi config = request.getConfiguration() data = request.getData() # go through the renderer callback to see if anyone else # wants to render. this renderer gets stored in the data dict # for downstream processing. r = tools.run_callback('renderer', {'request': request}, donefunc=lambda x: x != None, defaultfunc=lambda x: None) if not r: # get the renderer we want to use r = config.get("renderer", "blosxom") # import the renderer r = tools.importName("renderers", r) # get the renderer object r = r.Renderer(request, config.get("stdoutput", sys.stdout)) data['renderer'] = r #why in the world isn't this done in pyblosxom.cgi? request.addHttp({"form": cgi.FieldStorage()}) # process the path info to determine what kind of blog entry(ies) # this is tools.run_callback("pathinfo", {"request": request}, donefunc=lambda x: x != None, defaultfunc=blosxom_process_path_info) # call the filelist callback to generate a list of entries data["entry_list"] = tools.run_callback( "filelist", {"request": request}, donefunc=lambda x: x != None, defaultfunc=blosxom_file_list_handler) # we pass the request with the entry_list through the prepare callback # giving everyone a chance to transform the data. the request is # modified in place. tools.run_callback("prepare", {"request": request}) # now we pass the entry_list through the renderer entry_list = data["entry_list"] renderer = data['renderer'] if renderer and not renderer.rendered: if entry_list: renderer.setContent(entry_list) # Log it as success tools.run_callback( "logrequest", { 'filename': config.get('logfile', ''), 'return_code': '200', 'request': request }) else: renderer.addHeader('Status', '404 Not Found') renderer.setContent({ 'title': 'The page you are looking for is not available', 'body': 'Somehow I cannot find the page you want. ' + 'Go Back to <a href="%s">%s</a>?' % (config["base_url"], config["blog_title"]) }) # Log it as failure tools.run_callback( "logrequest", { 'filename': config.get('logfile', ''), 'return_code': '404', 'request': request }) renderer.render() elif not renderer: output = config.get('stdoutput', sys.stdout) output.write( "Content-Type: text/plain\n\nThere is something wrong with your setup.\n Check your config files and verify that your configuration is correct.\n" )
def runStaticRenderer(self, incremental=0): """ This will go through all possible things in the blog and statically render everything to the "static_dir" specified in the config file. This figures out all the possible path_info settings and calls self.run() a bazillion times saving each file. @param incremental: whether (1) or not (0) to incrementally render the pages. if we're incrementally rendering pages, then we render only the ones that have changed. @type incremental: boolean """ self.initialize() config = self._request.getConfiguration() data = self._request.getData() print "Performing static rendering." if incremental: print "Incremental is set." staticdir = config.get("static_dir", "") datadir = config["datadir"] if not staticdir: raise Exception("You must set static_dir in your config file.") flavours = config.get("static_flavours", ["html"]) renderme = [] monthnames = config.get("static_monthnames", 1) monthnumbers = config.get("static_monthnumbers", 0) dates = {} categories = {} # first we handle entries and categories listing = tools.Walk(self._request, datadir) for mem in listing: # skip the ones that have bad extensions ext = mem[mem.rfind(".") + 1:] if not ext in data["extensions"].keys(): continue # grab the mtime of the entry file mtime = time.mktime(tools.filestat(self._request, mem)) # remove the datadir from the front and the bit at the end mem = mem[len(datadir):mem.rfind(".")] # this is the static filename fn = os.path.normpath(staticdir + mem) # grab the mtime of one of the statically rendered file try: smtime = os.stat(fn + "." + flavours[0])[8] except: smtime = 0 # if the entry is more recent than the static, we want to re-render if smtime < mtime or not incremental: # grab the categories temp = os.path.dirname(mem).split(os.sep) for i in range(len(temp) + 1): p = os.sep.join(temp[0:i]) categories[p] = 0 # grab the date mtime = time.localtime(mtime) year = time.strftime("%Y", mtime) month = time.strftime("%m", mtime) # monthname = tools.num2month[month] day = time.strftime("%d", mtime) dates[year] = 1 if monthnumbers: dates[year + "/" + month] = 1 dates[year + "/" + month + "/" + day] = 1 if monthnames: dates[year + "/" + monthname] = 1 dates[year + "/" + monthname + "/" + day] = 1 # toss in the render queue for f in flavours: renderme.append((mem + "." + f, "")) print "rendering %d entries." % len(renderme) # handle categories categories = categories.keys() categories.sort() print "rendering %d category indexes." % len(categories) for mem in categories: mem = os.path.normpath(mem + "/index.") for f in flavours: renderme.append((mem + f, "")) # now we handle dates dates = dates.keys() dates.sort() print "rendering %d date indexes." % len(dates) for mem in dates: mem = os.path.normpath(mem + "/index.") for f in flavours: renderme.append((mem + f, "")) # now we handle arbitrary urls additional_stuff = config.get("static_urls", []) print "rendering %d arbitrary urls." % len(additional_stuff) for mem in additional_stuff: if mem.find("?") != -1: url = mem[:mem.find("?")] query = mem[mem.find("?") + 1:] else: url = mem query = "" renderme.append((url, query)) # now we pass the complete render list to all the plugins # via cb_staticrender_filelist and they can add to the filelist # any ( url, query ) tuples they want rendered. print "(before) building %s files." % len(renderme) handled = tools.run_callback("staticrender_filelist", { 'request': self._request, 'filelist': renderme, 'flavours': flavours }) print "building %s files." % len(renderme) for url, q in renderme: print "rendering '%s' ..." % url tools.render_url(config, url, q)
def blosxom_handler(request): """ This is the default blosxom handler. """ import cgi config = request.getConfiguration() data = request.getData() # go through the renderer callback to see if anyone else # wants to render. this renderer gets stored in the data dict # for downstream processing. r = tools.run_callback('renderer', {'request': request}, donefunc = lambda x: x != None, defaultfunc = lambda x: None) if not r: # get the renderer we want to use r = config.get("renderer", "blosxom") # import the renderer r = tools.importName("renderers", r) # get the renderer object r = r.Renderer(request, config.get("stdoutput", sys.stdout)) data['renderer'] = r #why in the world isn't this done in pyblosxom.cgi? request.addHttp( {"form": cgi.FieldStorage() } ) # process the path info to determine what kind of blog entry(ies) # this is tools.run_callback("pathinfo", {"request": request}, donefunc=lambda x:x != None, defaultfunc=blosxom_process_path_info) # call the filelist callback to generate a list of entries data["entry_list"] = tools.run_callback("filelist", {"request": request}, donefunc=lambda x:x != None, defaultfunc=blosxom_file_list_handler) # we pass the request with the entry_list through the prepare callback # giving everyone a chance to transform the data. the request is # modified in place. tools.run_callback("prepare", {"request": request}) # now we pass the entry_list through the renderer entry_list = data["entry_list"] renderer = data['renderer'] if renderer and not renderer.rendered: if entry_list: renderer.setContent(entry_list) # Log it as success tools.run_callback("logrequest", {'filename':config.get('logfile',''), 'return_code': '200', 'request': request}) else: renderer.addHeader('Status', '404 Not Found') renderer.setContent( {'title': 'The page you are looking for is not available', 'body': 'Somehow I cannot find the page you want. ' + 'Go Back to <a href="%s">%s</a>?' % (config["base_url"], config["blog_title"])}) # Log it as failure tools.run_callback("logrequest", {'filename':config.get('logfile',''), 'return_code': '404', 'request': request}) renderer.render() elif not renderer: output = config.get('stdoutput', sys.stdout) output.write("Content-Type: text/plain\n\nThere is something wrong with your setup.\n Check your config files and verify that your configuration is correct.\n")
def _lilith_handler(request): """This is the default lilith handler. - cb_filelist - cb_filestat - cb_sortlist - cb_entryparser - cb_preformat - cb_format - cb_postformat - cb_prepare """ config = request._config data = request._data # call the filelist callback to generate a list of entries log.debug('cb_filelist') request = tools.run_callback( "filelist", request, defaultfunc=_filelist) # chance to modify specific meta data e.g. datetime log.debug('cb_filestat') request = tools.run_callback( 'filestat', request, defaultfunc=_filestat) # use datetime to sort chronological log.debug('cb_sortlist') request = tools.run_callback( 'sortlist', request, defaultfunc=_sortlist) # entry specific callbacks log.debug('cb_entryparser') for i,entry in enumerate(request._data['entry_list']): request._data['entry_list'][i] = tools.run_callback( 'entryparser', {'entry': entry, 'config': request._config}, defaultfunc=_entryparser) # last modifications log.debug('cb_prepare') request = _prepare(request) from copy import deepcopy # performance? :S log.debug('cb_item') tools.run_callback('item', deepcopy(request), mapping=lambda x,y: y, defaultfunc=_item) log.debug('cb_page') tools.run_callback('page', deepcopy(request), mapping=lambda x,y: y, defaultfunc=_page) return request