Merge branch 'misc'

This commit is contained in:
Simon Conseil
2020-03-15 22:22:01 -03:00
25 changed files with 68 additions and 78 deletions

View File

@@ -34,7 +34,7 @@ matrix:
install: pip install -U tox-travis
script: tox
script: tox -- -v
after_success:
- pip install codecov

View File

@@ -1,5 +1,5 @@
The MIT License (MIT)
Copyright (c) 2009-2018 - Simon Conseil
Copyright (c) 2009-2020 - Simon Conseil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to

View File

@@ -51,7 +51,7 @@ A total of %d pull requests were merged for this release.
def get_authors(revision_range):
pat = u'^.*\\t(.*)$'
pat = '^.*\\t(.*)$'
lst_release, cur_release = [r.strip() for r in revision_range.split('..')]
# authors, in current release and previous to current release.
@@ -61,7 +61,7 @@ def get_authors(revision_range):
re.M))
# Append '+' to new authors.
authors = [s + u' +' for s in cur - pre] + [s for s in cur & pre]
authors = [s + ' +' for s in cur - pre] + [s for s in cur & pre]
authors.sort()
return authors
@@ -72,17 +72,17 @@ def get_pull_requests(repo, revision_range):
# From regular merges
merges = this_repo.git.log(
'--oneline', '--merges', revision_range)
issues = re.findall(u"Merge pull request \\#(\\d*)", merges)
issues = re.findall("Merge pull request \\#(\\d*)", merges)
prnums.extend(int(s) for s in issues)
# From Homu merges (Auto merges)
issues = re. findall(u"Auto merge of \\#(\\d*)", merges)
issues = re. findall("Auto merge of \\#(\\d*)", merges)
prnums.extend(int(s) for s in issues)
# From fast forward squash-merges
commits = this_repo.git.log(
'--oneline', '--no-merges', '--first-parent', revision_range)
issues = re.findall(u'^.*\\(\\#(\\d+)\\)$', commits, re.M)
issues = re.findall('^.*\\(\\#(\\d+)\\)$', commits, re.M)
prnums.extend(int(s) for s in issues)
# get PR data from github repo
@@ -99,19 +99,19 @@ def main(token, revision_range):
# document authors
authors = get_authors(revision_range)
heading = u"Contributors"
heading = "Contributors"
print()
print(heading)
print("=" * len(heading))
print(author_msg % len(authors))
for s in authors:
print(u'* ' + s)
print('* ' + s)
# document pull requests
pull_requests = get_pull_requests(github_repo, revision_range)
heading = u"Pull requests merged"
pull_msg = u"* `#{0} <{1}>`__: {2}"
heading = "Pull requests merged"
pull_msg = "* `#{0} <{1}>`__: {2}"
print()
print(heading)
@@ -119,11 +119,11 @@ def main(token, revision_range):
print(pull_request_msg % len(pull_requests))
for pull in pull_requests:
title = re.sub(u"\\s+", u" ", pull.title.strip())
title = re.sub("\\s+", " ", pull.title.strip())
if len(title) > 60:
remainder = re.sub(u"\\s.*$", u"...", title[60:])
remainder = re.sub("\\s.*$", "...", title[60:])
if len(remainder) > 20:
remainder = title[:80] + u"..."
remainder = title[:80] + "..."
else:
title = title[:60] + remainder
print(pull_msg.format(pull.number, pull.html_url, title))

View File

@@ -38,7 +38,7 @@ master_doc = 'index'
# General information about the project.
project = 'Sigal'
copyright = '2012-2019, Simon Conseil'
copyright = '2012-2020, Simon Conseil'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the

View File

@@ -21,7 +21,7 @@ Install sigal in development mode::
Install additional dependencies for development (Sphinx, pytest), and optional
dependencies::
pip install -r requirements.txt
pip install -e .\[all,tests\]
Building the docs
-----------------

View File

@@ -8,7 +8,7 @@ With pip::
Or to install with optional dependencies (listed below)::
$ pip install sigal\[all\]
$ pip install sigal\[all,tests\]
To install the development version, see the :doc:`contribute`.
@@ -29,8 +29,8 @@ The mandatory dependencies are:
- Pillow
- Python Markdown
There are also a number of optional dependencies for the :doc:`plugins`, listed
in the ``requirements.txt`` file:
There are also a number of optional dependencies for the :doc:`plugins`,
installable with the ``[all]`` marker:
- Brotli, zopfli (compress assets plugin)
- Boto (upload to S3 plugin)

View File

@@ -1,8 +1,12 @@
version: 2
build:
image: latest
python:
version: 3.7
install:
- method: pip
path: .
- requirements: requirements-doc.txt
extra_requirements:
- docs

View File

@@ -1,3 +0,0 @@
-r requirements.txt
alabaster
Sphinx

View File

@@ -1,13 +0,0 @@
blinker
boto
brotli
click
coverage
feedgenerator
Jinja2
Markdown
Pillow
pilkit
pytest
pytest-cov
zopfli

View File

