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 .tox
.coverage .coverage
htmlcov htmlcov
six-*.egg/
*.orig *.orig
venv venv
samples/output samples/output

1
THANKS
View file

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

View file

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

View file

@ -1,12 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import argparse import argparse
try: try:
import collections.abc as collections import collections.abc as collections
except ImportError: except ImportError:
import collections import collections
import locale
import logging import logging
import multiprocessing import multiprocessing
import os import os
@ -15,8 +13,6 @@ import sys
import time import time
import traceback import traceback
import six
# pelican.log has to be the first pelican module to be loaded # pelican.log has to be the first pelican module to be loaded
# because logging.setLoggerClass has to be called before logging.getLogger # because logging.setLoggerClass has to be called before logging.getLogger
from pelican.log import init as init_logging from pelican.log import init as init_logging
@ -76,11 +72,10 @@ class Pelican(object):
sys.path.insert(0, pluginpath) sys.path.insert(0, pluginpath)
for plugin in self.settings['PLUGINS']: for plugin in self.settings['PLUGINS']:
# if it's a string, then import it # if it's a string, then import it
if isinstance(plugin, six.string_types): if isinstance(plugin, str):
logger.debug("Loading plugin `%s`", plugin) logger.debug("Loading plugin `%s`", plugin)
try: try:
plugin = __import__(plugin, globals(), locals(), plugin = __import__(plugin, globals(), locals(), 'module')
str('module'))
except ImportError as e: except ImportError as e:
logger.error( logger.error(
"Cannot load plugin `%s`\n%s", plugin, e) "Cannot load plugin `%s`\n%s", plugin, e)
@ -375,15 +370,6 @@ def get_config(args):
config['BIND'] = args.bind config['BIND'] = args.bind
config['DEBUG'] = args.verbosity == logging.DEBUG 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 return config
@ -397,7 +383,7 @@ def get_instance(args):
settings = read_settings(config_file, override=get_config(args)) settings = read_settings(config_file, override=get_config(args))
cls = settings['PELICAN_CLASS'] cls = settings['PELICAN_CLASS']
if isinstance(cls, six.string_types): if isinstance(cls, str):
module, cls_name = cls.rsplit('.', 1) module, cls_name = cls.rsplit('.', 1)
module = __import__(module) module = __import__(module)
cls = getattr(module, cls_name) cls = getattr(module, cls_name)

View file

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

View file

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

View file

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

View file

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

View file

@ -1,17 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import locale
import logging import logging
import os import os
import sys import sys
from collections import defaultdict from collections import defaultdict
try:
from collections.abc import Mapping
except ImportError:
from collections import Mapping
import six
__all__ = [ __all__ = [
'init' 'init'
@ -29,20 +21,17 @@ class BaseFormatter(logging.Formatter):
# format multiline messages 'nicely' to make it clear they are together # format multiline messages 'nicely' to make it clear they are together
record.msg = record.msg.replace('\n', '\n | ') record.msg = record.msg.replace('\n', '\n | ')
record.args = tuple(arg.replace('\n', '\n | ') if record.args = tuple(arg.replace('\n', '\n | ') if
isinstance(arg, six.string_types) else isinstance(arg, str) else
arg for arg in record.args) arg for arg in record.args)
return super(BaseFormatter, self).format(record) return super(BaseFormatter, self).format(record)
def formatException(self, ei): def formatException(self, ei):
''' prefix traceback info for better representation ''' ''' 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) s = super(BaseFormatter, self).formatException(ei)
# fancy format traceback # 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 # separate the traceback from the preceding lines
s = str(' |___\n{}').format(s) s = ' |___\n{}'.format(s)
return s return s
def _get_levelname(self, name): def _get_levelname(self, name):
@ -140,41 +129,7 @@ class LimitFilter(logging.Filter):
return True return True
class SafeLogger(logging.Logger): class LimitLogger(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):
""" """
A logger which adds LimitFilter automatically A logger which adds LimitFilter automatically
""" """

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

120
poetry.lock generated
View file

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

View file

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

View file

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

View file

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

View file

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