Browse Source

New settings to define the sort order for albums and medias (closes #2).

pull/87/merge
Simon Conseil 12 years ago
parent
commit
befc3581c4
  1. 3
      docs/changelog.rst
  2. 8
      sigal/compat.py
  3. 33
      sigal/gallery.py
  4. 4
      sigal/image.py
  5. 3
      sigal/settings.py
  6. 10
      sigal/templates/sigal.conf.py
  7. BIN
      tests/sample/pictures/dir1/test2/archlinux-kiss-1024x640.png
  8. 34
      tests/test_gallery.py

3
docs/changelog.rst

@ -18,6 +18,9 @@ Released on 2014-xx-xx.
``album.title``, ``media.file`` => ``media.filename``, ``media.thumb`` =>
``media.thumbnail``, ``zip_gallery`` => ``album.zip``
- New settings to define the sort order for albums and medias:
``albums_sort_reverse``, ``medias_sort_attr``, ``medias_sort_reverse``.
Version 0.6.0
~~~~~~~~~~~~~

8
sigal/compat.py

@ -9,9 +9,7 @@ if not PY2:
text_type = str
string_types = (str,)
unichr = chr
from functools import cmp_to_key
alpha_sort = {'key': cmp_to_key(locale.strcoll)}
strxfrm = locale.strxfrm
from http import server
import socketserver
@ -19,7 +17,9 @@ else:
text_type = unicode # NOQA
string_types = (str, unicode) # NOQA
unichr = unichr
alpha_sort = {'cmp': locale.strcoll}
def strxfrm(s):
return locale.strxfrm(s.encode('utf-8'))
import SimpleHTTPServer as server
import SocketServer as socketserver

33
sigal/gallery.py

@ -32,11 +32,12 @@ import sys
import zipfile
from collections import defaultdict
from os.path import isfile, join
from datetime import datetime
from os.path import isfile, join, splitext
from PIL import Image as PILImage
from . import image, video
from .compat import UnicodeMixin, alpha_sort
from .compat import UnicodeMixin, strxfrm
from .image import process_image, get_exif_tags
from .log import colored, BLUE
from .settings import get_thumb, get_orig
@ -76,6 +77,7 @@ class Media(UnicodeMixin):
self.logger = logging.getLogger(__name__)
self.raw_exif = None
self.exif = None
self.date = None
def __repr__(self):
return "<%s>(%r)" % (self.__class__.__name__, self.file_path)
@ -120,6 +122,8 @@ class Image(Media):
def __init__(self, filename, path, settings):
super(Image, self).__init__(filename, path, settings)
self.raw_exif, self.exif = get_exif_tags(self.src_path)
if self.exif is not None and 'dateobj' in self.exif:
self.date = self.exif['dateobj']
class Video(Media):
@ -130,7 +134,7 @@ class Video(Media):
def __init__(self, filename, path, settings):
super(Video, self).__init__(filename, path, settings)
base = os.path.splitext(filename)[0]
base = splitext(filename)[0]
self.file_path = join(path, base + '.webm')
self.dst_path = join(settings['destination'], path, base + '.webm')
@ -188,19 +192,17 @@ class Album(UnicodeMixin):
self.index_url = os.path.relpath(settings['destination'],
self.dst_path) + '/' + self.url_ext
# sort images and sub-albums by name
filenames.sort(**alpha_sort)
dirnames.sort(**alpha_sort)
# sort sub-albums
dirnames.sort(key=strxfrm, reverse=settings['albums_sort_reverse'])
self.subdirs = dirnames
#: List of all medias in the album (:class:`~sigal.gallery.Image` and
#: :class:`~sigal.gallery.Video`).
self.medias = []
self.medias = medias = []
self.medias_count = defaultdict(int)
for f in filenames:
ext = os.path.splitext(f)[1]
ext = splitext(f)[1]
if ext in Image.extensions:
media = Image(f, self.path, settings)
elif ext in Video.extensions:
@ -209,7 +211,16 @@ class Album(UnicodeMixin):
continue
self.medias_count[media.type] += 1
self.medias.append(media)
medias.append(media)
# sort images
medias_sort_attr = settings['medias_sort_attr']
if medias_sort_attr == 'date':
key = lambda s: s.date or datetime.now()
else:
key = lambda s: strxfrm(getattr(s, medias_sort_attr))
medias.sort(key=key, reverse=settings['medias_sort_reverse'])
def __repr__(self):
return "<%s>(%r)" % (self.__class__.__name__, self.path)
@ -292,7 +303,7 @@ class Album(UnicodeMixin):
else:
# find and return the first landscape image
for f in self.medias:
ext = os.path.splitext(f.filename)[1]
ext = splitext(f.filename)[1]
if ext in Image.extensions:
im = PILImage.open(f.src_path)
if im.size[0] > im.size[1]:

4
sigal/image.py

@ -218,8 +218,8 @@ def get_exif_tags(source):
try:
# Remove null bytes at the end if necessary
date = data['DateTimeOriginal'].rsplit('\x00')[0]
dt = datetime.strptime(date, '%Y:%m:%d %H:%M:%S')
dt = dt.strftime('%A, %d. %B %Y')
simple['dateobj'] = datetime.strptime(date, '%Y:%m:%d %H:%M:%S')
dt = simple['dateobj'].strftime('%A, %d. %B %Y')
if compat.PY2:
simple['datetime'] = dt.decode('utf8')

3
sigal/settings.py

@ -31,6 +31,7 @@ from .compat import PY2
_DEFAULT_CONFIG = {
'adjust_options': {'color': 1.0, 'brightness': 1.0,
'contrast': 1.0, 'sharpness': 1.0},
'albums_sort_reverse': False,
'copy_exif_data': True,
'copyright': '',
'destination': '_build',
@ -44,6 +45,8 @@ _DEFAULT_CONFIG = {
'keep_orig': False,
'links': '',
'locale': '',
'medias_sort_attr': 'filename',
'medias_sort_reverse': False,
'make_thumbs': True,
'orig_dir': 'original',
'orig_link': False,

10
sigal/templates/sigal.conf.py

@ -61,6 +61,16 @@ thumb_size = (280, 210)
# Use symbolic links instead of copying the original images
# orig_link = False
# Reverse sort for albums
albums_sort_reverse = False
# Attribute of Media objects which is used to sort medias. 'date' can be used
# to sort with EXIF dates.
medias_sort_attr = 'filename'
# Reverse sort for medias
medias_sort_reverse = False
# Jpeg options
# jpg_options = {'quality': 85,
# 'optimize': True,

BIN
tests/sample/pictures/dir1/test2/archlinux-kiss-1024x640.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

34
tests/test_gallery.py

@ -1,5 +1,6 @@
# -*- coding:utf-8 -*-
import locale
import os
import pytest
@ -31,7 +32,7 @@ REF = {
'name': 'test2',
'thumbnail': 'test2/thumbnails/21.tn.jpg',
'subdirs': [],
'medias': ['21.jpg', '22.jpg'],
'medias': ['21.jpg', '22.jpg', 'archlinux-kiss-1024x640.png'],
},
'dir2': {
'title': 'Another example gallery with a very long name',
@ -39,9 +40,9 @@ REF = {
'thumbnail': 'dir2/thumbnails/m57_the_ring_nebula-587px.tn.jpg',
'subdirs': [],
'medias': ['exo20101028-b-full.jpg',
'm57_the_ring_nebula-587px.jpg',
'Hubble Interacting Galaxy NGC 5257.jpg',
'Hubble ultra deep field.jpg',
'Hubble Interacting Galaxy NGC 5257.jpg'],
'm57_the_ring_nebula-587px.jpg'],
},
u'accentué': {
'title': u'Accentué',
@ -118,6 +119,7 @@ def test_video(settings, tmpdir):
@pytest.mark.parametrize("path,album", REF.items())
def test_album(path, album, settings, tmpdir):
locale.setlocale(locale.LC_ALL, 'fr_FR')
gal = Gallery(settings, ncpu=1)
a = Album(path, settings, album['subdirs'], album['medias'], gal)
@ -129,7 +131,7 @@ def test_album(path, album, settings, tmpdir):
assert len(a) == len(album['medias'])
def test_album_medias(settings, tmpdir):
def test_album_medias(settings):
gal = Gallery(settings, ncpu=1)
album = REF['dir1/test1']
@ -143,6 +145,30 @@ def test_album_medias(settings, tmpdir):
assert list(a.images) == []
def test_albums_sort(settings):
gal = Gallery(settings, ncpu=1)
album = REF['dir1']
settings['albums_sort_reverse'] = True
a = Album('dir1', settings, album['subdirs'], album['medias'], gal)
assert [im.filename for im in a.images] == list(reversed(album['medias']))
def test_medias_sort(settings):
gal = Gallery(settings, ncpu=1)
album = REF['dir1/test2']
settings['medias_sort_reverse'] = True
a = Album('dir1/test2', settings, album['subdirs'], album['medias'], gal)
assert [im.filename for im in a.images] == list(reversed(album['medias']))
settings['medias_sort_attr'] = 'date'
settings['medias_sort_reverse'] = False
a = Album('dir1/test2', settings, album['subdirs'], album['medias'], gal)
assert [im.filename for im in a.images] == ['22.jpg', '21.jpg',
'archlinux-kiss-1024x640.png']
def test_gallery(settings, tmpdir):
"Test the Gallery class."

Loading…
Cancel
Save