Initial pass of removing Python 2 support

This commit removes Six as a dependency for Pelican, replacing the
relevant aliases with the proper Python 3 imports. It also removes
references to Python 2 logic that did not require Six.
This commit is contained in:
Kevin Yap 2019-11-05 23:17:19 -08:00
commit 1e0e541b57
43 changed files with 126 additions and 459 deletions

1
.gitignore vendored
View file

@ -11,7 +11,6 @@ tags
.tox
.coverage
htmlcov
six-*.egg/
*.orig
venv
samples/output

1
THANKS
View file

@ -92,6 +92,7 @@ Joshua Adelman
Julian Berman
Justin Mayer
Kevin Deldycke
Kevin Yap
Kyle Fuller
Laureline Guerin
Leonard Huang

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import sys

View file

@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import argparse
try:
import collections.abc as collections
except ImportError:
import collections
import locale
import logging
import multiprocessing
import os
@ -15,8 +13,6 @@ import sys
import time
import traceback
import six
# pelican.log has to be the first pelican module to be loaded
# because logging.setLoggerClass has to be called before logging.getLogger
from pelican.log import init as init_logging
@ -76,11 +72,10 @@ class Pelican(object):
sys.path.insert(0, pluginpath)
for plugin in self.settings['PLUGINS']:
# if it's a string, then import it
if isinstance(plugin, six.string_types):
if isinstance(plugin, str):
logger.debug("Loading plugin `%s`", plugin)
try:
plugin = __import__(plugin, globals(), locals(),
str('module'))
plugin = __import__(plugin, globals(), locals(), 'module')
except ImportError as e:
logger.error(
"Cannot load plugin `%s`\n%s", plugin, e)
@ -375,15 +370,6 @@ def get_config(args):
config['BIND'] = args.bind
config['DEBUG'] = args.verbosity == logging.DEBUG
# argparse returns bytes in Py2. There is no definite answer as to which
# encoding argparse (or sys.argv) uses.
# "Best" option seems to be locale.getpreferredencoding()
# http://mail.python.org/pipermail/python-list/2006-October/405766.html
if not six.PY3:
enc = locale.getpreferredencoding()
for key in config:
if key in ('PATH', 'OUTPUT_PATH', 'THEME'):
config[key] = config[key].decode(enc)
return config
@ -397,7 +383,7 @@ def get_instance(args):
settings = read_settings(config_file, override=get_config(args))
cls = settings['PELICAN_CLASS']
if isinstance(cls, six.string_types):
if isinstance(cls, str):
module, cls_name = cls.rsplit('.', 1)
module = __import__(module)
cls = getattr(module, cls_name)

View file

@ -1,7 +1,6 @@
"""
python -m pelican module entry point to run via python -m
"""
from __future__ import absolute_import
from . import main

View file

@ -1,11 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import hashlib
import logging
import os
from six.moves import cPickle as pickle
import pickle
from pelican.utils import mkdir_p

View file

@ -1,25 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import copy
import datetime
import locale
import logging
import os
import re
import sys
from urllib.parse import urljoin, urlparse, urlunparse
import pytz
import six
from six.moves.urllib.parse import urljoin, urlparse, urlunparse
from pelican import signals
from pelican.settings import DEFAULT_CONFIG
from pelican.utils import (SafeDatetime, deprecated_attribute, memoized,
path_to_url, posixize_path,
python_2_unicode_compatible, sanitised_join,
set_date_tzinfo, slugify, strftime,
truncate_html_words)
from pelican.utils import (deprecated_attribute, memoized, path_to_url,
posixize_path, sanitised_join, set_date_tzinfo,
slugify, truncate_html_words)
# Import these so that they're avalaible when you import from pelican.contents.
from pelican.urlwrappers import (Author, Category, Tag, URLWrapper) # NOQA
@ -27,7 +22,6 @@ from pelican.urlwrappers import (Author, Category, Tag, URLWrapper) # NOQA
logger = logging.getLogger(__name__)
@python_2_unicode_compatible
class Content(object):
"""Represents a content.
@ -121,9 +115,6 @@ class Content(object):
if isinstance(self.date_format, tuple):
locale_string = self.date_format[0]
if sys.version_info < (3, ) and isinstance(locale_string,
six.text_type):
locale_string = locale_string.encode('ascii')
locale.setlocale(locale.LC_ALL, locale_string)
self.date_format = self.date_format[1]
@ -133,11 +124,11 @@ class Content(object):
if hasattr(self, 'date'):
self.date = set_date_tzinfo(self.date, timezone)
self.locale_date = strftime(self.date, self.date_format)
self.locale_date = self.date.strftime(self.date_format)
if hasattr(self, 'modified'):
self.modified = set_date_tzinfo(self.modified, timezone)
self.locale_modified = strftime(self.modified, self.date_format)
self.locale_modified = self.modified.strftime(self.date_format)
# manage status
if not hasattr(self, 'status'):
@ -213,7 +204,7 @@ class Content(object):
'path': path_to_url(path),
'slug': getattr(self, 'slug', ''),
'lang': getattr(self, 'lang', 'en'),
'date': getattr(self, 'date', SafeDatetime.now()),
'date': getattr(self, 'date', datetime.datetime.now()),
'author': self.author.slug if hasattr(self, 'author') else '',
'category': self.category.slug if hasattr(self, 'category') else ''
})
@ -512,22 +503,21 @@ class Article(Content):
# handle WITH_FUTURE_DATES (designate article to draft based on date)
if not self.settings['WITH_FUTURE_DATES'] and hasattr(self, 'date'):
if self.date.tzinfo is None:
now = SafeDatetime.now()
now = datetime.datetime.now()
else:
now = SafeDatetime.utcnow().replace(tzinfo=pytz.utc)
now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
if self.date > now:
self.status = 'draft'
# if we are a draft and there is no date provided, set max datetime
if not hasattr(self, 'date') and self.status == 'draft':
self.date = SafeDatetime.max
self.date = datetime.datetime.max
def _expand_settings(self, key):
klass = 'draft' if self.status == 'draft' else 'article'
return super(Article, self)._expand_settings(key, klass)
@python_2_unicode_compatible
class Static(Content):
mandatory_properties = ('title',)
default_status = 'published'

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import calendar
import errno
@ -15,15 +14,12 @@ from operator import attrgetter
from jinja2 import (BaseLoader, ChoiceLoader, Environment, FileSystemLoader,
PrefixLoader, TemplateNotFound)
import six
from pelican import signals
from pelican.cache import FileStampDataCacher
from pelican.contents import Article, Page, Static
from pelican.readers import Readers
from pelican.utils import (DateFormatter, copy, mkdir_p, order_content,
posixize_path, process_translations,
python_2_unicode_compatible)
posixize_path, process_translations)
logger = logging.getLogger(__name__)
@ -33,7 +29,6 @@ class PelicanTemplateNotFound(Exception):
pass
@python_2_unicode_compatible
class Generator(object):
"""Baseclass generator"""
@ -138,7 +133,7 @@ class Generator(object):
extensions are allowed)
"""
# backward compatibility for older generators
if isinstance(paths, six.string_types):
if isinstance(paths, str):
paths = [paths]
# group the exclude dir names by parent path, for use with os.walk()
@ -513,8 +508,6 @@ class ArticlesGenerator(CachingGenerator):
context["period"] = (_period,)
else:
month_name = calendar.month_name[_period[1]]
if not six.PY3:
month_name = month_name.decode('utf-8')
if key == period_date_key['month']:
context["period"] = (_period[0],
month_name)

