diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bcbd94d4..4b81530f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -66,7 +66,9 @@ jobs: with: pandoc-version: "2.9.2" - name: Install tox - run: python -m pip install -U pip tox + run: | + python -m pip install -U pip + python -m pip install --use-feature=2020-resolver -U tox - name: Info run: | echo "===== PYTHON =====" @@ -96,7 +98,9 @@ jobs: restore-keys: | ${{ runner.os }}-pip- - name: Install tox - run: python -m pip install -U pip tox + run: | + python -m pip install -U pip + python -m pip install --use-feature=2020-resolver -U tox - name: Check run: tox -e flake8 @@ -120,11 +124,59 @@ jobs: restore-keys: | ${{ runner.os }}-pip- - name: Install tox - run: python -m pip install -U pip tox + run: | + python -m pip install -U pip + python -m pip install --use-feature=2020-resolver -U tox - name: Check run: tox -e docs + install_sdist: + name: Install sdist on Windows + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup Python + uses: actions/setup-python@v1.1.1 + with: + python-version: 3.6 + - name: Test sdist installation on Windows + run: | + python -m pip install -U pip + python -m pip install --use-feature=2020-resolver -U poetry + poetry build + echo "Pip version:" + python -m pip --version + python -m pip install --use-feature=2020-resolver ${env:GITHUB_WORKSPACE}\dist\pelican-4.2.0.tar.gz + echo "Pelican version:" + pelican --version + python -m pip uninstall -y pelican + + + install_wheel: + name: Install wheel on Windows + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup Python + uses: actions/setup-python@v1.1.1 + with: + python-version: 3.6 + - name: Test wheel installation on Windows + run: | + python -m pip install -U pip + python -m pip install --use-feature=2020-resolver -U poetry + poetry build + echo "Pip version:" + python -m pip --version + python -m pip install --use-feature=2020-resolver ${env:GITHUB_WORKSPACE}\dist\pelican-4.2.0-py3-none-any.whl + echo "Pelican version:" + pelican --version + python -m pip uninstall -y pelican + + deploy: name: Deploy needs: [test, lint, docs] @@ -140,10 +192,10 @@ jobs: - name: Check release id: check_release run: | - python -m pip install pip --upgrade - pip install poetry - pip install githubrelease - pip install --pre autopub + python -m pip install --use-feature=2020-resolver pip --upgrade + pip install --use-feature=2020-resolver poetry + pip install --use-feature=2020-resolver githubrelease + pip install --use-feature=2020-resolver --pre autopub echo "##[set-output name=release;]$(autopub check)" - name: Publish if: ${{ steps.check_release.outputs.release=='' }} diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 9561b04f..61935f62 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -43,7 +43,7 @@ publicly-accessible location: * Describe what version of Pelican you are running (output of ``pelican --version`` or the HEAD commit hash if you cloned the repo) and how exactly you installed - it (the full command you used, e.g. ``pip install pelican``). + it (the full command you used, e.g. ``python -m pip install pelican``). * If you are looking for a way to get some end result, prepare a detailed description of what the end result should look like (preferably in the form of an image or a mock-up page) and explain in detail what you have done so far to diff --git a/docs/contribute.rst b/docs/contribute.rst index 66890ae7..62ed51f9 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -44,9 +44,9 @@ to manually create and activate a virtual environment:: Install the needed dependencies and set up the project:: - pip install invoke + python -m pip install invoke invoke setup - pip install -e ~/projects/pelican + python -m pip install -e ~/projects/pelican Your local environment should now be ready to go! diff --git a/docs/faq.rst b/docs/faq.rst index c35cd6c6..8532ab3f 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -74,7 +74,7 @@ Markdown format, you will need to explicitly install the Markdown library. You can do so by typing the following command, prepending ``sudo`` if permissions require it:: - pip install markdown + python -m pip install markdown Can I use arbitrary metadata in my templates? ============================================= diff --git a/docs/install.rst b/docs/install.rst index 03480e79..eb618035 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -1,19 +1,17 @@ Installing Pelican ################## -Pelican currently runs best on Python 2.7.x and 3.5+; earlier versions of -Python are not supported. +Pelican currently runs best on 3.6+; earlier versions of Python are not supported. -You can install Pelican via several different methods. The simplest is via -`pip `_:: +You can install Pelican via several different methods. The simplest is via Pip_:: - pip install pelican + python -m pip install pelican Or, if you plan on using Markdown:: - pip install pelican[Markdown] + python -m pip install "pelican[markdown]" -(Keep in mind that operating systems will often require you to prefix the above +(Keep in mind that some operating systems will require you to prefix the above command with ``sudo`` in order to install Pelican system-wide.) While the above is the simplest method, the recommended approach is to create a @@ -26,7 +24,7 @@ session and create a new virtual environment for Pelican:: source bin/activate Once the virtual environment has been created and activated, Pelican can be -installed via ``pip install pelican`` as noted above. Alternatively, if you +installed via ``python -m pip install pelican`` as noted above. Alternatively, if you have the project source, you can install Pelican using the distutils method:: cd path-to-Pelican-source @@ -35,7 +33,7 @@ have the project source, you can install Pelican using the distutils method:: If you have Git installed and prefer to install the latest bleeding-edge version of Pelican rather than a stable release, use the following command:: - pip install -e "git+https://github.com/getpelican/pelican.git#egg=pelican" + python -m pip install -e "git+https://github.com/getpelican/pelican.git#egg=pelican" Once Pelican is installed, you can run ``pelican --help`` to see basic usage options. For more detail, refer to the :doc:`Publish` section. @@ -46,17 +44,13 @@ Optional packages If you plan on using `Markdown `_ as a 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 + python -m pip install "pelican[markdown]" Typographical enhancements can be enabled in your settings file, but first the requisite `Typogrify `_ library must be installed:: - pip install typogrify + python -m pip install typogrify Dependencies ------------ @@ -75,9 +69,8 @@ automatically installed without any action on your part: broadcast signaling system * `unidecode `_, for ASCII transliterations of Unicode text -* `six `_, for Python 2 and 3 compatibility utilities -* `MarkupSafe `_, for a markup safe +* `MarkupSafe `_, for a markup-safe string implementation * `python-dateutil `_, to read the date metadata @@ -85,10 +78,10 @@ automatically installed without any action on your part: Upgrading --------- -If you installed a stable Pelican release via ``pip`` and wish to upgrade to +If you installed a stable Pelican release via Pip_ and wish to upgrade to the latest stable release, you can do so by adding ``--upgrade``:: - pip install --upgrade pelican + python -m pip install --upgrade pelican If you installed Pelican via distutils or the bleeding-edge method, simply perform the same step to install the most recent version. @@ -126,4 +119,5 @@ content):: The next step is to begin to adding content to the *content* folder that has been created for you. +.. _Pip: https://pip.pypa.io/ .. _virtualenv: https://virtualenv.pypa.io/en/latest/ diff --git a/docs/internals.rst b/docs/internals.rst index 5b41070e..01d60c39 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -44,17 +44,22 @@ HTML content and some metadata. Take a look at the Markdown reader:: + from pelican.readers import BaseReader + from pelican.utils import pelican_open + from markdown import Markdown + class MarkdownReader(BaseReader): - enabled = bool(Markdown) + enabled = True def read(self, source_path): """Parse content and metadata of markdown files""" - text = pelican_open(source_path) - md_extensions = {'markdown.extensions.meta': {}, - 'markdown.extensions.codehilite': {}} - md = Markdown(extensions=md_extensions.keys(), - extension_configs=md_extensions) - content = md.convert(text) + + with pelican_open(source_path) as text: + md_extensions = {'markdown.extensions.meta': {}, + 'markdown.extensions.codehilite': {}} + md = Markdown(extensions=md_extensions.keys(), + extension_configs=md_extensions) + content = md.convert(text) metadata = {} for name, value in md.Meta.items(): diff --git a/docs/publish.rst b/docs/publish.rst index 9bea8938..ae1428f5 100644 --- a/docs/publish.rst +++ b/docs/publish.rst @@ -118,7 +118,7 @@ in a wide range of environments. The downside is that it must be installed separately. Use the following command to install Invoke, prefixing with ``sudo`` if your environment requires it:: - pip install invoke + python -m pip install invoke Take a moment to open the ``tasks.py`` file that was generated in your project root. You will see a number of commands, any one of which can be renamed, @@ -139,7 +139,7 @@ http://localhost:8000/:: invoke serve To serve the generated site with automatic browser reloading every time a -change is detected, first ``pip install livereload``, then use the +change is detected, first ``python -m pip install livereload``, then use the following command:: invoke livereload diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 1f6358a7..ddc42651 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -8,10 +8,10 @@ Installation ------------ 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:: +3.6+ by running the following command in your preferred terminal, prefixing +with ``sudo`` if permissions warrant:: - pip install pelican[Markdown] + python -m pip install "pelican[markdown]" Create a project ---------------- diff --git a/docs/settings.rst b/docs/settings.rst index 2b99072f..377051b0 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -9,6 +9,12 @@ line:: If you used the ``pelican-quickstart`` command, your primary settings file will be named ``pelicanconf.py`` by default. +You can also specify extra settings via ``-e`` / ``--extra-settings`` option +flags, which will override default settings as well as any defined within +settings files:: + + pelican content -e DELETE_OUTPUT_DIRECTORY=true + .. note:: When experimenting with different settings (especially the metadata ones) @@ -271,7 +277,7 @@ Basic settings If set to True, several typographical improvements will be incorporated into the generated HTML via the `Typogrify `_ library, which can be installed - via: ``pip install typogrify`` + via: ``python -m pip install typogrify`` .. data:: TYPOGRIFY_IGNORE_TAGS = [] @@ -297,10 +303,10 @@ Basic settings does not otherwise specify a summary. Setting to ``None`` will cause the summary to be a copy of the original content. -.. data:: SUMMARY_END_MARKER = '…' +.. data:: SUMMARY_END_SUFFIX = '…' When creating a short summary of an article and the result was truncated to - match the required word length, this will be used as the truncation marker. + match the required word length, this will be used as the truncation suffix. .. data:: WITH_FUTURE_DATES = True @@ -770,7 +776,7 @@ Template pages .. data:: TEMPLATE_PAGES = None A mapping containing template pages that will be rendered with the blog - entries. See :ref:`template_pages`. + entries. If you want to generate custom pages besides your blog entries, you can point any Jinja2 template file with a path pointing to the file and the diff --git a/pelican/__init__.py b/pelican/__init__.py index 6469c607..82366117 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -23,7 +23,7 @@ from pelican.plugins import signals from pelican.plugins._utils import load_plugins from pelican.readers import Readers from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer -from pelican.settings import read_settings +from pelican.settings import coerce_overrides, read_settings from pelican.utils import (FileSystemWatcher, clean_output_dir, maybe_pluralize) from pelican.writers import Writer @@ -230,6 +230,18 @@ class PrintSettings(argparse.Action): parser.exit() +class ParseDict(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + d = {} + if values: + for item in values: + split_items = item.split("=", 1) + key = split_items[0].strip() + value = split_items[1].strip() + d[key] = value + setattr(namespace, self.dest, d) + + def parse_arguments(argv=None): parser = argparse.ArgumentParser( description='A tool to generate a static blog, ' @@ -323,6 +335,16 @@ def parse_arguments(argv=None): help='IP to bind to when serving files via HTTP ' '(default: 127.0.0.1)') + parser.add_argument('-e', '--extra-settings', dest='overrides', + help='Specify one or more SETTING=VALUE pairs to ' + 'override settings. If VALUE contains spaces, ' + 'add quotes: SETTING="VALUE". Values other than ' + 'integers and strings can be specified via JSON ' + 'notation. (e.g., SETTING=none)', + nargs='*', + action=ParseDict + ) + args = parser.parse_args(argv) if args.port is not None and not args.listen: @@ -358,6 +380,7 @@ def get_config(args): if args.bind is not None: config['BIND'] = args.bind config['DEBUG'] = args.verbosity == logging.DEBUG + config.update(coerce_overrides(args.overrides)) return config diff --git a/pelican/contents.py b/pelican/contents.py index 2bb2e3a0..6470ee45 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -392,7 +392,7 @@ class Content: return truncate_html_words(self.content, self.settings['SUMMARY_MAX_LENGTH'], - self.settings['SUMMARY_END_MARKER']) + self.settings['SUMMARY_END_SUFFIX']) @property def summary(self): diff --git a/pelican/readers.py b/pelican/readers.py index 8c108510..15d09908 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -227,7 +227,7 @@ class RstReader(BaseReader): if element.tagname == 'field': # custom fields (e.g. summary) name_elem, body_elem = element.children name = name_elem.astext() - if name in formatted_fields: + if name.lower() in formatted_fields: value = render_node_to_html( document, body_elem, self.field_body_translator_class) diff --git a/pelican/settings.py b/pelican/settings.py index 7b333de8..ea3ee8eb 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -1,6 +1,7 @@ import copy import importlib.util import inspect +import json import locale import logging import os @@ -135,7 +136,7 @@ DEFAULT_CONFIG = { 'TYPOGRIFY': False, 'TYPOGRIFY_IGNORE_TAGS': [], 'TYPOGRIFY_DASHES': 'default', - 'SUMMARY_END_MARKER': '…', + 'SUMMARY_END_SUFFIX': '…', 'SUMMARY_MAX_LENGTH': 50, 'PLUGIN_PATHS': [], 'PLUGINS': None, @@ -658,3 +659,25 @@ def configure_settings(settings): continue # setting not specified, nothing to do return settings + + +def coerce_overrides(overrides): + if overrides is None: + return {} + coerced = {} + types_to_cast = {int, str, bool} + for k, v in overrides.items(): + if k not in DEFAULT_CONFIG: + logger.warning('Override for unknown setting %s, ignoring', k) + continue + setting_type = type(DEFAULT_CONFIG[k]) + if setting_type not in types_to_cast: + coerced[k] = json.loads(v) + else: + try: + coerced[k] = setting_type(v) + except ValueError: + logger.debug('ValueError for %s override with %s, try to ' + 'load as json', k, v) + coerced[k] = json.loads(v) + return coerced diff --git a/pelican/tests/content/article_with_capitalized_metadata.rst b/pelican/tests/content/article_with_capitalized_metadata.rst new file mode 100644 index 00000000..93ed5b15 --- /dev/null +++ b/pelican/tests/content/article_with_capitalized_metadata.rst @@ -0,0 +1,16 @@ + +This is a super article ! +######################### + +:TAGS: foo, bar, foobar +:DATE: 2010-12-02 10:14 +:MODIFIED: 2010-12-02 10:20 +:CATEGORY: yeah +:AUTHOR: Alexis Métaireau +:SUMMARY: + Multi-line metadata should be supported + as well as **inline markup** and stuff to "typogrify"... +:CUSTOM_FIELD: http://notmyidea.org +:CUSTOM_FORMATTED_FIELD: + Multi-line metadata should also be supported + as well as *inline markup* and stuff to "typogrify"... diff --git a/pelican/tests/test_contents.py b/pelican/tests/test_contents.py index 93f5b212..1a520bc7 100644 --- a/pelican/tests/test_contents.py +++ b/pelican/tests/test_contents.py @@ -110,14 +110,14 @@ class TestPage(TestBase): page = Page(**page_kwargs) self.assertEqual(page.summary, '') - def test_summary_end_marker(self): - # If a :SUMMARY_END_MARKER: is set, and there is no other summary, + def test_summary_end_suffix(self): + # If a :SUMMARY_END_SUFFIX: is set, and there is no other summary, # generated summary should contain the specified marker at the end. page_kwargs = self._copy_page_kwargs() settings = get_settings() page_kwargs['settings'] = settings del page_kwargs['metadata']['summary'] - settings['SUMMARY_END_MARKER'] = 'test_marker' + settings['SUMMARY_END_SUFFIX'] = 'test_marker' settings['SUMMARY_MAX_LENGTH'] = 10 page = Page(**page_kwargs) self.assertEqual(page.summary, truncate_html_words(TEST_CONTENT, 10, diff --git a/pelican/tests/test_generators.py b/pelican/tests/test_generators.py index 332d7e78..169765ac 100644 --- a/pelican/tests/test_generators.py +++ b/pelican/tests/test_generators.py @@ -260,6 +260,7 @@ class TestArticlesGenerator(unittest.TestCase): ['This is a super article !', 'published', 'yeah', 'article'], ['This is a super article !', 'published', 'yeah', 'article'], ['This is a super article !', 'published', 'yeah', 'article'], + ['This is a super article !', 'published', 'yeah', 'article'], ['This is a super article !', 'published', 'Default', 'article'], ['Article with an inline SVG', 'published', 'Default', 'article'], ['This is an article with category !', 'published', 'yeah', @@ -576,6 +577,7 @@ class TestArticlesGenerator(unittest.TestCase): 'This is a super article !', 'This is a super article !', 'This is a super article !', + 'This is a super article !', 'This is an article with category !', ('This is an article with multiple authors in lastname, ' 'firstname format!'), diff --git a/pelican/tests/test_readers.py b/pelican/tests/test_readers.py index de2a1b22..ea5f3bdd 100644 --- a/pelican/tests/test_readers.py +++ b/pelican/tests/test_readers.py @@ -155,6 +155,24 @@ class RstReaderTest(ReaderTest): self.assertDictHasSubset(page.metadata, expected) + def test_article_with_capitalized_metadata(self): + page = self.read_file(path='article_with_capitalized_metadata.rst') + expected = { + 'category': 'yeah', + 'author': 'Alexis Métaireau', + 'title': 'This is a super article !', + 'summary': '

