Пример #1
0
    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})
Пример #2
0
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
Пример #3
0
    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})
Пример #4
0
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
Пример #5
0
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
Пример #6
0
    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)
Пример #7
0
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
Пример #8
0
    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})
Пример #9
0
    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})
Пример #10
0
 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)
Пример #11
0
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
    
Пример #12
0
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
Пример #13
0
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
Пример #14
0
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
Пример #15
0
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
Пример #16
0
    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)
Пример #17
0
    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")
Пример #18
0
    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)
Пример #19
0
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"
        )
Пример #20
0
    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)
Пример #21
0
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")
Пример #22
0
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