View file

@ -1,17 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import locale
import logging
import os
import sys
from collections import defaultdict
try:
from collections.abc import Mapping
except ImportError:
from collections import Mapping
import six
__all__ = [
'init'
@ -29,20 +21,17 @@ class BaseFormatter(logging.Formatter):
# format multiline messages 'nicely' to make it clear they are together
record.msg = record.msg.replace('\n', '\n | ')
record.args = tuple(arg.replace('\n', '\n | ') if
isinstance(arg, six.string_types) else
isinstance(arg, str) else
arg for arg in record.args)
return super(BaseFormatter, self).format(record)
def formatException(self, ei):
''' prefix traceback info for better representation '''
# .formatException returns a bytestring in py2 and unicode in py3
# since .format will handle unicode conversion,
# str() calls are used to normalize formatting string
s = super(BaseFormatter, self).formatException(ei)
# fancy format traceback
s = str('\n').join(str(' | ') + line for line in s.splitlines())
s = '\n'.join(' | ' + line for line in s.splitlines())
# separate the traceback from the preceding lines
s = str(' |___\n{}').format(s)
s = ' |___\n{}'.format(s)
return s
def _get_levelname(self, name):
@ -140,41 +129,7 @@ class LimitFilter(logging.Filter):
return True
class SafeLogger(logging.Logger):
"""
Base Logger which properly encodes Exceptions in Py2
"""
_exc_encoding = locale.getpreferredencoding()
def _log(self, level, msg, args, exc_info=None, extra=None):
# if the only argument is a Mapping, Logger uses that for formatting
# format values for that case
if args and len(args) == 1 and isinstance(args[0], Mapping):
args = ({k: self._decode_arg(v) for k, v in args[0].items()},)
# otherwise, format each arg
else:
args = tuple(self._decode_arg(arg) for arg in args)
super(SafeLogger, self)._log(
level, msg, args, exc_info=exc_info, extra=extra)
def _decode_arg(self, arg):
'''
properly decode an arg for Py2 if it's Exception
localized systems have errors in native language if locale is set
so convert the message to unicode with the correct encoding
'''
if isinstance(arg, Exception):
text = str('%s: %s') % (arg.__class__.__name__, arg)
if six.PY2:
text = text.decode(self._exc_encoding)
return text
else:
return arg
class LimitLogger(SafeLogger):
class LimitLogger(logging.Logger):
"""
A logger which adds LimitFilter automatically
"""

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import functools
import logging
@ -7,8 +6,6 @@ import os
from collections import namedtuple
from math import ceil
import six
logger = logging.getLogger(__name__)
PaginationRule = namedtuple(
'PaginationRule',
@ -131,7 +128,7 @@ class Page(object):
prop_value = getattr(rule, key)
if not isinstance(prop_value, six.string_types):
if not isinstance(prop_value, str):
logger.warning('%s is set to %s', key, prop_value)
return prop_value

View file

@ -1,10 +1,12 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import datetime
import logging
import os
import re
from collections import OrderedDict
from html.parser import HTMLParser
from io import StringIO
import docutils
import docutils.core
@ -12,16 +14,11 @@ import docutils.io
from docutils.parsers.rst.languages import get_language as get_docutils_lang
from docutils.writers.html4css1 import HTMLTranslator, Writer
import six
from six import StringIO
from six.moves.html_parser import HTMLParser
from pelican import rstdirectives # NOQA
from pelican import signals
from pelican.cache import FileStampDataCacher
from pelican.contents import Author, Category, Page, Tag
from pelican.utils import SafeDatetime, escape_html, get_date, pelican_open, \
posixize_path
from pelican.utils import escape_html, get_date, pelican_open, posixize_path
try:
from markdown import Markdown
@ -79,7 +76,7 @@ def ensure_metadata_list(text):
Regardless, all list items undergo .strip() before returning, and
empty items are discarded.
"""
if isinstance(text, six.text_type):
if isinstance(text, str):
if ';' in text:
text = text.split(';')
else:
@ -212,8 +209,7 @@ class RstReader(BaseReader):
"""
def __init__(self, *args, **kwargs):
if six.PY3:
kwargs['mode'] = kwargs.get('mode', 'r').replace('U', '')
kwargs['mode'] = kwargs.get('mode', 'r').replace('U', '')
docutils.io.FileInput.__init__(self, *args, **kwargs)
def __init__(self, *args, **kwargs):
@ -685,10 +681,10 @@ def default_metadata(settings=None, process=None):
metadata['category'] = value
if settings.get('DEFAULT_DATE', None) and \
settings['DEFAULT_DATE'] != 'fs':
if isinstance(settings['DEFAULT_DATE'], six.string_types):
if isinstance(settings['DEFAULT_DATE'], str):
metadata['date'] = get_date(settings['DEFAULT_DATE'])
else:
metadata['date'] = SafeDatetime(*settings['DEFAULT_DATE'])
metadata['date'] = datetime.datetime(*settings['DEFAULT_DATE'])
return metadata
@ -696,7 +692,7 @@ def path_metadata(full_path, source_path, settings=None):
metadata = {}
if settings:
if settings.get('DEFAULT_DATE', None) == 'fs':
metadata['date'] = SafeDatetime.fromtimestamp(
metadata['date'] = datetime.datetime.fromtimestamp(
os.stat(full_path).st_mtime)
# Apply EXTRA_PATH_METADATA for the source path and the paths of any
@ -731,7 +727,7 @@ def parse_path_metadata(source_path, settings=None, process=None):
... process=reader.process_metadata)
>>> pprint.pprint(metadata) # doctest: +ELLIPSIS
{'category': <pelican.urlwrappers.Category object at ...>,
'date': SafeDatetime(2013, 1, 1, 0, 0),
'date': datetime.datetime(2013, 1, 1, 0, 0),
'slug': 'my-slug'}
"""
metadata = {}

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import re
@ -10,8 +9,6 @@ from pygments import highlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import TextLexer, get_lexer_by_name
import six
import pelican.settings as pys
@ -49,7 +46,7 @@ class Pygments(Directive):
# Fetch the defaults
if pys.PYGMENTS_RST_OPTIONS is not None:
for k, v in six.iteritems(pys.PYGMENTS_RST_OPTIONS):
for k, v in pys.PYGMENTS_RST_OPTIONS.items():
# Locally set options overrides the defaults
if k not in self.options:
self.options[k] = v

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import argparse
import logging
@ -7,16 +6,14 @@ import os
import posixpath
import ssl
import sys
import urllib
from http import server
try:
from magic import from_file as magic_from_file
except ImportError:
magic_from_file = None
from six.moves import BaseHTTPServer
from six.moves import SimpleHTTPServer as srvmod
from six.moves import urllib
from pelican.log import init as init_logging
logger = logging.getLogger(__name__)
@ -44,7 +41,7 @@ def parse_arguments():
return parser.parse_args()
class ComplexHTTPRequestHandler(srvmod.SimpleHTTPRequestHandler):
class ComplexHTTPRequestHandler(server.SimpleHTTPRequestHandler):
SUFFIXES = ['.html', '/index.html', '/', '']
def translate_path(self, path):
@ -76,7 +73,7 @@ class ComplexHTTPRequestHandler(srvmod.SimpleHTTPRequestHandler):
if not self.path:
return
srvmod.SimpleHTTPRequestHandler.do_GET(self)
server.SimpleHTTPRequestHandler.do_GET(self)
def get_path_that_exists(self, original_path):
# Try to strip trailing slash
@ -96,7 +93,7 @@ class ComplexHTTPRequestHandler(srvmod.SimpleHTTPRequestHandler):
def guess_type(self, path):
"""Guess at the mime type for the specified file.
"""
mimetype = srvmod.SimpleHTTPRequestHandler.guess_type(self, path)
mimetype = server.SimpleHTTPRequestHandler.guess_type(self, path)
# If the default guess is too generic, try the python-magic library
if mimetype == 'application/octet-stream' and magic_from_file:
@ -105,9 +102,9 @@ class ComplexHTTPRequestHandler(srvmod.SimpleHTTPRequestHandler):
return mimetype
class RootedHTTPServer(BaseHTTPServer.HTTPServer):
class RootedHTTPServer(server.HTTPServer):
def __init__(self, base_path, *args, **kwargs):
BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs)
server.HTTPServer.__init__(self, *args, **kwargs)
self.RequestHandlerClass.base_path = base_path

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import copy
import inspect
@ -10,8 +9,6 @@ import re
from os.path import isabs
from posixpath import join as posix_join
import six
from pelican.log import LimitFilter
@ -278,7 +275,7 @@ def handle_deprecated_settings(settings):
del settings['PLUGIN_PATH']
# PLUGIN_PATHS: str -> [str]
if isinstance(settings.get('PLUGIN_PATHS'), six.string_types):
if isinstance(settings.get('PLUGIN_PATHS'), str):
logger.warning("Defining PLUGIN_PATHS setting as string "
"has been deprecated (should be a list)")
settings['PLUGIN_PATHS'] = [settings['PLUGIN_PATHS']]
@ -547,13 +544,13 @@ def configure_settings(settings):
# standardize strings to lists
for key in ['LOCALE']:
if key in settings and isinstance(settings[key], six.string_types):
if key in settings and isinstance(settings[key], str):
settings[key] = [settings[key]]
# check settings that must be a particular type
for key, types in [
('OUTPUT_SOURCES_EXTENSION', six.string_types),
('FILENAME_METADATA', six.string_types),
('OUTPUT_SOURCES_EXTENSION', str),
('FILENAME_METADATA', str),
]:
if key in settings and not isinstance(settings[key], types):
value = settings.pop(key)
@ -647,7 +644,7 @@ def configure_settings(settings):
'PAGE_PATHS',
)
for PATH_KEY in filter(lambda k: k in settings, path_keys):
if isinstance(settings[PATH_KEY], six.string_types):
if isinstance(settings[PATH_KEY], str):
logger.warning("Detected misconfiguration with %s setting "
"(must be a list), falling back to the default",
PATH_KEY)

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
from blinker import signal

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
AUTHOR = 'Alexis Métaireau'
SITENAME = "Alexis' log"
SITEURL = 'http://blog.notmyidea.org'

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import locale
import logging
@ -10,12 +9,11 @@ import sys
import unittest
from contextlib import contextmanager
from functools import wraps
from io import StringIO
from logging.handlers import BufferingHandler
from shutil import rmtree
from tempfile import mkdtemp
from six import StringIO
from pelican.contents import Article
from pelican.readers import default_metadata
from pelican.settings import DEFAULT_CONFIG

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
from shutil import rmtree

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import datetime
import locale
import logging
import os.path
@ -9,15 +9,12 @@ from sys import platform
from jinja2.utils import generate_lorem_ipsum
import six
from pelican.contents import Article, Author, Category, Page, Static
from pelican.settings import DEFAULT_CONFIG
from pelican.signals import content_object_init
from pelican.tests.support import (LoggedTestCase, get_context, get_settings,
unittest)
from pelican.utils import (SafeDatetime, path_to_url, posixize_path,
truncate_html_words)
from pelican.utils import (path_to_url, posixize_path, truncate_html_words)
# generate one paragraph, enclosed with <p>
@ -185,7 +182,7 @@ class TestPage(LoggedTestCase):
def test_datetime(self):
# If DATETIME is set to a tuple, it should be used to override LOCALE
dt = SafeDatetime(2015, 9, 13)
dt = datetime.datetime(2015, 9, 13)
page_kwargs = self._copy_page_kwargs()
@ -286,9 +283,7 @@ class TestPage(LoggedTestCase):
'<a href="http://notmyidea.org/category/category.html">link</a>'))
def test_intrasite_link(self):
# type does not take unicode in PY2 and bytes in PY3, which in
# combination with unicode literals leads to following insane line:
cls_name = '_DummyArticle' if six.PY3 else b'_DummyArticle'
cls_name = '_DummyArticle'
article = type(cls_name, (object,), {'url': 'article.html'})
args = self.page_kwargs.copy()
@ -370,9 +365,7 @@ class TestPage(LoggedTestCase):
self.assertEqual(p.custom, linked)
def test_intrasite_link_more(self):
# type does not take unicode in PY2 and bytes in PY3, which in
# combination with unicode literals leads to following insane line:
cls_name = '_DummyAsset' if six.PY3 else b'_DummyAsset'
cls_name = '_DummyAsset'
args = self.page_kwargs.copy()
args['settings'] = get_settings()
@ -487,9 +480,7 @@ class TestPage(LoggedTestCase):
)
def test_intrasite_link_markdown_spaces(self):
# Markdown introduces %20 instead of spaces, this tests that
# we support markdown doing this.
cls_name = '_DummyArticle' if six.PY3 else b'_DummyArticle'
cls_name = '_DummyArticle'
article = type(cls_name, (object,), {'url': 'article-spaces.html'})
args = self.page_kwargs.copy()
@ -512,7 +503,7 @@ class TestPage(LoggedTestCase):
def test_intrasite_link_source_and_generated(self):
"""Test linking both to the source and the generated article
"""
cls_name = '_DummyAsset' if six.PY3 else b'_DummyAsset'
cls_name = '_DummyAsset'
args = self.page_kwargs.copy()
args['settings'] = get_settings()
@ -538,7 +529,7 @@ class TestPage(LoggedTestCase):
def test_intrasite_link_to_static_content_with_filename(self):
"""Test linking to a static resource with deprecated {filename}
"""
cls_name = '_DummyAsset' if six.PY3 else b'_DummyAsset'
cls_name = '_DummyAsset'
args = self.page_kwargs.copy()
args['settings'] = get_settings()

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import locale
import os

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import locale
import os

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import locale

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
try:
import collections.abc as collections

View file

@ -1,10 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import os
import six
from pelican import readers
from pelican.tests.support import get_settings, unittest
from pelican.utils import SafeDatetime
@ -64,8 +61,7 @@ class TestAssertDictHasSubset(ReaderTest):
self.assertDictHasSubset(self.dictionary, self.dictionary)
def test_fail_not_set(self):
six.assertRaisesRegex(
self,
self.assertRaisesRegex(
AssertionError,
r'Expected.*key-c.*to have value.*val-c.*but was not in Dict',
self.assertDictHasSubset,
@ -73,8 +69,7 @@ class TestAssertDictHasSubset(ReaderTest):
{'key-c': 'val-c'})
def test_fail_wrong_val(self):
six.assertRaisesRegex(
self,
self.assertRaisesRegex(
AssertionError,
r'Expected .*key-a.* to have value .*val-b.* but was .*val-a.*',
self.assertDictHasSubset,
@ -445,7 +440,7 @@ class RstReaderTest(ReaderTest):
def test_parse_error(self):
# Verify that it raises an Exception, not nothing and not SystemExit or
# some such
with six.assertRaisesRegex(self, Exception, "underline too short"):
with self.assertRaisesRegex(Exception, "underline too short"):
self.read_file(path='../parse_error/parse_error.rst')

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
from pelican.tests.support import unittest

View file

@ -1,9 +1,8 @@
import os
from io import BytesIO
from shutil import rmtree
from tempfile import mkdtemp
from six import BytesIO
from pelican.server import ComplexHTTPRequestHandler
from pelican.tests.support import unittest

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import copy
import locale

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import warnings

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from pelican.tests.support import unittest
from pelican.urlwrappers import Author, Category, Tag, URLWrapper

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
import locale
import logging
@ -11,8 +10,6 @@ from tempfile import mkdtemp
import pytz
import six
from pelican import utils
from pelican.generators import TemplatePagesGenerator
from pelican.settings import read_settings
@ -720,8 +717,7 @@ class TestSanitisedJoin(unittest.TestCase):
@unittest.skipIf(platform == 'win32',
"Different filesystem root on Windows")
def test_detect_parent_breakout(self):
with six.assertRaisesRegex(
self,
with self.assertRaisesRegex(
RuntimeError,
"Attempted to break out of output directory to /foo/test"):
utils.sanitised_join(
@ -732,8 +728,7 @@ class TestSanitisedJoin(unittest.TestCase):
@unittest.skipIf(platform == 'win32',
"Different filesystem root on Windows")
def test_detect_root_breakout(self):
with six.assertRaisesRegex(
self,
with self.assertRaisesRegex(
RuntimeError,
"Attempted to break out of output directory to /test"):
utils.sanitised_join(

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import argparse
import logging
@ -11,10 +10,9 @@ import sys
import time
from codecs import open
from collections import defaultdict
from six.moves.urllib.error import URLError
from six.moves.urllib.parse import quote, urlparse, urlsplit, urlunsplit
from six.moves.urllib.request import urlretrieve
from urllib.error import URLError
from urllib.parse import quote, urlparse, urlsplit, urlunsplit
from urllib.request import urlretrieve
# because logging.setLoggerClass has to be called before logging.getLogger
from pelican.log import init
@ -24,7 +22,7 @@ from pelican.utils import SafeDatetime, slugify
try:
from html import unescape # py3.5+
except ImportError:
from six.moves.html_parser import HTMLParser
from html.parser import HTMLParser
unescape = HTMLParser().unescape
logger = logging.getLogger(__name__)
@ -396,19 +394,8 @@ def posterous2fields(api_token, email, password):
"""Imports posterous posts"""
import base64
from datetime import timedelta
try:
# py3k import
import json
except ImportError:
# py2 import
import simplejson as json
try:
# py3k import
import urllib.request as urllib_request
except ImportError:
# py2 import
import urllib2 as urllib_request
import json
import urllib.request as urllib_request
def get_posterous_posts(api_token, email, password, page=1):
base64string = base64.encodestring(
@ -451,19 +438,8 @@ def posterous2fields(api_token, email, password):
def tumblr2fields(api_key, blogname):
""" Imports Tumblr posts (API v2)"""
try:
# py3k import
import json
except ImportError:
# py2 import
import simplejson as json
try:
# py3k import
import urllib.request as urllib_request
except ImportError:
# py2 import
import urllib2 as urllib_request
import json
import urllib.request as urllib_request
def get_tumblr_posts(api_key, blogname, offset=0):
url = ("http://api.tumblr.com/v2/blog/%s.tumblr.com/"

View file

@ -1,12 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import argparse
import codecs
import locale
import os
import sys
from jinja2 import Environment, FileSystemLoader
@ -23,8 +21,6 @@ try:
except ImportError:
_DEFAULT_TIMEZONE = 'Europe/Paris'
import six
from pelican import __version__
locale.setlocale(locale.LC_ALL, '')
@ -77,41 +73,24 @@ CONF = {
# url for list of valid timezones
_TZ_URL = 'http://en.wikipedia.org/wiki/List_of_tz_database_time_zones'
_input_compat = six.moves.input
str_compat = six.text_type
# Create a 'marked' default path, to determine if someone has supplied
# a path on the command-line.
class _DEFAULT_PATH_TYPE(str_compat):
class _DEFAULT_PATH_TYPE(str):
is_default_path = True
_DEFAULT_PATH = _DEFAULT_PATH_TYPE(os.curdir)
def decoding_strings(f):
def wrapper(*args, **kwargs):
out = f(*args, **kwargs)
if isinstance(out, six.string_types) and not six.PY3:
# todo: make encoding configurable?
if six.PY3:
return out
else:
return out.decode(sys.stdin.encoding)
return out
return wrapper
@decoding_strings
def ask(question, answer=str_compat, default=None, length=None):
if answer == str_compat:
def ask(question, answer=str, default=None, length=None):
if answer == str:
r = ''
while True:
if default:
r = _input_compat('> {0} [{1}] '.format(question, default))
r = input('> {0} [{1}] '.format(question, default))
else:
r = _input_compat('> {0} '.format(question, default))
r = input('> {0} '.format(question, default))
r = r.strip()
@ -133,11 +112,11 @@ def ask(question, answer=str_compat, default=None, length=None):
r = None
while True:
if default is True:
r = _input_compat('> {0} (Y/n) '.format(question))
r = input('> {0} (Y/n) '.format(question))
elif default is False:
r = _input_compat('> {0} (y/N) '.format(question))
r = input('> {0} (y/N) '.format(question))
else:
r = _input_compat('> {0} (y/n) '.format(question))
r = input('> {0} (y/n) '.format(question))
r = r.strip().lower()
@ -157,9 +136,9 @@ def ask(question, answer=str_compat, default=None, length=None):
r = None
while True:
if default:
r = _input_compat('> {0} [{1}] '.format(question, default))
r = input('> {0} [{1}] '.format(question, default))
else:
r = _input_compat('> {0} '.format(question))
r = input('> {0} '.format(question))
r = r.strip()
@ -175,14 +154,14 @@ def ask(question, answer=str_compat, default=None, length=None):
return r
else:
raise NotImplementedError(
'Argument `answer` must be str_compat, bool, or integer')
'Argument `answer` must be str, bool, or integer')
def ask_timezone(question, default, tzurl):
"""Prompt for time zone and validate input"""
lower_tz = [tz.lower() for tz in pytz.all_timezones]
while True:
r = ask(question, str_compat, default)
r = ask(question, str, default)
r = r.strip().replace(' ', '_').lower()
if r in lower_tz:
r = pytz.all_timezones[lower_tz.index(r)]
@ -227,20 +206,20 @@ needed by Pelican.
else:
CONF['basedir'] = os.path.abspath(os.path.expanduser(
ask('Where do you want to create your new web site?',
answer=str_compat, default=args.path)))
answer=str, default=args.path)))
CONF['sitename'] = ask('What will be the title of this web site?',
answer=str_compat, default=args.title)
answer=str, default=args.title)
CONF['author'] = ask('Who will be the author of this web site?',
answer=str_compat, default=args.author)
answer=str, default=args.author)
CONF['lang'] = ask('What will be the default language of this web site?',
str_compat, args.lang or CONF['lang'], 2)
str, args.lang or CONF['lang'], 2)
if ask('Do you want to specify a URL prefix? e.g., https://example.com ',
answer=bool, default=True):
CONF['siteurl'] = ask('What is your URL prefix? (see '
'above example; no trailing slash)',
str_compat, CONF['siteurl'])
str, CONF['siteurl'])
CONF['with_pagination'] = ask('Do you want to enable article pagination?',
bool, bool(CONF['default_pagination']))
@ -263,49 +242,49 @@ needed by Pelican.
answer=bool, default=False):
CONF['ftp'] = True,
CONF['ftp_host'] = ask('What is the hostname of your FTP server?',
str_compat, CONF['ftp_host'])
str, CONF['ftp_host'])
CONF['ftp_user'] = ask('What is your username on that server?',
str_compat, CONF['ftp_user'])
str, CONF['ftp_user'])
CONF['ftp_target_dir'] = ask('Where do you want to put your '
'web site on that server?',
str_compat, CONF['ftp_target_dir'])
str, CONF['ftp_target_dir'])
if ask('Do you want to upload your website using SSH?',
answer=bool, default=False):
CONF['ssh'] = True,
CONF['ssh_host'] = ask('What is the hostname of your SSH server?',
str_compat, CONF['ssh_host'])
str, CONF['ssh_host'])
CONF['ssh_port'] = ask('What is the port of your SSH server?',
int, CONF['ssh_port'])
CONF['ssh_user'] = ask('What is your username on that server?',
str_compat, CONF['ssh_user'])
str, CONF['ssh_user'])
CONF['ssh_target_dir'] = ask('Where do you want to put your '
'web site on that server?',
str_compat, CONF['ssh_target_dir'])
str, CONF['ssh_target_dir'])
if ask('Do you want to upload your website using Dropbox?',
answer=bool, default=False):
CONF['dropbox'] = True,
CONF['dropbox_dir'] = ask('Where is your Dropbox directory?',
str_compat, CONF['dropbox_dir'])
str, CONF['dropbox_dir'])
if ask('Do you want to upload your website using S3?',
answer=bool, default=False):
CONF['s3'] = True,
CONF['s3_bucket'] = ask('What is the name of your S3 bucket?',
str_compat, CONF['s3_bucket'])
str, CONF['s3_bucket'])
if ask('Do you want to upload your website using '
'Rackspace Cloud Files?', answer=bool, default=False):
CONF['cloudfiles'] = True,
CONF['cloudfiles_username'] = ask('What is your Rackspace '
'Cloud username?', str_compat,
'Cloud username?', str,
CONF['cloudfiles_username'])
CONF['cloudfiles_api_key'] = ask('What is your Rackspace '
'Cloud API key?', str_compat,
'Cloud API key?', str,
CONF['cloudfiles_api_key'])
CONF['cloudfiles_container'] = ask('What is the name of your '
'Cloud Files container?',
str_compat,
str,
CONF['cloudfiles_container'])
if ask('Do you want to upload your website using GitHub Pages?',
@ -363,9 +342,7 @@ needed by Pelican.
try:
with codecs.open(os.path.join(CONF['basedir'], 'Makefile'),
'w', 'utf-8') as fd:
py_v = 'python'
if six.PY3:
py_v = 'python3'
py_v = 'python3'
_template = _jinja_env.get_template('Makefile.jinja2')
fd.write(_template.render(py_v=py_v, **CONF))
fd.close()

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import argparse
import os

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
AUTHOR = {{author}}
SITENAME = {{sitename}}

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
# This file is only used if you use `make publish` or
# explicitly specify it as your config file.

View file

@ -1,18 +1,14 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import functools
import logging
import os
import six
from pelican.utils import python_2_unicode_compatible, slugify
from pelican.utils import slugify
logger = logging.getLogger(__name__)
@python_2_unicode_compatible
@functools.total_ordering
class URLWrapper(object):
def __init__(self, name, settings):
@ -66,26 +62,26 @@ class URLWrapper(object):
def _normalize_key(self, key):
subs = self.settings.get('SLUG_REGEX_SUBSTITUTIONS', [])
return six.text_type(slugify(key, regex_subs=subs))
return str(slugify(key, regex_subs=subs))
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.slug == other.slug
if isinstance(other, six.text_type):
if isinstance(other, str):
return self.slug == self._normalize_key(other)
return False
def __ne__(self, other):
if isinstance(other, self.__class__):
return self.slug != other.slug
if isinstance(other, six.text_type):
if isinstance(other, str):
return self.slug != self._normalize_key(other)
return True
def __lt__(self, other):
if isinstance(other, self.__class__):
return self.slug < other.slug
if isinstance(other, six.text_type):
if isinstance(other, str):
return self.slug < self._normalize_key(other)
return False
@ -105,7 +101,7 @@ class URLWrapper(object):
"""
setting = "%s_%s" % (self.__class__.__name__.upper(), key)
value = self.settings[setting]
if not isinstance(value, six.string_types):
if not isinstance(value, str):
logger.warning('%s is set to %s', setting, value)
return value
else:

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import codecs
import datetime
@ -12,12 +11,15 @@ import re
import shutil
import sys
import traceback
import urllib
try:
from collections.abc import Hashable
except ImportError:
from collections import Hashable
from contextlib import contextmanager
from functools import partial
from html import entities
from html.parser import HTMLParser
from itertools import groupby
from operator import attrgetter
@ -27,10 +29,6 @@ from jinja2 import Markup
import pytz
import six
from six.moves import html_entities
from six.moves.html_parser import HTMLParser
try:
from html import escape
except ImportError:
@ -98,10 +96,6 @@ def strftime(date, date_format):
else:
formatted = date.strftime(candidate)
# convert Py2 result to unicode
if not six.PY3 and enc is not None:
formatted = formatted.decode(enc)
# strip zeros if '-' prefix is used
if conversion:
formatted = conversion(formatted)
@ -150,22 +144,6 @@ class DateFormatter(object):
return formatted
def python_2_unicode_compatible(klass):
"""
A decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.
To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
From django.utils.encoding.
"""
if not six.PY3:
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass
class memoized(object):
"""Function decorator to cache return values.
@ -214,15 +192,15 @@ def deprecated_attribute(old, new, since=None, remove=None, doc=None):
content of the dummy method is ignored.
"""
def _warn():
version = '.'.join(six.text_type(x) for x in since)
version = '.'.join(str(x) for x in since)
message = ['{} has been deprecated since {}'.format(old, version)]
if remove:
version = '.'.join(six.text_type(x) for x in remove)
version = '.'.join(str(x) for x in remove)
message.append(
' and will be removed by version {}'.format(version))
message.append('. Use {} instead.'.format(new))
logger.warning(''.join(message))
logger.debug(''.join(six.text_type(x) for x
logger.debug(''.join(str(x) for x
in traceback.format_stack()))
def fget(self):
@ -279,10 +257,8 @@ def slugify(value, regex_subs=()):
# value must be unicode per se
import unicodedata
from unidecode import unidecode
# unidecode returns str in Py2 and 3, so in Py2 we have to make
# it unicode again
value = unidecode(value)
if isinstance(value, six.binary_type):
if isinstance(value, bytes):
value = value.decode('ascii')
# still unicode
value = unicodedata.normalize('NFKD', value)
@ -584,8 +560,8 @@ class _HTMLWordTruncator(HTMLParser):
`name` is the entity ref without ampersand and semicolon (e.g. `mdash`)
"""
try:
codepoint = html_entities.name2codepoint[name]
char = six.unichr(codepoint)
codepoint = entities.name2codepoint[name]
char = chr(codepoint)
except KeyError:
char = ''
self._handle_ref(name, char)
@ -602,7 +578,7 @@ class _HTMLWordTruncator(HTMLParser):
codepoint = int(name[1:], 16)
else:
codepoint = int(name)
char = six.unichr(codepoint)
char = chr(codepoint)
except (ValueError, OverflowError):
char = ''
self._handle_ref('#' + name, char)
@ -663,7 +639,7 @@ def process_translations(content_list, translation_id=None):
if not translation_id:
return content_list, []
if isinstance(translation_id, six.string_types):
if isinstance(translation_id, str):
translation_id = {translation_id}
index = []
@ -753,7 +729,7 @@ def order_content(content_list, order_by='slug'):
content_list.sort(key=order_by)
except Exception:
logger.error('Error sorting with function %s', order_by)
elif isinstance(order_by, six.string_types):
elif isinstance(order_by, str):
if order_by.startswith('reversed-'):
order_reversed = True
order_by = order_by.replace('reversed-', '', 1)
@ -901,8 +877,7 @@ def is_selected_for_writing(settings, path):
def path_to_file_url(path):
'''Convert file-system path to file:// URL'''
return six.moves.urllib_parse.urljoin(
"file://", six.moves.urllib.request.pathname2url(path))
return urllib.parse.urljoin("file://", urllib.request.pathname2url(path))
def maybe_pluralize(count, singular, plural):

View file

@ -1,24 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals, with_statement
import logging
import os
from urllib.parse import urljoin
from feedgenerator import Atom1Feed, Rss201rev2Feed, get_tag_uri
from jinja2 import Markup
import six
from six.moves.urllib.parse import urljoin
from pelican import signals
from pelican.paginator import Paginator
from pelican.utils import (get_relative_path, is_selected_for_writing,
path_to_url, sanitised_join, set_date_tzinfo)
if not six.PY3:
from codecs import open
logger = logging.getLogger(__name__)
@ -165,8 +159,7 @@ class Writer(object):
except Exception:
pass
encoding = 'utf-8' if six.PY3 else None
with self._open_w(complete_path, encoding, override_output) as fp:
with self._open_w(complete_path, 'utf-8', override_output) as fp:
feed.write(fp, 'utf-8')
logger.info('Writing %s', complete_path)

120
poetry.lock generated
View file

@ -17,15 +17,6 @@ version = "2.7.0"
[package.dependencies]
pytz = ">=2015.7"
[[package]]
category = "dev"
description = "backports.functools_lru_cache"
marker = "python_version < \"3\""
name = "backports.functools-lru-cache"
optional = false
python-versions = ">=2.6"
version = "1.5"
[[package]]
category = "dev"
description = "Screen-scraping library"
@ -54,24 +45,6 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.4.1"
[[package]]
category = "dev"
description = "Updated configparser from Python 3.7 for Python 2.6+."
marker = "python_version < \"3.2\""
name = "configparser"
optional = false
python-versions = ">=2.6"
version = "3.7.4"
[[package]]
category = "dev"
description = "Backports and enhancements for the contextlib module"
marker = "python_version < \"3\""
name = "contextlib2"
optional = false
python-versions = "*"
version = "0.5.5"
[[package]]
category = "main"
description = "Docutils -- Python Documentation Utilities"
@ -88,20 +61,6 @@ optional = false
python-versions = ">=2.7"
version = "0.3"
[package.dependencies]
[package.dependencies.configparser]
python = ">=2.7,<2.8"
version = ">=3.5"
[[package]]
category = "dev"
description = "Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4"
marker = "python_version < \"3.4\""
name = "enum34"
optional = false
python-versions = "*"
version = "1.1.6"
[[package]]
category = "main"
description = "Standalone version of django.utils.feedgenerator"
@ -136,22 +95,6 @@ mccabe = ">=0.6.0,<0.7.0"
pycodestyle = ">=2.5.0,<2.6.0"
pyflakes = ">=2.1.0,<2.2.0"
[package.dependencies.configparser]
python = "<3.2"
version = "*"
[package.dependencies.enum34]
python = "<3.4"
version = "*"
[package.dependencies.functools32]
python = "<3.2"
version = "*"
[package.dependencies.typing]
python = "<3.5"
version = "*"
[[package]]
category = "dev"
description = "Flake8 and pylama plugin that checks the ordering of import statements."
@ -164,28 +107,6 @@ version = "0.18.1"
pycodestyle = "*"
setuptools = "*"
[package.dependencies.enum34]
python = "<2.8"
version = "*"
[[package]]
category = "dev"
description = "Python function signatures from PEP362 for Python 2.6, 2.7 and 3.2+"
marker = "python_version < \"3.3\""
name = "funcsigs"
optional = false
python-versions = "*"
version = "1.0.2"
[[package]]
category = "dev"
description = "Backport of the functools module from Python 3.2.3 for use on 2.7 and PyPy."
marker = "python_version < \"3.2\""
name = "functools32"
optional = false
python-versions = "*"
version = "3.2.3-2"
[[package]]
category = "dev"
description = "Getting image size from png/jpeg/jpeg2000/gif file"
@ -205,14 +126,6 @@ version = "0.18"
[package.dependencies]
zipp = ">=0.5"
[package.dependencies.configparser]
python = "<3"
version = ">=3.5"
[package.dependencies.contextlib2]
python = "<3"
version = "*"
[[package]]
category = "main"
description = "A small but fast and easy to use stand-alone template engine written in pure python."
@ -270,10 +183,6 @@ version = "3.0.5"
[package.dependencies]
six = "*"
[package.dependencies.funcsigs]
python = "<3.3"
version = ">=1"
[[package]]
category = "dev"
description = "Core utilities for Python packages"
@ -362,7 +271,7 @@ description = "Python 2 and 3 compatibility utilities"
name = "six"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
version = "1.12.0"
version = "1.13.0"
[[package]]
category = "dev"
@ -388,11 +297,6 @@ optional = false
python-versions = "*"
version = "1.9.2"
[package.dependencies]
[package.dependencies."backports.functools-lru-cache"]
python = "<3"
version = "*"
[[package]]
category = "dev"
description = "Python documentation generator"
@ -449,15 +353,6 @@ six = ">=1.0.0,<2"
toml = ">=0.9.4"
virtualenv = ">=14.0.0"
[[package]]
category = "dev"
description = "Type Hints for Python"
marker = "python_version < \"3.5\""
name = "typing"
optional = false
python-versions = "*"
version = "3.7.4"
[[package]]
category = "dev"
description = "Filters to enhance web typography, including support for Django & Jinja templates"
@ -497,27 +392,21 @@ version = "0.5.1"
markdown = ["markdown"]
[metadata]
content-hash = "d22ff0db3331186ab2f809313de1f9efef1f9c708cc354eaa1638a5111404612"
python-versions = "~2.7 || ^3.5"
content-hash = "0163177d87dca0955d111319de9481cf2ed0ef014e63a3740ffaf32a1cf07212"
python-versions = "^3.5"
[metadata.hashes]
alabaster = ["446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", "a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"]
babel = ["af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", "e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"]
"backports.functools-lru-cache" = ["9d98697f088eb1b0fa451391f91afb5e3ebde16bbdb272819fd091151fda4f1a", "f0b0e4eba956de51238e17573b7087e852dfe9854afd2e9c873f73fc0ca0a6dd"]
beautifulsoup4 = ["034740f6cb549b4e932ae1ab975581e6103ac8f942200a0e9759065984391858", "945065979fb8529dd2f37dbb58f00b661bdbcbebf954f93b32fdf5263ef35348", "ba6d5c59906a85ac23dadfe5c88deaf3e179ef565f4898671253e50a78680718"]
blinker = ["471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"]
colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
configparser = ["8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32", "da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75"]
contextlib2 = ["509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48", "f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"]
docutils = ["02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", "51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", "7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"]
entrypoints = ["589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", "c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"]
enum34 = ["2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", "644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", "6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", "8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"]
feedgenerator = ["5ae05daa9cfa47fa406ee4744d0b7fa1c8a05a7a47ee0ad328ddf55327cfb106"]
filelock = ["18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", "929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"]
flake8 = ["859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", "a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8"]
flake8-import-order = ["90a80e46886259b9c396b578d75c749801a41ee969a235e163cfe1be7afd2543", "a28dc39545ea4606c1ac3c24e9d05c849c6e5444a50fb7e9cdd430fc94de6e92"]
funcsigs = ["330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", "a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"]
functools32 = ["89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0", "f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d"]
imagesize = ["3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", "f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"]
importlib-metadata = ["6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7", "cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db"]
jinja2 = ["065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", "14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"]
@ -535,7 +424,7 @@ pygments = ["71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127",
pyparsing = ["1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", "9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"]
python-dateutil = ["7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", "c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"]
pytz = ["303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", "d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"]
six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
six = ["1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", "30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"]
smartypants = ["8db97f7cbdf08d15b158a86037cd9e116b4cf37703d24e0419a0d64ca5808f0d"]
snowballstemmer = ["9f3b9ffe0809d174f7047e121431acf99c89a7040f0ca84f94ba53a498e6d0c9"]
soupsieve = ["72b5f1aea9101cf720a36bb2327ede866fd6f1a07b1e87c92a1cc18113cbc946", "e4e9c053d59795e440163733a7fec6c5972210e1790c507e4c7b051d6c5259de"]
@ -543,7 +432,6 @@ sphinx = ["82cd2728c906be96e307b81352d3fd9fb731869234c6b835cc25e9a3dfb4b7e4", "b
sphinx-rtd-theme = ["00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4", "728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a"]
toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"]
tox = ["dab0b0160dd187b654fc33d690ee1d7bf328bd5b8dc6ef3bb3cc468969c659ba", "ee35ffce74933a6c6ac10c9a0182e41763140a5a5070e21b114feca56eaccdcd"]
typing = ["38566c558a0a94d6531012c8e917b1b8518a41e418f7f15f00e129cc80162ad3", "53765ec4f83a2b720214727e319607879fec4acde22c4fbb54fa2604e79e44ce", "84698954b4e6719e912ef9a42a2431407fe3755590831699debda6fba92aac55"]
typogrify = ["8be4668cda434163ce229d87ca273a11922cb1614cb359970b7dc96eed13cb38"]
unidecode = ["1d7a042116536098d05d599ef2b8616759f02985c85b4fef50c78a5aaf10822a", "2b6aab710c2a1647e928e36d69c21e76b453cd455f4e2621000e54b2a9b8cce8"]
virtualenv = ["b7335cddd9260a3dd214b73a2521ffc09647bde3e9457fcca31dc3be3999d04a", "d28ca64c0f3f125f59cabf13e0a150e1c68e5eea60983cc4395d88c584495783"]

View file

@ -37,7 +37,6 @@ unidecode = "^1.1"
python-dateutil = "^2.8"
docutils = "^0.14"
markdown = {version = "~3.1.1", optional = true}
six = "^1.4"
[tool.poetry.dev-dependencies]
BeautifulSoup4 = "^4.7"

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
AUTHOR = 'Alexis Métaireau'
SITENAME = "Alexis' log"

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
AUTHOR = 'Alexis Métaireau'
SITENAME = "Alexis' log"

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
import sys
from io import open
from os import walk
from os.path import join, relpath
@ -10,8 +10,7 @@ from setuptools import setup
version = "4.2.0"
requires = ['feedgenerator >= 1.9', 'jinja2 >= 2.7', 'pygments', 'docutils',
'pytz >= 0a', 'blinker', 'unidecode', 'six >= 1.4',
'python-dateutil']
'pytz >= 0a', 'blinker', 'unidecode', 'python-dateutil']
entry_points = {
'console_scripts': [
@ -25,9 +24,7 @@ entry_points = {
README = open('README.rst', encoding='utf-8').read()
CHANGELOG = open('docs/changelog.rst', encoding='utf-8').read()
description = u'\n'.join([README, CHANGELOG])
if sys.version_info.major < 3:
description = description.encode('utf-8')
description = '\n'.join([README, CHANGELOG])
setup(
name='pelican',