Multi-line metadata should be' + ' supported\nas well as inline' + ' markup and stuff to "typogrify' + '"...

\n', + 'date': SafeDatetime(2010, 12, 2, 10, 14), + 'modified': SafeDatetime(2010, 12, 2, 10, 20), + 'tags': ['foo', 'bar', 'foobar'], + 'custom_field': 'http://notmyidea.org', + } + + self.assertDictHasSubset(page.metadata, expected) + def test_article_with_filename_metadata(self): page = self.read_file( path='2012-11-29_rst_w_filename_meta#foo-bar.rst', diff --git a/pelican/tests/test_settings.py b/pelican/tests/test_settings.py index 708c0981..83203ae5 100644 --- a/pelican/tests/test_settings.py +++ b/pelican/tests/test_settings.py @@ -7,8 +7,8 @@ from sys import platform from pelican.settings import (DEFAULT_CONFIG, DEFAULT_THEME, _printf_s_to_format_field, - configure_settings, handle_deprecated_settings, - read_settings) + coerce_overrides, configure_settings, + handle_deprecated_settings, read_settings) from pelican.tests.support import unittest @@ -304,3 +304,18 @@ class TestSettingsConfiguration(unittest.TestCase): [(r'C\+\+', 'cpp')] + self.settings['SLUG_REGEX_SUBSTITUTIONS']) self.assertNotIn('SLUG_SUBSTITUTIONS', settings) + + def test_coerce_overrides(self): + overrides = coerce_overrides({ + 'ARTICLE_EXCLUDES': '["testexcl"]', + 'READERS': '{"foo": "bar"}', + 'STATIC_EXCLUDE_SOURCES': 'true', + 'THEME_STATIC_DIR': 'theme', + }) + expected = { + 'ARTICLE_EXCLUDES': ["testexcl"], + 'READERS': {"foo": "bar"}, + 'STATIC_EXCLUDE_SOURCES': True, + 'THEME_STATIC_DIR': 'theme', + } + self.assertDictEqual(overrides, expected) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index 1a98ab14..41ddea3c 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -41,7 +41,7 @@ _jinja_env = Environment( _GITHUB_PAGES_BRANCHES = { - 'personal': 'master', + 'personal': 'main', 'project': 'gh-pages' } diff --git a/pelican/tools/templates/Makefile.jinja2 b/pelican/tools/templates/Makefile.jinja2 index 0184cc88..a60f1e16 100644 --- a/pelican/tools/templates/Makefile.jinja2 +++ b/pelican/tools/templates/Makefile.jinja2 @@ -101,32 +101,16 @@ regenerate: "$(PELICAN)" -r "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) serve: -ifdef PORT - "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -p $(PORT) -else "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -endif serve-global: -ifdef PORT - "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -p $(PORT) -b $(SERVER) -else "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b $(SERVER) -endif devserver: -ifdef PORT - "$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -p $(PORT) -else "$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -endif devserver-global: -ifdef PORT - $(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) -b 0.0.0.0 -else $(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -b 0.0.0.0 -endif publish: "$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(PUBLISHCONF)" $(PELICANOPTS) @@ -139,7 +123,7 @@ ssh_upload: publish {% set upload = upload + ["rsync_upload"] %} rsync_upload: publish - rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --cvs-exclude --delete "$(OUTPUTDIR)"/ "$(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)" + rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --include tags --cvs-exclude --delete "$(OUTPUTDIR)"/ "$(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)" {% endif %} {% if dropbox %} diff --git a/pyproject.toml b/pyproject.toml index 20196d15..6aafee89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,45 +18,48 @@ classifiers = [ "License :: OSI Approved :: GNU Affero General Public License v3", "Operating System :: OS Independent", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Internet :: WWW/HTTP", "Topic :: Software Development :: Libraries :: Python Modules", ] +[tool.poetry.urls] +"Funding" = "https://donate.getpelican.com/" +"Tracker" = "https://github.com/getpelican/pelican/issues" + [tool.poetry.dependencies] python = "^3.6" +blinker = "^1.4" +docutils = "^0.16" feedgenerator = "^1.9" jinja2 = "~2.11" pygments = "~2.6.1" -pytz = "^2019.1" -blinker = "^1.4" -unidecode = "^1.1" python-dateutil = "^2.8" -docutils = "^0.15" -markdown = {version = "~3.1.1", optional = true} +pytz = "^2020.1" +unidecode = "^1.1" +markdown = {version = "~3.2.2", optional = true} [tool.poetry.dev-dependencies] -BeautifulSoup4 = "^4.7" +BeautifulSoup4 = "^4.9" lxml = "^4.3" -markdown = "~3.1.1" +markdown = "~3.2.2" typogrify = "^2.0" -sphinx = "=1.4.9" -sphinx_rtd_theme = "^0.4.3" +sphinx = "^3.0" +sphinx_rtd_theme = "^0.5" livereload = "^2.6" -mock = "^3.0" -pytest = "~5.3.5" +pytest = "^6.0" pytest-cov = "^2.8" pytest-pythonpath = "^0.7.3" -pytest-sugar = "^0.9.2" -pytest-xdist = "^1.31" +pytest-sugar = "^0.9.4" +pytest-xdist = "^2.0" tox = "^3.13" -flake8 = "^3.7" +flake8 = "^3.8" flake8-import-order = "^0.18.1" invoke = "^1.3" -isort = "^4.3.21" +isort = "^5.2" black = {version = "^19.10b0", allow-prereleases = true} [tool.poetry.extras] @@ -64,6 +67,10 @@ markdown = ["markdown"] [tool.poetry.scripts] pelican = "pelican.__main__:main" +pelican-import = "pelican.tools.pelican_import:main" +pelican-plugins = "pelican.plugins._utils:list_plugins" +pelican-quickstart = "pelican.tools.pelican_quickstart:main" +pelican-themes = "pelican.tools.pelican_themes:main" [tool.autopub] project-name = "Pelican" @@ -76,4 +83,5 @@ version-strings = ["setup.py"] build-system = "setuptools" [build-system] -requires = ["setuptools >= 40.6.0", "wheel"] +requires = ["poetry>=1.0"] +build-backend = "poetry.masonry.api" diff --git a/requirements/test.pip b/requirements/test.pip index 973b27ca..647a8694 100644 --- a/requirements/test.pip +++ b/requirements/test.pip @@ -1,6 +1,6 @@ # Tests Pygments==2.6.1 -pytest==5.3.5 +pytest pytest-cov pytest-xdist diff --git a/setup.py b/setup.py index 2d831aa4..af96c726 100755 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from os import walk from os.path import join, relpath -from setuptools import setup +from setuptools import setup, find_packages version = "4.2.0" @@ -44,19 +44,14 @@ setup( keywords='static web site generator SSG reStructuredText Markdown', license='AGPLv3', long_description=description, - packages=['pelican', 'pelican.tools', 'pelican.plugins'], - package_data={ - # we manually collect the package data, as opposed to using, - # include_package_data=True because we don't want the tests to be - # included automatically as package data (MANIFEST.in is too greedy) + packages=find_packages(), + include_package_data=True, # includes all in MANIFEST.in if in package + # NOTE : This will collect any files that happen to be in the themes + # directory, even though they may not be checked into version control. + package_data={ # pelican/themes is not a package, so include manually 'pelican': [relpath(join(root, name), 'pelican') for root, _, names in walk(join('pelican', 'themes')) for name in names], - 'pelican.tools': [relpath(join(root, name), join('pelican', 'tools')) - for root, _, names in walk(join('pelican', - 'tools', - 'templates')) - for name in names], }, install_requires=requires, extras_require={ diff --git a/tasks.py b/tasks.py index 52bfe6a3..76c48834 100644 --- a/tasks.py +++ b/tasks.py @@ -64,7 +64,7 @@ def isort(c, check=False, diff=False): if diff: diff_flag = "--diff" c.run( - f"{VENV_BIN}/isort {check_flag} {diff_flag} --recursive {PKG_PATH}/* tasks.py" + f"{VENV_BIN}/isort {check_flag} {diff_flag} ." ) diff --git a/tox.ini b/tox.ini index 18b0e7a4..69281e30 100644 --- a/tox.ini +++ b/tox.ini @@ -28,7 +28,7 @@ commands = filterwarnings = default::DeprecationWarning error:.*:Warning:pelican -addopts = -n 2 -r a +addopts = -n auto -r a [flake8] application-import-names = pelican