@@ -38,6 +38,8 @@ install_requires =
[options.extras_require]
all = boto; brotli; feedgenerator; zopfli
tests = pytest; pytest-cov
docs = Sphinx; alabaster
[options.packages.find]
exclude =

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2009-2018 - Simon Conseil
# Copyright (c) 2009-2020 - Simon Conseil
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -74,7 +74,7 @@ def init(path):
with open(path, 'w', encoding='utf-8') as f:
f.write(conf.decode('utf8'))
print("Sample config file created: {}".format(path))
print(f"Sample config file created: {path}")
@main.command()
@@ -224,11 +224,11 @@ def serve(destination, port, config):
.format(destination=destination, config=config))
sys.exit(2)
print('DESTINATION : {}'.format(destination))
print(f'DESTINATION : {destination}')
os.chdir(destination)
Handler = server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", port), Handler, False)
print(" * Running on http://127.0.0.1:{}/".format(port))
print(f" * Running on http://127.0.0.1:{port}/")
try:
httpd.allow_reuse_address = True
@@ -255,7 +255,7 @@ def set_meta(target, keys, overwrite=False):
"""
if not os.path.exists(target):
sys.stderr.write("The target {} does not exist.\n".format(target))
sys.stderr.write(f"The target {target} does not exist.\n")
sys.exit(1)
if len(keys) < 2 or len(keys) % 2 > 0:
sys.stderr.write("Need an even number of arguments.\n")
@@ -273,5 +273,5 @@ def set_meta(target, keys, overwrite=False):
with open(descfile, "w") as fp:
for i in range(len(keys) // 2):
k, v = keys[i * 2:(i + 1) * 2]
fp.write("{}: {}\n".format(k.capitalize(), v))
fp.write(f"{k.capitalize()}: {v}\n")
print("{} metadata key(s) written to {}".format(len(keys) // 2, descfile))

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2009-2018 - Simon Conseil
# Copyright (c) 2009-2020 - Simon Conseil
# Copyright (c) 2013 - Christophe-Marie Duquesne
# Copyright (c) 2014 - Jonas Kaufmann
# Copyright (c) 2015 - François D.
@@ -91,7 +91,7 @@ class Media:
signals.media_initialized.send(self)
def __repr__(self):
return "<%s>(%r)" % (self.__class__.__name__, str(self))
return "<{}>({!r})".format(self.__class__.__name__, str(self))
def __str__(self):
return join(self.path, self.filename)
@@ -195,7 +195,7 @@ class Image(Media):
if self.raw_exif and self.ext in ('.jpg', '.jpeg') else None)
def _get_metadata(self):
super(Image, self)._get_metadata()
super()._get_metadata()
# If a title or description hasn't been obtained by other means, look
# for the information in IPTC fields
if self.title and self.description:
@@ -244,7 +244,7 @@ class Video(Media):
type = 'video'
def __init__(self, filename, path, settings):
super(Video, self).__init__(filename, path, settings)
super().__init__(filename, path, settings)
base, ext = splitext(filename)
self.src_filename = filename
self.date = self._get_file_date()
@@ -322,12 +322,12 @@ class Album:
signals.album_initialized.send(self)
def __repr__(self):
return "<%s>(path=%r, title=%r)" % (self.__class__.__name__, self.path,
self.title)
return "<{}>(path={!r}, title={!r})".format(
self.__class__.__name__, self.path, self.title)
def __str__(self):
return ('{} : '.format(self.path) +
', '.join('{} {}s'.format(count, _type)
return (f'{self.path} : ' +
', '.join(f'{count} {_type}s'
for _type, count in self.medias_count.items()))
def __len__(self):
@@ -544,7 +544,7 @@ class Album:
return None
class Gallery(object):
class Gallery:
def __init__(self, settings, ncpu=None, quiet=False):
self.settings = settings

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2009-2018 - Simon Conseil
# Copyright (c) 2009-2020 - Simon Conseil
# Copyright (c) 2015 - François D.
# Copyright (c) 2018 - Edwin Steele
@@ -105,7 +105,7 @@ def generate_image(source, outname, settings, options=None):
if settings['autorotate_images']:
try:
img = Transpose().process(img)
except (IOError, IndexError):
except (OSError, IndexError):
pass
# Resize the image
@@ -195,7 +195,7 @@ def get_size(file_path):
"""Return image size (width and height)."""
try:
im = _read_image(file_path)
except (IOError, IndexError, TypeError, AttributeError) as e:
except (OSError, IndexError, TypeError, AttributeError) as e:
logger = logging.getLogger(__name__)
logger.error("Could not read size of %s due to %r", file_path, e)
else:

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2013-2018 - Simon Conseil
# Copyright (c) 2013-2020 - Simon Conseil
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to

View File

@@ -83,7 +83,7 @@ class BaseCompressor:
file_stats = None
compressed_stats = None
compressed_filename = '{}.{}'.format(filename, self.suffix)
compressed_filename = f'{filename}.{self.suffix}'
try:
file_stats = os.stat(filename)
compressed_stats = os.stat(compressed_filename)
@@ -146,7 +146,7 @@ def get_compressor(settings):
logger.error('Unable to import brotli module')
else:
logger.error('No such compressor {}'.format(name))
logger.error(f'No such compressor {name}')
def compress_gallery(gallery):

View File

@@ -58,9 +58,9 @@ def generate_feed(gallery, medias, feed_type=None, feed_url='', nb_items=0):
for item in medias[:nb_items]:
if theme == 'galleria':
link = '%s/%s/#%s' % (base_url, item.path, item.url)
link = f'{base_url}/{item.path}/#{item.url}'
else:
link = '%s/%s/' % (base_url, item.path)
link = f'{base_url}/{item.path}/'
feed.add_item(
title=Markup.escape(item.title or item.url),
@@ -68,7 +68,7 @@ def generate_feed(gallery, medias, feed_type=None, feed_url='', nb_items=0):
# unique_id='tag:%s,%s:%s' % (urlparse(link).netloc,
# item.date.date(),
# urlparse(link).path.lstrip('/')),
description='<img src="%s/%s/%s" />' % (base_url, item.path,
description='<img src="{}/{}/{}" />'.format(base_url, item.path,
item.thumbnail),
# categories=item.tags if hasattr(item, 'tags') else None,
author_name=getattr(item, 'author', ''),

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2009-2018 - Simon Conseil
# Copyright (c) 2009-2020 - Simon Conseil
# Copyright (c) 2014 - Jamie Starke
# Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@@ -104,7 +104,7 @@ def filter_nomedia(album, settings=None):
album.medias = []
else:
with open(nomediapath, "r") as nomediaFile:
with open(nomediapath) as nomediaFile:
logger.info("Found a .nomedia file in %s, ignoring its "
"entries", album.name)
ignored = nomediaFile.read().split("\n")

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2009-2018 - Simon Conseil
# Copyright (c) 2009-2020 - Simon Conseil
# Copyright (c) 2013 - Christophe-Marie Duquesne
# Copyright (c) 2017 - Mate Lakat
@@ -86,7 +86,7 @@ _DEFAULT_CONFIG = {
}
class Status(object):
class Status:
SUCCESS = 0
FAILURE = 1

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2011-2018 - Simon Conseil
# Copyright (c) 2011-2020 - Simon Conseil
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -32,7 +32,7 @@ VIDEO_MIMES = {'.mp4': 'video/mp4',
MD = None
class Devnull(object):
class Devnull:
"""'Black hole' for output that should not be printed"""
def write(self, *_):
@@ -82,7 +82,7 @@ def read_markdown(filename):
# Use utf-8-sig codec to remove BOM if it is present. This is only possible
# this way prior to feeding the text to the markdown parser (which would
# also default to pure utf-8)
with open(filename, 'r', encoding='utf-8-sig') as f:
with open(filename, encoding='utf-8-sig') as f:
text = f.read()
if MD is None:
@@ -122,7 +122,7 @@ def get_mime(ext):
return VIDEO_MIMES[ext]
class cached_property(object):
class cached_property:
""" A property that is only computed once per instance and then replaces
itself with an ordinary attribute. Deleting the attribute resets the
property.

