2015-12-03 06:09:29 +01:00
#!/usr/bin/env python
import os
2015-12-08 06:57:17 +01:00
import sys
2015-12-11 09:22:36 +01:00
import json
2015-12-08 07:04:07 +01:00
import yaml
2015-12-08 09:28:54 +01:00
import shutil
2015-12-08 07:04:07 +01:00
2015-12-08 08:06:39 +01:00
from jinja2 import Environment , FileSystemLoader
templates = Environment ( loader = FileSystemLoader ( [ os . path . realpath ( os . path . join ( os . getcwd ( ) , " templates " ) ) , os . path . join ( os . path . split ( os . path . realpath ( __file__ ) ) [ 0 ] , " templates " ) ] ) )
index_template = templates . get_template ( " index.html " )
gallery_index_template = templates . get_template ( " gallery-index.html " )
2016-02-09 21:03:21 +01:00
page_template = templates . get_template ( " page.html " )
2015-12-08 07:28:57 +01:00
2016-01-18 00:34:46 +01:00
DEFAULT_GM_QUALITY = 75
2016-02-08 04:55:34 +01:00
CACHE_VERSION = 1
2016-02-08 04:56:38 +01:00
2015-12-11 09:22:36 +01:00
class Cache ( object ) :
cache_file_path = os . path . join ( os . getcwd ( ) , " .prosopopee_cache " )
2016-02-09 07:30:45 +01:00
def __init__ ( self , json ) :
# fix: I need to keep a reference to json because for whatever reason
# modules are set to None during python shutdown thus totally breaking
# the __del__ call to save the cache
# This wonderfully stupid behavior has been fixed in 3.4 (which nobody uses)
self . json = json
2015-12-11 09:22:36 +01:00
if os . path . exists ( os . path . join ( os . getcwd ( ) , " .prosopopee_cache " ) ) :
self . cache = json . load ( open ( self . cache_file_path , " r " ) )
else :
2016-02-09 07:30:23 +01:00
self . cache = { " version " : CACHE_VERSION }
2016-02-08 04:55:34 +01:00
if " version " not in self . cache or self . cache [ " version " ] != CACHE_VERSION :
print " info: cache format as changed, prune cache "
2016-02-09 07:30:23 +01:00
self . cache = { " version " : CACHE_VERSION }
2015-12-11 09:22:36 +01:00
2016-02-09 06:30:43 +01:00
def thumbnail_needs_to_be_generated ( self , source , target , image ) :
2015-12-11 09:22:36 +01:00
if not os . path . exists ( target ) :
return True
if target not in self . cache :
return True
2016-02-09 06:30:43 +01:00
cached_thumbnail = self . cache [ target ]
2016-01-18 00:34:46 +01:00
2016-02-09 06:30:43 +01:00
if cached_thumbnail [ " size " ] != os . path . getsize ( source ) or cached_thumbnail [ " options " ] != image . options :
2015-12-11 09:22:36 +01:00
return True
return False
2016-02-09 06:30:43 +01:00
def cache_thumbnail ( self , source , target , image ) :
self . cache [ target ] = { " size " : os . path . getsize ( source ) , " options " : image . options }
2015-12-11 09:22:36 +01:00
def __del__ ( self ) :
2016-02-09 07:30:45 +01:00
self . json . dump ( self . cache , open ( self . cache_file_path , " w " ) )
2015-12-11 09:22:36 +01:00
2016-02-09 07:30:45 +01:00
CACHE = Cache ( json = json )
2015-12-11 09:22:36 +01:00
2016-02-09 07:31:37 +01:00
class Image ( object ) :
base_dir = " "
target_dir = " "
2015-12-11 09:22:36 +01:00
2016-02-09 07:31:37 +01:00
def __init__ ( self , options ) :
# assuming string
if not isinstance ( options , dict ) :
name = options
options = { " name " : options }
2015-12-11 09:22:36 +01:00
2016-02-09 07:31:37 +01:00
self . name = name
self . quality = options . get ( " quality " , DEFAULT_GM_QUALITY )
self . options = options . copy ( ) # used for caching, if it's modified -> regenerate
del self . options [ " name " ]
2015-12-08 09:29:38 +01:00
2016-02-09 07:31:37 +01:00
def copy ( self ) :
source , target = os . path . join ( self . base_dir , self . name ) , os . path . join ( self . target_dir , self . name )
2015-12-11 09:13:52 +01:00
# XXX doing this DOESN'T improve perf at all (or something like 0.1%)
# if os.path.exists(target) and os.path.getsize(source) == os.path.getsize(target):
# print "Skiped %s since the file hasn't been modified based on file size" % source
# return ""
shutil . copyfile ( source , target )
2016-01-18 00:34:46 +01:00
2015-12-11 09:13:52 +01:00
print source , " -> " , target
2015-12-08 09:29:38 +01:00
return " "
2016-02-09 07:31:37 +01:00
def generate_thumbnail ( self , gm_geometry ) :
thumbnail_name = self . name . split ( " . " )
2015-12-09 07:05:48 +01:00
thumbnail_name [ - 2 ] + = " -small "
thumbnail_name = " . " . join ( thumbnail_name )
2016-02-09 07:31:37 +01:00
source , target = os . path . join ( self . base_dir , self . name ) , os . path . join ( self . target_dir , thumbnail_name )
2015-12-11 09:22:36 +01:00
2016-02-09 07:31:37 +01:00
if CACHE . thumbnail_needs_to_be_generated ( source , target , self ) :
command = " gm convert %s -resize %s -quality %s %s " % ( source , gm_geometry , self . quality , target )
2015-12-11 09:51:11 +01:00
print command
2015-12-11 09:22:36 +01:00
os . system ( command )
2016-02-09 07:31:37 +01:00
CACHE . cache_thumbnail ( source , target , self )
2015-12-11 09:51:11 +01:00
else :
2016-02-09 06:30:43 +01:00
print " skiped %s since it ' s already generated (based on source unchanged size and images options set in your gallery ' s settings.yaml) " % target
2015-12-11 09:22:36 +01:00
2015-12-09 07:05:48 +01:00
return thumbnail_name
2016-02-09 07:31:37 +01:00
def __repr__ ( self ) :
return self . name
2015-12-08 09:29:38 +01:00
2015-12-08 07:28:57 +01:00
def error ( test , error_message ) :
2015-12-08 10:43:11 +01:00
if test :
return
sys . stderr . write ( error_message )
sys . stderr . write ( " \n " )
sys . stderr . write ( " Abort. \n " )
sys . exit ( 1 )
2015-12-08 06:57:17 +01:00
2015-12-08 07:28:57 +01:00
def main ( ) :
2015-12-09 06:57:53 +01:00
if os . system ( " which gm > /dev/null " ) != 0 :
2016-02-09 06:35:31 +01:00
sys . stderr . write ( " ERROR: I can ' t locate the ' gm ' binary, I won ' t be able to resize images, please install the ' graphicsmagick ' package. \n " )
sys . exit ( 1 )
2015-12-09 06:57:53 +01:00
2015-12-08 08:06:47 +01:00
error ( os . path . exists ( os . path . join ( os . getcwd ( ) , " settings.yaml " ) ) , " I can ' t find a settings.yaml in the current working directory " )
2015-12-08 07:28:57 +01:00
2015-12-08 07:36:17 +01:00
settings = yaml . safe_load ( open ( " settings.yaml " , " r " ) )
2015-12-08 07:04:07 +01:00
2015-12-08 07:28:57 +01:00
error ( isinstance ( settings , dict ) , " Your settings.yaml should be a dict " )
error ( settings . get ( " title " ) , " You should specify a title in your main settings.yaml " )
2015-12-08 07:34:55 +01:00
front_page_galleries_cover = [ ]
2015-12-08 07:18:41 +01:00
2015-12-08 07:11:55 +01:00
dirs = filter ( lambda x : x not in ( " . " , " .. " ) and os . path . isdir ( x ) and os . path . exists ( os . path . join ( os . getcwd ( ) , x , " settings.yaml " ) ) , os . listdir ( os . getcwd ( ) ) )
2016-01-24 12:57:19 +01:00
error ( dirs , " I can ' t find at least one directory with a settings.yaml in the current working directory (NOT the settings.yml in your current directory, but a one INSIDE A DIRECTORY in your current working directory), you don ' t have any gallery? " )
2015-12-08 07:34:55 +01:00
2015-12-08 09:28:54 +01:00
if not os . path . exists ( " build " ) :
os . makedirs ( " build " )
# XXX recursively merge directories
2015-12-09 09:03:18 +01:00
if os . path . exists ( os . path . join ( os . getcwd ( ) , " build " , " static " ) ) :
shutil . rmtree ( os . path . join ( os . getcwd ( ) , " build " , " static " ) )
2015-12-08 09:28:54 +01:00
shutil . copytree ( os . path . join ( os . path . split ( os . path . realpath ( __file__ ) ) [ 0 ] , " static " ) , os . path . join ( os . getcwd ( ) , " build " , " static " ) )
2015-12-08 07:34:55 +01:00
for gallery in dirs :
2015-12-08 08:06:47 +01:00
gallery_settings = yaml . safe_load ( open ( os . path . join ( os . getcwd ( ) , gallery , " settings.yaml " ) , " r " ) )
2015-12-08 07:34:55 +01:00
2015-12-08 08:06:47 +01:00
error ( isinstance ( gallery_settings , dict ) , " Your %s should be a dict " % ( os . path . join ( gallery , " settings.yaml " ) ) )
2015-12-08 07:34:55 +01:00
error ( gallery_settings . get ( " title " ) , " You should specify a title in %s " % ( os . path . join ( gallery , " settings.yaml " ) ) )
error ( gallery_settings . get ( " cover " ) , " You should specify a path to a cover picture in %s " % ( os . path . join ( gallery , " settings.yaml " ) ) )
2015-12-08 10:41:32 +01:00
cover_image_path = os . path . join ( gallery , gallery_settings [ " cover " ] )
2015-12-08 08:22:08 +01:00
2015-12-08 10:37:21 +01:00
error ( os . path . exists ( cover_image_path ) , " File for %s cover image doesn ' t exists at %s " % ( gallery , cover_image_path ) )
2015-12-08 08:22:08 +01:00
2015-12-08 07:34:55 +01:00
gallery_title = gallery_settings [ " title " ]
gallery_sub_title = gallery_settings . get ( " sub_title " , " " )
2015-12-08 08:08:32 +01:00
gallery_date = gallery_settings [ " date " ] if " date " in gallery_settings else " "
2015-12-08 07:34:55 +01:00
2015-12-10 01:45:42 +01:00
if gallery_settings . get ( " public " , True ) :
front_page_galleries_cover . append ( {
" title " : gallery_title ,
" link " : gallery ,
" sub_title " : gallery_sub_title ,
" date " : gallery_date ,
" cover " : cover_image_path ,
} )
2015-12-08 07:11:55 +01:00
2015-12-08 09:29:31 +01:00
if not os . path . exists ( os . path . join ( " build " , gallery ) ) :
os . makedirs ( os . path . join ( " build " , gallery ) )
2015-12-08 08:41:02 +01:00
2016-02-09 07:31:37 +01:00
# this should probably be a factory
Image . base_dir = os . path . join ( os . getcwd ( ) , gallery )
Image . target_dir = os . path . join ( os . getcwd ( ) , " build " , gallery )
open ( os . path . join ( " build " , gallery , " index.html " ) , " w " ) . write ( gallery_index_template . render ( settings = settings , gallery = gallery_settings , Image = Image ) . encode ( " Utf-8 " ) )
2015-12-08 08:07:24 +01:00
2015-12-10 00:51:21 +01:00
front_page_galleries_cover = reversed ( sorted ( front_page_galleries_cover , key = lambda x : x [ " date " ] ) )
2015-12-08 06:55:01 +01:00
2016-02-08 11:28:11 +01:00
if settings . get ( ' menu ' ) :
for item in settings [ " menu " ] :
2016-02-09 21:03:21 +01:00
for link in item :
item_file = link
error ( os . path . exists ( os . path . join ( os . getcwd ( ) , item_file + " .yaml " ) ) , " I can ' t find a " + item_file + " .yaml in the current working directory " )
2016-02-09 21:24:41 +01:00
open ( os . path . join ( " build " , item_file + " .html " ) , " w " ) . write ( page_template . render ( settings = settings , pages = yaml . safe_load ( open ( item_file + " .yaml " , " r " ) ) , galleries = front_page_galleries_cover ) . encode ( " Utf-8 " ) )
2016-02-08 11:28:11 +01:00
2016-02-09 07:31:37 +01:00
Image . base_dir = os . getcwd ( )
Image . target_dir = os . path . join ( os . getcwd ( ) , " build " )
open ( os . path . join ( " build " , " index.html " ) , " w " ) . write ( index_template . render ( settings = settings , galleries = front_page_galleries_cover , Image = Image ) . encode ( " Utf-8 " ) )
2015-12-08 10:42:00 +01:00
2015-12-08 06:55:01 +01:00
if __name__ == ' __main__ ' :
main ( )