degal/commands/update.py
author Tero Marttila <terom@fixme.fi>
Thu, 02 Jul 2009 21:59:01 +0300
changeset 144 97505a789003
parent 132 degal/commands/main.py@c2b2f4b6fe6d
permissions -rw-r--r--
reorganize/rename the commands and their options stuff, options like --force-html are now split out from main.py into commands/update.py
from degal.command import command, Option
from degal.concurrent import task
from degal import templates

def render_image_html (ctx, image) :
    """
        Render and write out the static .html file for the give image.
    """

    ctx.log_debug("%s", image.html)

    # render full-xhtml-document
    tpl = templates.master(ctx.gallery, image, 
        # with content
        templates.image_page(image)
    )
    
    # write output
    tpl.render_file(image.html)

def update_image_thumbs (image) :
    """
        Update/render and write out the thumbnails (thumb+preview) for the given image, returning the image object
        itself.

        This /should/ be threadsafe. XXX: but it probably isn't entirely.
    """
    
    # this will unconditionally update the image
    image.update()

    return image

def render_folder_images (ctx, images) :
    """
        Render the given series of images (html+thumbnails) as required based on the settings.

        This is capable of rendering the given set of images in parallel.
    """

    # first, update HTML
    for image in images :
        if ctx.options.force_html or image.stale() :
            render_image_html(ctx, image)
    
    # define the render-tasks
    tasks = (task(update_image_thumbs, image) for image in images if ctx.options.force_thumb or image.stale())
    
    # render the thumbnails themselves concurrently, returning the rendered Image objects
    for image in ctx.concurrent.execute(tasks) :
        # log image path
        ctx.log_info("%s", image)

        # release large objects that are not needed anymore
        image.cleanup()

def render_folder_html (ctx, folder) :
    """
        Render and write out the required static .html files for the given folder.

        This will paginate large numbers of images, handle Folders with only subfolders within as a single page, and as
        a bonus, will not render anything for (non-recursively) empty folders.
    """

    # render each page separately
    for page in xrange(folder.page_count) :
        # output .html path
        html = folder.html_page(page)
    
        ctx.log_debug("%s", html)
        
        # render full-html template
        tpl = templates.master(ctx.gallery, folder,
            # content
            templates.folder_page(folder, page)
        )

        # write output
        tpl.render_file(html)

def render_folder (ctx, folder) :
    """
        Recursively render a folder, with render_folder_images and render_folder.

        This does a depth-first search of subfolders.
        
        Updates the Images as needed (based on config.force_thumbs/config.force_html).

        Currently, this will always update the .html for non-empty Folders.
    """

    # do depth-first recursion
    for subfolder in folder.subfolders :
        render_folder(ctx, subfolder)

    if folder.empty :
        # warn
        ctx.log_debug("%s - empty, skipping", folder)
        
        return
 
    # force-update HTML, every time
    render_folder_html(ctx, folder)
    
    # get the list of images that we are going to update, only those that are stale unless any force_update
    update_images = list(folder.index_images(for_update=not ctx.options.force_index))
    
    if update_images :
        # status
        ctx.log_info("%s - rendering %d/%d images", folder, len(update_images), len(folder.images))

        # update images as needed
        render_folder_images(ctx, folder.images)
    
    else :
        # nothing to do
        ctx.log_info("%s - up-to-date", folder)

@command(
    options = (
        Option('--force-html',    help="Force-update HTML documents", action="store_true", default="False"), 
        Option('--force-thumb',   help="Force-update thumbnails", action="store_true", default="False"),
        Option('-F', '--force-update', help="Force-update both", action="store_true", default="False"),
    )
)
def update (ctx, *filter) :
    """
        Scan the gallery for new folders/images, and render updated ones.
    """
    
    # do the force_update/force_index semantics
    if ctx.options.force_update :
        ctx.options.force_index = ctx.options.force_html = ctx.options.force_thumb = True

    elif ctx.options.force_html or ctx.options.force_thumb :
        ctx.options.force_index = True
    
    else :
        ctx.options.force_index = False

    # render the gallery root as a folder
    render_folder(ctx, ctx.gallery)