diff --git a/qalbum/Qalbum.py b/qalbum/Qalbum.py index 4c5d89a..a453a90 100755 --- a/qalbum/Qalbum.py +++ b/qalbum/Qalbum.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2016 Ville Rantanen # @@ -18,6 +18,8 @@ import sys,os import re import urllib +import urllib.parse +from html.parser import HTMLParser import shutil import csv import subprocess @@ -27,7 +29,7 @@ from datetime import datetime # (c) ville.q.rantanen@gmail.com -__version__='2.20190411a' +__version__='2.20200922' FILECONFIG=".config" FILEDESC="descriptions.csv" @@ -72,8 +74,8 @@ singlequotes=re.compile("'") stripquotes=re.compile('^"|"$') def getheader(path,parent,title=""): - if title=="": - title=unicode(os.path.basename(path),encoding="utf8").encode('ascii', 'xmlcharrefreplace') + if title == "": + title = unescape(os.path.basename(path)) return ''' @@ -89,6 +91,7 @@ def getheader(path,parent,title=""): ''' + def getfooter(): return ''' @@ -177,49 +180,53 @@ def getpathlist(path,options=False): paths.sort(key=lambda x: natural_sort_key(x)) return paths + def pathscript(path,list): ''' Returns the javascript string of pathlist and pathimage arrays ''' - scrstr='' + scrstr += ','.join(elements) + '];' return scrstr + def pathlinks(path,list): ''' Returns the HTML string of subfolders ''' - if len(list)==0: + if len(list) == 0: return '
' - pathstr='
' - pathstr+='

Subfolders

' + pathstr = '
' + pathstr += '

Subfolders

