From a7e58ac3a354e5476beb23200d968ec1cd9d0e7f Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sun, 28 Jul 2019 07:09:40 +0200 Subject: [PATCH 01/25] Keep building packages via setuptools for now While it may make sense to switch to an alternate build system (such as Poetry) at some point, at this early stage it seems prudent to designate setuptools as the build system in pyproject.toml until the more modern build system tooling matures. --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f27dc047..903e4532 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,5 +60,4 @@ markdown = ["markdown"] pelican = "pelican.__main__:main" [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["setuptools >= 40.6.0", "wheel"] From 06dee4de581fffddc3e188b9ab8074f6a98bd461 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sun, 28 Jul 2019 07:15:48 +0200 Subject: [PATCH 02/25] Add AutoPub to auto-publish releases on PR merge Contributors will henceforth be asked to include a `RELEASE.md` file containing the release type and summary of changes, which will be used by the continuous integration (CI) system to automatically publish a new release to PyPI when the pull request is merged. For more details, see: https://github.com/autopub/autopub --- .travis.yml | 23 +++++++++++++++++++++++ CONTRIBUTING.rst | 8 ++++++++ pyproject.toml | 7 +++++++ 3 files changed, 38 insertions(+) diff --git a/.travis.yml b/.travis.yml index 762ada98..a4a1e1f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,31 @@ before_install: install: - pip install tox==2.5.0 script: tox -e $TOX_ENV +before_deploy: + - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then travis_terminate 0; fi' + - pip install githubrelease + - pip install --pre autopub + - autopub check || travis_terminate 0 + - pip install poetry + - pip install twine + - git checkout ${TRAVIS_BRANCH} + - git remote set-url origin https://$GITHUB_TOKEN@github.com/$TRAVIS_REPO_SLUG +deploy: + provider: script + script: autopub deploy + skip_cleanup: true + on: + branch: master + python: "3.7" notifications: irc: channels: - "irc.freenode.org#pelican" on_success: change +env: + global: + - PYPI_USERNAME=autopub + - secure: "h5V/+YL+CrqvfAesNkSb824Ngk5x+f0eFzj/LBbmnzjvArKAmc6R6WGyx8SDD7WF/PlaTf0M1fH3a7pjIS8Ee+TS1Rb0Lt1HPqUs1yntg1+Js2ZQp3p20wfsDc+bZ4/2g8xLsSMv1EJ4np7/GJ5fXqpSxjr/Xs5LYA7ZLwNNwDw=" + - secure: "GiDFfmjH7uzYNnkjQMV/mIkbRdmgkGmtbFPeaj9taBNA5tPp3IBt3GOOS6UL/zm9xiwu9Xo6sxZWkGzY19Hsdv28YPH34N3abo0QSnz4IGiHs152Hi7Qi6Tb0QkT5D3OxuSIm8LmFL7+su89Q7vBFowrT6HL1Mn8CDDWSj3eqbo=" + - TWINE_USERNAME=$PYPI_USERNAME + - TWINE_PASSWORD=$PYPI_PASSWORD diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 49660ea1..7ae47593 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -97,6 +97,14 @@ Using Git and GitHub For example, if you're hacking on a new feature and find a bugfix that doesn't *require* your new feature, **make a new distinct branch and pull request** for the bugfix. +* Add a ``RELEASE.md`` file in the root of the project that contains the + release type (major, minor, patch) and a summary of the changes that will be + used as the release changelog entry. For example:: + + Release type: minor + + Reload browser window upon changes to content, settings, or theme + * Check for unnecessary whitespace via ``git diff --check`` before committing. * First line of your commit message should start with present-tense verb, be 50 characters or less, and include the relevant issue number(s) if applicable. diff --git a/pyproject.toml b/pyproject.toml index 903e4532..185c605b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,5 +59,12 @@ markdown = ["markdown"] [tool.poetry.scripts] pelican = "pelican.__main__:main" +[tool.autopub] +project-name = "Pelican" +git-username = "botpub" +git-email = "botpub@autopub.rocks" +version-strings = ["setup.py"] +build-system = "setuptools" + [build-system] requires = ["setuptools >= 40.6.0", "wheel"] From 360ff420d34603ffa490aff29ff8c66fd6cf4223 Mon Sep 17 00:00:00 2001 From: Lucas Cimon Date: Thu, 1 Aug 2019 13:53:56 +0200 Subject: [PATCH 03/25] Allowing to pass `argv` to pelican `main` entrypoint --- pelican/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pelican/__init__.py b/pelican/__init__.py index 0a06d905..86c956b0 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -307,7 +307,7 @@ class PrintSettings(argparse.Action): parser.exit() -def parse_arguments(): +def parse_arguments(argv=None): parser = argparse.ArgumentParser( description='A tool to generate a static blog, ' ' with restructured text input files.', @@ -400,7 +400,7 @@ def parse_arguments(): help='IP to bind to when serving files via HTTP ' '(default: 127.0.0.1)') - args = parser.parse_args() + args = parser.parse_args(argv) if args.port is not None and not args.listen: logger.warning('--port without --listen has no effect') @@ -560,8 +560,8 @@ def listen(server, port, output, excqueue=None): return -def main(): - args = parse_arguments() +def main(argv=None): + args = parse_arguments(argv) logs_dedup_min_level = getattr(logging, args.logs_dedup_min_level) init_logging(args.verbosity, args.fatal, logs_dedup_min_level=logs_dedup_min_level) From 7c2a7478d7a6024f6f854f934f213e7130666e2b Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Fri, 2 Aug 2019 14:53:51 +0200 Subject: [PATCH 04/25] Consolidate duplicate Travis `env` definitions --- .travis.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index a4a1e1f7..7bb5ef3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,18 @@ language: python python: - "3.6" env: - - TOX_ENV=docs - - TOX_ENV=flake8 - - TOX_ENV=py27 - - TOX_ENV=py35 - - TOX_ENV=py36 + global: + - PYPI_USERNAME=autopub + - secure: "h5V/+YL+CrqvfAesNkSb824Ngk5x+f0eFzj/LBbmnzjvArKAmc6R6WGyx8SDD7WF/PlaTf0M1fH3a7pjIS8Ee+TS1Rb0Lt1HPqUs1yntg1+Js2ZQp3p20wfsDc+bZ4/2g8xLsSMv1EJ4np7/GJ5fXqpSxjr/Xs5LYA7ZLwNNwDw=" + - secure: "GiDFfmjH7uzYNnkjQMV/mIkbRdmgkGmtbFPeaj9taBNA5tPp3IBt3GOOS6UL/zm9xiwu9Xo6sxZWkGzY19Hsdv28YPH34N3abo0QSnz4IGiHs152Hi7Qi6Tb0QkT5D3OxuSIm8LmFL7+su89Q7vBFowrT6HL1Mn8CDDWSj3eqbo=" + - TWINE_USERNAME=$PYPI_USERNAME + - TWINE_PASSWORD=$PYPI_PASSWORD + matrix: + - TOX_ENV=docs + - TOX_ENV=flake8 + - TOX_ENV=py27 + - TOX_ENV=py35 + - TOX_ENV=py36 matrix: include: - python: 3.7 @@ -44,10 +51,3 @@ notifications: channels: - "irc.freenode.org#pelican" on_success: change -env: - global: - - PYPI_USERNAME=autopub - - secure: "h5V/+YL+CrqvfAesNkSb824Ngk5x+f0eFzj/LBbmnzjvArKAmc6R6WGyx8SDD7WF/PlaTf0M1fH3a7pjIS8Ee+TS1Rb0Lt1HPqUs1yntg1+Js2ZQp3p20wfsDc+bZ4/2g8xLsSMv1EJ4np7/GJ5fXqpSxjr/Xs5LYA7ZLwNNwDw=" - - secure: "GiDFfmjH7uzYNnkjQMV/mIkbRdmgkGmtbFPeaj9taBNA5tPp3IBt3GOOS6UL/zm9xiwu9Xo6sxZWkGzY19Hsdv28YPH34N3abo0QSnz4IGiHs152Hi7Qi6Tb0QkT5D3OxuSIm8LmFL7+su89Q7vBFowrT6HL1Mn8CDDWSj3eqbo=" - - TWINE_USERNAME=$PYPI_USERNAME - - TWINE_PASSWORD=$PYPI_PASSWORD From b2da535fecafa7a81feee2dd5b19eb1fffcc9a94 Mon Sep 17 00:00:00 2001 From: MinchinWeb Date: Tue, 20 Aug 2019 19:39:14 -0600 Subject: [PATCH 05/25] Set default content status to a blank string rather than `None`. Fixes #2558. Fixes issues encountered by comment plugins among others c.f. [1](https://github.com/bstpierre/pelican-comments/pull/4), [2](https://github.com/Scheirle/pelican_comment_system/issues/8), [3](https://github.com/Scheirle/pelican_comment_system/pull/7) --- RELEASE.md | 7 +++++++ pelican/contents.py | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..dccbdff8 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,7 @@ +Release type: patch + +Set default content status to a blank string rather than `None`. Fixes +[#2558](https://github.com/getpelican/pelican/issues/2558). Fixes issues +encountered by comment plugins among others +([1](https://github.com/bstpierre/pelican-comments/pull/4), +[2](https://github.com/Scheirle/pelican_comment_system/issues/8)). diff --git a/pelican/contents.py b/pelican/contents.py index 9292f14f..74524d60 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -141,7 +141,9 @@ class Content(object): # manage status if not hasattr(self, 'status'): - self.status = getattr(self, 'default_status', None) + # using None as the default here breaks comment plugins (and + # probably others) + self.status = getattr(self, 'default_status', '') # store the summary metadata if it is set if 'summary' in metadata: From f1430472b8cb43302516de8acf356c56706b92ff Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Wed, 21 Aug 2019 14:31:51 +0200 Subject: [PATCH 06/25] Configure AutoPub for Pelican changelog path & format --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 185c605b..6a0e048a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,6 +63,9 @@ pelican = "pelican.__main__:main" project-name = "Pelican" git-username = "botpub" git-email = "botpub@autopub.rocks" +changelog-file = "docs/changelog.rst" +changelog-header = "###############" +version-header = "=" version-strings = ["setup.py"] build-system = "setuptools" From 8353cea6b6b66f73893f6ccc7d886eb227cb1ce0 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Wed, 21 Aug 2019 14:38:17 +0200 Subject: [PATCH 07/25] Add changelog entries to prepare for release --- RELEASE.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index dccbdff8..920b6a14 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,7 +1,6 @@ Release type: patch -Set default content status to a blank string rather than `None`. Fixes -[#2558](https://github.com/getpelican/pelican/issues/2558). Fixes issues -encountered by comment plugins among others -([1](https://github.com/bstpierre/pelican-comments/pull/4), -[2](https://github.com/Scheirle/pelican_comment_system/issues/8)). +* Add AutoPub to auto-publish releases on PR merge +* Add CSS classes for reStructuredText figures +* Pass `argv` to Pelican `main` entrypoint +* Set default content status to a blank string rather than `None` From 2ee423017bb444e1370b50862340559012bda739 Mon Sep 17 00:00:00 2001 From: MinchinWeb Date: Tue, 20 Aug 2019 19:01:39 -0600 Subject: [PATCH 08/25] Skip some non-Windows tests on Windows Some tests will never pass on Windows due to differences in filesystems between Windows and Linux. --- RELEASE.md | 4 ++++ pelican/tests/test_contents.py | 9 +++++---- pelican/tests/test_generators.py | 19 ++++++++++++++++--- pelican/tests/test_utils.py | 6 ++++++ 4 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..521973a9 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,4 @@ +Release type: patch + +Skip some tests (on Windows) that are un-able to pass on Windows due to the +difference in Windows vs Linux filesystems. diff --git a/pelican/tests/test_contents.py b/pelican/tests/test_contents.py index 104bc889..efc438c8 100644 --- a/pelican/tests/test_contents.py +++ b/pelican/tests/test_contents.py @@ -14,9 +14,10 @@ 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, truncate_html_words +from pelican.tests.support import (LoggedTestCase, get_context, get_settings, + unittest) +from pelican.utils import (SafeDatetime, path_to_url, posixize_path, + truncate_html_words) # generate one paragraph, enclosed with

@@ -943,7 +944,7 @@ class TestStatic(LoggedTestCase): source_path=os.path.join('dir', 'foo.jpg'), context=self.settings.copy()) - expected_save_as = os.path.join('dir', 'foo.jpg') + expected_save_as = posixize_path(os.path.join('dir', 'foo.jpg')) self.assertEqual(static.status, 'draft') self.assertEqual(static.save_as, expected_save_as) self.assertEqual(static.url, path_to_url(expected_save_as)) diff --git a/pelican/tests/test_generators.py b/pelican/tests/test_generators.py index 267571da..2455d1f4 100644 --- a/pelican/tests/test_generators.py +++ b/pelican/tests/test_generators.py @@ -1089,7 +1089,12 @@ class TestStaticGenerator(unittest.TestCase): os.mkdir(os.path.join(self.temp_output, "static")) self.generator.fallback_to_symlinks = True self.generator.generate_context() - self.generator.generate_output(None) + try: + self.generator.generate_output(None) + except OSError as e: + # On Windows, possibly others, due to not holding symbolic link + # privilege + self.skipTest(e) self.assertTrue(os.path.islink(self.endfile)) def test_existing_symlink_is_considered_up_to_date(self): @@ -1097,7 +1102,11 @@ class TestStaticGenerator(unittest.TestCase): with open(self.startfile, "w") as f: f.write("staticcontent") os.mkdir(os.path.join(self.temp_output, "static")) - os.symlink(self.startfile, self.endfile) + try: + os.symlink(self.startfile, self.endfile) + except OSError as e: + # On Windows, possibly others + self.skipTest(e) staticfile = MagicMock() staticfile.source_path = self.startfile staticfile.save_as = self.endfile @@ -1109,7 +1118,11 @@ class TestStaticGenerator(unittest.TestCase): with open(self.startfile, "w") as f: f.write("staticcontent") os.mkdir(os.path.join(self.temp_output, "static")) - os.symlink("invalid", self.endfile) + try: + os.symlink("invalid", self.endfile) + except OSError as e: + # On Windows, possibly others + self.skipTest(e) staticfile = MagicMock() staticfile.source_path = self.startfile staticfile.save_as = self.endfile diff --git a/pelican/tests/test_utils.py b/pelican/tests/test_utils.py index 2831eeed..444190d3 100644 --- a/pelican/tests/test_utils.py +++ b/pelican/tests/test_utils.py @@ -717,6 +717,8 @@ class TestDateFormatter(unittest.TestCase): class TestSanitisedJoin(unittest.TestCase): + @unittest.skipIf(platform == 'win32', + "Different filesystem root on Windows") def test_detect_parent_breakout(self): with six.assertRaisesRegex( self, @@ -727,6 +729,8 @@ class TestSanitisedJoin(unittest.TestCase): "../test" ) + @unittest.skipIf(platform == 'win32', + "Different filesystem root on Windows") def test_detect_root_breakout(self): with six.assertRaisesRegex( self, @@ -737,6 +741,8 @@ class TestSanitisedJoin(unittest.TestCase): "/test" ) + @unittest.skipIf(platform == 'win32', + "Different filesystem root on Windows") def test_pass_deep_subpaths(self): self.assertEqual( utils.sanitised_join( From 9db42658e50254bf72b0f9a16755bb631f601b6c Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Fri, 23 Aug 2019 17:02:47 +0200 Subject: [PATCH 09/25] Prevent Travis IRC spam from forks See: https://github.com/travis-ci/travis-ci/issues/5063 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7bb5ef3b..6641d4cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,8 +46,9 @@ deploy: on: branch: master python: "3.7" +# The channel name "irc.freenode.org#pelican" is encrypted against getpelican/pelican to prevent IRC spam of forks notifications: irc: channels: - - "irc.freenode.org#pelican" + - secure: "JP57f61QovrhmLoAF6oPOzIK2aXGfSO06FHg7yiuKBOWMiaxQejZUGJX919muCLhWJXDugsviIqCMoAWwNV3o1WQbqIr+G5TR+N9MrtCs4Zi6vpGj09bR8giKUKx+PPKEoe1Ew56E4y2LxzGO4Lj9hZx8M2YVdwPNWrWZgp6WXE=" on_success: change From f6ef0270144b96863ae9811edbc802c56091a2a3 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Fri, 23 Aug 2019 19:02:48 +0200 Subject: [PATCH 10/25] Tidy and shorten a comment --- pelican/contents.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pelican/contents.py b/pelican/contents.py index 74524d60..a862db2d 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -141,8 +141,7 @@ class Content(object): # manage status if not hasattr(self, 'status'): - # using None as the default here breaks comment plugins (and - # probably others) + # Previous default of None broke comment plugins and perhaps others self.status = getattr(self, 'default_status', '') # store the summary metadata if it is set From e44aa294b0641655165fefdcbce72484e3ce7c57 Mon Sep 17 00:00:00 2001 From: botpub Date: Fri, 23 Aug 2019 17:06:52 +0000 Subject: [PATCH 11/25] Release Pelican 4.1.1 --- RELEASE.md | 6 ------ docs/changelog.rst | 8 ++++++++ pyproject.toml | 2 +- setup.py | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) delete mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 920b6a14..00000000 --- a/RELEASE.md +++ /dev/null @@ -1,6 +0,0 @@ -Release type: patch - -* Add AutoPub to auto-publish releases on PR merge -* Add CSS classes for reStructuredText figures -* Pass `argv` to Pelican `main` entrypoint -* Set default content status to a blank string rather than `None` diff --git a/docs/changelog.rst b/docs/changelog.rst index be87ed17..fd7cada4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,14 @@ Release history ############### +4.1.1 - 2019-08-23 +================== + +* Add AutoPub to auto-publish releases on PR merge +* Add CSS classes for reStructuredText figures +* Pass `argv` to Pelican `main` entrypoint +* Set default content status to a blank string rather than `None` + 4.1.0 - 2019-07-14 ================== diff --git a/pyproject.toml b/pyproject.toml index 6a0e048a..31bb1829 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pelican" -version = "4.1.0" +version = "4.1.1" description = "Static site generator supporting Markdown and reStructuredText" authors = ["Justin Mayer "] license = "AGPLv3" diff --git a/setup.py b/setup.py index f9076f4d..1bdeee80 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from os.path import join, relpath from setuptools import setup -version = "4.1.0" +version = "4.1.1" requires = ['feedgenerator >= 1.9', 'jinja2 >= 2.7', 'pygments', 'docutils', 'pytz >= 0a', 'blinker', 'unidecode', 'six >= 1.4', From 41fbf3adb29d35dd558999420858538bc41108a3 Mon Sep 17 00:00:00 2001 From: Jorge Maldonado Ventura Date: Mon, 26 Aug 2019 00:35:53 +0200 Subject: [PATCH 12/25] [Documentation] Add comma after 'for instance' --- docs/themes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/themes.rst b/docs/themes.rst index 354e0c36..b00d0236 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -75,7 +75,7 @@ output_file The name of the file currently being generated. For articles The list of articles, ordered descending by date. All the elements are `Article` objects, so you can access their attributes (e.g. title, summary, author - etc.). Sometimes this is shadowed (for instance in + etc.). Sometimes this is shadowed (for instance, in the tags page). You will then find info about it in the `all_articles` variable. dates The same list of articles, but ordered by date, From 7f4e614bb8f7f43b8419c896ee0cd1bedd4e0a9c Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 21 Sep 2019 10:57:35 -0600 Subject: [PATCH 13/25] Fix formatting, etc in Settings documentation --- docs/settings.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 7085db84..5d090a62 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -983,7 +983,7 @@ By default, pages subsequent to ``.../foo.html`` are created as ``.../foo2.html``, etc. The ``PAGINATION_PATTERNS`` setting can be used to change this. It takes a sequence of triples, where each triple consists of:: - (minimum_page, page_url, page_save_as,) + (minimum_page, page_url, page_save_as,) For ``page_url`` and ``page_save_as``, you may use a number of variables. ``{url}`` and ``{save_as}`` correspond respectively to the ``*_URL`` and @@ -997,7 +997,7 @@ subsequent pages at ``.../page/2/`` etc, you could set ``PAGINATION_PATTERNS`` as follows:: PAGINATION_PATTERNS = ( - (1, '{url}', '{save_as}`, + (1, '{url}', '{save_as}', (2, '{base_name}/page/{number}/', '{base_name}/page/{number}/index.html'), ) @@ -1238,7 +1238,7 @@ ignored. Simply populate the list with the log messages you want to hide, and they will be filtered out. For example:: - + import logging LOG_FILTER = [(logging.WARN, 'TAG_SAVE_AS is set to False')] From 589a31ddd0d447934b7cf09d8675bb0c73a92d90 Mon Sep 17 00:00:00 2001 From: Lucas Cimon Date: Mon, 23 Sep 2019 19:38:18 +0200 Subject: [PATCH 14/25] Pushing Python compatibility to Python 3.5+ --- docs/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 4e6714b4..4ad9416f 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -8,7 +8,7 @@ Installation ------------ Install Pelican (and optionally Markdown if you intend to use it) on Python -2.7.x or Python 3.3+ by running the following command in your preferred +2.7.x or Python 3.5+ by running the following command in your preferred terminal, prefixing with ``sudo`` if permissions warrant:: pip install pelican markdown From 367245cc47e9acae03e06f37de088551165154c7 Mon Sep 17 00:00:00 2001 From: Lucas Cimon Date: Mon, 23 Sep 2019 17:48:56 +0200 Subject: [PATCH 15/25] Fix pelican.settings.load_source to avoid caching issues --- RELEASE.md | 3 +++ pelican/settings.py | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..5c1ba5d3 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,3 @@ +Release type: patch + +Fix pelican.settings.load_source to avoid caching issues - PR #2621 diff --git a/pelican/settings.py b/pelican/settings.py index a957b26c..4aa31afe 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -14,12 +14,16 @@ import six from pelican.log import LimitFilter + try: - # SourceFileLoader is the recommended way in Python 3.3+ - from importlib.machinery import SourceFileLoader + # spec_from_file_location is the recommended way in Python 3.5+ + import importlib.util def load_source(name, path): - return SourceFileLoader(name, path).load_module() + spec = importlib.util.spec_from_file_location(name, path) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod except ImportError: # but it does not exist in Python 2.7, so fall back to imp import imp From 3f96cb8a4a91742a85fe8b548749efd4b12a1ff0 Mon Sep 17 00:00:00 2001 From: botpub Date: Mon, 23 Sep 2019 18:21:15 +0000 Subject: [PATCH 16/25] Release Pelican 4.1.2 --- RELEASE.md | 3 --- docs/changelog.rst | 5 +++++ pyproject.toml | 2 +- setup.py | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 5c1ba5d3..00000000 --- a/RELEASE.md +++ /dev/null @@ -1,3 +0,0 @@ -Release type: patch - -Fix pelican.settings.load_source to avoid caching issues - PR #2621 diff --git a/docs/changelog.rst b/docs/changelog.rst index fd7cada4..5e5d7cdf 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,11 @@ Release history ############### +4.1.2 - 2019-09-23 +================== + +Fix pelican.settings.load_source to avoid caching issues - PR #2621 + 4.1.1 - 2019-08-23 ================== diff --git a/pyproject.toml b/pyproject.toml index 31bb1829..fce734f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pelican" -version = "4.1.1" +version = "4.1.2" description = "Static site generator supporting Markdown and reStructuredText" authors = ["Justin Mayer "] license = "AGPLv3" diff --git a/setup.py b/setup.py index 1bdeee80..e4f2995a 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from os.path import join, relpath from setuptools import setup -version = "4.1.1" +version = "4.1.2" requires = ['feedgenerator >= 1.9', 'jinja2 >= 2.7', 'pygments', 'docutils', 'pytz >= 0a', 'blinker', 'unidecode', 'six >= 1.4', From 8734bd1a6f0944442ac8536bf3d92a5ad28f9201 Mon Sep 17 00:00:00 2001 From: Romain Porte Date: Tue, 24 Sep 2019 22:07:01 +0200 Subject: [PATCH 17/25] templates: tasks.py: introduce "production_port" to fix #2623 The syntax passed to rsync for specifying the port is incorrect. In the Makefile template, the -e option is correctly used to pass the port. We use the same syntax here to pass the SSH port. This fix issue #2623. Signed-off-by: Romain Porte --- pelican/tools/templates/tasks.py.jinja2 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pelican/tools/templates/tasks.py.jinja2 b/pelican/tools/templates/tasks.py.jinja2 index a800b79b..1c063f08 100644 --- a/pelican/tools/templates/tasks.py.jinja2 +++ b/pelican/tools/templates/tasks.py.jinja2 @@ -23,7 +23,8 @@ CONFIG = { 'deploy_path': SETTINGS['OUTPUT_PATH'], {% if ssh %} # Remote server configuration - 'production': '{{ssh_user}}@{{ssh_host}}:{{ssh_port}}', + 'production': '{{ssh_user}}@{{ssh_host}}', + 'production_port': {{ssh_port}}, 'dest_path': '{{ssh_target_dir}}', {% endif %} {% if cloudfiles %} @@ -130,6 +131,7 @@ def publish(c): c.run('pelican -s {settings_publish}'.format(**CONFIG)) c.run( 'rsync --delete --exclude ".DS_Store" -pthrvz -c ' + '-e "ssh -p {production_port}" ' '{} {production}:{dest_path}'.format( CONFIG['deploy_path'].rstrip('/') + '/', **CONFIG)) From db04f012971f154c3f7601ced1d666bee0ea8da9 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 28 Sep 2019 13:45:58 -0700 Subject: [PATCH 18/25] Add related project URLs for display on PyPI Adding `project_urls` and `keywords` to setup.py ensures they will be available for the PyPI package page and any other place/service that may look for these fields. --- setup.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index e4f2995a..5eea85b6 100755 --- a/setup.py +++ b/setup.py @@ -33,11 +33,17 @@ setup( name='pelican', version=version, url='https://getpelican.com/', - author='Alexis Metaireau', - maintainer='Justin Mayer', + author='Justin Mayer', author_email='authors@getpelican.com', description="Static site generator supporting reStructuredText and " "Markdown source content.", + project_urls={ + 'Documentation': 'https://docs.getpelican.com/', + 'Funding': 'https://donate.getpelican.com/', + 'Source': 'https://github.com/getpelican/pelican', + 'Tracker': 'https://github.com/getpelican/pelican/issues', + }, + keywords='static web site generator SSG reStructuredText Markdown', license='AGPLv3', long_description=description, packages=['pelican', 'pelican.tools'], From 047d884323a67495a4358acee984b276d3456f07 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 28 Sep 2019 13:51:20 -0700 Subject: [PATCH 19/25] Fix quick-start docs regarding `pelican --listen` Reverts 2ab91bbaaa565dcb89726b6cac0002c1e0644dc3 and resolves #2626 --- docs/publish.rst | 16 ++++------------ docs/quickstart.rst | 6 +++--- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/docs/publish.rst b/docs/publish.rst index 96d67d58..489558d8 100644 --- a/docs/publish.rst +++ b/docs/publish.rst @@ -54,20 +54,12 @@ HTML files directly:: firefox output/index.html Because the above method may have trouble locating your CSS and other linked -assets, running a simple web server using Python will often provide a more -reliable previewing experience. +assets, running Pelican's simple built-in web server will often provide a more +reliable previewing experience:: -For Python 2, run:: + pelican --listen - cd output - python -m SimpleHTTPServer - -For Python 3, run:: - - cd output - python -m http.server - -Once the basic server has been started, you can preview your site at +Once the web server has been started, you can preview your site at: http://localhost:8000/ Deployment diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 4ad9416f..646dd987 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -50,18 +50,18 @@ Given that this example article is in Markdown format, save it as Generate your site ------------------ -From your site directory, run the ``pelican`` command to generate your site:: +From your project root directory, run the ``pelican`` command to generate your site:: pelican content -Your site has now been generated inside the ``output`` directory. (You may see +Your site has now been generated inside the ``output/`` directory. (You may see a warning related to feeds, but that is normal when developing locally and can be ignored for now.) Preview your site ----------------- -Open a new terminal session, navigate to your generated output directory and +Open a new terminal session, navigate to your project root directory, and run the following command to launch Pelican's web server:: pelican --listen From 2c8e7b3e6bc43f8e151b814957de617213f48382 Mon Sep 17 00:00:00 2001 From: Oliver Urs Lenz Date: Fri, 4 Oct 2019 22:28:24 +0200 Subject: [PATCH 20/25] place all deprecated settings handling together --- pelican/__init__.py | 61 --------------------------------------------- pelican/settings.py | 61 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/pelican/__init__.py b/pelican/__init__.py index 86c956b0..499ded04 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -11,7 +11,6 @@ import logging import multiprocessing import os import pprint -import re import sys import time import traceback @@ -52,7 +51,6 @@ class Pelican(object): # define the default settings self.settings = settings - self._handle_deprecation() self.path = settings['PATH'] self.theme = settings['THEME'] @@ -94,65 +92,6 @@ class Pelican(object): logger.debug('Restoring system path') sys.path = _sys_path - def _handle_deprecation(self): - - if self.settings.get('CLEAN_URLS', False): - logger.warning('Found deprecated `CLEAN_URLS` in settings.' - ' Modifying the following settings for the' - ' same behaviour.') - - self.settings['ARTICLE_URL'] = '{slug}/' - self.settings['ARTICLE_LANG_URL'] = '{slug}-{lang}/' - self.settings['PAGE_URL'] = 'pages/{slug}/' - self.settings['PAGE_LANG_URL'] = 'pages/{slug}-{lang}/' - - for setting in ('ARTICLE_URL', 'ARTICLE_LANG_URL', 'PAGE_URL', - 'PAGE_LANG_URL'): - logger.warning("%s = '%s'", setting, self.settings[setting]) - - if self.settings.get('AUTORELOAD_IGNORE_CACHE'): - logger.warning('Found deprecated `AUTORELOAD_IGNORE_CACHE` in ' - 'settings. Use --ignore-cache instead.') - self.settings.pop('AUTORELOAD_IGNORE_CACHE') - - if self.settings.get('ARTICLE_PERMALINK_STRUCTURE', False): - logger.warning('Found deprecated `ARTICLE_PERMALINK_STRUCTURE` in' - ' settings. Modifying the following settings for' - ' the same behaviour.') - - structure = self.settings['ARTICLE_PERMALINK_STRUCTURE'] - - # Convert %(variable) into {variable}. - structure = re.sub(r'%\((\w+)\)s', r'{\g<1>}', structure) - - # Convert %x into {date:%x} for strftime - structure = re.sub(r'(%[A-z])', r'{date:\g<1>}', structure) - - # Strip a / prefix - structure = re.sub('^/', '', structure) - - for setting in ('ARTICLE_URL', 'ARTICLE_LANG_URL', 'PAGE_URL', - 'PAGE_LANG_URL', 'DRAFT_URL', 'DRAFT_LANG_URL', - 'ARTICLE_SAVE_AS', 'ARTICLE_LANG_SAVE_AS', - 'DRAFT_SAVE_AS', 'DRAFT_LANG_SAVE_AS', - 'PAGE_SAVE_AS', 'PAGE_LANG_SAVE_AS'): - self.settings[setting] = os.path.join(structure, - self.settings[setting]) - logger.warning("%s = '%s'", setting, self.settings[setting]) - - for new, old in [('FEED', 'FEED_ATOM'), ('TAG_FEED', 'TAG_FEED_ATOM'), - ('CATEGORY_FEED', 'CATEGORY_FEED_ATOM'), - ('TRANSLATION_FEED', 'TRANSLATION_FEED_ATOM')]: - if self.settings.get(new, False): - logger.warning( - 'Found deprecated `%(new)s` in settings. Modify %(new)s ' - 'to %(old)s in your settings and theme for the same ' - 'behavior. Temporarily setting %(old)s for backwards ' - 'compatibility.', - {'new': new, 'old': old} - ) - self.settings[old] = self.settings[new] - def run(self): """Run the generators and return""" start_time = time.time() diff --git a/pelican/settings.py b/pelican/settings.py index 4aa31afe..ca415791 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -442,6 +442,67 @@ def handle_deprecated_settings(settings): 'Falling back to default.', key) settings[key] = DEFAULT_CONFIG[key] + # CLEAN_URLS + if settings.get('CLEAN_URLS', False): + logger.warning('Found deprecated `CLEAN_URLS` in settings.' + ' Modifying the following settings for the' + ' same behaviour.') + + settings['ARTICLE_URL'] = '{slug}/' + settings['ARTICLE_LANG_URL'] = '{slug}-{lang}/' + settings['PAGE_URL'] = 'pages/{slug}/' + settings['PAGE_LANG_URL'] = 'pages/{slug}-{lang}/' + + for setting in ('ARTICLE_URL', 'ARTICLE_LANG_URL', 'PAGE_URL', + 'PAGE_LANG_URL'): + logger.warning("%s = '%s'", setting, settings[setting]) + + # AUTORELOAD_IGNORE_CACHE -> --ignore-cache + if settings.get('AUTORELOAD_IGNORE_CACHE'): + logger.warning('Found deprecated `AUTORELOAD_IGNORE_CACHE` in ' + 'settings. Use --ignore-cache instead.') + settings.pop('AUTORELOAD_IGNORE_CACHE') + + # ARTICLE_PERMALINK_STRUCTURE + if settings.get('ARTICLE_PERMALINK_STRUCTURE', False): + logger.warning('Found deprecated `ARTICLE_PERMALINK_STRUCTURE` in' + ' settings. Modifying the following settings for' + ' the same behaviour.') + + structure = settings['ARTICLE_PERMALINK_STRUCTURE'] + + # Convert %(variable) into {variable}. + structure = re.sub(r'%\((\w+)\)s', r'{\g<1>}', structure) + + # Convert %x into {date:%x} for strftime + structure = re.sub(r'(%[A-z])', r'{date:\g<1>}', structure) + + # Strip a / prefix + structure = re.sub('^/', '', structure) + + for setting in ('ARTICLE_URL', 'ARTICLE_LANG_URL', 'PAGE_URL', + 'PAGE_LANG_URL', 'DRAFT_URL', 'DRAFT_LANG_URL', + 'ARTICLE_SAVE_AS', 'ARTICLE_LANG_SAVE_AS', + 'DRAFT_SAVE_AS', 'DRAFT_LANG_SAVE_AS', + 'PAGE_SAVE_AS', 'PAGE_LANG_SAVE_AS'): + settings[setting] = os.path.join(structure, + settings[setting]) + logger.warning("%s = '%s'", setting, settings[setting]) + + # {,TAG,CATEGORY,TRANSLATION}_FEED -> {,TAG,CATEGORY,TRANSLATION}_FEED_ATOM + for new, old in [('FEED', 'FEED_ATOM'), ('TAG_FEED', 'TAG_FEED_ATOM'), + ('CATEGORY_FEED', 'CATEGORY_FEED_ATOM'), + ('TRANSLATION_FEED', 'TRANSLATION_FEED_ATOM')]: + if settings.get(new, False): + logger.warning( + 'Found deprecated `%(new)s` in settings. Modify %(new)s ' + 'to %(old)s in your settings and theme for the same ' + 'behavior. Temporarily setting %(old)s for backwards ' + 'compatibility.', + {'new': new, 'old': old} + ) + settings[old] = settings[new] + return settings From b88b5f7b3679f98d1aa3934f5fcf818b2a726ea8 Mon Sep 17 00:00:00 2001 From: Andrea Grandi Date: Sat, 5 Oct 2019 15:25:31 +0200 Subject: [PATCH 21/25] Set default binding addres to 127.0.0.1 --- pelican/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/settings.py b/pelican/settings.py index 4aa31afe..d79f64fe 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -170,7 +170,7 @@ DEFAULT_CONFIG = { 'WRITE_SELECTED': [], 'FORMATTED_FIELDS': ['summary'], 'PORT': 8000, - 'BIND': '', + 'BIND': '127.0.0.1', } PYGMENTS_RST_OPTIONS = None From bc450b3339d9eb4ce4649a5989836dcee496688f Mon Sep 17 00:00:00 2001 From: David Alfonso Date: Wed, 9 Oct 2019 11:08:39 +0200 Subject: [PATCH 22/25] Add extra/optional Markdown dependency to setup.py - Modify documentation to use the extra dependency in order to install the recommended markdown package version. --- docs/install.rst | 10 +++++++++- docs/quickstart.rst | 2 +- setup.py | 3 +++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/install.rst b/docs/install.rst index 571de95e..2da7b9be 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -9,6 +9,10 @@ You can install Pelican via several different methods. The simplest is via pip install pelican +Or, if you plan on using Markdown:: + + pip install pelican[Markdown] + (Keep in mind that operating systems will often require you to prefix the above command with ``sudo`` in order to install Pelican system-wide.) @@ -40,7 +44,11 @@ Optional packages ----------------- If you plan on using `Markdown `_ as a -markup format, you'll need to install the Markdown library:: +markup format, you can install Pelican with Markdown support:: + + pip install pelican[Markdown] + +Or you might need to install it a posteriori:: pip install Markdown diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 646dd987..484a318f 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -11,7 +11,7 @@ Install Pelican (and optionally Markdown if you intend to use it) on Python 2.7.x or Python 3.5+ by running the following command in your preferred terminal, prefixing with ``sudo`` if permissions warrant:: - pip install pelican markdown + pip install pelican[Markdown] Create a project ---------------- diff --git a/setup.py b/setup.py index 5eea85b6..0979d1c4 100755 --- a/setup.py +++ b/setup.py @@ -61,6 +61,9 @@ setup( for name in names], }, install_requires=requires, + extras_require={ + 'Markdown': ['markdown~=3.1.1'] + }, entry_points=entry_points, classifiers=[ 'Development Status :: 5 - Production/Stable', From f52f276f2ea9c23311cdd8c49d19358d432925a8 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Wed, 9 Oct 2019 11:17:44 -0700 Subject: [PATCH 23/25] Separate SSH user/host/path vars in tasks.py Refs #2623 --- pelican/tools/templates/tasks.py.jinja2 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pelican/tools/templates/tasks.py.jinja2 b/pelican/tools/templates/tasks.py.jinja2 index 1c063f08..0362eba7 100644 --- a/pelican/tools/templates/tasks.py.jinja2 +++ b/pelican/tools/templates/tasks.py.jinja2 @@ -23,9 +23,10 @@ CONFIG = { 'deploy_path': SETTINGS['OUTPUT_PATH'], {% if ssh %} # Remote server configuration - 'production': '{{ssh_user}}@{{ssh_host}}', - 'production_port': {{ssh_port}}, - 'dest_path': '{{ssh_target_dir}}', + 'ssh_user': '{{ssh_user}}', + 'ssh_host': '{{ssh_host}}', + 'ssh_port': '{{ssh_port}}', + 'ssh_path': '{{ssh_target_dir}}', {% endif %} {% if cloudfiles %} # Rackspace Cloud Files configuration settings @@ -131,8 +132,8 @@ def publish(c): c.run('pelican -s {settings_publish}'.format(**CONFIG)) c.run( 'rsync --delete --exclude ".DS_Store" -pthrvz -c ' - '-e "ssh -p {production_port}" ' - '{} {production}:{dest_path}'.format( + '-e "ssh -p {ssh_port}" ' + '{} {ssh_user}@{ssh_host}:{ssh_path}'.format( CONFIG['deploy_path'].rstrip('/') + '/', **CONFIG)) From f9975ed47e8af49e723aa0c4cde50686e127292a Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Wed, 9 Oct 2019 11:28:53 -0700 Subject: [PATCH 24/25] Update RELEASE.md --- RELEASE.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 521973a9..02c40331 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,4 +1,9 @@ Release type: patch -Skip some tests (on Windows) that are un-able to pass on Windows due to the -difference in Windows vs Linux filesystems. +* Fix quick-start docs regarding `pelican --listen` +* Set default listen address to 127.0.0.1 +* Add extra/optional Markdown dependency to setup.py +* Use correct SSH port syntax for rsync in tasks.py +* Place all deprecated settings handling together +* Add related project URLs for display on PyPI +* Skip some tests on Windows that can't pass due to filesystem differences From 643bccc497183d9cc2d7c80423fbd8e088dd3dad Mon Sep 17 00:00:00 2001 From: botpub Date: Wed, 9 Oct 2019 18:45:18 +0000 Subject: [PATCH 25/25] Release Pelican 4.1.3 --- RELEASE.md | 9 --------- docs/changelog.rst | 11 +++++++++++ pyproject.toml | 2 +- setup.py | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) delete mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 02c40331..00000000 --- a/RELEASE.md +++ /dev/null @@ -1,9 +0,0 @@ -Release type: patch - -* Fix quick-start docs regarding `pelican --listen` -* Set default listen address to 127.0.0.1 -* Add extra/optional Markdown dependency to setup.py -* Use correct SSH port syntax for rsync in tasks.py -* Place all deprecated settings handling together -* Add related project URLs for display on PyPI -* Skip some tests on Windows that can't pass due to filesystem differences diff --git a/docs/changelog.rst b/docs/changelog.rst index 5e5d7cdf..befe358a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,17 @@ Release history ############### +4.1.3 - 2019-10-09 +================== + +* Fix quick-start docs regarding `pelican --listen` +* Set default listen address to 127.0.0.1 +* Add extra/optional Markdown dependency to setup.py +* Use correct SSH port syntax for rsync in tasks.py +* Place all deprecated settings handling together +* Add related project URLs for display on PyPI +* Skip some tests on Windows that can't pass due to filesystem differences + 4.1.2 - 2019-09-23 ================== diff --git a/pyproject.toml b/pyproject.toml index fce734f6..11c91c42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pelican" -version = "4.1.2" +version = "4.1.3" description = "Static site generator supporting Markdown and reStructuredText" authors = ["Justin Mayer "] license = "AGPLv3" diff --git a/setup.py b/setup.py index 0979d1c4..23857608 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from os.path import join, relpath from setuptools import setup -version = "4.1.2" +version = "4.1.3" requires = ['feedgenerator >= 1.9', 'jinja2 >= 2.7', 'pygments', 'docutils', 'pytz >= 0a', 'blinker', 'unidecode', 'six >= 1.4',