From 1cb3a11ae8a104181e664c4354a2d5bbce369216 Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Thu, 18 Aug 2022 21:40:00 -0700 Subject: [PATCH 01/12] fix: test: remove more py2 cruft from doctesting (py3.10 warnings) Signed-off-by: Stephen L Arnold --- pystache/tests/doctesting.py | 49 +++--------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/pystache/tests/doctesting.py b/pystache/tests/doctesting.py index 9615217b..6b5e18d2 100644 --- a/pystache/tests/doctesting.py +++ b/pystache/tests/doctesting.py @@ -11,16 +11,11 @@ import sys import traceback -# if sys.version_info >= (3,): -# # Then pull in modules needed for 2to3 conversion. The modules -# # below are not necessarily available in older versions of Python. -# from lib2to3.main import main as lib2to3main # new in Python 2.6? -# from shutil import copyfile - from pystache.tests.common import TEXT_DOCTEST_PATHS from pystache.tests.common import get_module_names - +# This module is now a stub due to py 3.10 warnings - 18 Aug 2022 +# # This module follows the guidance documented here: # # http://docs.python.org/library/doctest.html#unittest-api @@ -41,15 +36,9 @@ def get_doctests(text_file_dir): # # http://docs.python.org/library/doctest.html#doctest.DocFileSuite # - paths = [os.path.normpath(os.path.join(text_file_dir, path)) for path in TEXT_DOCTEST_PATHS] - - if sys.version_info >= (3,): - # Skip the README doctests in Python 3 for now because examples - # rendering to unicode do not give consistent results - # (e.g. 'foo' vs u'foo'). - # paths = _convert_paths(paths) - paths = [] + # paths = [os.path.normpath(os.path.join(text_file_dir, path)) for path in TEXT_DOCTEST_PATHS] + paths = [] suites = [] for path in paths: @@ -62,33 +51,3 @@ def get_doctests(text_file_dir): suites.append(suite) return suites - - -def _convert_2to3(path): - """ - Convert the given file, and return the path to the converted files. - - """ - base, ext = os.path.splitext(path) - # For example, "README.temp2to3.rst". - new_path = "%s.temp2to3%s" % (base, ext) - - copyfile(path, new_path) - - args = ['--doctests_only', '--no-diffs', '--write', '--nobackups', new_path] - lib2to3main("lib2to3.fixes", args=args) - - return new_path - - -def _convert_paths(paths): - """ - Convert the given files, and return the paths to the converted files. - - """ - new_paths = [] - for path in paths: - new_path = _convert_2to3(path) - new_paths.append(new_path) - - return new_paths From faa500c8da5c83045321877390df9b213f32c745 Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Sun, 11 Sep 2022 22:43:52 -0700 Subject: [PATCH 02/12] fix: dev: cleanup imports/packaging, remove archaic doc processing * update/simplify setup and packaging files, migrate tool configs * add versioningit to build deps, update __init__.py * remove readme doc processing, prep for readme conversion * global import cleanup, add isort tox cmd * update .pre-commit-config.yaml and coverage.yml Signed-off-by: Stephen L Arnold --- .coveragerc | 38 - .github/workflows/coverage.yml | 4 +- .gitignore | 3 +- .pre-commit-config.yaml | 15 +- .pylintrc | 2 +- bandit_baseline.json | 682 ------------------ pyproject.toml | 48 +- pystache/__init__.py | 8 +- pystache/commands/render.py | 3 +- pystache/context.py | 1 - pystache/defaults.py | 1 - pystache/loader.py | 4 +- pystache/locator.py | 2 +- pystache/parser.py | 1 - pystache/renderer.py | 8 +- pystache/tests/data/views.py | 1 + pystache/tests/doctesting.py | 3 +- pystache/tests/examples/inverted.py | 1 + pystache/tests/examples/lambdas.py | 1 + pystache/tests/examples/nested_context.py | 1 + .../tests/examples/partials_with_lambdas.py | 1 + pystache/tests/examples/simple.py | 1 + pystache/tests/examples/template_partial.py | 1 + pystache/tests/examples/unicode_input.py | 1 + pystache/tests/main.py | 10 +- pystache/tests/test___init__.py | 1 + pystache/tests/test_commands.py | 1 - pystache/tests/test_context.py | 17 +- pystache/tests/test_defaults.py | 1 - pystache/tests/test_examples.py | 14 +- pystache/tests/test_loader.py | 7 +- pystache/tests/test_locator.py | 10 +- pystache/tests/test_pystache.py | 3 +- pystache/tests/test_renderengine.py | 10 +- pystache/tests/test_renderer.py | 13 +- pystache/tests/test_simple.py | 9 +- pystache/tests/test_specloader.py | 27 +- setup.cfg | 22 +- setup.py | 292 +------- setup_description.rst | 560 -------------- tox.ini | 60 +- 41 files changed, 216 insertions(+), 1672 deletions(-) delete mode 100644 .coveragerc delete mode 100644 bandit_baseline.json delete mode 100644 setup_description.rst diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 2678dd77..00000000 --- a/.coveragerc +++ /dev/null @@ -1,38 +0,0 @@ -# .coveragerc to control coverage.py -[run] -branch = True - -source = pystache - -omit = - .tox/* - setup.py - pystache/tests/* - -plugins = - coverage_python_version - -[report] -# must set this to True to see missing -show_missing = True - -# Regexes for lines to exclude from consideration -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about missing debug-only code: - def __repr__ - if self\.debug - - # Don't complain if tests don't hit defensive assertion code: - raise AssertionError - raise NotImplementedError - - # Don't complain if non-runnable code isn't run: - if 0: - -ignore_errors = True - -[html] -directory = coverage diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 4e9b030d..4662b614 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -152,7 +152,7 @@ jobs: tox -e py - name: Code Coverage Summary Report (data) - uses: irongut/CodeCoverageSummary@v1.1.0 + uses: irongut/CodeCoverageSummary@v1.2.0 with: filename: coverage.xml output: 'both' @@ -176,7 +176,7 @@ jobs: echo "Current coverage is: ${COVERAGE}%" - name: Code Coverage Summary Report - uses: irongut/CodeCoverageSummary@v1.1.0 + uses: irongut/CodeCoverageSummary@v1.2.0 if: ${{ github.event_name == 'pull_request' }} with: filename: coverage.xml diff --git a/.gitignore b/.gitignore index e44990cc..d0101368 100644 --- a/.gitignore +++ b/.gitignore @@ -11,9 +11,10 @@ # TextMate project file *.tmproj # Distribution-related folders and files. +pystache/_version.py +pystache.egg-info build dist MANIFEST -pystache.egg-info coverage.xml .coverage diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3366751c..f5f3d9a0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: - id: check-useless-excludes - id: check-hooks-apply - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.3.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -17,7 +17,6 @@ repos: - id: mixed-line-ending args: [--fix=lf] - id: check-toml - - id: check-json - id: check-yaml exclude: '(conda/meta.yaml|.pep8speaks.yml)' @@ -40,7 +39,7 @@ repos: # exclude: '(.*tests/.*|.*test.py$|^setup.py$|^test_pystache.py$)' - repo: "https://github.com/asottile/blacken-docs" - rev: "v1.11.0" + rev: "v1.12.1" hooks: - id: "blacken-docs" name: "Format docs (blacken-docs)" @@ -49,7 +48,7 @@ repos: - "black==21.9b0" - repo: https://github.com/PyCQA/doc8 - rev: 0.9.1 + rev: v1.0.0 hooks: - id: doc8 args: @@ -65,7 +64,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/myint/autoflake - rev: v1.4 + rev: v1.5.3 hooks: - id: autoflake exclude: '(.*tests/.*|.*test.py$|^setup.py$|^test_.*.py$)' @@ -83,13 +82,13 @@ repos: additional_dependencies: ["flake8-bugbear"] - repo: https://github.com/PyCQA/bandit - rev: 1.7.0 + rev: 1.7.4 hooks: - id: bandit - args: ["-ll", "-b", "bandit_baseline.json"] + args: ["-ll", "-x", "pystache/tests"] - repo: https://github.com/PyCQA/pylint - rev: v2.11.1 + rev: v2.15.2 hooks: - id: pylint exclude: '(.*tests/.*|.*test.py$|^setup.py$|^test_.*.py$)' diff --git a/.pylintrc b/.pylintrc index 69c84a9a..c2091e52 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,6 +1,6 @@ # https://github.com/cmheisel/pylintrcs/blob/master/pylintrc [MASTER] -#ignore=pystache/tests +ignore=_version.py ignore-paths= .*tests/, diff --git a/bandit_baseline.json b/bandit_baseline.json deleted file mode 100644 index 93fd1c8b..00000000 --- a/bandit_baseline.json +++ /dev/null @@ -1,682 +0,0 @@ -{ - "errors": [], - "generated_at": "2021-10-09T22:51:02Z", - "metrics": { - "_totals": { - "CONFIDENCE.HIGH": 1.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 1.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 4377, - "nosec": 0 - }, - "pystache/__init__.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 6, - "nosec": 0 - }, - "pystache/commands/__init__.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 3, - "nosec": 0 - }, - "pystache/commands/render.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 41, - "nosec": 0 - }, - "pystache/commands/test.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 9, - "nosec": 0 - }, - "pystache/common.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 33, - "nosec": 0 - }, - "pystache/context.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 218, - "nosec": 0 - }, - "pystache/defaults.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 20, - "nosec": 0 - }, - "pystache/init.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 12, - "nosec": 0 - }, - "pystache/loader.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 114, - "nosec": 0 - }, - "pystache/locator.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 113, - "nosec": 0 - }, - "pystache/parsed.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 33, - "nosec": 0 - }, - "pystache/parser.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 252, - "nosec": 0 - }, - "pystache/renderengine.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 114, - "nosec": 0 - }, - "pystache/renderer.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 331, - "nosec": 0 - }, - "pystache/specloader.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 55, - "nosec": 0 - }, - "pystache/template_spec.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 35, - "nosec": 0 - }, - "pystache/tests/__init__.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 3, - "nosec": 0 - }, - "pystache/tests/benchmark.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 71, - "nosec": 0 - }, - "pystache/tests/common.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 151, - "nosec": 0 - }, - "pystache/tests/data/__init__.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 3, - "nosec": 0 - }, - "pystache/tests/data/locator/__init__.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 3, - "nosec": 0 - }, - "pystache/tests/data/views.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 11, - "nosec": 0 - }, - "pystache/tests/doctesting.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 51, - "nosec": 0 - }, - "pystache/tests/examples/__init__.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 3, - "nosec": 0 - }, - "pystache/tests/examples/comments.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 6, - "nosec": 0 - }, - "pystache/tests/examples/complex.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 18, - "nosec": 0 - }, - "pystache/tests/examples/delimiters.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 10, - "nosec": 0 - }, - "pystache/tests/examples/double_section.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 8, - "nosec": 0 - }, - "pystache/tests/examples/escaped.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 6, - "nosec": 0 - }, - "pystache/tests/examples/inverted.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 21, - "nosec": 0 - }, - "pystache/tests/examples/lambdas.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 26, - "nosec": 0 - }, - "pystache/tests/examples/nested_context.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 21, - "nosec": 0 - }, - "pystache/tests/examples/partials_with_lambdas.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 7, - "nosec": 0 - }, - "pystache/tests/examples/readme.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 6, - "nosec": 0 - }, - "pystache/tests/examples/simple.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 9, - "nosec": 0 - }, - "pystache/tests/examples/template_partial.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 17, - "nosec": 0 - }, - "pystache/tests/examples/unescaped.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 6, - "nosec": 0 - }, - "pystache/tests/examples/unicode_input.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 8, - "nosec": 0 - }, - "pystache/tests/examples/unicode_output.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 6, - "nosec": 0 - }, - "pystache/tests/main.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 89, - "nosec": 0 - }, - "pystache/tests/spectesting.py": { - "CONFIDENCE.HIGH": 1.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 1.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 161, - "nosec": 0 - }, - "pystache/tests/test___init__.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 22, - "nosec": 0 - }, - "pystache/tests/test_commands.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 27, - "nosec": 0 - }, - "pystache/tests/test_context.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 344, - "nosec": 0 - }, - "pystache/tests/test_defaults.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 49, - "nosec": 0 - }, - "pystache/tests/test_examples.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 76, - "nosec": 0 - }, - "pystache/tests/test_loader.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 141, - "nosec": 0 - }, - "pystache/tests/test_locator.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 109, - "nosec": 0 - }, - "pystache/tests/test_parser.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 15, - "nosec": 0 - }, - "pystache/tests/test_pystache.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 93, - "nosec": 0 - }, - "pystache/tests/test_renderengine.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 526, - "nosec": 0 - }, - "pystache/tests/test_renderer.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 505, - "nosec": 0 - }, - "pystache/tests/test_simple.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 57, - "nosec": 0 - }, - "pystache/tests/test_specloader.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 303, - "nosec": 0 - } - }, - "results": [ - { - "code": "239 # ast.literal_eval will not work here => lambda expression\n240 return eval(value['python'], {})\n241 \n", - "filename": "pystache/tests/spectesting.py", - "issue_confidence": "HIGH", - "issue_severity": "MEDIUM", - "issue_text": "Use of possibly insecure function - consider using safer ast.literal_eval.", - "line_number": 240, - "line_range": [ - 240 - ], - "more_info": "https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html#b307-eval", - "test_id": "B307", - "test_name": "blacklist" - } - ] -} diff --git a/pyproject.toml b/pyproject.toml index 29a7bcd0..1f1eb68b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,42 @@ [build-system] -requires = ["setuptools>=40.8.0", "wheel"] +requires = [ + "setuptools>=42", + "versioningit >= 1.1.1", +] + build-backend = "setuptools.build_meta" +[tool.pytest.ini_options] +minversion = "6.0" +testpaths = ["pystache/tests",] +log_cli = false +doctest_optionflags = ["ELLIPSIS", "NORMALIZE_WHITESPACE",] +addopts = "--strict-markers" +markers = "subscript" + [tool.coverage.run] branch = true source = ["pystache"] - +plugins = ["coverage_python_version"] +omit = [ + "pystache/tests/*", + "setup.py", + ".tox", +] [tool.coverage.paths] source = ["pystache"] [tool.coverage.report] fail_under = 95 show_missing = true +ignore_errors = true +exclude_lines = [ + "pragma: no cover", + "raise NotImplementedError", + "raise AssertionError", + "if typing.TYPE_CHECKING:", + "if TYPE_CHECKING:", +] [tool.black] line-length = 110 @@ -31,3 +56,22 @@ exclude = ''' | pystache/tests )/ ''' + +[tool.isort] +line_length = 72 +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +ensure_newline_before_comments = true + +[tool.versioningit.next-version] +method = "smallest" + +[tool.versioningit.format] +distance = "{next_version}.dev{distance}" +dirty = "{version}+d{build_date:%Y%m%d}" +distance-dirty = "{next_version}.dev{distance}" + +[tool.versioningit.write] +file = "pystache/_version.py" diff --git a/pystache/__init__.py b/pystache/__init__.py index f98dc1f2..13414bf0 100644 --- a/pystache/__init__.py +++ b/pystache/__init__.py @@ -5,8 +5,10 @@ # We keep all initialization code in a separate module. -from pystache.init import parse, render, Renderer, TemplateSpec +from pystache.init import Renderer, TemplateSpec, parse, render -__all__ = ['parse', 'render', 'Renderer', 'TemplateSpec'] +from ._version import __version__ -__version__ = '0.6.0' +version = __version__ + +__all__ = ['parse', 'render', 'Renderer', 'TemplateSpec', 'version'] diff --git a/pystache/commands/render.py b/pystache/commands/render.py index 3fb6ddd3..3cd98c13 100644 --- a/pystache/commands/render.py +++ b/pystache/commands/render.py @@ -8,12 +8,12 @@ """ import json +import sys # TODO: switch to argparse already, sheesh... # The optparse module is deprecated in Python 2.7 in favor of argparse. # However, argparse is not available in Python 2.6 and earlier. from optparse import OptionParser -import sys # We use absolute imports here to allow use of this script from its # location in source control (e.g. for development purposes). @@ -24,7 +24,6 @@ from pystache.common import TemplateNotFoundError from pystache.renderer import Renderer - USAGE = """\ %prog [-h] template context diff --git a/pystache/context.py b/pystache/context.py index 84417760..20e1e5d3 100644 --- a/pystache/context.py +++ b/pystache/context.py @@ -16,7 +16,6 @@ from pystache.common import PystacheError - # This equals '__builtin__' in Python 2 and 'builtins' in Python 3. _BUILTIN_MODULE = type(0).__module__ diff --git a/pystache/defaults.py b/pystache/defaults.py index ba9fba12..7d13fcc4 100644 --- a/pystache/defaults.py +++ b/pystache/defaults.py @@ -19,7 +19,6 @@ from pystache.common import MissingTags - # How to handle encoding errors when decoding strings from str to unicode. # # This value is passed as the "errors" argument to Python's built-in diff --git a/pystache/loader.py b/pystache/loader.py index 570b608c..6607c45b 100644 --- a/pystache/loader.py +++ b/pystache/loader.py @@ -7,11 +7,9 @@ import platform -from pystache import common -from pystache import defaults +from pystache import common, defaults from pystache.locator import Locator - # We make a function so that the current defaults take effect. # TODO: revisit whether this is necessary. diff --git a/pystache/locator.py b/pystache/locator.py index 85981f2d..34155ba8 100644 --- a/pystache/locator.py +++ b/pystache/locator.py @@ -9,8 +9,8 @@ import re import sys -from pystache.common import TemplateNotFoundError from pystache import defaults +from pystache.common import TemplateNotFoundError class Locator(object): diff --git a/pystache/parser.py b/pystache/parser.py index a33bee85..e6d6f33e 100644 --- a/pystache/parser.py +++ b/pystache/parser.py @@ -10,7 +10,6 @@ from pystache import defaults from pystache.parsed import ParsedTemplate - END_OF_LINE_CHARACTERS = ['\r', '\n'] NON_BLANK_RE = re.compile(r'^(.)', re.M) diff --git a/pystache/renderer.py b/pystache/renderer.py index bb979f17..92d68c8c 100644 --- a/pystache/renderer.py +++ b/pystache/renderer.py @@ -7,11 +7,15 @@ from pystache import defaults -from pystache.common import TemplateNotFoundError, MissingTags, is_string +from pystache.common import ( + MissingTags, + TemplateNotFoundError, + is_string, +) from pystache.context import ContextStack, KeyNotFoundError from pystache.loader import Loader from pystache.parsed import ParsedTemplate -from pystache.renderengine import context_get, RenderEngine +from pystache.renderengine import RenderEngine, context_get from pystache.specloader import SpecLoader from pystache.template_spec import TemplateSpec diff --git a/pystache/tests/data/views.py b/pystache/tests/data/views.py index 0b963093..457df0f1 100644 --- a/pystache/tests/data/views.py +++ b/pystache/tests/data/views.py @@ -7,6 +7,7 @@ from pystache import TemplateSpec + class SayHello(object): def to(self): diff --git a/pystache/tests/doctesting.py b/pystache/tests/doctesting.py index 6b5e18d2..f6162dc8 100644 --- a/pystache/tests/doctesting.py +++ b/pystache/tests/doctesting.py @@ -11,8 +11,7 @@ import sys import traceback -from pystache.tests.common import TEXT_DOCTEST_PATHS -from pystache.tests.common import get_module_names +from pystache.tests.common import TEXT_DOCTEST_PATHS, get_module_names # This module is now a stub due to py 3.10 warnings - 18 Aug 2022 # diff --git a/pystache/tests/examples/inverted.py b/pystache/tests/examples/inverted.py index 12212b49..d73c625c 100644 --- a/pystache/tests/examples/inverted.py +++ b/pystache/tests/examples/inverted.py @@ -6,6 +6,7 @@ from pystache import TemplateSpec + class Inverted(object): def t(self): diff --git a/pystache/tests/examples/lambdas.py b/pystache/tests/examples/lambdas.py index 3bc08ff3..3712b0d2 100644 --- a/pystache/tests/examples/lambdas.py +++ b/pystache/tests/examples/lambdas.py @@ -6,6 +6,7 @@ from pystache import TemplateSpec + def rot(s, n=13): r = "" for c in s: diff --git a/pystache/tests/examples/nested_context.py b/pystache/tests/examples/nested_context.py index a2661b9c..5bf6d49e 100644 --- a/pystache/tests/examples/nested_context.py +++ b/pystache/tests/examples/nested_context.py @@ -6,6 +6,7 @@ from pystache import TemplateSpec + class NestedContext(TemplateSpec): def __init__(self, renderer): diff --git a/pystache/tests/examples/partials_with_lambdas.py b/pystache/tests/examples/partials_with_lambdas.py index 638aa363..c6e0f9ad 100644 --- a/pystache/tests/examples/partials_with_lambdas.py +++ b/pystache/tests/examples/partials_with_lambdas.py @@ -6,6 +6,7 @@ from pystache.tests.examples.lambdas import rot + class PartialsWithLambdas(object): def rot(self): diff --git a/pystache/tests/examples/simple.py b/pystache/tests/examples/simple.py index ea82e9d0..e1c9db35 100644 --- a/pystache/tests/examples/simple.py +++ b/pystache/tests/examples/simple.py @@ -6,6 +6,7 @@ from pystache import TemplateSpec + class Simple(TemplateSpec): def thing(self): diff --git a/pystache/tests/examples/template_partial.py b/pystache/tests/examples/template_partial.py index 1c4d1a01..b8a341fb 100644 --- a/pystache/tests/examples/template_partial.py +++ b/pystache/tests/examples/template_partial.py @@ -6,6 +6,7 @@ from pystache import TemplateSpec + class TemplatePartial(TemplateSpec): def __init__(self, renderer): diff --git a/pystache/tests/examples/unicode_input.py b/pystache/tests/examples/unicode_input.py index d0457575..70b427fd 100644 --- a/pystache/tests/examples/unicode_input.py +++ b/pystache/tests/examples/unicode_input.py @@ -6,6 +6,7 @@ from pystache import TemplateSpec + class UnicodeInput(TemplateSpec): template_encoding = 'utf8' diff --git a/pystache/tests/main.py b/pystache/tests/main.py index 17f2fb28..cb87904c 100644 --- a/pystache/tests/main.py +++ b/pystache/tests/main.py @@ -13,12 +13,16 @@ from unittest import TestCase, TestProgram import pystache -from pystache.tests.common import PACKAGE_DIR, PROJECT_DIR, UNITTEST_FILE_PREFIX -from pystache.tests.common import get_module_names, get_spec_test_dir +from pystache.tests.common import ( + PACKAGE_DIR, + PROJECT_DIR, + UNITTEST_FILE_PREFIX, + get_module_names, + get_spec_test_dir, +) from pystache.tests.doctesting import get_doctests from pystache.tests.spectesting import get_spec_tests - # If this command option is present, then the spec test and doctest directories # will be inserted if not provided. FROM_SOURCE_OPTION = "--from-source" diff --git a/pystache/tests/test___init__.py b/pystache/tests/test___init__.py index 63d2c3bf..ca8ff669 100644 --- a/pystache/tests/test___init__.py +++ b/pystache/tests/test___init__.py @@ -8,6 +8,7 @@ # Calling "import *" is allowed only at the module level. GLOBALS_INITIAL = list(globals().keys()) from pystache import * + GLOBALS_PYSTACHE_IMPORTED = list(globals().keys()) import unittest diff --git a/pystache/tests/test_commands.py b/pystache/tests/test_commands.py index 34fe8ba2..7c55b9ae 100644 --- a/pystache/tests/test_commands.py +++ b/pystache/tests/test_commands.py @@ -10,7 +10,6 @@ from pystache.commands.render import main - ORIGINAL_STDOUT = sys.stdout diff --git a/pystache/tests/test_context.py b/pystache/tests/test_context.py index 238e4b00..c995f34a 100644 --- a/pystache/tests/test_context.py +++ b/pystache/tests/test_context.py @@ -5,11 +5,22 @@ """ -from datetime import datetime import unittest +from datetime import datetime + +from pystache.context import ( + _NOT_FOUND, + ContextStack, + KeyNotFoundError, + _get_value, +) +from pystache.tests.common import ( + AssertExceptionMixin, + AssertIsMixin, + AssertStringMixin, + Attachable, +) -from pystache.context import _NOT_FOUND, _get_value, KeyNotFoundError, ContextStack -from pystache.tests.common import AssertIsMixin, AssertStringMixin, AssertExceptionMixin, Attachable class SimpleObject(object): diff --git a/pystache/tests/test_defaults.py b/pystache/tests/test_defaults.py index 5399bb03..6f0474e5 100644 --- a/pystache/tests/test_defaults.py +++ b/pystache/tests/test_defaults.py @@ -8,7 +8,6 @@ import unittest import pystache - from pystache.tests.common import AssertStringMixin diff --git a/pystache/tests/test_examples.py b/pystache/tests/test_examples.py index 9f93de30..1b090d94 100644 --- a/pystache/tests/test_examples.py +++ b/pystache/tests/test_examples.py @@ -7,18 +7,18 @@ import unittest +from pystache import Renderer +from pystache.tests.common import EXAMPLES_DIR, AssertStringMixin + from .examples.comments import Comments +from .examples.delimiters import Delimiters from .examples.double_section import DoubleSection from .examples.escaped import Escaped -from .examples.unescaped import Unescaped +from .examples.nested_context import NestedContext from .examples.template_partial import TemplatePartial -from .examples.delimiters import Delimiters -from .examples.unicode_output import UnicodeOutput +from .examples.unescaped import Unescaped from .examples.unicode_input import UnicodeInput -from .examples.nested_context import NestedContext -from pystache import Renderer -from pystache.tests.common import EXAMPLES_DIR -from pystache.tests.common import AssertStringMixin +from .examples.unicode_output import UnicodeOutput class TestView(unittest.TestCase, AssertStringMixin): diff --git a/pystache/tests/test_loader.py b/pystache/tests/test_loader.py index c2f382b5..f5afe3e9 100644 --- a/pystache/tests/test_loader.py +++ b/pystache/tests/test_loader.py @@ -9,10 +9,13 @@ import sys import unittest -from pystache.tests.common import AssertStringMixin, DATA_DIR, SetupDefaults from pystache import defaults from pystache.loader import Loader - +from pystache.tests.common import ( + DATA_DIR, + AssertStringMixin, + SetupDefaults, +) # We use the same directory as the locator tests for now. LOADER_DATA_DIR = os.path.join(DATA_DIR, 'locator') diff --git a/pystache/tests/test_locator.py b/pystache/tests/test_locator.py index ee1c2ff8..281b7b20 100644 --- a/pystache/tests/test_locator.py +++ b/pystache/tests/test_locator.py @@ -5,20 +5,22 @@ """ -from datetime import datetime import os import sys import unittest +from datetime import datetime # TODO: remove this alias. from pystache.common import TemplateNotFoundError from pystache.loader import Loader as Reader from pystache.locator import Locator - -from pystache.tests.common import DATA_DIR, EXAMPLES_DIR, AssertExceptionMixin +from pystache.tests.common import ( + DATA_DIR, + EXAMPLES_DIR, + AssertExceptionMixin, +) from pystache.tests.data.views import SayHello - LOCATOR_DATA_DIR = os.path.join(DATA_DIR, 'locator') diff --git a/pystache/tests/test_pystache.py b/pystache/tests/test_pystache.py index cf5d6afd..db24b152 100644 --- a/pystache/tests/test_pystache.py +++ b/pystache/tests/test_pystache.py @@ -3,8 +3,7 @@ import unittest import pystache -from pystache import defaults -from pystache import renderer +from pystache import defaults, renderer from pystache.tests.common import html_escape diff --git a/pystache/tests/test_renderengine.py b/pystache/tests/test_renderengine.py index ed604c59..295d9e39 100644 --- a/pystache/tests/test_renderengine.py +++ b/pystache/tests/test_renderengine.py @@ -8,12 +8,16 @@ import sys import unittest -from pystache.context import ContextStack, KeyNotFoundError from pystache import defaults +from pystache.context import ContextStack, KeyNotFoundError from pystache.parser import ParsingError +from pystache.renderengine import RenderEngine, context_get from pystache.renderer import Renderer -from pystache.renderengine import context_get, RenderEngine -from pystache.tests.common import AssertStringMixin, AssertExceptionMixin, Attachable +from pystache.tests.common import ( + AssertExceptionMixin, + AssertStringMixin, + Attachable, +) def _get_unicode_char(): diff --git a/pystache/tests/test_renderer.py b/pystache/tests/test_renderer.py index e0d2448e..9e47b513 100644 --- a/pystache/tests/test_renderer.py +++ b/pystache/tests/test_renderer.py @@ -10,16 +10,19 @@ import sys import unittest -from .examples.simple import Simple -from pystache import Renderer -from pystache import TemplateSpec +from pystache import Renderer, TemplateSpec from pystache.common import TemplateNotFoundError from pystache.context import ContextStack, KeyNotFoundError from pystache.loader import Loader - -from pystache.tests.common import get_data_path, AssertStringMixin, AssertExceptionMixin +from pystache.tests.common import ( + AssertExceptionMixin, + AssertStringMixin, + get_data_path, +) from pystache.tests.data.views import SayHello +from .examples.simple import Simple + def _make_renderer(): """ diff --git a/pystache/tests/test_simple.py b/pystache/tests/test_simple.py index b88bf35e..c771c588 100644 --- a/pystache/tests/test_simple.py +++ b/pystache/tests/test_simple.py @@ -2,14 +2,13 @@ import pystache from pystache import Renderer -from .examples.nested_context import NestedContext +from pystache.tests.common import EXAMPLES_DIR, AssertStringMixin + from .examples.complex import Complex from .examples.lambdas import Lambdas -from .examples.template_partial import TemplatePartial +from .examples.nested_context import NestedContext from .examples.simple import Simple - -from pystache.tests.common import EXAMPLES_DIR -from pystache.tests.common import AssertStringMixin +from .examples.template_partial import TemplatePartial class TestSimple(unittest.TestCase, AssertStringMixin): diff --git a/pystache/tests/test_specloader.py b/pystache/tests/test_specloader.py index dcdc55f5..6eaf1deb 100644 --- a/pystache/tests/test_specloader.py +++ b/pystache/tests/test_specloader.py @@ -9,21 +9,24 @@ import sys import unittest -from . import examples -from .examples.simple import Simple -from .examples.complex import Complex -from .examples.lambdas import Lambdas -from .examples.inverted import Inverted, InvertedLists -from pystache import Renderer -from pystache import TemplateSpec +from pystache import Renderer, TemplateSpec from pystache.common import TemplateNotFoundError -from pystache.locator import Locator from pystache.loader import Loader +from pystache.locator import Locator from pystache.specloader import SpecLoader -from pystache.tests.common import DATA_DIR, EXAMPLES_DIR -from pystache.tests.common import AssertIsMixin, AssertStringMixin -from pystache.tests.data.views import SampleView -from pystache.tests.data.views import NonAscii +from pystache.tests.common import ( + DATA_DIR, + EXAMPLES_DIR, + AssertIsMixin, + AssertStringMixin, +) +from pystache.tests.data.views import NonAscii, SampleView + +from . import examples +from .examples.complex import Complex +from .examples.inverted import Inverted, InvertedLists +from .examples.lambdas import Lambdas +from .examples.simple import Simple class Thing(object): diff --git a/setup.cfg b/setup.cfg index c61f2074..b39fdd7f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,6 +6,8 @@ author_email = chris@ozmm.org maintainer = Thomas David Baker maintainer_email = bakert@gmail.com description = Mustache for Python +long_description = file: README.md +long_description_content_type = text/markdown url = https://github.com/PennyDreadfulMTG/pystache license = MIT license_files = LICENSE @@ -18,6 +20,7 @@ classifiers = Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 [options] python_requires = >=3.6 @@ -42,20 +45,31 @@ cov = coverage coverage_python_version +doc = + sphinx + recommonmark + sphinx_rtd_theme + sphinxcontrib-apidoc + +all = + %(cov)s + %(doc)s + %(test)s + [check] metadata = true restructuredtext = true strict = false -[bdist_wheel] -universal = 0 - [check-manifest] ignore = - .codeclimate.yml + .gitchangelog.rc .gitattributes .coveragerc .gitignore + .gitmodules .pep8speaks.yml + .pre-commit-config.yaml + .pylintrc coverage* conda/** diff --git a/setup.py b/setup.py index cffd44b8..bac24a43 100644 --- a/setup.py +++ b/setup.py @@ -1,292 +1,6 @@ #!/usr/bin/env python -# coding: utf-8 -""" -This script supports publishing Pystache to PyPI. +import setuptools -This docstring contains instructions to Pystache maintainers on how -to release a new version of Pystache. - -(1) Prepare the release. - -Make sure the code is finalized and merged to master. Bump the version -number in setup.py, update the release date in the HISTORY file, etc. - -Generate the reStructuredText long_description using-- - - $ python setup.py prep - -and be sure this new version is checked in. You must have pandoc installed -to do this step: - - http://johnmacfarlane.net/pandoc/ - -It helps to review this auto-generated file on GitHub prior to uploading -because the long description will be sent to PyPI and appear there after -publishing. PyPI attempts to convert this string to HTML before displaying -it on the PyPI project page. If PyPI finds any issues, it will render it -instead as plain-text, which we do not want. - -To check in advance that PyPI will accept and parse the reST file as HTML, -you can use the rst2html.py program installed by the docutils package -(http://docutils.sourceforge.net/). To install docutils: - - $ pip install docutils - -To check the file, run the following command and confirm that it reports -no warnings: - - $ python setup.py --long-description | rst2html.py -v --no-raw > out.html - -See here for more information: - - http://docs.python.org/distutils/uploading.html#pypi-package-display - -(2) Push to PyPI. To release a new version of Pystache to PyPI-- - - http://pypi.python.org/pypi/pystache - -create a PyPI user account if you do not already have one. The user account -will need permissions to push to PyPI. A current "Package Index Owner" of -Pystache can grant you those permissions. - -When you have permissions, run the following: - - python setup.py publish - -If you get an error like the following-- - - Upload failed (401): You must be identified to edit package information - -then add a file called .pyirc to your home directory with the following -contents: - - [server-login] - username: - password: - -as described here, for example: - - http://docs.python.org/release/2.5.2/dist/pypirc.html - -(3) Tag the release on GitHub. Here are some commands for tagging. - -List current tags: - - git tag -l -n3 - -Create an annotated tag: - - git tag -a -m "Version 0.5.1" "v0.5.1" - -Push a tag to GitHub: - - git push --tags defunkt v0.5.1 - -""" - -import os -import sys -import subprocess as sp - -from setuptools import setup -from shlex import split - -FILE_ENCODING = 'utf-8' - -README_PATH = 'README.md' -HISTORY_PATH = 'HISTORY.md' -LICENSE_PATH = 'LICENSE' - -RST_DESCRIPTION_PATH = 'setup_description.rst' - -TEMP_EXTENSION = '.temp' - -PREP_COMMAND = 'prep' - -# Comments in reST begin with two dots. -RST_LONG_DESCRIPTION_INTRO = """\ -.. Do not edit this file. This file is auto-generated for PyPI by setup.py -.. using pandoc, so edits should go in the source files rather than here. -""" - - -def read(path): - """ - Read and return the contents of a text file as a unicode string. - - """ - # This function implementation was chosen to be compatible across Python 2/3. - f = open(path, 'rb') - # We avoid use of the with keyword for Python 2.4 support. - try: - b = f.read() - finally: - f.close() - - return b.decode(FILE_ENCODING) - - -def write(u, path): - """ - Write a unicode string to a file (as utf-8). - - """ - print(("writing to: %s" % path)) - # This function implementation was chosen to be compatible across Python 2/3. - f = open(path, "wb") - try: - b = u.encode(FILE_ENCODING) - f.write(b) - finally: - f.close() - - -def make_temp_path(path, new_ext=None): - """ - Arguments: - - new_ext: the new file extension, including the leading dot. - Defaults to preserving the existing file extension. - - """ - root, ext = os.path.splitext(path) - if new_ext is None: - new_ext = ext - temp_path = root + TEMP_EXTENSION + new_ext - return temp_path - - -def strip_html_comments(text): - """Strip HTML comments from a unicode string.""" - lines = text.splitlines(True) # preserve line endings. - - # Remove HTML comments (which we only allow to take a special form). - new_lines = [line for line in lines if not line.startswith("{command}") - - if os.path.exists(rst_temp_path): - os.remove(rst_temp_path) - - sp.check_call(split(command)) - - if not os.path.exists(rst_temp_path): - s = (f"Error running: {command}\n" - " Did you install pandoc per the {__file__} docstring?") - sys.exit(s) - - return read(rst_temp_path) - - -# The long_description needs to be formatted as reStructuredText. -# See the following for more information: -# -# http://docs.python.org/distutils/setupscript.html#additional-meta-data -# http://docs.python.org/distutils/uploading.html#pypi-package-display -# -def make_long_description(): - """ - Generate the reST long_description for setup() from source files. - - Returns the generated long_description as a unicode string. - - """ - readme_path = README_PATH - - # Remove our HTML comments because PyPI does not allow it. - # See the setup.py docstring for more info on this. - readme_md = strip_html_comments(read(readme_path)) - history_md = strip_html_comments(read(HISTORY_PATH)) - license_md = """\ -License -======= - -""" + read(LICENSE_PATH) - - sections = [readme_md, history_md, license_md] - md_description = '\n\n'.join(sections) - - # Write the combined Markdown file to a temp path. - md_ext = os.path.splitext(readme_path)[1] - md_description_path = make_temp_path(RST_DESCRIPTION_PATH, new_ext=md_ext) - write(md_description, md_description_path) - - rst_temp_path = make_temp_path(RST_DESCRIPTION_PATH) - long_description = convert_md_to_rst(md_path=md_description_path, - rst_temp_path=rst_temp_path) - - return "\n".join([RST_LONG_DESCRIPTION_INTRO, long_description]) - - -def prep(): - """Update the reST long_description file.""" - long_description = make_long_description() - write(long_description, RST_DESCRIPTION_PATH) - - -def publish(): - """Publish this package to PyPI (aka "the Cheeseshop").""" - long_description = make_long_description() - - if long_description != read(RST_DESCRIPTION_PATH): - print(("""\ -Description file not up-to-date: %s -Run the following command and commit the changes-- - - python setup.py %s -""" % (RST_DESCRIPTION_PATH, PREP_COMMAND))) - sys.exit() - - print(("Description up-to-date: %s" % RST_DESCRIPTION_PATH)) - - answer = input("Are you sure you want to publish to PyPI (yes/no)?") - - if answer != "yes": - exit("Aborted: nothing published") - - os.system('python setup.py sdist upload') - - -def main(sys_argv): - - # TODO: use the logging module instead of printing. - command = sys_argv[-1] - - if command == 'publish': - publish() - sys.exit() - elif command == PREP_COMMAND: - prep() - sys.exit() - - long_description = read(RST_DESCRIPTION_PATH) - - setup( - long_description=long_description, - long_description_content_type='text/x-rst', - ) - - -if __name__=='__main__': - main(sys.argv) +if __name__ == "__main__": + setuptools.setup() diff --git a/setup_description.rst b/setup_description.rst deleted file mode 100644 index d7f1bc00..00000000 --- a/setup_description.rst +++ /dev/null @@ -1,560 +0,0 @@ -.. Do not edit this file. This file is auto-generated for PyPI by setup.py -.. using pandoc, so edits should go in the source files rather than here. - -Pystache -======== - -|ci| |Conda| |Wheels| |Release| |Python| - -|Latest release| |License| |Maintainability| |codecov| - -This updated fork of Pystache is currently tested on Python 3.6+ and in -Conda, on Linux, Macos, and Windows (Python 2.7 support has been -removed). - -|image9| - -`Pystache `__ is a Python -implementation of `Mustache `__. Mustache -is a framework-agnostic, logic-free templating system inspired by -`ctemplate `__ and -`et `__. -Like ctemplate, Mustache "emphasizes separating logic from presentation: -it is impossible to embed application logic in this template language." - -The `mustache(5) `__ man -page provides a good introduction to Mustache's syntax. For a more -complete (and more current) description of Mustache's behavior, see the -official `Mustache spec `__. - -Pystache is `semantically versioned `__ and older -versions can still be found on -`PyPI `__. This version of -Pystache now passes all tests in `version -1.1.3 `__ of the spec. - -Requirements ------------- - -Pystache is tested with-- - -- Python 3.6 -- Python 3.7 -- Python 3.8 -- Python 3.9 -- Conda (py36-py39) - -`Distribute `__ (the setuptools -fork) is no longer required over -`setuptools `__, as the current -packaging is now PEP517-compliant. - -JSON support is needed only for the command-line interface and to run -the spec tests; PyYAML can still be used (see the Develop section). - -Official support for Python 2 will end with Pystache version 0.6.0. - -Install It ----------- - -:: - - pip install -U pystache -f https://github.com/sarnold/pystache/releases/ - -And test it-- - -:: - - pystache-test - -To install and test from source (e.g. from GitHub), see the Develop -section. - -Use It ------- - -:: - - >>> import pystache - >>> print(pystache.render('Hi {{person}}!', {'person': 'Mom'})) - Hi Mom! - -You can also create dedicated view classes to hold your view logic. - -Here's your view class (in ../pystache/tests/examples/readme.py): - -:: - - class SayHello(object): - def to(self): - return "Pizza" - -Instantiating like so: - -:: - - >>> from pystache.tests.examples.readme import SayHello - >>> hello = SayHello() - -Then your template, say_hello.mustache (by default in the same directory -as your class definition): - -:: - - Hello, {{to}}! - -Pull it together: - -:: - - >>> renderer = pystache.Renderer() - >>> print(renderer.render(hello)) - Hello, Pizza! - -For greater control over rendering (e.g. to specify a custom template -directory), use the ``Renderer`` class like above. One can pass -attributes to the Renderer class constructor or set them on a Renderer -instance. To customize template loading on a per-view basis, subclass -``TemplateSpec``. See the docstrings of the -`Renderer `__ -class and -`TemplateSpec `__ -class for more information. - -You can also pre-parse a template: - -:: - - >>> parsed = pystache.parse(u"Hey {{#who}}{{.}}!{{/who}}") - >>> print(parsed) - ['Hey ', _SectionNode(key='who', index_begin=12, index_end=18, parsed=[_EscapeNode(key='.'), '!'])] - -And then: - -:: - - >>> print(renderer.render(parsed, {'who': 'Pops'})) - Hey Pops! - >>> print(renderer.render(parsed, {'who': 'you'})) - Hey you! - -Python 3 --------- - -Pystache has supported Python 3 since version 0.5.1. Pystache behaves -slightly differently between Python 2 and 3, as follows: - -- In Python 2, the default html-escape function ``cgi.escape()`` does - not escape single quotes. In Python 3, the default escape function - ``html.escape()`` does escape single quotes. -- In both Python 2 and 3, the string and file encodings default to - ``sys.getdefaultencoding()``. However, this function can return - different values under Python 2 and 3, even when run from the same - system. Check your own system for the behavior on your system, or do - not rely on the defaults by passing in the encodings explicitly (e.g. - to the ``Renderer`` class). - -Unicode -------- - -This section describes how Pystache handles unicode, strings, and -encodings. - -Internally, Pystache uses `only unicode -strings `__ -(``str`` in Python 3 and ``unicode`` in Python 2). For input, Pystache -accepts both unicode strings and byte strings (``bytes`` in Python 3 and -``str`` in Python 2). For output, Pystache's template rendering methods -return only unicode. - -Pystache's ``Renderer`` class supports a number of attributes to control -how Pystache converts byte strings to unicode on input. These include -the ``file_encoding``, ``string_encoding``, and ``decode_errors`` -attributes. - -The ``file_encoding`` attribute is the encoding the renderer uses to -convert to unicode any files read from the file system. Similarly, -``string_encoding`` is the encoding the renderer uses to convert any -other byte strings encountered during the rendering process into unicode -(e.g. context values that are encoded byte strings). - -The ``decode_errors`` attribute is what the renderer passes as the -``errors`` argument to Python's built-in unicode-decoding function -(``str()`` in Python 3 and ``unicode()`` in Python 2). The valid values -for this argument are ``strict``, ``ignore``, and ``replace``. - -Each of these attributes can be set via the ``Renderer`` class's -constructor using a keyword argument of the same name. See the Renderer -class's docstrings for further details. In addition, the -``file_encoding`` attribute can be controlled on a per-view basis by -subclassing the ``TemplateSpec`` class. When not specified explicitly, -these attributes default to values set in Pystache's ``defaults`` -module. - -Develop -------- - -To test from a source distribution (without installing)-- - -:: - - python test_pystache.py - -To test Pystache with multiple versions of Python (with a single -command!) and different platforms, you can use -`tox `__: - -:: - - pip install tox - tox -e setup - -To run tests on multiple versions with coverage, run: - -:: - - tox -e py38-linux,py39-linux # for example - -(substitute your platform above, eg, macos or windows) - -The source distribution tests also include doctests and tests from the -Mustache spec. To include tests from the Mustache spec in your test -runs: - -:: - - git submodule init - git submodule update - -The test harness parses the spec's (more human-readable) yaml files if -`PyYAML `__ is present. Otherwise, -it parses the json files. To install PyYAML-- - -:: - - pip install pyyaml - -Once the submodule is available, you can run the full test set with: - -:: - - tox -e setup . ext/spec/specs - -To run a subset of the tests, you can use -`nose `__: - -:: - - pip install nose - nosetests --tests pystache/tests/test_context.py:GetValueTests.test_dictionary__key_present - -Mailing List (old) ------------------- - -There is(was) a `mailing -list `__. Note that there is a -bit of a delay between posting a message and seeing it appear in the -mailing list archive. - -Credits -------- - -:: - - >>> import pystache - >>> context = { 'author': 'Chris Wanstrath', 'maintainer': 'Chris Jerdonek','refurbisher': 'Steve Arnold' } - >>> print(pystache.render("Author: {{author}}\nMaintainer: {{maintainer}}\nRefurbisher: {{refurbisher}}", context)) - Author: Chris Wanstrath - Maintainer: Chris Jerdonek - Refurbisher: Steve Arnold - -Pystache logo by `David Phillips `__ is -licensed under a `Creative Commons Attribution-ShareAlike 3.0 Unported -License `__. -|image10| - -History -======= - -**Note:** Official support for Python 2.7 will end with Pystache version -0.6.0. - -0.6.0 (2021-03-04) ------------------- - -- Bump spec versions to latest => v1.1.3 -- Modernize python and CI tools, update docs/doctests -- Update unicode conversion test for py3-only -- Add pep8speaks cfg, cleanup warnings -- Remove superfluous setup test/unused imports -- Add conda recipe/CI build - -.. _section-1: - -0.5.6 (2021-02-28) ------------------- - -- Use correct wheel name in release workflow, limit wheels -- Add install check/test of downloaded wheel -- Update/add ci workflows and tox cfg, bump to next dev0 version - -.. _section-2: - -0.5.5 (2020-12-16) ------------------- - -- fix document processing, update pandoc args and history -- add release.yml to CI, test env settings -- fix bogus commit message, update versions and tox cf -- add post-test steps for building pkgs with/without doc updates -- add CI build check, fix MANIFEST.in pruning - -.. _section-3: - -0.5.4-2 (2020-11-09) --------------------- - -- Merge pull request #1 from sarnold/rebase-up -- Bugfix: test_specloader.py: fix test_find__with_directory on other - OSs -- Bugfix: pystache/loader.py: remove stray windows line-endings -- fix crufty (and insecure) http urls -- Bugfix: modernize python versions (keep py27) and fix spec_test load - cmd - -.. _section-4: - -0.5.4 (2014-07-11) ------------------- - -- Bugfix: made test with filenames OS agnostic (issue #162). - -.. _section-5: - -0.5.3 (2012-11-03) ------------------- - -- Added ability to customize string coercion (e.g. to have None render - as ``''``) (issue #130). -- Added Renderer.render_name() to render a template by name (issue - #122). -- Added TemplateSpec.template_path to specify an absolute path to a - template (issue #41). -- Added option of raising errors on missing tags/partials: - ``Renderer(missing_tags='strict')`` (issue #110). -- Added support for finding and loading templates by file name in - addition to by template name (issue #127). [xgecko] -- Added a ``parse()`` function that yields a printable, pre-compiled - parse tree. -- Added support for rendering pre-compiled templates. -- Added Python 3.3 to the list of supported versions. -- Added support for `PyPy `__ (issue #125). -- Added support for `Travis CI `__ (issue #124). - [msabramo] -- Bugfix: ``defaults.DELIMITERS`` can now be changed at runtime (issue - #135). [bennoleslie] -- Bugfix: exceptions raised from a property are no longer swallowed - when getting a key from a context stack (issue #110). -- Bugfix: lambda section values can now return non-ascii, non-unicode - strings (issue #118). -- Bugfix: allow ``test_pystache.py`` and ``tox`` to pass when run from - a downloaded sdist (i.e. without the spec test directory). -- Convert HISTORY and README files from reST to Markdown. -- More robust handling of byte strings in Python 3. -- Added Creative Commons license for David Phillips's logo. - -.. _section-6: - -0.5.2 (2012-05-03) ------------------- - -- Added support for dot notation and version 1.1.2 of the spec (issue - #99). [rbp] -- Missing partials now render as empty string per latest version of - spec (issue #115). -- Bugfix: falsey values now coerced to strings using str(). -- Bugfix: lambda return values for sections no longer pushed onto - context stack (issue #113). -- Bugfix: lists of lambdas for sections were not rendered (issue #114). - -.. _section-7: - -0.5.1 (2012-04-24) ------------------- - -- Added support for Python 3.1 and 3.2. -- Added tox support to test multiple Python versions. -- Added test script entry point: pystache-test. -- Added \__version_\_ package attribute. -- Test harness now supports both YAML and JSON forms of Mustache spec. -- Test harness no longer requires nose. - -.. _section-8: - -0.5.0 (2012-04-03) ------------------- - -This version represents a major rewrite and refactoring of the code base -that also adds features and fixes many bugs. All functionality and -nearly all unit tests have been preserved. However, some backwards -incompatible changes to the API have been made. - -Below is a selection of some of the changes (not exhaustive). - -Highlights: - -- Pystache now passes all tests in version 1.0.3 of the `Mustache - spec `__. [pvande] -- Removed View class: it is no longer necessary to subclass from View - or from any other class to create a view. -- Replaced Template with Renderer class: template rendering behavior - can be modified via the Renderer constructor or by setting attributes - on a Renderer instance. -- Added TemplateSpec class: template rendering can be specified on a - per-view basis by subclassing from TemplateSpec. -- Introduced separation of concerns and removed circular dependencies - (e.g. between Template and View classes, cf. `issue - #13 `__). -- Unicode now used consistently throughout the rendering process. -- Expanded test coverage: nosetests now runs doctests and ~105 test - cases from the Mustache spec (increasing the number of tests from 56 - to ~315). -- Added a rudimentary benchmarking script to gauge performance while - refactoring. -- Extensive documentation added (e.g. docstrings). - -Other changes: - -- Added a command-line interface. [vrde] -- The main rendering class now accepts a custom partial loader (e.g. a - dictionary) and a custom escape function. -- Non-ascii characters in str strings are now supported while - rendering. -- Added string encoding, file encoding, and errors options for decoding - to unicode. -- Removed the output encoding option. -- Removed the use of markupsafe. - -Bug fixes: - -- Context values no longer processed as template strings. - [jakearchibald] -- Whitespace surrounding sections is no longer altered, per the spec. - [heliodor] -- Zeroes now render correctly when using PyPy. [alex] -- Multline comments now permitted. [fczuardi] -- Extensionless template files are now supported. -- Passing ``**kwargs`` to ``Template()`` no longer modifies the - context. -- Passing ``**kwargs`` to ``Template()`` with no context no longer - raises an exception. - -.. _section-9: - -0.4.1 (2012-03-25) ------------------- - -- Added support for Python 2.4. [wangtz, jvantuyl] - -.. _section-10: - -0.4.0 (2011-01-12) ------------------- - -- Add support for nested contexts (within template and view) -- Add support for inverted lists -- Decoupled template loading - -.. _section-11: - -0.3.1 (2010-05-07) ------------------- - -- Fix package - -.. _section-12: - -0.3.0 (2010-05-03) ------------------- - -- View.template_path can now hold a list of path -- Add {{& blah}} as an alias for {{{ blah }}} -- Higher Order Sections -- Inverted sections - -.. _section-13: - -0.2.0 (2010-02-15) ------------------- - -- Bugfix: Methods returning False or None are not rendered -- Bugfix: Don't render an empty string when a tag's value is 0. - [enaeseth] -- Add support for using non-callables as View attributes. - [joshthecoder] -- Allow using View instances as attributes. [joshthecoder] -- Support for Unicode and non-ASCII-encoded bytestring output. - [enaeseth] -- Template file encoding awareness. [enaeseth] - -.. _section-14: - -0.1.1 (2009-11-13) ------------------- - -- Ensure we're dealing with strings, always -- Tests can be run by executing the test file directly - -.. _section-15: - -0.1.0 (2009-11-12) ------------------- - -- First release - -License -======= - -Copyright (C) 2012 Chris Jerdonek. All rights reserved. - -Copyright (c) 2009 Chris Wanstrath - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -.. |ci| image:: https://github.com/sarnold/pystache/actions/workflows/ci.yml/badge.svg - :target: https://github.com/sarnold/pystache/actions/workflows/ci.yml -.. |Conda| image:: https://github.com/sarnold/pystache/actions/workflows/conda.yml/badge.svg - :target: https://github.com/sarnold/pystache/actions/workflows/conda.yml -.. |Wheels| image:: https://github.com/sarnold/pystache/actions/workflows/wheels.yml/badge.svg - :target: https://github.com/sarnold/pystache/actions/workflows/wheels.yml -.. |Release| image:: https://github.com/sarnold/pystache/actions/workflows/release.yml/badge.svg - :target: https://github.com/sarnold/pystache/actions/workflows/release.yml -.. |Python| image:: https://img.shields.io/badge/python-3.6+-blue.svg - :target: https://www.python.org/downloads/ -.. |Latest release| image:: https://img.shields.io/github/v/release/sarnold/pystache?include_prereleases - :target: https://github.com/sarnold/pystache/releases/latest -.. |License| image:: https://img.shields.io/github/license/sarnold/pystache - :target: https://github.com/sarnold/pystache/blob/master/LICENSE -.. |Maintainability| image:: https://api.codeclimate.com/v1/badges/a8fa1bf4638bfc6581b6/maintainability - :target: https://codeclimate.com/github/sarnold/pystache/maintainability -.. |codecov| image:: https://codecov.io/gh/sarnold/pystache/branch/master/graph/badge.svg?token=5PZNMZBI6K - :target: https://codecov.io/gh/sarnold/pystache -.. |image9| image:: gh/images/logo_phillips_small.png -.. |image10| image:: http://i.creativecommons.org/l/by-sa/3.0/88x31.png diff --git a/tox.ini b/tox.ini index c6bde7e0..67b3ce28 100644 --- a/tox.ini +++ b/tox.ini @@ -14,20 +14,24 @@ python = [gh-actions:env] PLATFORM = - ubuntu-18.04: linux + ubuntu-20.04: linux macos-latest: macos windows-latest: windows +[base] +deps = + pip>=21.1 + versioningit + [testenv] passenv = CI PYTHON PYTHONIOENCODING allowlist_externals = bash deps = - pip>=20.0.1 + {[base]deps} .[test,cov] commands = - #nosetests -sx . {posargs} python -m pytest . --capture=no --doctest-modules --doctest-glob="*.rst" --doctest-glob="*.py" --cov pystache --cov-branch --cov-report term-missing coverage xml bash -c './gh/fix_pkg_name.sh' @@ -36,7 +40,7 @@ commands = # Change the working directory so that we don't import the pystache located # in the original location. deps = - pip>=20.0.1 + {[base]deps} -e . changedir = @@ -49,7 +53,7 @@ commands = passenv = CI PYTHON PYTHONIOENCODING deps = - pip>=20.0.1 + {[base]deps} # uncomment for comparison, posargs expects a number, eg, 10000 #chevron @@ -63,7 +67,7 @@ commands = passenv = CI PYTHON PYTHONIOENCODING deps = - pip>=20.0.1 + {[base]deps} pyyaml # this is becoming even more deprecated (possibly failing) BUT, @@ -82,9 +86,13 @@ commands = passenv = CI PYTHON PYTHONIOENCODING deps = - pip>=20.0.1 + {[base]deps} pylint +commands_pre = + # need to generate version info in a fresh checkout + python setup.py egg_info + commands = pylint --rcfile={toxinidir}/.pylintrc --fail-under=8.10 pystache/ @@ -92,7 +100,7 @@ commands = passenv = CI PYTHON PYTHONIOENCODING deps = - pip>=20.0.1 + {[base]deps} flake8 commands = @@ -100,11 +108,9 @@ commands = [testenv:deploy] passenv = CI PYTHON PYTHONIOENCODING -allowlist_externals = bash deps = - pip>=19.0.1 - wheel + {[base]deps} build twine @@ -131,23 +137,35 @@ passenv = CI PYTHON PYTHONIOENCODING skip_install = true deps = - pip>=20.0.1 + {[base]deps} bandit +commands_pre = + # need to generate version info in a fresh checkout + python setup.py egg_info + commands = bandit -r pystache/ -x pystache/tests - #bandit -r pystache/ -[testenv:docs] -passenv = CI PYTHON PYTHONIOENCODING +[testenv:isort] +skip_install = true + +setenv = PYTHONPATH = {toxinidir} + +deps = + {[base]deps} + isort + +commands = + python -m isort pystache/ + +[testenv:clean] +skip_install = true allowlist_externals = bash deps = - pip>=19.0.1 - wheel - docutils - # apt/emerge pandoc first + pip>=21.1 commands = - python setup.py prep - bash -c 'python setup.py --long-description | rst2html.py -v --no-raw > out.html' + #bash -c 'make -C docs/ clean' + bash -c 'rm -rf build/ dist/ pystache.egg-info/ pystache/_version.py docs/source/api/' From 565cf4dd5966dc5b20afc75770669c265451676e Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Mon, 12 Sep 2022 20:11:55 -0700 Subject: [PATCH 03/12] chg: doc: convert readme.md to readme.rst, move extra docs Signed-off-by: Stephen L Arnold --- README.md | 272 -------------- README.rst | 351 +++++++++++++++++++ TODO.md => TODO.rst | 0 docs/{ => source}/dev/generate_changelog.rst | 0 docs/{ => source}/dev/pre-commit-config.rst | 0 docs/{ => source}/dev/pre-commit-usage.rst | 0 6 files changed, 351 insertions(+), 272 deletions(-) delete mode 100644 README.md create mode 100644 README.rst rename TODO.md => TODO.rst (100%) rename docs/{ => source}/dev/generate_changelog.rst (100%) rename docs/{ => source}/dev/pre-commit-config.rst (100%) rename docs/{ => source}/dev/pre-commit-usage.rst (100%) diff --git a/README.md b/README.md deleted file mode 100644 index 1f7c462d..00000000 --- a/README.md +++ /dev/null @@ -1,272 +0,0 @@ -Pystache -======== - - - - - - - - - - -[![CI](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/ci.yml/badge.svg)](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/ci.yml) -[![Conda](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/conda.yml/badge.svg)](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/conda.yml) -[![Coverage](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/coverage.yml/badge.svg)](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/coverage.yml) -[![Security check - Bandit](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/bandit.yml/badge.svg)](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/bandit.yml) -[![Release](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/release.yml/badge.svg)](https://github.com/PennyDreadfulMTG/pystache/actions/workflows/release.yml) - -[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) -[![Maintainability](https://api.codeclimate.com/v1/badges/a8fa1bf4638bfc6581b6/maintainability)](https://codeclimate.com/github/PennyDreadfulMTG/pystache/maintainability) - -[![Latest release](https://img.shields.io/github/v/release/PennyDreadfulMTG/pystache?include_prereleases)](https://github.com/PennyDreadfulMTG/pystache/releases/latest) -[![License](https://img.shields.io/github/license/PennyDreadfulMTG/pystache)](https://github.com/PennyDreadfulMTG/pystache/blob/master/LICENSE) -[![Python](https://img.shields.io/badge/python-3.6+-blue.svg)](https://www.python.org/downloads/) - -This updated fork of Pystache is currently tested on Python 3.6+ and in -Conda, on Linux, Macos, and Windows (Python 2.7 support has been removed). - -![](gh/images/logo_phillips_small.png "mustachioed, monocled snake by David Phillips") - -[Pystache](http://PennyDreadfulMTG.github.com/pystache) is a Python -implementation of [Mustache](http://mustache.github.com/). Mustache is a -framework-agnostic, logic-free templating system inspired by -[ctemplate](https://code.google.com/p/google-ctemplate/) and -et by Ivan Formichev. Like ctemplate, Mustache "emphasizes separating -logic from presentation: it is impossible to embed application logic in -this template language." - -The [mustache(5)](https://mustache.github.com/mustache.5.html) man page -provides a good introduction to Mustache's syntax. For a more complete -(and more current) description of Mustache's behavior, see the official -[Mustache spec](https://github.com/mustache/spec). - -Pystache is [semantically versioned](http://semver.org) and older versions -can still be found on [PyPI](http://pypi.python.org/pypi/pystache). This -version of Pystache now passes all tests in [version -1.1.3](https://github.com/mustache/spec/tree/v1.1.3) of the spec. - - -Making Changes & Contributing ------------------------------ - -This repo is now pre-commit enabled for various linting and format checks -(and in many cases, automatic fixes). The checks run on commit/push and will -fail the commit (if not clean) with some checks performing simple file corrections. -Simply review the changes and adjust (if needed) then `git add` the files and continue. - -If other checks fail on commit, the failure display should explain the error -types and line numbers. Note you must fix any fatal errors for the commit to -succeed; some errors should be fixed automatically (use `git status` and -` git diff` to review any changes). - -Note `pylint` is the primary check that requires your own input, as well -as a decision as to the appropriate fix action. You must fix any `pylint` -warnings (relative to the baseline config score) for the commit to succeed. - -See the pre-commit docs under `docs/dev/` for more information. - -- [pre-commit-config](docs/dev/pre-commit-config.rst) -- [pre-commit-usage](docs/dev/pre-commit-usage.rst) - -You will need to install pre-commit before contributing any changes; -installing it using your system's package manager is recommended, -otherwise install with pip into your local user's virtual environment -using something like: - - $ sudo emerge pre-commit --or-- - $ pip install pre-commit - -then install it into the repo you just cloned: - - $ git clone https://github.com/PennyDreadfulMTG/pystache - $ cd pystache - $ pre-commit install - $ pre-commit install-hooks - -It's usually a good idea to update the hooks to the latest version: - - pre-commit autoupdate - -Requirements ------------- - -Pystache is tested with-- - -- Python 3.6 -- Python 3.7 -- Python 3.8 -- Python 3.9 -- Conda (py36-py39) - -[Distribute](http://packages.python.org/distribute/) (the setuptools fork) -is no longer required over [setuptools](http://pypi.python.org/pypi/setuptools), -as the current packaging is now PEP517-compliant. - -JSON support is needed only for the command-line interface and to run -the spec tests; PyYAML can still be used (see the Develop section). - -Official support for Python 2 will end with Pystache version 0.6.0. - -Install It ----------- - - pip install -U pystache -f https://github.com/PennyDreadfulMTG/pystache/releases/ - -And test it: - - pystache-test - -To install and test from source (e.g. from GitHub), see the Develop -section. - -Use It ------- - - >>> import pystache - >>> print(pystache.render('Hi {{person}}!', {'person': 'Mom'})) - Hi Mom! - -You can also create dedicated view classes to hold your view logic. - -Here's your view class (in ../pystache/tests/examples/readme.py): - - class SayHello(object): - def to(self): - return "Pizza" - -Instantiating like so: - - >>> from pystache.tests.examples.readme import SayHello - >>> hello = SayHello() - -Then your template, say\_hello.mustache (by default in the same -directory as your class definition): - - Hello, {{to}}! - -Pull it together: - - >>> renderer = pystache.Renderer() - >>> print(renderer.render(hello)) - Hello, Pizza! - -For greater control over rendering (e.g. to specify a custom template -directory), use the `Renderer` class like above. One can pass attributes -to the Renderer class constructor or set them on a Renderer instance. To -customize template loading on a per-view basis, subclass `TemplateSpec`. -See the docstrings of the -[Renderer](https://github.com/PennyDreadfulMTG/pystache/blob/master/pystache/renderer.py) -class and -[TemplateSpec](https://github.com/PennyDreadfulMTG/pystache/blob/master/pystache/template_spec.py) -class for more information. - -You can also pre-parse a template: - - >>> parsed = pystache.parse(u"Hey {{#who}}{{.}}!{{/who}}") - >>> print(parsed) - ['Hey ', _SectionNode(key='who', index_begin=12, index_end=18, parsed=[_EscapeNode(key='.'), '!'])] - -And then: - - >>> print(renderer.render(parsed, {'who': 'Pops'})) - Hey Pops! - >>> print(renderer.render(parsed, {'who': 'you'})) - Hey you! - -Unicode -------- - -This section describes how Pystache handles unicode, strings, and -encodings. - -Internally, Pystache uses [only unicode strings](https://docs.python.org/howto/unicode.html#tips-for-writing-unicode-aware-programs). -For input, Pystache accepts both unicode strings and byte strings. -For output, Pystache's template rendering methods return only unicode. - -Pystache's `Renderer` class supports a number of attributes to control -how Pystache converts byte strings to unicode on input. These include -the `file_encoding`, `string_encoding`, and `decode_errors` attributes. - -The `file_encoding` attribute is the encoding the renderer uses to -convert to unicode any files read from the file system. Similarly, -`string_encoding` is the encoding the renderer uses to convert any other -byte strings encountered during the rendering process into unicode (e.g. -context values that are encoded byte strings). - -The `decode_errors` attribute is what the renderer passes as the -`errors` argument to `str()`. The valid values for -this argument are `strict`, `ignore`, and `replace`. - -Each of these attributes can be set via the `Renderer` class's -constructor using a keyword argument of the same name. See the Renderer -class's docstrings for further details. In addition, the `file_encoding` -attribute can be controlled on a per-view basis by subclassing the -`TemplateSpec` class. When not specified explicitly, these attributes -default to values set in Pystache's `defaults` module. - -Develop -------- - -To test from a source distribution (without installing)-- - - python test_pystache.py - -To test Pystache with multiple versions of Python (with a single -command!) and different platforms, you can use [tox](http://pypi.python.org/pypi/tox): - - pip install tox - tox -e py - -To run tests on multiple versions with coverage, run: - - tox -e py38-linux,py39-linux # for example - -(substitute your platform above, eg, macos or windows) - -The source distribution tests also include doctests and tests from the -Mustache spec. To include tests from the Mustache spec in your test -runs: - - git submodule update --init - -The test harness parses the spec's (more human-readable) yaml files if -[PyYAML](https://pypi.python.org/pypi/PyYAML) is present. Otherwise, it -parses the json files. To install PyYAML-- - - pip install pyyaml # note this is installed automatically by tox - -Once the submodule is available, you can run the full test set with: - - tox -e setup ext/spec/specs - -To run a subset of the tests, you can use -[nose](https://somethingaboutorange.com/mrl/projects/nose/0.11.1/testing.html): - - pip install nose - nosetests --tests pystache/tests/test_context.py:GetValueTests.test_dictionary__key_present - - -Mailing List (old) ------------------- - -There is(was) a [mailing list](http://librelist.com/browser/pystache/). Note -that there is a bit of a delay between posting a message and seeing it -appear in the mailing list archive. - -Credits -------- - - >>> import pystache - >>> context = { 'author': 'Chris Wanstrath', 'maintainer': 'Chris Jerdonek','refurbisher': 'Steve Arnold', 'new_maintainer': 'Thomas David Baker' } - >>> print(pystache.render("Author: {{author}}\nMaintainer: {{maintainer}}\nRefurbisher: {{refurbisher}}\nNew maintainer: {{new_maintainer}}", context)) - Author: Chris Wanstrath - Maintainer: Chris Jerdonek - Refurbisher: Steve Arnold - New maintainer: Thomas David Baker - -Pystache logo by [David Phillips](https://davidphillips.us/) is licensed -under a [Creative Commons Attribution-ShareAlike 3.0 Unported -License](https://creativecommons.org/licenses/by-sa/3.0/deed.en_US). -![](https://i.creativecommons.org/l/by-sa/3.0/88x31.png "Creative -Commons Attribution-ShareAlike 3.0 Unported License") diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..df0d9719 --- /dev/null +++ b/README.rst @@ -0,0 +1,351 @@ +Pystache +======== + +|ci| |conda| |coverage| |bandit| |release| + +|pre| |cov| |climate| + +|tag| |license| |python| + + +This updated fork of Pystache is currently tested on Python 3.6+ and in +Conda, on Linux, Macos, and Windows (Python 2.7 support has been removed). + +|logo| + +`Pystache `__ is a Python +implementation of `Mustache `__. Mustache +is a framework-agnostic, logic-free templating system inspired by +`ctemplate `__ and +`et `__. +Like ctemplate, Mustache "emphasizes separating logic from presentation: +it is impossible to embed application logic in this template language." + +The `mustache(5) `__ man +page provides a good introduction to Mustache's syntax. For a more +complete (and more current) description of Mustache's behavior, see the +official `Mustache spec `__. + +Pystache is `semantically versioned `__ and older +versions can still be found on +`PyPI `__. This version of +Pystache now passes all tests in `version +1.1.3 `__ of the spec. + + +Requirements +============ + +Pystache is tested with: + +- Python 3.6 +- Python 3.7 +- Python 3.8 +- Python 3.9 +- Python 3.10 +- Conda (py36-py39) + +`Distribute `__ (the setuptools +fork) is no longer required over +`setuptools `__, as the current +packaging is now PEP517-compliant. + +JSON support is needed only for the command-line interface and to run +the spec tests; PyYAML can still be used (see the Develop section). + +Official support for Python 2 will end with Pystache version 0.6.0. + +Quick Start +=========== + +Be sure to get the latest release from either Pypi or Github. + +Install It +---------- + +From Pypi:: + + $ pip install pystache + +Or Github:: + + $ pip install -U pystache -f https://github.com/PennyDreadfulMTG/pystache/releases/ + + +And test it:: + + $ pystache-test + +To install and test from source (e.g. from GitHub), see the Develop +section. + +Use It +------ + +Open a python console:: + + >>> import pystache + >>> print(pystache.render('Hi {{person}}!', {'person': 'Mom'})) + Hi Mom! + +You can also create dedicated view classes to hold your view logic. + +Here's your view class (in ../pystache/tests/examples/readme.py): + +:: + + class SayHello(object): + def to(self): + return "Pizza" + +Instantiating like so: + +:: + + >>> from pystache.tests.examples.readme import SayHello + >>> hello = SayHello() + +Then your template, say_hello.mustache (by default in the same directory +as your class definition): + +:: + + Hello, {{to}}! + +Pull it together: + +:: + + >>> renderer = pystache.Renderer() + >>> print(renderer.render(hello)) + Hello, Pizza! + +For greater control over rendering (e.g. to specify a custom template +directory), use the ``Renderer`` class like above. One can pass +attributes to the Renderer class constructor or set them on a Renderer +instance. To customize template loading on a per-view basis, subclass +``TemplateSpec``. See the docstrings of the +`Renderer `__ +class and +`TemplateSpec `__ +class for more information. + +You can also pre-parse a template: + +:: + + >>> parsed = pystache.parse(u"Hey {{#who}}{{.}}!{{/who}}") + >>> print(parsed) + ['Hey ', _SectionNode(key='who', index_begin=12, index_end=18, parsed=[_EscapeNode(key='.'), '!'])] + +And then: + +:: + + >>> print(renderer.render(parsed, {'who': 'Pops'})) + Hey Pops! + >>> print(renderer.render(parsed, {'who': 'you'})) + Hey you! + + +Unicode +------- + +This section describes how Pystache handles unicode, strings, and +encodings. + +Internally, Pystache uses `only unicode strings`_ (``str`` in Python 3). +For input, Pystache accepts byte strings (``bytes`` in Python 3). +For output, Pystache's template rendering methods return only unicode. + +.. _only unicode strings: http://docs.python.org/howto/unicode.html#tips-for-writing-unicode-aware-programs + +Pystache's ``Renderer`` class supports a number of attributes to control +how Pystache converts byte strings to unicode on input. These include +the ``file_encoding``, ``string_encoding``, and ``decode_errors`` attributes. + +The ``file_encoding`` attribute is the encoding the renderer uses to +convert to unicode any files read from the file system. Similarly, +``string_encoding`` is the encoding the renderer uses to convert any other +byte strings encountered during the rendering process into unicode (e.g. +context values that are encoded byte strings). + +The ``decode_errors`` attribute is what the renderer passes as the +``errors`` argument to Python's built-in unicode-decoding function +(``str()`` in Python 3). The valid values for this argument are +``strict``, ``ignore``, and ``replace``. + +Each of these attributes can be set via the ``Renderer`` class's +constructor using a keyword argument of the same name. See the Renderer +class's docstrings for further details. In addition, the ``file_encoding`` +attribute can be controlled on a per-view basis by subclassing the +``TemplateSpec`` class. When not specified explicitly, these attributes +default to values set in Pystache's ``defaults`` module. + + +Develop +======= + +To test from a source distribution (without installing): + + $ python test_pystache.py + +To test Pystache with multiple versions of Python (with a single +command!) and different platforms, you can use [tox](http://pypi.python.org/pypi/tox): + + $ pip install tox + $ tox -e py + +To run tests on multiple versions with coverage, run: + + $ tox -e py38-linux,py39-linux # for example + +(substitute your platform above, eg, macos or windows) + +The source distribution tests also include doctests and tests from the +Mustache spec. To include tests from the Mustache spec in your test +runs: + + $ git submodule update --init + +The test harness parses the spec's (more human-readable) yaml files if +[PyYAML](https://pypi.python.org/pypi/PyYAML) is present. Otherwise, it +parses the json files. To install PyYAML-- + + $ pip install pyyaml # note this is installed automatically by tox + +Once the submodule is available, you can run the full test set with: + + $ tox -e setup ext/spec/specs + + +Making Changes & Contributing +----------------------------- + +We use the gitchangelog_ action to generate our github Release page, as +well as the gitchangelog message format to help it categorize/filter +commits for a tidier release page. Please use the appropriate ACTION +modifiers in any Pull Requests. + +This repo is also pre-commit_ enabled for various linting and format +checks. The checks run automatically on commit and will fail the +commit (if not clean) with some checks performing simple file corrections. + +If other checks fail on commit, the failure display should explain the error +types and line numbers. Note you must fix any fatal errors for the +commit to succeed; some errors should be fixed automatically (use +``git status`` and ``git diff`` to review any changes). + +Note ``pylint`` is the primary check that requires your own input, as well +as a decision as to the appropriate fix action. You must fix any ``pylint`` +warnings (relative to the baseline config score) for the commit to succeed. + +See the following pages for more information on gitchangelog and pre-commit. + +.. inclusion-marker-1 + +* generate-changelog_ +* pre-commit-config_ +* pre-commit-usage_ + +.. _generate-changelog: docs/source/dev/generate-changelog.rst +.. _pre-commit-config: docs/source/dev/pre-commit-config.rst +.. _pre-commit-usage: docs/source/dev/pre-commit-usage.rst +.. inclusion-marker-2 + +You will need to install pre-commit before contributing any changes; +installing it using your system's package manager is recommended, +otherwise install with pip into your usual virtual environment using +something like:: + + $ sudo emerge pre-commit --or-- + $ pip install pre-commit + +then install it into the repo you just cloned:: + + $ git clone https://github.com/PennyDreadfulMTG/pystache + $ cd pystache/ + $ pre-commit install + +It's usually a good idea to update the hooks to the latest version:: + + pre-commit autoupdate + +.. _gitchangelog: https://github.com/sarnold/gitchangelog-action +.. _pre-commit: http://pre-commit.com/ + + +Mailing List (old) +------------------ + +There is(was) a [mailing list](http://librelist.com/browser/pystache/). Note +that there is a bit of a delay between posting a message and seeing it +appear in the mailing list archive. + + +Credits +======= + + >>> import pystache + >>> context = { 'author': 'Chris Wanstrath', 'maintainer': 'Chris Jerdonek','refurbisher': 'Steve Arnold', 'new_maintainer': 'Thomas David Baker' } + >>> print(pystache.render("Author: {{author}}\nMaintainer: {{maintainer}}\nRefurbisher: {{refurbisher}}\nNew maintainer: {{new_maintainer}}", context)) + Author: Chris Wanstrath + Maintainer: Chris Jerdonek + Refurbisher: Steve Arnold + New maintainer: Thomas David Baker + + +Pystache logo by `David Phillips `__ is +licensed under a `Creative Commons Attribution-ShareAlike 3.0 Unported +License `__. + +|ccbysa| + + +.. |ci| image:: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/ci.yml/badge.svg + :target: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/ci.yml + :alt: CI Status + +.. |conda| image:: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/conda.yml/badge.svg + :target: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/conda.yml + :alt: Conda Status + +.. |coverage| image:: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/coverage.yml/badge.svg + :target: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/coverage.yml + :alt: Coverage workflow + +.. |bandit| image:: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/bandit.yml/badge.svg + :target: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/bandit.yml + :alt: Security check - Bandit + +.. |release| image:: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/release.yml/badge.svg + :target: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/release.yml + :alt: Release Status + +.. |cov| image:: https://raw.githubusercontent.com/PennyDreadfulMTG/pystache/badges/master/test-coverage.svg + :target: https://github.com/PennyDreadfulMTG/pystache/ + :alt: Test coverage + +.. |climate| image:: https://api.codeclimate.com/v1/badges/a8fa1bf4638bfc6581b6/maintainability + :target: https://codeclimate.com/github/PennyDreadfulMTG/pystache/maintainability + :alt: Maintainability + +.. |license| image:: https://img.shields.io/github/license/PennyDreadfulMTG/pystache + :target: https://github.com/PennyDreadfulMTG/pystache/blob/master/LICENSE + :alt: License + +.. |tag| image:: https://img.shields.io/github/v/tag/PennyDreadfulMTG/pystache?color=green&include_prereleases&label=latest%20release + :target: https://github.com/PennyDreadfulMTG/pystache/releases + :alt: GitHub tag + +.. |python| image:: https://img.shields.io/badge/python-3.6+-blue.svg + :target: https://www.python.org/downloads/ + :alt: Python + +.. |pre| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white + :target: https://github.com/pre-commit/pre-commit + :alt: pre-commit + +.. |logo| image:: gh/images/logo_phillips_small.png + +.. |ccbysa| image:: http://i.creativecommons.org/l/by-sa/3.0/88x31.png diff --git a/TODO.md b/TODO.rst similarity index 100% rename from TODO.md rename to TODO.rst diff --git a/docs/dev/generate_changelog.rst b/docs/source/dev/generate_changelog.rst similarity index 100% rename from docs/dev/generate_changelog.rst rename to docs/source/dev/generate_changelog.rst diff --git a/docs/dev/pre-commit-config.rst b/docs/source/dev/pre-commit-config.rst similarity index 100% rename from docs/dev/pre-commit-config.rst rename to docs/source/dev/pre-commit-config.rst diff --git a/docs/dev/pre-commit-usage.rst b/docs/source/dev/pre-commit-usage.rst similarity index 100% rename from docs/dev/pre-commit-usage.rst rename to docs/source/dev/pre-commit-usage.rst From 906a0d483073033b7d93ed9db72739435add32ac Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Mon, 12 Sep 2022 21:17:14 -0700 Subject: [PATCH 04/12] new: doc: add full sphinx apidoc build, include readme/extras * add new tox commands for 'docs' and 'docs-lint' * cleanup link errors found by docs-lint * add sphinx doc build workflow, update ci workflow * remove new version var from __init__.py globals Signed-off-by: Stephen L Arnold --- .github/workflows/ci.yml | 17 +-- .github/workflows/sphinx.yml | 48 +++++++++ README.rst | 49 ++++----- docs/Makefile | 20 ++++ docs/make.bat | 36 +++++++ docs/source/conf.py | 183 +++++++++++++++++++++++++++++++++ docs/source/index.rst | 20 ++++ docs/source/readme_include.rst | 6 ++ pystache/__init__.py | 2 +- tox.ini | 24 ++++- 10 files changed, 357 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/sphinx.yml create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/readme_include.rst diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9636c5b..f493dc45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v2 with: - submodules: True + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 @@ -49,18 +49,3 @@ jobs: tox env: PLATFORM: ${{ matrix.os }} - - - name: Test with specs and pystache-test - run: | - tox -e setup ext/spec/specs - - - name: Check pkg builds - run: | - tox -e deploy,check - - - name: Check docs - if: runner.os == 'Linux' - run: | - sudo apt-get -qq update - sudo apt-get install -y pandoc - tox -e docs diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml new file mode 100644 index 00000000..faf82bf7 --- /dev/null +++ b/.github/workflows/sphinx.yml @@ -0,0 +1,48 @@ +name: Docs +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v2 + with: + python-version: '3.9' + + - name: Add python requirements + run: | + python -m pip install --upgrade pip + pip install tox + + - name: Build docs + run: | + tox -e docs-lint + tox -e docs + + - uses: actions/upload-artifact@v2 + with: + name: ApiDocsHTML + path: "docs/_build/html/" + + - name: set nojekyll for github + run: | + sudo touch docs/_build/html/.nojekyll + + - name: Deploy docs to gh-pages + if: ${{ github.event_name == 'push' }} + uses: JamesIves/github-pages-deploy-action@3.7.1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: gh-pages + FOLDER: docs/_build/html/ + SINGLE_COMMIT: true diff --git a/README.rst b/README.rst index df0d9719..be45ed4c 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ Pystache |ci| |conda| |coverage| |bandit| |release| -|pre| |cov| |climate| +|pre| |cov| |tag| |license| |python| @@ -13,24 +13,22 @@ Conda, on Linux, Macos, and Windows (Python 2.7 support has been removed). |logo| -`Pystache `__ is a Python -implementation of `Mustache `__. Mustache -is a framework-agnostic, logic-free templating system inspired by -`ctemplate `__ and -`et `__. -Like ctemplate, Mustache "emphasizes separating logic from presentation: +`Pystache `__ is a Python +implementation of `Mustache `__. +Mustache is a framework-agnostic, logic-free templating system inspired +by `ctemplate `__ and +et. Like ctemplate, Mustache "emphasizes separating logic from presentation: it is impossible to embed application logic in this template language." -The `mustache(5) `__ man +The `mustache(5) `__ man page provides a good introduction to Mustache's syntax. For a more complete (and more current) description of Mustache's behavior, see the official `Mustache spec `__. -Pystache is `semantically versioned `__ and older -versions can still be found on -`PyPI `__. This version of -Pystache now passes all tests in `version -1.1.3 `__ of the spec. +Pystache is `semantically versioned `__ and older +versions can still be found on `PyPI `__. +This version of Pystache now passes all tests in `version 1.1.3 +`__ of the spec. Requirements @@ -45,11 +43,6 @@ Pystache is tested with: - Python 3.10 - Conda (py36-py39) -`Distribute `__ (the setuptools -fork) is no longer required over -`setuptools `__, as the current -packaging is now PEP517-compliant. - JSON support is needed only for the command-line interface and to run the spec tests; PyYAML can still be used (see the Develop section). @@ -158,7 +151,7 @@ Internally, Pystache uses `only unicode strings`_ (``str`` in Python 3). For input, Pystache accepts byte strings (``bytes`` in Python 3). For output, Pystache's template rendering methods return only unicode. -.. _only unicode strings: http://docs.python.org/howto/unicode.html#tips-for-writing-unicode-aware-programs +.. _only unicode strings: https://docs.python.org/howto/unicode.html#tips-for-writing-unicode-aware-programs Pystache's ``Renderer`` class supports a number of attributes to control how Pystache converts byte strings to unicode on input. These include @@ -191,7 +184,7 @@ To test from a source distribution (without installing): $ python test_pystache.py To test Pystache with multiple versions of Python (with a single -command!) and different platforms, you can use [tox](http://pypi.python.org/pypi/tox): +command!) and different platforms, you can use [tox](https://pypi.python.org/pypi/tox): $ pip install tox $ tox -e py @@ -209,8 +202,8 @@ runs: $ git submodule update --init The test harness parses the spec's (more human-readable) yaml files if -[PyYAML](https://pypi.python.org/pypi/PyYAML) is present. Otherwise, it -parses the json files. To install PyYAML-- +`PyYAML `__ is present. Otherwise, +it parses the json files. To install PyYAML-- $ pip install pyyaml # note this is installed automatically by tox @@ -272,13 +265,13 @@ It's usually a good idea to update the hooks to the latest version:: pre-commit autoupdate .. _gitchangelog: https://github.com/sarnold/gitchangelog-action -.. _pre-commit: http://pre-commit.com/ +.. _pre-commit: https://pre-commit.com/ Mailing List (old) ------------------ -There is(was) a [mailing list](http://librelist.com/browser/pystache/). Note +There is(was) a [mailing list](https://librelist.com/browser/pystache/). Note that there is a bit of a delay between posting a message and seeing it appear in the mailing list archive. @@ -297,7 +290,7 @@ Credits Pystache logo by `David Phillips `__ is licensed under a `Creative Commons Attribution-ShareAlike 3.0 Unported -License `__. +License `__. |ccbysa| @@ -326,10 +319,6 @@ License `__. :target: https://github.com/PennyDreadfulMTG/pystache/ :alt: Test coverage -.. |climate| image:: https://api.codeclimate.com/v1/badges/a8fa1bf4638bfc6581b6/maintainability - :target: https://codeclimate.com/github/PennyDreadfulMTG/pystache/maintainability - :alt: Maintainability - .. |license| image:: https://img.shields.io/github/license/PennyDreadfulMTG/pystache :target: https://github.com/PennyDreadfulMTG/pystache/blob/master/LICENSE :alt: License @@ -348,4 +337,4 @@ License `__. .. |logo| image:: gh/images/logo_phillips_small.png -.. |ccbysa| image:: http://i.creativecommons.org/l/by-sa/3.0/88x31.png +.. |ccbysa| image:: https://i.creativecommons.org/l/by-sa/3.0/88x31.png diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..b18d40d3 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SPHINXPROJ = MAVConn +SOURCEDIR = source +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..d806eb7f --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build +set SPHINXPROJ=MAVConn + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..8c15de34 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# MAVConn documentation build configuration file, created by +# sphinx-quickstart on Tue Oct 31 14:20:31 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys + +import pkg_resources + + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) + +__version__ = pkg_resources.get_distribution('pystache').version + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinxcontrib.apidoc', + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', + 'recommonmark', +] + +apidoc_module_dir = '../../pystache/' +apidoc_output_dir = 'api' +apidoc_excluded_paths = ['ext'] +apidoc_separate_modules = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'pystache' +copyright = '2022, PennyDreadfulMTG' +author = 'Thomas David Baker' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +description = 'A Python implementation of Mustache (spec v1.1.3).' +version = __version__ +release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pystachedoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pystache.tex', 'pystache Documentation', + [author], 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pystache', 'pystache Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pystache', 'pystache Documentation', + [author], 'pystache', description, + 'Miscellaneous'), +] diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..83631a2f --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,20 @@ +Welcome to the pystache documentation! +====================================== + +.. toctree:: + :maxdepth: 4 + :caption: Contents: + + readme_include + dev/generate-changelog + dev/pre-commit-config + dev/pre-commit-usage + api/modules + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/readme_include.rst b/docs/source/readme_include.rst new file mode 100644 index 00000000..4760b412 --- /dev/null +++ b/docs/source/readme_include.rst @@ -0,0 +1,6 @@ +.. include:: ../../README.rst + :end-before: inclusion-marker-1 + + +.. include:: ../../README.rst + :start-after: inclusion-marker-2 diff --git a/pystache/__init__.py b/pystache/__init__.py index 13414bf0..71976507 100644 --- a/pystache/__init__.py +++ b/pystache/__init__.py @@ -11,4 +11,4 @@ version = __version__ -__all__ = ['parse', 'render', 'Renderer', 'TemplateSpec', 'version'] +__all__ = ['parse', 'render', 'Renderer', 'TemplateSpec'] diff --git a/tox.ini b/tox.ini index 67b3ce28..017fed96 100644 --- a/tox.ini +++ b/tox.ini @@ -132,6 +132,28 @@ commands = python -m pip install $WHL_FILE' pystache-test +[testenv:docs] +skip_install = true +allowlist_externals = + make + +deps = + {[base]deps} + .[doc] + +commands = make -C docs html + +[testenv:docs-lint] +skip_install = true +allowlist_externals = + make + +deps = + {[base]deps} + .[doc] + +commands = make -C docs linkcheck + [testenv:sec] passenv = CI PYTHON PYTHONIOENCODING skip_install = true @@ -167,5 +189,5 @@ deps = pip>=21.1 commands = - #bash -c 'make -C docs/ clean' + bash -c 'make -C docs/ clean' bash -c 'rm -rf build/ dist/ pystache.egg-info/ pystache/_version.py docs/source/api/' From 69fd900a01179c9a8aed31498c85a4ba9fe6e92b Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Tue, 13 Sep 2022 10:49:28 -0700 Subject: [PATCH 05/12] fix: doc: fix included filename and link cleanup Signed-off-by: Stephen L Arnold --- .gitignore | 2 ++ README.rst | 7 ++++--- .../dev/{generate_changelog.rst => generate-changelog.rst} | 0 3 files changed, 6 insertions(+), 3 deletions(-) rename docs/source/dev/{generate_changelog.rst => generate-changelog.rst} (100%) diff --git a/.gitignore b/.gitignore index d0101368..d52fe3c3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ # Distribution-related folders and files. pystache/_version.py pystache.egg-info +docs/_build +docs/source/api build dist MANIFEST diff --git a/README.rst b/README.rst index be45ed4c..9c1fc821 100644 --- a/README.rst +++ b/README.rst @@ -271,11 +271,12 @@ It's usually a good idea to update the hooks to the latest version:: Mailing List (old) ------------------ -There is(was) a [mailing list](https://librelist.com/browser/pystache/). Note -that there is a bit of a delay between posting a message and seeing it -appear in the mailing list archive. +There is(was) a `mailing list`_. Note that there is a bit of a delay +between posting a message and seeing it appear in the mailing list archive. +.. _: https://librelist.com/browser/pystache/ + Credits ======= diff --git a/docs/source/dev/generate_changelog.rst b/docs/source/dev/generate-changelog.rst similarity index 100% rename from docs/source/dev/generate_changelog.rst rename to docs/source/dev/generate-changelog.rst From 73d6089e03a3ec272bc915094fec450aa0995bdc Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Tue, 13 Sep 2022 10:56:52 -0700 Subject: [PATCH 06/12] chg: dev: limit coverage PR comment to repo_owner match * add pylint badge workflow and update readme (docs-lint will fail until badge is created on PR merge) Signed-off-by: Stephen L Arnold --- .github/workflows/coverage.yml | 2 +- .github/workflows/pylint.yml | 115 +++++++++++++++++++++++++++++++++ README.rst | 6 +- 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/pylint.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 4662b614..a60f53de 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -274,7 +274,7 @@ jobs: - name: Comment PR with test coverage delta uses: marocchino/sticky-pull-request-comment@v2.2.0 - if: env.HAVE_BASE_COVERAGE == 'true' + if: env.HAVE_BASE_COVERAGE == 'true' && github.actor == github.repository_owner with: header: delta recreate: true diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 00000000..21d550ec --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,115 @@ +name: Pylint + +on: + workflow_dispatch: + pull_request: + push: + branches: [ master ] + +jobs: + pylint: + + runs-on: ubuntu-20.04 + defaults: + run: + shell: bash + outputs: + branch: ${{ steps.extract_branch.outputs.branch }} + rating: ${{ steps.analyze.outputs.rating }} + path: ${{ steps.analyze.outputs.path }} + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Extract base branch name + id: extract_branch + shell: bash + run: | + TMP_PULL_BASE_REF="${{ github.base_ref }}" + TMP_GITHUB_REF="${GITHUB_REF#refs/heads/}" + EXPORT_VALUE="" + if [ "${TMP_PULL_BASE_REF}" != "" ] + then + EXPORT_VALUE="${TMP_PULL_BASE_REF}" + else + EXPORT_VALUE="${TMP_GITHUB_REF}" + fi + echo "##[set-output name=branch;]${EXPORT_VALUE}" + + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install tox + run: | + python -m pip install --upgrade pip wheel + pip install tox tox-gh-actions + + #- name: Run tox + #run: | + #bash -c 'tox -e lint' + + - name: Run pylint + id: analyze + env: + BADGE_PATH: badges/pylint-score.svg + run: | + rating=$(bash -c 'tox -e lint' | grep 'Your code has been rated at' | cut -f7 -d " ") + echo "Pylint score: ${rating}" + echo "##[set-output name=rating;]${rating}" + echo "##[set-output name=path;]${BADGE_PATH}" + + badge: + # Only generate and publish if these conditions are met: + # - The previous job/analyze step ended successfully + # - At least one of these is true: + # - This is a push event and the push event is on branch 'master' or 'develop' + # Note: if this repo is personal (ie, not an org repo) then you can + # use the following to change the scope of the next 2 jobs + # instead of running on branch push as shown below: + # - This is a pull request event and the pull actor is the same as the repo owner + # if: ${{ ( github.event_name == 'pull_request' && github.actor == github.repository_owner ) || github.ref == 'refs/heads/master' }} + name: Generate badge image with pylint score + runs-on: ubuntu-20.04 + needs: [pylint] + if: ${{ github.event_name == 'push' }} + + steps: + - uses: actions/checkout@v2 + with: + ref: badges + path: badges + + # Use the output from the `analyze` step + - name: Create pylint badge + uses: emibcn/badge-action@v1 + id: badge + with: + label: 'Pylint score' + status: ${{ needs.pylint.outputs.rating }} + color: 'green' + path: ${{ needs.pylint.outputs.path }} + + - name: Commit badge + env: + BRANCH: ${{ needs.pylint.outputs.branch }} + FILE: 'pylint-score.svg' + working-directory: ./badges + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + mkdir -p "${BRANCH}" + mv "${FILE}" "${BRANCH}" + git add "${BRANCH}/${FILE}" + # Will give error if badge has not changed + git commit -m "Add/Update badge" || true + + - name: Push badge commit + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: badges + directory: badges diff --git a/README.rst b/README.rst index 9c1fc821..4de279b5 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ Pystache |ci| |conda| |coverage| |bandit| |release| -|pre| |cov| +|pre| |cov| |lint| |tag| |license| |python| @@ -320,6 +320,10 @@ License `__. :target: https://github.com/PennyDreadfulMTG/pystache/ :alt: Test coverage +.. |pylint| image:: https://raw.githubusercontent.com/PennyDreadfulMTG/pystache/badges/master/pylint-score.svg + :target: https://github.com/PennyDreadfulMTG/pystache/actions/workflows/pylint.yml + :alt: Pylint Score + .. |license| image:: https://img.shields.io/github/license/PennyDreadfulMTG/pystache :target: https://github.com/PennyDreadfulMTG/pystache/blob/master/LICENSE :alt: License From 9f35362ae0b171813826adf588adef84af653019 Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Tue, 13 Sep 2022 22:10:23 -0700 Subject: [PATCH 07/12] chg: dev: allow docs build without linting, cleanup readme * docs-lint will not pass without the link to pylint badge (which does not yet exist upstream) Signed-off-by: Stephen L Arnold --- .github/workflows/sphinx.yml | 2 +- README.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index faf82bf7..742b5399 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -26,7 +26,7 @@ jobs: - name: Build docs run: | - tox -e docs-lint + #tox -e docs-lint tox -e docs - uses: actions/upload-artifact@v2 diff --git a/README.rst b/README.rst index 4de279b5..2aa6efe8 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ Pystache |ci| |conda| |coverage| |bandit| |release| -|pre| |cov| |lint| +|pre| |cov| |pylint| |tag| |license| |python| @@ -275,7 +275,7 @@ There is(was) a `mailing list`_. Note that there is a bit of a delay between posting a message and seeing it appear in the mailing list archive. -.. _: https://librelist.com/browser/pystache/ +.. _mailing list: https://librelist.com/browser/pystache/ Credits ======= From 489304a6fbb22c7ed47cfcdff165682dcf158b0a Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Tue, 13 Sep 2022 22:27:41 -0700 Subject: [PATCH 08/12] fix: dev: add new build dep for conda recipe/workflow * update conda recipe, needs version dep in host and run * cleanup setup.cfg and manifest files Signed-off-by: Stephen L Arnold --- .github/workflows/conda.yml | 2 +- MANIFEST.in | 18 +++++------------- conda/meta.yaml | 11 ++++++----- setup.cfg | 4 ++-- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index d6dcb179..931cd26d 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu-18.04, windows-latest, macos-latest] + platform: [ubuntu-20.04, windows-latest, macos-latest] python-version: [3.7, 3.9] runs-on: ${{ matrix.platform }} diff --git a/MANIFEST.in b/MANIFEST.in index 1593143f..e1d62166 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,13 +1,5 @@ -include README.md HISTORY.md TODO.md LICENSE -include setup_description.rst -include tox.ini -include test_pystache.py -# You cannot use package_data, for example, to include data files in a -# source distribution when using Distribute. -recursive-include pystache/tests *.mustache *.txt -# We deliberately exclude the gh/ directory because it contains copies -# of resources needed only for the web page hosted on GitHub (via the -# gh-pages branch). -exclude *.ini *travis* -prune gh -prune .git* +graft docs + +include tox.ini README.rst + +global-exclude *~ *.py[cod] diff --git a/conda/meta.yaml b/conda/meta.yaml index e7f4fd9c..e3272a05 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -1,5 +1,5 @@ {% set name = "pystache" %} -{% set version = "0.6.0.dev0" %} +{% set version = "0.6.1.dev0" %} package: name: {{ name|lower }} @@ -17,12 +17,14 @@ build: - pystache-test = pystache.commands.test:main requirements: - build: + host: + - pip - python - setuptools - + - versioningit run: - - python + - python >=3.7 + - versioningit test: imports: @@ -37,7 +39,6 @@ test: - pystache --help - pystache-test - about: home: https://github.com/sarnold/pystache license: MIT diff --git a/setup.cfg b/setup.cfg index b39fdd7f..93c470af 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,8 +6,8 @@ author_email = chris@ozmm.org maintainer = Thomas David Baker maintainer_email = bakert@gmail.com description = Mustache for Python -long_description = file: README.md -long_description_content_type = text/markdown +long_description = file: README.rst +long_description_content_type = text/rst; charset=UTF-8 url = https://github.com/PennyDreadfulMTG/pystache license = MIT license_files = LICENSE From 8a3f2f09261b4bcecd6f91be87c13b94f26fed01 Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Wed, 14 Sep 2022 15:35:03 -0700 Subject: [PATCH 09/12] fix: dev: use built-in pystache-test for post-conda install * work-around for import error in github project source dir Signed-off-by: Stephen L Arnold --- .github/workflows/conda.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index 931cd26d..3f9abac7 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -52,4 +52,4 @@ jobs: run: conda install -c ${CONDA_PREFIX}/conda-bld/ pystache - name: Test - run: python test_pystache.py + run: pystache-test From 1236ed59e8b50cdb2013214258b58c5f72b5b785 Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Wed, 14 Sep 2022 16:46:19 -0700 Subject: [PATCH 10/12] new: dev: add pypi upload to release workflow, update .gitchangelog.rc * pypi action step is not fully enabled yet, requires setup * check pre-release packaging artifacts for sdist/bdist * start capturing rst CHANGES file from v0.6.0 onwards Signed-off-by: Stephen L Arnold --- .gitchangelog.rc | 18 +++++++++--------- .github/workflows/release.yml | 32 ++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/.gitchangelog.rc b/.gitchangelog.rc index 5cf63a0d..c41cc29b 100644 --- a/.gitchangelog.rc +++ b/.gitchangelog.rc @@ -152,18 +152,18 @@ subject_process = (strip | ## ## Tags that will be used for the changelog must match this regexp. ## -#tag_filter_regexp = r'^v?[0-9]+\.[0-9]+(\.[0-9]+)?$' -tag_filter_regexp = r'^[0-9]+\.[0-9]+(\.[0-9]+)?$' +tag_filter_regexp = r'^v?[0-9]+\.[0-9]+(\.[0-9]+)?$' +#tag_filter_regexp = r'^[0-9]+\.[0-9]+(\.[0-9]+)?$' ## ``unreleased_version_label`` is a string or a callable that outputs a string ## ## This label will be used as the changelog Title of the last set of changes ## between last valid tag and HEAD if any. -unreleased_version_label = "(unreleased)" -#unreleased_version_label = lambda: swrap( -# ["git", "describe", "--tags"], -#shell=False) +#unreleased_version_label = "(unreleased)" +unreleased_version_label = lambda: swrap( + ["git", "describe", "--tags"], +shell=False) ## ``output_engine`` is a callable @@ -194,9 +194,9 @@ unreleased_version_label = "(unreleased)" ## Examples: ## - makotemplate("restructuredtext") ## -#output_engine = rest_py +output_engine = rest_py #output_engine = mustache("restructuredtext") -output_engine = mustache("markdown") +#output_engine = mustache("markdown") #output_engine = makotemplate("restructuredtext") @@ -204,7 +204,7 @@ output_engine = mustache("markdown") ## ## This option tells git-log whether to include merge commits in the log. ## The default is to include them. -include_merge = True +include_merge = False ## ``log_encoding`` is a string identifier diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10d233bc..09941a87 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: - '*' jobs: - wheels: + packaging: runs-on: ${{ matrix.os }} defaults: @@ -49,13 +49,13 @@ jobs: if: matrix.python-version == 3.7 && runner.os == 'Linux' uses: actions/upload-artifact@v2 with: - name: wheels - path: ./dist/*.whl + name: packages + path: ./dist/pystache* create_release: name: Create Release - needs: [wheels] - runs-on: ubuntu-18.04 + needs: [packaging] + runs-on: ubuntu-20.04 steps: - name: Get version @@ -88,4 +88,24 @@ jobs: draft: false prerelease: false files: | - wheels/pystache*.whl + packages/pystache* + + # When a GitHub release is made, upload the artifacts to PyPI + upload: + name: Upload to PyPI + runs-on: ubuntu-20.04 + needs: [packaging] + + steps: + - uses: actions/setup-python@v2 + + - uses: actions/download-artifact@v2 + + - name: check artifacts + run: find . -maxdepth 2 -name pystache-\* -type f + +# - name: Publish bdist and sdist packages +# uses: pypa/gh-action-pypi-publish@v1.4.1 +# with: +# password: ${{ secrets.pypi_password }} +# packages_dir: packages/ From 2953755b39e5374f6199deb0c33ea104716a3bf4 Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Wed, 14 Sep 2022 17:34:12 -0700 Subject: [PATCH 11/12] do pre-release (manual) updates for changes and conda recipe * create changes file: gitchangelog v0.6.0.. > CHANGELOG.rst * edit top line in CHANGELOG.rst using current date/new tag * edit conda/meta.yaml using new tag, then tag this commit Signed-off-by: Stephen L Arnold --- CHANGELOG.rst | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ conda/meta.yaml | 4 ++-- 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 00000000..0cb13445 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,62 @@ +v0.6.2 (2022-09-14) +-------------------- + +New +~~~ +- Add full sphinx apidoc build, include readme/extras. [Stephen L + Arnold] + + * add new tox commands for 'docs' and 'docs-lint' + * cleanup link errors found by docs-lint + * add sphinx doc build workflow, update ci workflow + * remove new version var from __init__.py globals + +Changes +~~~~~~~ +- Convert readme.md to readme.rst, move extra docs. [Stephen L Arnold] + +Fixes +~~~~~ +- Fix included filename and link cleanup. [Stephen L Arnold] +- Remove more py2 cruft from doctesting (py3.10 warnings) [Stephen L Arnold] +- Update maintainer info and spec test cmd. [Stephen L Arnold] + + * update coverage value for delta/base, allow digits only +- Use updated bandit action and workflow excludes (exclude test) + [Stephen L Arnold] + + * also fix missing PR event check in coverage workflow +- Use current org-level coverage workflow. [Stephen L Arnold] + + * increase fetch depth and update regex + * updated action deps, relaxed run criteria + * go back to "normal" tokens, remove permission hacks + * still needs more job isolation => refactor for another day + +Other +~~~~~ +- Use buildbot account. [Katelyn Gigante] +- Use ACCESS_TOKEN secret rather than provided GITHUB_TOKEN. [Katelyn + Gigante] + + Should fix the coverage badge + + +v0.6.1 (2021-11-24) +------------------- + +Changes +~~~~~~~ +- Add shallow checkout for testing. [Stephen L Arnold] +- Bump comment action to latest release, verify checkout depth. [Stephen + L Arnold] + + * see: https://github.com/marocchino/sticky-pull-request-comment/issues/298 + in upstream action repo + +Fixes +~~~~~ +- Use workflow PR target and checkout params. [Stephen L Arnold] +- Split coverage (checkout) job from PR comment job. [Stephen L Arnold] +- Use correct tox env cmd for single platform/version. [Stephen L + Arnold] diff --git a/conda/meta.yaml b/conda/meta.yaml index e3272a05..209d9cc7 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -1,5 +1,5 @@ {% set name = "pystache" %} -{% set version = "0.6.1.dev0" %} +{% set version = "0.6.2" %} package: name: {{ name|lower }} @@ -40,7 +40,7 @@ test: - pystache-test about: - home: https://github.com/sarnold/pystache + home: https://github.com/PennyDreadfulMTG/pystache license: MIT license_family: MIT license_file: LICENSE From 52f72a045ef57c776db502c27837f7f6c19b450d Mon Sep 17 00:00:00 2001 From: Stephen L Arnold Date: Wed, 14 Sep 2022 19:00:27 -0700 Subject: [PATCH 12/12] chg: dev: update pypi publish step to use api token plus readme cleanup * using release workflow to publish pypi packages needs first-time setup * first see the upstream readme for how to setup the token secret * then uncomment the publish step in release.yml and commit https://github.com/pypa/gh-action-pypi-publish * finally push a tag and wait.... Signed-off-by: Stephen L Arnold --- .github/workflows/release.yml | 11 ++++++----- README.rst | 24 +++++++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 09941a87..cbf7300a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,7 +50,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: packages - path: ./dist/pystache* + path: ./dist/pystache-* create_release: name: Create Release @@ -83,12 +83,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ env.VERSION }} - name: Release v${{ env.VERSION }} + name: Release ${{ env.VERSION }} body_path: CHANGES.md draft: false prerelease: false files: | - packages/pystache* + packages/pystache-* # When a GitHub release is made, upload the artifacts to PyPI upload: @@ -105,7 +105,8 @@ jobs: run: find . -maxdepth 2 -name pystache-\* -type f # - name: Publish bdist and sdist packages -# uses: pypa/gh-action-pypi-publish@v1.4.1 +# uses: pypa/gh-action-pypi-publish@release/v1 # with: -# password: ${{ secrets.pypi_password }} +# password: ${{ secrets.PYPI_API_TOKEN }} # packages_dir: packages/ +# print_hash: true diff --git a/README.rst b/README.rst index 2aa6efe8..4dd2f014 100644 --- a/README.rst +++ b/README.rst @@ -46,7 +46,17 @@ Pystache is tested with: JSON support is needed only for the command-line interface and to run the spec tests; PyYAML can still be used (see the Develop section). -Official support for Python 2 will end with Pystache version 0.6.0. +Official support for Python 2 has ended with Pystache version 0.6.0. + + +.. note:: This project uses versioningit_ to generate and maintain the + version file, which only gets included in the sdist/wheel + packages. In a fresh clone, running any of the tox_ commands + should generate the current version file. + +.. _versioningit: https://github.com/jwodder/versioningit +.. _tox: https://github.com/tox-dev/tox + Quick Start =========== @@ -179,17 +189,17 @@ default to values set in Pystache's ``defaults`` module. Develop ======= -To test from a source distribution (without installing): +To test from a source distribution (without installing):: $ python test_pystache.py To test Pystache with multiple versions of Python (with a single -command!) and different platforms, you can use [tox](https://pypi.python.org/pypi/tox): +command!) and different platforms, you can use [tox](https://pypi.python.org/pypi/tox):: $ pip install tox $ tox -e py -To run tests on multiple versions with coverage, run: +To run tests on multiple versions with coverage, run:: $ tox -e py38-linux,py39-linux # for example @@ -197,17 +207,17 @@ To run tests on multiple versions with coverage, run: The source distribution tests also include doctests and tests from the Mustache spec. To include tests from the Mustache spec in your test -runs: +runs:: $ git submodule update --init The test harness parses the spec's (more human-readable) yaml files if `PyYAML `__ is present. Otherwise, -it parses the json files. To install PyYAML-- +it parses the json files. To install PyYAML:: $ pip install pyyaml # note this is installed automatically by tox -Once the submodule is available, you can run the full test set with: +Once the submodule is available, you can run the full test set with:: $ tox -e setup ext/spec/specs