' for p in list: - nice=nicestring(p) - imglist=getimagelist(os.path.join(path,p)) - nsum=str(len(imglist)) - imgstr="" - if len(imglist)>0: - imgstr='' + nice = nicestring(p) + imglist = getimagelist(os.path.join(path,p)) + nsum = str(len(imglist)) + imgstr = "" + if len(imglist) > 0: + imgstr = '' else: - imgstr='' + imgstr = '' pathstr += '%s%s (%s)'%( - unicode(p,encoding="utf8").encode('ascii', 'xmlcharrefreplace'), - urllib.quote(p), + unescape(p), + urllib.parse.quote(p), imgstr, - nice.encode('ascii', 'xmlcharrefreplace'), + unescape(nice), nsum ) - pathstr+='' - pathstr+='
' + pathstr += '' + pathstr += '
' return pathstr + def imagescript(path,list): ''' Returns the javascript string of imagelist and imagedesc ''' strout='' return strout + def imagelinks(path,list): ''' Returns the HTML string of images ''' - if len(list)==0: + if len(list) == 0: return '
' - strout='
' return strout + def filescript(path,list): ''' Returns the javascript string of filelist ''' - strout='' + elements.append('"' + unescape(i) + '"') + strout += ','.join(elements)+ '];' return strout + def filelinks(path,list): ''' Returns the HTML string of non image files ''' - strout='
' - if len(list)>0: - strout+='

Attachments

' + strout = '
' + if len(list) > 0: + strout += '

Attachments

' n=0 for i in list: - size=sizestring(os.path.getsize(os.path.join(path,i))) - strout+=''+unicode(i,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+' ['+size+']' - n+=1 - strout+='
' + size = sizestring(os.path.getsize(os.path.join(path,i))) + strout += '' + unescape(i) +' ['+size+']' + n += 1 + strout += '
' return strout + def cleanthumbs(path): ''' clears .med and .tn for unused thumbs ''' print('clearing unused thumbs...') @@ -299,6 +310,7 @@ def cleanthumbs(path): clearfolder(path,os.path.join(path,'.med'),re.compile("(.*)(.jpg)")) return + def clearfolder(path,tnpath,regex): ''' clears given folder ''' list=getimagelist(tnpath) @@ -312,6 +324,7 @@ def clearfolder(path,tnpath,regex): continue return + def createthumbs(path,list,options): ''' Runs imagemagick Convert to create medium sized and thumbnail images ''' if len(list)==0: @@ -320,15 +333,15 @@ def createthumbs(path,list,options): os.mkdir(os.path.join(path,'.tn')) if not os.path.exists(os.path.join(path,'.med')): os.mkdir(os.path.join(path,'.med')) - n=1 - nsum=len(list) - r=str(options.width) - res=r+'x'+r+'>' + n = 1 + nsum = len(list) + r = str(options.width) + res = r + 'x' + r + '>' print('') for i in list: - outmedium=os.path.join(path,'.med',i+'.jpg') - outthumb=os.path.join(path,'.tn',i+'.jpg') - inpath=os.path.join(path,i) + outmedium = os.path.join(path,'.med',i+'.jpg') + outthumb = os.path.join(path,'.tn',i+'.jpg') + inpath = os.path.join(path,i) if (options.force) and os.path.exists(outmedium): os.unlink(outmedium) if (options.force) and os.path.exists(outthumb): @@ -343,6 +356,7 @@ def createthumbs(path,list,options): print_clear('') return + def create_medium_bitmap(infile,outfile,r,link=False,vector=False): if link: os.symlink('../'+os.path.basename(infile),outfile) @@ -355,6 +369,7 @@ def create_medium_bitmap(infile,outfile,r,link=False,vector=False): convp=subprocess.call(convargs) return + def create_thumb_bitmap(infile,outfile,vector=False,gravity='Center'): if vector: convargs=['convert','-density','300x300',infile,'-background','white','-flatten','-thumbnail','90x90^','-gravity',gravity,'-crop','90x90+0+0','+repage','-quality','75',outfile] @@ -363,13 +378,14 @@ def create_thumb_bitmap(infile,outfile,vector=False,gravity='Center'): convp=subprocess.call(convargs) return + def getdescriptions(path,list): ''' Read descriptions.csv file and returns a list of descriptions. Missing descriptions are replaced with the file name. ''' if not os.path.exists(os.path.join(path,FILEDESC)): return list desc=[i for i in list] - reader = csv.reader(open(os.path.join(path,FILEDESC),'rb'), + reader = csv.reader(open(os.path.join(path,FILEDESC),'rt'), delimiter='\t', doublequote=False, escapechar='\\', @@ -381,6 +397,7 @@ def getdescriptions(path,list): desc[i]=stripquotes.sub('',row[1]) return desc + def getinfo(path,options): ''' Read info.txt file and returns the content. Missing info file returns empty string. ''' @@ -389,34 +406,36 @@ def getinfo(path,options): reader = open(os.path.join(path,options.infofile),'r') return unicode(reader.read(),encoding="utf8",errors="ignore").encode('ascii','xmlcharrefreplace') -def crumblinks(crumbs,title,parent): - ''' Create the HTML string for crumb trails ''' - strout='
' +def crumblinks(crumbs, title, parent): + ''' Create the HTML string for crumb trails ''' + strout = '
' if parent: if not parent.startswith('http://'): - parent="../"*(len(crumbs))+parent - strout+=''+'Home'.encode('ascii', 'xmlcharrefreplace')+': ' - i=1 + parent = "../"*(len(crumbs))+parent + strout += '' + 'Home' + ': ' + i = 1 for c in crumbs: - cname=os.path.basename(c) - if i==1: - cname=title - cdepth=len(crumbs)-i - clink="../"*cdepth - strout+=''+unicode(cname,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+': ' - i+=1 - strout+='
' + cname = os.path.basename(c) + if i == 1: + cname = title + cdepth = len(crumbs) - i + clink = "../"*cdepth + strout += ''+ unescape(cname) + ': ' + i += 1 + strout += '
' return strout + def print_clear(s): sys.stdout.write("\033[1K\r") sys.stdout.write(str(s)) sys.stdout.flush() + def nicestring(s): ''' Returns a nice version of a long string ''' - s = unicode(s, encoding = "utf8") + s = unescape(s) if len(s)<20: return s s=s.replace("_"," ") @@ -425,6 +444,7 @@ def nicestring(s): s=s[0:26]+".."+s[-3:] return s + def sizestring(size): ''' Returns human readable file size string ''' for x in ['b','kb','Mb','Gb','Tb']: @@ -436,6 +456,10 @@ def sizestring(size): size /= 1024.0 +def unescape(s): + return HTMLParser().unescape(s) + + def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): ''' Natural sort / Claudiu@Stackoverflow ''' return [int(text) if text.isdigit() else text.lower() @@ -459,6 +483,7 @@ def which(program): return None + def traverse(path,crumbs,inputs,options): ''' The recursive main function to create the index.html and seek sub folders ''' diff --git a/qalbum/Qnano2.py b/qalbum/Qnano2.py index f434d9f..66da04d 100755 --- a/qalbum/Qnano2.py +++ b/qalbum/Qnano2.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2018 Ville Rantanen # @@ -18,10 +18,11 @@ import sys,os import re import urllib +import urllib.parse import csv import string from datetime import datetime -from Qalbum import \ +from qalbum.Qalbum import \ cleanthumbs, \ createthumbs, \ crumblinks, \ @@ -34,12 +35,13 @@ from Qalbum import \ nicestring, \ readconfig, \ sizestring, \ + unescape, \ which, \ writeconfig # (c) ville.q.rantanen@gmail.com -__version__='0.20190411a' +__version__='0.20200922' imagesearch=re.compile('.*\.jpg$|.*\.jpeg$|.*\.gif$|.*\.png$|.*\.tif$|.*\.svg$|.*\.pdf$',re.I) vectorsearch=re.compile('.*\.svg$|.*\.pdf$',re.I) @@ -53,9 +55,10 @@ FILECONFIG=".config" FILEINFO="info.txt" FILEDESC="descriptions.csv" + def getheader(path,parent,title=""): if title=="": - title=unicode(os.path.basename(path),encoding="utf8").encode('ascii', 'xmlcharrefreplace') + title=unescape(os.path.basename(path)) return ''' @@ -125,6 +128,8 @@ body { ''' + + def getfooter(): return ''' @@ -132,6 +137,7 @@ def getfooter(): ''' + def imagelinks(path,list): ''' Returns the HTML string of images ''' strout='''\n' - pathstr='

Folders

' + pathstr = '

Folders

' for p in list: nice = nicestring(p) - imglist=getimagelist(os.path.join(path,p)) - nsum=str(len(imglist)) - imgstr="" + imglist = getimagelist(os.path.join(path,p)) + nsum = str(len(imglist)) + imgstr = "" #~ if len(imglist)>0: #~ imgstr='' #~ else: - imgstr='' + imgstr = '' pathstr += ''%( - unicode(p,encoding="utf8").encode('ascii', 'xmlcharrefreplace'), - urllib.quote(p), + unescape(p), + urllib.parse.quote(p), imgstr, - nice.encode('ascii', 'xmlcharrefreplace'), + nice, nsum ) - pathstr+='
' + pathstr += '
' return pathstr + def filelinks(path, list): ''' Returns the HTML string of non image files ''' if len(list) == 0: @@ -204,11 +212,12 @@ def filelinks(path, list): strout = '
' strout += '

Attachments

' for i in list: - size=sizestring(os.path.getsize(os.path.join(path,i))) - strout+='
  • '+unicode(i,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+' ['+size+']
  • ' - strout+='
    ' + size = sizestring(os.path.getsize(os.path.join(path,i))) + strout += '
  • ' + unescape(i) +' ['+size+']
  • ' + strout += '' return strout + def traverse(path,crumbs,inputs,options): ''' The recursive main function to create the index.html and seek sub folders ''' @@ -253,6 +262,7 @@ def traverse(path,crumbs,inputs,options): traverse(os.path.join(path,p),nextcrumbs,inputs,options) return + def setupoptions(): ''' Setup the command line options ''' from argparse import ArgumentParser @@ -327,6 +337,7 @@ def setupdefaultoptions(options): options.width=850 return options + def execute_plain(): ''' Main execution function ''' options=setupoptions() diff --git a/qalbum/__init__.py b/qalbum/__init__.py index a2d1064..b5a16c5 100644 --- a/qalbum/__init__.py +++ b/qalbum/__init__.py @@ -1 +1 @@ -from Qalbum import * +from qalbum.Qalbum import * diff --git a/scripts/Qalbum b/scripts/Qalbum index 66c4ea4..6fedb62 100755 --- a/scripts/Qalbum +++ b/scripts/Qalbum @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- import re diff --git a/scripts/Qalbum-descriptor b/scripts/Qalbum-descriptor index fc3619a..4d0cfae 100755 --- a/scripts/Qalbum-descriptor +++ b/scripts/Qalbum-descriptor @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2016 Ville Rantanen # @@ -17,7 +17,7 @@ import sys,os import subprocess -from argparse import ArgumentParser +from argparse import ArgumentParser from qalbum import Qalbum # (c) ville.q.rantanen@gmail.com @@ -39,13 +39,14 @@ def createdesc(path,list,options): nsum=len(list) for i in list: inpath=os.path.join(path,i) - desc=create_description(inpath,options.format).rstrip().replace('\n','
    ') + desc = create_description(inpath,options.format).decode('utf-8').rstrip().replace('\n','
    ') outfile.write(i+"\t"+desc+'\n') outfile.flush() print('('+str(n)+'/'+str(nsum)+') '+i+"\t"+desc) n+=1 return + def create_description(infile,format): if format=='AbsolutelyEverything': idargs=['identify','-verbose',infile+'[0]'] @@ -55,6 +56,7 @@ def create_description(infile,format): output = idp.stdout.read() return output + def traverse(path,options): ''' The recursive main function to create the thumbs and seek sub folders ''' print(path) @@ -68,6 +70,7 @@ def traverse(path,options): traverse(os.path.join(path,p),options) return + def execute(): ''' Main execution ''' parser=ArgumentParser() @@ -75,7 +78,7 @@ def execute(): parser.add_argument("-f",action="store_true",dest="force",default=False, help="Force rewriting of descriptions") parser.add_argument("--format",type=str,dest="format",default="", - help="""Formatting string, see: http://www.imagemagick.org/script/escape.php. + help="""Formatting string, see: http://www.imagemagick.org/script/escape.php. Setting this option will override the presets""") parser.add_argument("-r",action="store_true",dest="recursive",default=False, help="Recurse in to subfolders") @@ -92,20 +95,20 @@ def execute(): '%f: %wx%h %[size]', '%f
    %[EXIF:DateTimeOriginal] %[EXIF:ExposureTime]s F%[EXIF:FNumber]', 'AbsolutelyEverything'] - if options.preset<1: - print "Presets:" + if options.preset < 1: + print("Presets:") for row in range(len(presets)): - print row+1," ",presets[row] + print(row+1," ",presets[row]) sys.exit(0) if options.format=="": if options.preset>len(presets): parser.error("No such preset, list with -p 0") options.format=presets[options.preset-1] - + traverse(options.startpath,options) return execute() sys.exit(0) - + diff --git a/scripts/Qalbum-thumbnailer b/scripts/Qalbum-thumbnailer index c3518c7..fd67217 100755 --- a/scripts/Qalbum-thumbnailer +++ b/scripts/Qalbum-thumbnailer @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2016 Ville Rantanen # @@ -16,7 +16,7 @@ # along with this program. If not, see . from qalbum import Qalbum -from argparse import ArgumentParser +from argparse import ArgumentParser import os # (c) ville.q.rantanen@gmail.com @@ -37,6 +37,7 @@ def traverse(path,options): traverse(os.path.join(path,p),options) return + def setupoptions(): ''' Setup options ''' usage='''Usage: %(prog)s [options] folder @@ -62,13 +63,15 @@ folder is the root folder of the image album (defaults to current folder).''' options=Qalbum.setupdefaultoptions(options) return options + def execute(): ''' Main execution ''' options=setupoptions() traverse(options.startpath,options) return + if __name__ == "__main__": execute() - + diff --git a/scripts/Qnano2 b/scripts/Qnano2 index c54373d..446055e 100755 --- a/scripts/Qnano2 +++ b/scripts/Qnano2 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- import re diff --git a/setup.py b/setup.py index e99bba1..b2c20f1 100644 --- a/setup.py +++ b/setup.py @@ -1,20 +1,20 @@ from distutils.core import setup setup( name = 'qalbum', - packages = ['qalbum'], + packages = ['qalbum'], scripts = ['scripts/Qalbum', 'scripts/Qalbum-thumbnailer', 'scripts/Qnano2', 'scripts/Qalbum-descriptor'], package_data={'':['lib/*']}, include_package_data=True, - version = '2.20190411a', + version = '2.20200922', description = 'A tool to create a web gallery from a folder structure of images / other files.', author = 'Ville Rantanen', author_email = 'ville.q.rantanen@gmail.com', url = 'https://bitbucket.org/MoonQ/qalbum', - download_url = 'https://bitbucket.org/MoonQ/qalbum/get/tip.tar.gz', - keywords = ['album', 'generator', 'javascript'], + download_url = 'https://bitbucket.org/MoonQ/qalbum/get/master.tar.gz', + keywords = ['album', 'generator', 'javascript'], classifiers = [], license = 'MIT', )