From e46b6232546a75b31f5cf3ae8f9aa9a624344915 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 9 Nov 2019 08:36:45 -0800 Subject: [PATCH 01/13] Add initial Invoke tasks.py file --- tasks.py | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tasks.py diff --git a/tasks.py b/tasks.py new file mode 100644 index 00000000..7d9ff1d9 --- /dev/null +++ b/tasks.py @@ -0,0 +1,81 @@ +import os +from pathlib import Path +from shutil import which + +from invoke import task + +PKG_NAME = "pelican" +PKG_PATH = Path("pelican") +ACTIVE_VENV = os.environ.get("VIRTUAL_ENV", None) +VENV_HOME = Path(os.environ.get("WORKON_HOME", "~/virtualenvs")) +VENV_PATH = Path(ACTIVE_VENV) if ACTIVE_VENV else (VENV_HOME / PKG_NAME) +VENV = str(VENV_PATH.expanduser()) + +TOOLS = ["poetry", "pre-commit"] +POETRY = which("poetry") if which("poetry") else (VENV / Path("bin") / "poetry") +PRECOMMIT = ( + which("pre-commit") if which("pre-commit") else (VENV / Path("bin") / "pre-commit") +) + + +@task +def tests(c): + """Run the test suite""" + c.run(f"{VENV}/bin/python -Wd -m unittest discover", pty=True) + + +@task +def black(c, check=False, diff=False): + """Run Black auto-formatter, optionally with --check or --diff""" + check_flag, diff_flag = "", "" + if check: + check_flag = "--check" + if diff: + diff_flag = "--diff" + c.run(f"{VENV}/bin/black {check_flag} {diff_flag} {PKG_PATH} tasks.py") + + +@task +def isort(c, check=False, diff=False): + check_flag, diff_flag = "", "" + if check: + check_flag = "-c" + if diff: + diff_flag = "--diff" + c.run( + f"{VENV}/bin/isort {check_flag} {diff_flag} --recursive {PKG_PATH}/* tasks.py" + ) + + +@task +def flake8(c): + c.run(f"{VENV}/bin/flake8 {PKG_PATH} tasks.py") + + +@task +def lint(c): + isort(c, check=True) + black(c, check=True) + flake8(c) + + +@task +def tools(c): + """Install tools in the virtual environment if not already on PATH""" + for tool in TOOLS: + if not which(tool): + c.run(f"{VENV}/bin/pip install {tool}") + + +@task +def precommit(c): + """Install pre-commit hooks to .git/hooks/pre-commit""" + c.run(f"{PRECOMMIT} install") + + +@task +def setup(c): + c.run(f"{VENV}/bin/pip install -U pip") + tools(c) + c.run(f"{POETRY} install") + precommit(c) From d859f93c7b7ed659eee4d8653e060e309f51cc2d Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 9 Nov 2019 08:37:11 -0800 Subject: [PATCH 02/13] Add initial Pre-commit configuration file --- .pre-commit-config.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..ef27cfcf --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +# See https://pre-commit.com/hooks.html for info on hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-added-large-files + - id: check-ast + - id: check-toml + - id: check-yaml + - id: debug-statements + - id: detect-private-key + - id: end-of-file-fixer + - id: trailing-whitespace From 272778bc673bd10ff8a0031fd993676199cf60c9 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 9 Nov 2019 08:37:54 -0800 Subject: [PATCH 03/13] Add initial EditorConfig configuration --- .editorconfig | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..b42ca8c2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.py] +max_line_length = 79 + +[*.yml] +indent_size = 2 From 04a602e381f8ec079482b7a87a412e02d133aa97 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 9 Nov 2019 08:40:26 -0800 Subject: [PATCH 04/13] Add Invoke as dependency in pyproject --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 996570d0..c498ef15 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ sphinx_rtd_theme = "^0.4.3" tox = "^3.13" flake8 = "^3.7" flake8-import-order = "^0.18.1" +invoke = "^1.3" [tool.poetry.extras] markdown = ["markdown"] From 68c9ef76b2503a33bf5595069ab6d693a7eaf130 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sat, 9 Nov 2019 09:43:55 -0800 Subject: [PATCH 05/13] Update CONTRIBUTING docs for Python 2.x removal This also updates the Contributing documentation with information on new development tooling. --- CONTRIBUTING.rst | 5 +- docs/contribute.rst | 180 +++++++++++++++++++++++++------------------- 2 files changed, 105 insertions(+), 80 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 7ae47593..ac120128 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -137,8 +137,7 @@ Contribution quality standards code/formatting can be improved. If you are relying on your editor for PEP8 compliance, note that the line length specified by PEP8 is 79 (excluding the line break). -* Ensure your code is compatible with the latest Python 2.7 and 3.x releases — see our - `compatibility cheatsheet`_ for more details. +* Ensure your code is compatible with the `officially-supported Python releases`_. * Add docs and tests for your changes. Undocumented and untested features will not be accepted. * `Run all the tests`_ **on all versions of Python supported by Pelican** to @@ -155,4 +154,4 @@ need assistance or have any questions about these guidelines. .. _`Git Tips`: https://github.com/getpelican/pelican/wiki/Git-Tips .. _`PEP8 coding standards`: https://www.python.org/dev/peps/pep-0008/ .. _`ask for help`: `How to get help`_ -.. _`compatibility cheatsheet`: https://docs.getpelican.com/en/latest/contribute.html#python-3-development-tips +.. _`officially-supported Python releases`: https://devguide.python.org/#status-of-python-branches diff --git a/docs/contribute.rst b/docs/contribute.rst index 5a314751..1e884463 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -7,72 +7,78 @@ can also help out by reviewing and commenting on `existing issues `_. Don't hesitate to fork Pelican and submit an issue or pull request on GitHub. -When doing so, please adhere to the following guidelines. +When doing so, please consider the following guidelines. .. include:: ../CONTRIBUTING.rst Setting up the development environment ====================================== -While there are many ways to set up one's development environment, we recommend -using `Virtualenv `_. This tool allows -you to set up separate environments for separate Python projects that are -isolated from one another so you can use different packages (and package -versions) for each. +While there are many ways to set up one's development environment, the following +instructions will utilize Pip_ and Poetry_. These tools facilitate managing +virtual environments for separate Python projects that are isolated from one +another, so you can use different packages (and package versions) for each. -If you don't have ``virtualenv`` installed, you can install it via:: +Please note that Python 3.6+ is required for Pelican development. - $ pip install virtualenv +*(Optional)* If you prefer to install Poetry once for use with multiple projects, +you can install it via:: -Use ``virtualenv`` to create and activate a virtual environment:: + curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python - $ virtualenv ~/virtualenvs/pelican - $ cd ~/virtualenvs/pelican - $ . bin/activate +Point your web browser to the `Pelican repository`_ and tap the **Fork** button +at top-right. Then clone the source for your fork and add the upstream project +as a Git remote:: -Clone the Pelican source into a subfolder called ``src/pelican``:: + mkdir ~/projects + git clone https://github.com/YOUR_USERNAME/pelican.git ~/projects/pelican + cd ~/projects/pelican + git remote add upstream https://github.com/getpelican/pelican.git - $ git clone https://github.com/getpelican/pelican.git src/pelican - $ cd src/pelican +While Poetry can dynamically create and manage virtual environments, we're going +to manually create and activate a virtual environment:: -Install the development dependencies:: + mkdir ~/virtualenvs + python3 -m venv ~/virtualenvs/pelican + source ~/virtualenvs/pelican/bin/activate - $ pip install -r requirements/developer.pip +Install the needed dependencies and set up the project:: -Install Pelican and its dependencies:: + pip install -e ~/projects/pelican invoke + invoke setup - $ python setup.py develop +Your local environment should now be ready to go! -Or using ``pip``:: +.. _Pip: https://pip.pypa.io/ +.. _Poetry: https://poetry.eustace.io/docs/#installation +.. _Pelican repository: https://github.com/getpelican/pelican - $ pip install -e . +Development +=========== -To conveniently test on multiple Python versions, we also provide a ``.tox`` -file. +Once Pelican has been set up for local development, create a topic branch for +your bug fix or feature: + git checkout -b name-of-your-bugfix-or-feature -Building the docs -================= - -If you make changes to the documentation, you should preview your changes -before committing them:: - - $ pip install -r requirements/docs.pip - $ cd docs - $ make html - -Open ``_build/html/index.html`` in your browser to preview the documentation. +Now you can make changes to Pelican, its documentation, and/or other aspects of +the project. Running the test suite -====================== +---------------------- -Each time you add a feature, there are two things to do regarding tests: check -that the existing tests pass, and add tests for the new feature or bugfix. +Each time you make changes to Pelican, there are two things to do regarding +tests: check that the existing tests pass, and add tests for any new features +or bug fixes. The tests are located in ``pelican/tests``, and you can run them +via:: -The tests live in ``pelican/tests`` and you can run them using the -"discover" feature of ``unittest``:: + invoke tests - $ python -Wd -m unittest discover +In addition to running the test suite, the above invocation will also check code +style and let you know whether non-conforming patterns were found. In some cases +these linters will make the needed changes directly, while in other cases you +may need to make additional changes until ``invoke tests`` no longer reports any +code style violations. After making your changes and running the tests, you may see a test failure mentioning that "some generated files differ from the expected functional tests @@ -82,11 +88,11 @@ the nature of your changes, then you should update the output used by the functional tests. To do so, **make sure you have both** ``en_EN.utf8`` **and** ``fr_FR.utf8`` **locales installed**, and then run the following two commands:: - $ LC_ALL=en_US.utf8 pelican -o pelican/tests/output/custom/ \ + LC_ALL=en_US.utf8 pelican -o pelican/tests/output/custom/ \ -s samples/pelican.conf.py samples/content/ - $ LC_ALL=fr_FR.utf8 pelican -o pelican/tests/output/custom_locale/ \ + LC_ALL=fr_FR.utf8 pelican -o pelican/tests/output/custom_locale/ \ -s samples/pelican.conf_FR.py samples/content/ - $ LC_ALL=en_US.utf8 pelican -o pelican/tests/output/basic/ \ + LC_ALL=en_US.utf8 pelican -o pelican/tests/output/basic/ \ samples/content/ You may also find that some tests are skipped because some dependency (e.g., @@ -101,48 +107,68 @@ environments. .. _Tox: https://tox.readthedocs.io/en/latest/ -Python 2/3 compatibility development tips -========================================= +Building the docs +----------------- -Here are some tips that may be useful for writing code that is compatible with -both Python 2.7 and Python 3: +If you make changes to the documentation, you should preview your changes +before committing them:: -- Use new syntax. For example: + cd docs + make html - - ``print .. -> print(..)`` - - ``except .., e -> except .. as e`` +Open ``_build/html/index.html`` in your browser to preview the documentation. -- Use new methods. For example: +Plugin development +------------------ - - ``dict.iteritems() -> dict.items()`` - - ``xrange(..) - > list(range(..))`` +To create a *new* Pelican plugin, please refer to the `plugin template`_ +repository for detailed instructions. -- Use ``six`` where necessary. For example: +If you want to contribute to an *existing* Pelican plugin, follow the steps +above to set up Pelican for local development, and then create a directory to +store cloned plugin repositories:: - - ``isinstance(.., basestring) -> isinstance(.., six.string_types)`` - - ``isinstance(.., unicode) -> isinstance(.., six.text_type)`` + mkdir -p ~/projects/pelican-plugins -- Assume every string and literal is Unicode: +Assuming you wanted to contribute to the Simple Footnotes plugin, you would +first browse to the `Simple Footnotes`_ repository on GitHub and tap the **Fork** +button at top-right. Then clone the source for your fork and add the upstream +project as a Git remote:: - - Use ``from __future__ import unicode_literals`` - - Do not use the prefix ``u'`` before strings. - - Do not encode/decode strings in the middle of something. Follow the code to - the source/target of a string and encode/decode at the first/last possible - point. - - In particular, write your functions to expect and to return Unicode. - - Encode/decode strings if the string is the output of a Python function that - is known to handle this badly. For example, ``strftime()`` in Python 2. - - Do not use the magic method ``__unicode()__`` in new classes. Use only - ``__str()__`` and decorate the class with ``@python_2_unicode_compatible``. + git clone https://github.com/YOUR_USERNAME/simple-footnotes.git ~/projects/pelican-plugins/simple-footnotes + cd ~/projects/pelican-plugins/simple-footnotes + git remote add upstream https://github.com/pelican-plugins/simple-footnotes.git -- ``setlocale()`` in Python 2 fails when we give the locale name as Unicode, - and since we are using ``from __future__ import unicode_literals``, we do - that everywhere! As a workaround, enclose the locale name with ``str()``; - in Python 2 this casts the name to a byte string, while in Python 3 this - should do nothing, because the locale name was already Unicode. -- Do not start integer literals with a zero. This is a syntax error in Python 3. -- Unfortunately there seems to be no octal notation that is valid in both - Python 2 and 3. Use decimal notation instead. +Install the needed dependencies and set up the project:: + + invoke setup + +After writing new tests for your plugin changes, run the plugin test suite:: + + invoke tests + +.. _plugin template: https://github.com/getpelican/cookiecutter-pelican-plugin +.. _Simple Footnotes: https://github.com/pelican-plugins/simple-footnotes + +Submitting your changes +----------------------- + +Assuming linting validation and tests pass, 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: patch + + Fix browser reloading upon changes to content, settings, or theme + +Commit your changes and push your topic branch:: + + git add . + git commit -m "Your detailed description of your changes" + git push origin name-of-your-bugfix-or-feature + +Finally, browse to your repository fork on GitHub and submit a pull request. Logging tips @@ -160,8 +186,8 @@ For logging messages that are not repeated, use the usual Python way:: logger.warning("A warning with %s formatting", arg_to_be_formatted) Do not format log messages yourself. Use ``%s`` formatting in messages and pass -arguments to logger. This is important, because Pelican logger will preprocess -some arguments (like Exceptions) for Py2/Py3 compatibility. +arguments to logger. This is important, because the Pelican logger will +preprocess some arguments, such as exceptions. Limiting extraneous log messages -------------------------------- From e713407f898f964f927053ffa924edb9adbcc1bb Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sun, 10 Nov 2019 20:08:47 -0800 Subject: [PATCH 06/13] Add Pytest `filterwarnings` config section Fixes #2650 --- tox.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tox.ini b/tox.ini index 15dbaee8..97f3a210 100644 --- a/tox.ini +++ b/tox.ini @@ -29,6 +29,11 @@ changedir = docs commands = sphinx-build -W -b html -d {envtmpdir}/doctrees . _build/html +[pytest] +filterwarnings = + default::DeprecationWarning + error:.*:Warning:pelican + [flake8] application-import-names = pelican import-order-style = cryptography From 2d232d15aae0af895ede1146c0f2810adc8410e1 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sun, 10 Nov 2019 20:10:59 -0800 Subject: [PATCH 07/13] Switch `invoke tests` test runner to Pytest --- tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks.py b/tasks.py index 7d9ff1d9..41ac2bde 100644 --- a/tasks.py +++ b/tasks.py @@ -21,7 +21,7 @@ PRECOMMIT = ( @task def tests(c): """Run the test suite""" - c.run(f"{VENV}/bin/python -Wd -m unittest discover", pty=True) + c.run(f"{VENV}/bin/pytest", pty=True) @task From dad376e0db64e583a2d7d81219c9eef48a7a4cae Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Mon, 11 Nov 2019 13:51:25 -0800 Subject: [PATCH 08/13] Switch Tox test runner from Nose to Pytest --- tox.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index 97f3a210..1c20b282 100644 --- a/tox.ini +++ b/tox.ini @@ -11,14 +11,14 @@ passenv = * usedevelop=True deps = -rrequirements/test.pip - nose - nose-cov + pytest + pytest-cov coveralls pygments==2.1.3 commands = {envpython} --version - nosetests -sv --with-coverage --cover-package=pelican pelican + pytest -sv --cov=pelican pelican - coveralls [testenv:docs] From c0df11ecb80f51d63dd33202fa059727a84d5c29 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Mon, 11 Nov 2019 13:53:14 -0800 Subject: [PATCH 09/13] Remove Coveralls from Tox configuration --- tox.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/tox.ini b/tox.ini index 1c20b282..f975dd59 100644 --- a/tox.ini +++ b/tox.ini @@ -13,13 +13,11 @@ deps = -rrequirements/test.pip pytest pytest-cov - coveralls pygments==2.1.3 commands = {envpython} --version pytest -sv --cov=pelican pelican - - coveralls [testenv:docs] basepython = python3.6 From 703c28108947222e25425f9b798fb0925cbdb89a Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 12 Nov 2019 07:28:55 -0800 Subject: [PATCH 10/13] Add missing colon in Contribute docs --- docs/contribute.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contribute.rst b/docs/contribute.rst index 1e884463..752565f6 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -57,7 +57,7 @@ Development =========== Once Pelican has been set up for local development, create a topic branch for -your bug fix or feature: +your bug fix or feature:: git checkout -b name-of-your-bugfix-or-feature From b7368f919fdfe75dea585e13c5bad3911a34514a Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 12 Nov 2019 07:40:05 -0800 Subject: [PATCH 11/13] Add Invoke task for updating functional test output --- docs/contribute.rst | 9 ++------- tasks.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/contribute.rst b/docs/contribute.rst index 752565f6..2f5ef873 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -86,14 +86,9 @@ output." If you have made changes that affect the HTML output generated by Pelican, and the changes to that output are expected and deemed correct given the nature of your changes, then you should update the output used by the functional tests. To do so, **make sure you have both** ``en_EN.utf8`` **and** -``fr_FR.utf8`` **locales installed**, and then run the following two commands:: +``fr_FR.utf8`` **locales installed**, and then run the following command:: - LC_ALL=en_US.utf8 pelican -o pelican/tests/output/custom/ \ - -s samples/pelican.conf.py samples/content/ - LC_ALL=fr_FR.utf8 pelican -o pelican/tests/output/custom_locale/ \ - -s samples/pelican.conf_FR.py samples/content/ - LC_ALL=en_US.utf8 pelican -o pelican/tests/output/basic/ \ - samples/content/ + invoke update-functional-tests You may also find that some tests are skipped because some dependency (e.g., Pandoc) is not installed. This does not automatically mean that these tests diff --git a/tasks.py b/tasks.py index 41ac2bde..8ecfc467 100644 --- a/tasks.py +++ b/tasks.py @@ -79,3 +79,17 @@ def setup(c): tools(c) c.run(f"{POETRY} install") precommit(c) + + +@task +def update_functional_tests(c): + """Update the generated functional test output""" + c.run( + f"bash -c 'LC_ALL=en_US.utf8 pelican -o {PKG_PATH}/tests/output/custom/ -s samples/pelican.conf.py samples/content/'" + ) + c.run( + f"bash -c 'LC_ALL=fr_FR.utf8 pelican -o {PKG_PATH}/tests/output/custom_locale/ -s samples/pelican.conf_FR.py samples/content/'" + ) + c.run( + f"bash -c 'LC_ALL=en_US.utf8 pelican -o {PKG_PATH}/tests/output/basic/ samples/content/'" + ) From f18429f23a2edc11e91fabea5150c06f20589b08 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 12 Nov 2019 07:45:36 -0800 Subject: [PATCH 12/13] Add Pytest as development dependency --- pyproject.toml | 7 ++++++- requirements/test.pip | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c498ef15..a7afc595 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,9 +46,14 @@ BeautifulSoup4 = "^4.7" lxml = "^4.3" markdown = "~3.1.1" typogrify = "^2.0" -mock = "^3.0" sphinx = "=1.4.9" sphinx_rtd_theme = "^0.4.3" +mock = "^3.0" +pytest = "^5.2" +pytest-cov = "^2.8" +pytest-emoji = "^0.2.0" +pytest-pythonpath = "^0.7.3" +pytest-sugar = "^0.9.2" tox = "^3.13" flake8 = "^3.7" flake8-import-order = "^0.18.1" diff --git a/requirements/test.pip b/requirements/test.pip index ec4ea874..f5d09e4a 100644 --- a/requirements/test.pip +++ b/requirements/test.pip @@ -1,5 +1,6 @@ # Tests mock +pytest # Optional Packages Markdown >= 3.1 From 535df9cd9ce5ac9217828ddf480aca07c822aafe Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 12 Nov 2019 08:36:22 -0800 Subject: [PATCH 13/13] Add Invoke tasks for building and serving docs --- docs/contribute.rst | 12 +++++++----- pyproject.toml | 1 + requirements/docs.pip | 1 + tasks.py | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/docs/contribute.rst b/docs/contribute.rst index 2f5ef873..a96f2d02 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -105,13 +105,15 @@ environments. Building the docs ----------------- -If you make changes to the documentation, you should preview your changes -before committing them:: +If you make changes to the documentation, you should build and inspect your +changes before committing them:: - cd docs - make html + invoke docserve -Open ``_build/html/index.html`` in your browser to preview the documentation. +Open http://localhost:8000 in your browser to review the documentation. While +the above task is running, any changes you make and save to the documentation +should automatically appear in the browser, as it live-reloads when it detects +changes to the documentation source files. Plugin development ------------------ diff --git a/pyproject.toml b/pyproject.toml index a7afc595..8b9db0c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,7 @@ markdown = "~3.1.1" typogrify = "^2.0" sphinx = "=1.4.9" sphinx_rtd_theme = "^0.4.3" +livereload = "^2.6" mock = "^3.0" pytest = "^5.2" pytest-cov = "^2.8" diff --git a/requirements/docs.pip b/requirements/docs.pip index 525bdc40..acc5d5f5 100644 --- a/requirements/docs.pip +++ b/requirements/docs.pip @@ -1,2 +1,3 @@ sphinx==1.4.9 sphinx_rtd_theme +livereload diff --git a/tasks.py b/tasks.py index 8ecfc467..42642e6a 100644 --- a/tasks.py +++ b/tasks.py @@ -6,6 +6,7 @@ from invoke import task PKG_NAME = "pelican" PKG_PATH = Path("pelican") +DOCS_PORT = os.environ.get("DOCS_PORT", 8000) ACTIVE_VENV = os.environ.get("VIRTUAL_ENV", None) VENV_HOME = Path(os.environ.get("WORKON_HOME", "~/virtualenvs")) VENV_PATH = Path(ACTIVE_VENV) if ACTIVE_VENV else (VENV_HOME / PKG_NAME) @@ -18,6 +19,24 @@ PRECOMMIT = ( ) +@task +def docbuild(c): + """Build documentation""" + c.run(f"{VENV}/bin/sphinx-build docs docs/_build") + + +@task(docbuild) +def docserve(c): + """Serve docs at http://localhost:$DOCS_PORT/ (default port is 8000)""" + from livereload import Server + + server = Server() + server.watch("docs/conf.py", lambda: docbuild(c)) + server.watch("CONTRIBUTING.rst", lambda: docbuild(c)) + server.watch("docs/*.rst", lambda: docbuild(c)) + server.serve(port=DOCS_PORT, root="docs/_build") + + @task def tests(c): """Run the test suite"""