degal/commands/main.py
changeset 132 c2b2f4b6fe6d
parent 131 7021d949222c
equal deleted inserted replaced
131:7021d949222c 132:c2b2f4b6fe6d
     2 from degal.concurrent import task
     2 from degal.concurrent import task
     3 from degal import templates
     3 from degal import templates
     4 
     4 
     5 def render_image_html (ctx, image) :
     5 def render_image_html (ctx, image) :
     6     """
     6     """
     7         Render the thumbnails and .html for one image
     7         Render and write out the static .html file for the give image.
     8     """
     8     """
     9 
     9 
    10     ctx.log_debug("%s", image.html)
    10     ctx.log_debug("%s", image.html)
    11 
    11 
    12     # render output
    12     # render full-xhtml-document
    13     tpl = templates.master(ctx.gallery, image, 
    13     tpl = templates.master(ctx.gallery, image, 
       
    14         # with content
    14         templates.image_page(image)
    15         templates.image_page(image)
    15     )
    16     )
    16     
    17     
    17     # write output
    18     # write output
    18     tpl.render_file(image.html)
    19     tpl.render_file(image.html)
    19 
    20 
    20 def update_image_thumbs (image) :
    21 def update_image_thumbs (image) :
    21     """
    22     """
    22         Render the thubmnails for the given image, returning the image.
    23         Update/render and write out the thumbnails (thumb+preview) for the given image, returning the image object
       
    24         itself.
    23 
    25 
    24         This /should/ be threadsafe.
    26         This /should/ be threadsafe. XXX: but it probably isn't entirely.
    25     """
    27     """
    26     
    28     
    27     # this will unconditionally update the image
    29     # this will unconditionally update the image
    28     image.update()
    30     image.update()
    29 
    31 
    30     return image
    32     return image
    31 
    33 
    32 def render_folder_images (ctx, images, for_update=True) :
    34 def render_folder_images (ctx, images) :
    33     """
    35     """
    34         Render the given series of images
    36         Render the given series of images (html+thumbnails) as required based on the settings.
       
    37 
       
    38         This is capable of rendering the given set of images in parallel.
    35     """
    39     """
    36 
    40 
    37     # XXX: handle this thumb-update/html-update stuff better
    41     # first, update HTML
    38 
       
    39     # render all HTML
       
    40     for image in images :
    42     for image in images :
    41         render_image_html(ctx, image)
    43         if ctx.config.force_html or image.stale() :
    42 
    44             render_image_html(ctx, image)
    43     
    45     
    44     # render the thumbnails concurrently
    46     # define the render-tasks
    45     for image in ctx.concurrent.execute(
    47     tasks = (task(update_image_thumbs, image) for image in images if ctx.config.force_thumb or image.stale())
    46         task(update_image_thumbs, image) 
    48     
    47 
    49     # render the thumbnails themselves concurrently, returning the rendered Image objects
    48             for image in images 
    50     for image in ctx.concurrent.execute(tasks) :
    49 
       
    50             # only test if not already filtered for update
       
    51             # XXX: externalize logic
       
    52             if for_update or ctx.config.force_thumb or image.stale()
       
    53     ) :
       
    54         # log image path
    51         # log image path
    55         ctx.log_info("%s", image)
    52         ctx.log_info("%s", image)
    56 
    53 
    57         # release large objects that are not needed anymore
    54         # release large objects that are not needed anymore
    58         image.cleanup()
    55         image.cleanup()
    59 
    56 
    60 def render_folder_html (ctx, folder) :
    57 def render_folder_html (ctx, folder) :
    61     """
    58     """
    62         Render the .html output for one folder
    59         Render and write out the required static .html files for the given folder.
       
    60 
       
    61         This will paginate large numbers of images, handle Folders with only subfolders within as a single page, and as
       
    62         a bonus, will not render anything for (non-recursively) empty folders.
    63     """
    63     """
    64 
    64 
    65     # render each page separately
    65     # render each page separately
    66     for page in xrange(folder.page_count) :
    66     for page in xrange(folder.page_count) :
    67         # output .html page
    67         # output .html path
    68         html = folder.html_page(page)
    68         html = folder.html_page(page)
    69     
    69     
    70         ctx.log_debug("%s", html)
    70         ctx.log_debug("%s", html)
    71         
    71         
    72         # render template
    72         # render full-html template
    73         tpl = templates.master(ctx.gallery, folder,
    73         tpl = templates.master(ctx.gallery, folder,
       
    74             # content
    74             templates.folder_page(folder, page)
    75             templates.folder_page(folder, page)
    75         )
    76         )
    76 
    77 
    77         # write output
    78         # write output
    78         tpl.render_file(html)
    79         tpl.render_file(html)
    79 
    80 
    80 def render_folder (ctx, folder) :
    81 def render_folder (ctx, folder) :
    81     """
    82     """
    82         Render the HTML/images for this folder if needed, and recrurse into subfolders.
    83         Recursively render a folder, with render_folder_images and render_folder.
    83 
    84 
    84         Returns True if any sub-images were found, False if this folder and all subfolders were completely empty and no
    85         This does a depth-first search of subfolders.
    85         HTML was generated.
       
    86         
    86         
    87         XXX: this logic is too complicated for one function. For one module?
    87         Updates the Images as needed (based on config.force_thumbs/config.force_html).
       
    88 
       
    89         Currently, this will always update the .html for non-empty Folders.
    88     """
    90     """
    89 
    91 
    90     # flag to track if we've rendered any contents.
    92     # do depth-first recursion
    91     empty = True
    93     for subfolder in folder.subfolders :
       
    94         render_folder(ctx, subfolder)
       
    95 
       
    96     if folder.empty :
       
    97         # warn
       
    98         ctx.log_debug("%s - empty, skipping", folder)
       
    99         
       
   100         return
       
   101  
       
   102     # force-update HTML, every time
       
   103     render_folder_html(ctx, folder)
    92     
   104     
    93     if ctx.config.force_html or ctx.config.force_thumb :
   105     # get the list of images that we are going to update, only those that are stale unless any force_update
    94         # index all
   106     update_images = list(folder.index_images(for_update=(not ctx.config.force_update)))
    95         for_update = False
   107     
       
   108     if update_images :
       
   109         # status
       
   110         ctx.log_info("%s - rendering %d/%d images", folder, len(update_images), len(folder.images))
    96 
   111 
       
   112         # update images as needed
       
   113         render_folder_images(ctx, folder.images)
       
   114     
    97     else :
   115     else :
    98         # only new images
   116         # nothing to do
    99         for_update = True
   117         ctx.log_info("%s - up-to-date", folder)
   100     
       
   101     # full count of images
       
   102     image_count = len(folder.images)
       
   103 
       
   104     # index selected images
       
   105     new_images = list(folder.index_images(for_update=for_update))
       
   106 
       
   107     # index subfolders
       
   108     for subfolder in folder.subfolders :
       
   109         if render_folder(ctx, subfolder) :
       
   110             # positive assertion
       
   111             empty = False
       
   112     
       
   113     if folder.images :
       
   114         empty = False
       
   115 
       
   116     # only render HTML if needed
       
   117     if not empty  :
       
   118         # update folder index
       
   119         render_folder_html(ctx, folder)
       
   120     
       
   121     # only render new images if needed   
       
   122     if new_images or ctx.config.force_html :
       
   123         ctx.log_info("%s - render %d/%d images", folder, len(new_images), image_count)
       
   124 
       
   125         # update images
       
   126         render_folder_images(ctx, new_images, for_update)
       
   127 
       
   128     else :
       
   129         ctx.log_info("%s - up to date", folder)
       
   130     
       
   131     # return flag
       
   132     return empty
       
   133 
   118 
   134 @command
   119 @command
   135 def main (ctx) :
   120 def main (ctx) :
   136     """
   121     """
   137         Scan the gallery for new folders/images, and render updated ones
   122         Scan the gallery for new folders/images, and render updated ones
   138     """
   123     """
   139 
   124 
   140     # render the gallery
   125     # render the gallery root as a folder
   141     render_folder(ctx, ctx.gallery)
   126     render_folder(ctx, ctx.gallery)
   142     
   127