View File

@@ -1,5 +1,5 @@
# Copyright (c) 2013 - Christophe-Marie Duquesne
# Copyright (c) 2013-2018 - Simon Conseil
# Copyright (c) 2013-2020 - Simon Conseil
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2009-2018 - Simon Conseil
# Copyright (c) 2009-2020 - Simon Conseil
# Copyright (c) 2013 - Christophe-Marie Duquesne
# Copyright (c) 2018 - Edwin Steele
@@ -37,7 +37,7 @@ THEMES_PATH = os.path.normpath(os.path.join(
os.path.abspath(os.path.dirname(__file__)), 'themes'))
class AbstractWriter(object):
class AbstractWriter:
template_file = None
def __init__(self, settings, index_title=''):

View File

@@ -39,4 +39,4 @@ def disconnect_signals():
def pytest_report_header(config):
return "project deps: Pillow-{}".format(PIL.__version__)
return f"project deps: Pillow-{PIL.__version__}"

View File

@@ -83,7 +83,7 @@ def test_media(settings):
assert m.title == "Foo Bar"
assert m.description == "<p>This is a funny description of this image</p>"
assert repr(m) == "<Media>('{}')".format(file_path)
assert repr(m) == f"<Media>('{file_path}')"
assert str(m) == file_path
@@ -244,7 +244,7 @@ def test_gallery(settings, tmpdir):
out_html = os.path.join(settings['destination'], 'index.html')
assert os.path.isfile(out_html)
with open(out_html, 'r') as f:
with open(out_html) as f:
html = f.read()
assert '<title>Sigal test gallery</title>' in html

View File

@@ -9,8 +9,9 @@ python =
3.8: py38
[testenv]
deps =
-r {toxinidir}/requirements.txt
extras =
all
tests
commands = pytest --cov sigal --cov-report term-missing tests/
[testenv:check]
@@ -28,8 +29,7 @@ commands =
[testenv:doc]
whitelist_externals = make
deps =
-r {toxinidir}/requirements-doc.txt
extras = docs
usedevelop = true
commands =
make -C docs html