Merge pull request #368 from riton/feature/nozip_file
Add new plugin to allow one to disable ZIP generation on a per album basis
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
Plugins
|
||||
=========
|
||||
|
||||
.. contents::
|
||||
|
||||
How to use plugins
|
||||
------------------
|
||||
|
||||
@@ -128,3 +130,8 @@ Watermark plugin
|
||||
================
|
||||
|
||||
.. automodule:: sigal.plugins.watermark
|
||||
|
||||
ZIP Gallery plugin
|
||||
==================
|
||||
|
||||
.. automodule:: sigal.plugins.zip_gallery
|
||||
|
||||
@@ -31,7 +31,6 @@ import os
|
||||
import pickle
|
||||
import random
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
from click import progressbar, get_terminal_size
|
||||
from collections import defaultdict
|
||||
@@ -521,37 +520,10 @@ class Album:
|
||||
|
||||
@cached_property
|
||||
def zip(self):
|
||||
"""Make a ZIP archive with all media files and return its path.
|
||||
|
||||
If the ``zip_gallery`` setting is set,it contains the location of a zip
|
||||
archive with all original images of the corresponding directory.
|
||||
|
||||
"""Placeholder ZIP method.
|
||||
The ZIP logic is controlled by the zip_gallery plugin
|
||||
"""
|
||||
zip_gallery = self.settings['zip_gallery']
|
||||
|
||||
if zip_gallery and len(self) > 0:
|
||||
zip_gallery = zip_gallery.format(album=self)
|
||||
archive_path = join(self.dst_path, zip_gallery)
|
||||
if (self.settings.get('zip_skip_if_exists', False) and
|
||||
isfile(archive_path)):
|
||||
self.logger.debug("Archive %s already created, passing",
|
||||
archive_path)
|
||||
return zip_gallery
|
||||
|
||||
archive = zipfile.ZipFile(archive_path, 'w', allowZip64=True)
|
||||
attr = ('src_path' if self.settings['zip_media_format'] == 'orig'
|
||||
else 'dst_path')
|
||||
|
||||
for p in self:
|
||||
path = getattr(p, attr)
|
||||
try:
|
||||
archive.write(path, os.path.split(path)[1])
|
||||
except OSError as e:
|
||||
self.logger.warn('Failed to add %s to the ZIP: %s', p, e)
|
||||
|
||||
archive.close()
|
||||
self.logger.debug('Created ZIP archive %s', archive_path)
|
||||
return zip_gallery
|
||||
return None
|
||||
|
||||
|
||||
class Gallery(object):
|
||||
|
||||
103
sigal/plugins/zip_gallery.py
Normal file
103
sigal/plugins/zip_gallery.py
Normal file
@@ -0,0 +1,103 @@
|
||||
# Copyright 2019 - Remi Ferrand
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
""" This plugin controls the generation of a ZIP archive for a gallery
|
||||
|
||||
If the ``zip_gallery`` setting is set, it contains the location of a zip
|
||||
archive with all original images of the corresponding directory.
|
||||
|
||||
To ignore a ZIP gallery generation for a particular album, put
|
||||
a ``.nozip_gallery`` file next to it in its parent folder. Only the existence
|
||||
of this ``.nozip_gallery`` file is tested. If no ``.nozip_gallery`` file is
|
||||
present, then make a ZIP archive with all media files.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from os.path import isfile, join, splitext
|
||||
from sigal import signals
|
||||
from sigal.gallery import Album
|
||||
from sigal.utils import cached_property
|
||||
import zipfile
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def _should_generate_album_zip(album):
|
||||
"""Checks whether a `.nozip_gallery` file exists in the album folder"""
|
||||
nozipgallerypath = os.path.join(album.src_path, ".nozip_gallery")
|
||||
return not os.path.isfile(nozipgallerypath)
|
||||
|
||||
def _generate_album_zip(album):
|
||||
"""Make a ZIP archive with all media files and return its path.
|
||||
|
||||
If the ``zip_gallery`` setting is set,it contains the location of a zip
|
||||
archive with all original images of the corresponding directory.
|
||||
"""
|
||||
|
||||
zip_gallery = album.settings['zip_gallery']
|
||||
|
||||
if zip_gallery and len(album) > 0:
|
||||
zip_gallery = zip_gallery.format(album=album)
|
||||
archive_path = join(album.dst_path, zip_gallery)
|
||||
if (album.settings.get('zip_skip_if_exists', False) and
|
||||
isfile(archive_path)):
|
||||
logger.debug("Archive %s already created, passing", archive_path)
|
||||
return zip_gallery
|
||||
|
||||
archive = zipfile.ZipFile(archive_path, 'w', allowZip64=True)
|
||||
attr = ('src_path' if album.settings['zip_media_format'] == 'orig'
|
||||
else 'dst_path')
|
||||
|
||||
for p in album:
|
||||
path = getattr(p, attr)
|
||||
try:
|
||||
archive.write(path, os.path.split(path)[1])
|
||||
except OSError as e:
|
||||
logger.warn('Failed to add %s to the ZIP: %s', p, e)
|
||||
|
||||
archive.close()
|
||||
logger.debug('Created ZIP archive %s', archive_path)
|
||||
return zip_gallery
|
||||
|
||||
return False
|
||||
|
||||
def generate_album_zip(album):
|
||||
"""Checks for .nozip_gallery file in album folder.
|
||||
If this file exists, no ZIP archive is generated.
|
||||
If the file is absent, make a ZIP archive with all media files and return its path.
|
||||
|
||||
If the ``zip_gallery`` setting is set,it contains the location of a zip
|
||||
archive with all original images of the corresponding directory.
|
||||
"""
|
||||
|
||||
# check if ZIP file generation as been disabled by .nozip_gallery file
|
||||
if not _should_generate_album_zip(album):
|
||||
logger.info("Ignoring ZIP gallery generation for album '%s' because of present "
|
||||
".nozip_gallery file", album.name)
|
||||
return False
|
||||
|
||||
return _generate_album_zip(album)
|
||||
|
||||
def nozip_gallery_file(album, settings=None):
|
||||
"""Filesystem based switch to disable ZIP generation for an Album"""
|
||||
Album.zip = cached_property(generate_album_zip)
|
||||
|
||||
def register(settings):
|
||||
signals.album_initialized.connect(nozip_gallery_file)
|
||||
0
tests/sample/pictures/dir2/.nozip_gallery
Normal file
0
tests/sample/pictures/dir2/.nozip_gallery
Normal file
@@ -9,9 +9,15 @@ links = [('Example link', 'http://example.org'),
|
||||
|
||||
files_to_copy = (('../watermark.png', 'watermark.png'),)
|
||||
|
||||
plugins = ['sigal.plugins.adjust', 'sigal.plugins.copyright',
|
||||
'sigal.plugins.watermark', 'sigal.plugins.feeds',
|
||||
'sigal.plugins.nomedia', 'sigal.plugins.extended_caching']
|
||||
plugins = [
|
||||
'sigal.plugins.adjust',
|
||||
'sigal.plugins.copyright',
|
||||
'sigal.plugins.extended_caching'
|
||||
'sigal.plugins.feeds',
|
||||
'sigal.plugins.nomedia',
|
||||
'sigal.plugins.watermark',
|
||||
'sigal.plugins.zip_gallery',
|
||||
]
|
||||
copyright = '© An example copyright message'
|
||||
adjust_options = {'color': 0.9, 'brightness': 1.0,
|
||||
'contrast': 1.0, 'sharpness': 0.0}
|
||||
|
||||
@@ -2,33 +2,33 @@ import os
|
||||
import glob
|
||||
import zipfile
|
||||
|
||||
from sigal import init_plugins
|
||||
from sigal.gallery import Gallery
|
||||
from sigal.settings import read_settings
|
||||
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
SAMPLE_DIR = os.path.join(CURRENT_DIR, 'sample')
|
||||
SAMPLE_SOURCE = os.path.join(SAMPLE_DIR, 'pictures', 'dir1')
|
||||
SAMPLE_SOURCE = os.path.join(SAMPLE_DIR, 'pictures')
|
||||
|
||||
|
||||
def make_gallery(**kwargs):
|
||||
def make_gallery(source_dir='dir1', **kwargs):
|
||||
default_conf = os.path.join(SAMPLE_DIR, 'sigal.conf.py')
|
||||
settings = read_settings(default_conf)
|
||||
settings['source'] = SAMPLE_SOURCE
|
||||
settings['source'] = os.path.join(SAMPLE_SOURCE, source_dir)
|
||||
settings.update(kwargs)
|
||||
init_plugins(settings)
|
||||
return Gallery(settings, ncpu=1)
|
||||
|
||||
|
||||
def test_zipped_correctly(tmpdir):
|
||||
outpath = str(tmpdir)
|
||||
gallery = make_gallery(destination=outpath,
|
||||
zip_gallery='archive.zip')
|
||||
gallery = make_gallery(destination=outpath, zip_gallery='archive.zip')
|
||||
gallery.build()
|
||||
|
||||
zipped1 = glob.glob(os.path.join(outpath, 'test1', '*.zip'))
|
||||
assert len(zipped1) == 1
|
||||
assert os.path.basename(zipped1[0]) == 'archive.zip'
|
||||
zipf = os.path.join(outpath, 'test1', 'archive.zip')
|
||||
assert os.path.isfile(zipf)
|
||||
|
||||
zip_file = zipfile.ZipFile(zipped1[0], 'r')
|
||||
zip_file = zipfile.ZipFile(zipf, 'r')
|
||||
expected = ('11.jpg', 'CMB_Timeline300_no_WMAP.jpg',
|
||||
'flickr_jerquiaga_2394751088_cc-by-nc.jpg',
|
||||
'example.gif')
|
||||
@@ -38,16 +38,23 @@ def test_zipped_correctly(tmpdir):
|
||||
|
||||
zip_file.close()
|
||||
|
||||
zipped2 = glob.glob(os.path.join(outpath, 'test2', '*.zip'))
|
||||
assert len(zipped2) == 1
|
||||
assert os.path.basename(zipped2[0]) == 'archive.zip'
|
||||
assert os.path.isfile(os.path.join(outpath, 'test2', 'archive.zip'))
|
||||
|
||||
|
||||
def test_not_zipped(tmpdir):
|
||||
# test that the zip file is not created when the .nozip_gallery file
|
||||
# is present
|
||||
outpath = str(tmpdir)
|
||||
gallery = make_gallery(destination=outpath, zip_gallery='archive.zip',
|
||||
source_dir='dir2')
|
||||
gallery.build()
|
||||
assert not os.path.isfile(os.path.join(outpath, 'archive.zip'))
|
||||
|
||||
|
||||
def test_no_archive(tmpdir):
|
||||
outpath = str(tmpdir)
|
||||
gallery = make_gallery(destination=outpath,
|
||||
zip_gallery=False)
|
||||
gallery = make_gallery(destination=outpath, zip_gallery=False)
|
||||
gallery.build()
|
||||
|
||||
assert not glob.glob(os.path.join(outpath, 'test1', '*.zip'))
|
||||
assert not glob.glob(os.path.join(outpath, 'test2', '*.zip'))
|
||||
assert not os.path.isfile(os.path.join(outpath, 'test1', 'archive.zip'))
|
||||
assert not os.path.isfile(os.path.join(outpath, 'test2', 'archive.zip'))
|
||||
|
||||
Reference in New Issue
Block a user