summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTizenOpenSource <tizenopensrc@samsung.com>2023-12-22 17:22:40 +0900
committerTizenOpenSource <tizenopensrc@samsung.com>2023-12-22 17:22:40 +0900
commit5efffcb792056674f04c67a35e28c8da5b146464 (patch)
tree77255bf2a673daba3808c5ea806090d9e5e8ac3a
parent7e49c80df47208a56b72e98221d3b4cf868bc585 (diff)
downloadpython3-Cheetah-5efffcb792056674f04c67a35e28c8da5b146464.tar.gz
python3-Cheetah-5efffcb792056674f04c67a35e28c8da5b146464.tar.bz2
python3-Cheetah-5efffcb792056674f04c67a35e28c8da5b146464.zip
Imported Upstream version 3.3.2b2upstream/3.3.2b2
-rw-r--r--.github/workflows/test-publish.yaml124
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml130
-rw-r--r--ANNOUNCE.rst43
-rw-r--r--Cheetah/CacheRegion.py4
-rwxr-xr-xCheetah/CheetahWrapper.py21
-rw-r--r--Cheetah/Compiler.py52
-rwxr-xr-xCheetah/DirectiveAnalyzer.py6
-rw-r--r--Cheetah/Django.py4
-rw-r--r--Cheetah/DummyTransaction.py2
-rw-r--r--Cheetah/ErrorCatchers.py2
-rw-r--r--Cheetah/FileUtils.py15
-rwxr-xr-xCheetah/Filters.py2
-rw-r--r--Cheetah/ImportHooks.py11
-rw-r--r--Cheetah/ImportManager.py19
-rw-r--r--Cheetah/LoadTemplate.py2
-rwxr-xr-xCheetah/NameMapper.py10
-rw-r--r--Cheetah/Parser.py13
-rw-r--r--Cheetah/SettingsManager.py8
-rw-r--r--Cheetah/SourceReader.py2
-rw-r--r--Cheetah/Template.py32
-rw-r--r--Cheetah/TemplateCmdLineIface.py2
-rw-r--r--Cheetah/Templates/_SkeletonPage.py3
-rwxr-xr-xCheetah/Tests/CheetahWrapper.py10
-rw-r--r--Cheetah/Tests/NameMapper_pure.py41
-rwxr-xr-xCheetah/Tests/SyntaxAndOutput.py37
-rwxr-xr-xCheetah/Tests/Test.py76
-rw-r--r--Cheetah/Tests/Unicode.py50
-rw-r--r--Cheetah/Utils/WebInputMixin.py2
-rw-r--r--Cheetah/Utils/htmlDecode.py2
-rwxr-xr-xCheetah/Version.py4
-rw-r--r--Cheetah/__init__.py2
-rw-r--r--Cheetah/compat.py2
-rw-r--r--Cheetah/convertTmplPathToModuleName.py2
-rw-r--r--LATEST-CHANGES.rst12
-rw-r--r--LICENSE2
-rw-r--r--MANIFEST.in2
-rw-r--r--README.rst79
-rw-r--r--SetupConfig.py5
-rw-r--r--SetupTools.py2
-rw-r--r--appveyor.yml122
-rw-r--r--devscripts/CI/appveyor_install_pypy.cmd7
-rwxr-xr-xdevscripts/CI/ghactions-release (renamed from devscripts/CI/travisci-release)30
-rwxr-xr-xdevscripts/CI/pip-install.py7
-rw-r--r--devscripts/CI/run_with_env.cmd88
-rw-r--r--devscripts/RELEASE-CHECKLIST20
-rwxr-xr-xdevscripts/build-all-docs2
-rwxr-xr-xdevscripts/postrelease6
-rwxr-xr-xdevscripts/prerelease13
-rwxr-xr-xdevscripts/prerelease-tag2
-rwxr-xr-xdevscripts/push-all4
-rwxr-xr-xdevscripts/release34
-rw-r--r--devscripts/requirements/requirements.txt1
-rw-r--r--devscripts/requirements/requirements_dev.txt3
-rw-r--r--devscripts/requirements/requirements_tox.txt2
-rwxr-xr-xdevscripts/setup10
-rw-r--r--devscripts/test-cheetah.cmd2
-rw-r--r--docs/api/Cheetah.Tests.NameMapper_pure.rst7
-rw-r--r--docs/authors.rst3
-rw-r--r--docs/developers.rst6
-rw-r--r--docs/download.rst2
-rw-r--r--docs/news.rst89
-rwxr-xr-xdocs/rebuild2
-rw-r--r--docs/users_guide/gettingStarted.rst4
-rw-r--r--tox.ini24
65 files changed, 573 insertions, 756 deletions
diff --git a/.github/workflows/test-publish.yaml b/.github/workflows/test-publish.yaml
new file mode 100644
index 0000000..b216b2a
--- /dev/null
+++ b/.github/workflows/test-publish.yaml
@@ -0,0 +1,124 @@
+name: Test, build, publish
+
+# Run tests (all branches),
+# for tags build wheels, publish wheels to PyPI and Github Releases.
+
+on: [push, pull_request]
+
+jobs:
+ run-tests:
+ env:
+ not_in_conda: "[]"
+
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ python-version: ["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "pypy3.7"]
+ include:
+ - os: ubuntu-latest
+ os-name: Linux
+ pip-cache-path: ~/.cache/pip
+ - os: macos-latest
+ os-name: MacOS
+ pip-cache-path: ~/Library/Caches/pip
+ - os: windows-latest
+ os-name: w32
+ pip-cache-path: ~\AppData\Local\pip\Cache
+ exclude:
+ - os: windows-latest
+ python-version: "pypy3.7"
+
+ name: Python ${{ matrix.python-version }} @ ${{ matrix.os-name }}
+ runs-on: ${{ matrix.os }}
+
+ steps:
+
+ # Setup Python/pip
+ - uses: actions/checkout@v2
+ # Python 3.7 is needed for ghactions-release script
+ - uses: s-weigand/setup-conda@v1
+ with:
+ conda-channels: conda-forge
+ python-version: "3.7"
+ if: ${{ matrix.python-version == '2.7' && runner.os != 'Windows' && startsWith(github.ref, 'refs/tags/') }}
+ - uses: s-weigand/setup-conda@v1
+ with:
+ conda-channels: conda-forge
+ python-version: ${{ matrix.python-version }}
+ if: ${{ !contains(fromJSON(env.not_in_conda), matrix.python-version) }}
+ - uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+ if: ${{ contains(fromJSON(env.not_in_conda), matrix.python-version) }}
+ - name: Cache pip
+ uses: actions/cache@v3
+ with:
+ path: ${{ matrix.pip-cache-path }}
+ key: ${{ runner.os }}-pip
+
+ # Setup tox
+ - name: Install dependencies
+ run: |
+ python --version
+ python -m ensurepip
+ python -m pip install --upgrade pip setuptools wheel
+ pip --version
+ pip install --upgrade virtualenv "tox >= 3.15, < 4"
+ - name: Set TOXENV
+ run: |
+ import os, sys
+ ld_library_path = None
+ if hasattr(sys, 'pypy_version_info'):
+ toxenv = 'pypy3'
+ else:
+ pyver = '%d%d' % tuple(sys.version_info[:2])
+ if os.name == 'posix':
+ if pyver == '27': # Python 2.7 on Linux requires `$LD_LIBRARY_PATH`
+ ld_library_path = os.path.join(
+ os.path.dirname(os.path.dirname(sys.executable)), 'lib')
+ toxenv = 'py%s' % pyver
+ if os.name == 'posix':
+ toxenv += ',py%s-flake8' % pyver
+ with open(os.environ['GITHUB_ENV'], 'a') as f:
+ if ld_library_path:
+ f.write('LD_LIBRARY_PATH=' + ld_library_path + '\n')
+ f.write('TOXENV=' + toxenv + '\n')
+ print(toxenv)
+ shell: python
+
+ - name: Run tox
+ run: |
+ python -c "import os; print(os.environ['TOXENV'])"
+ tox --version
+ tox
+
+ - name: Build and publish sdist and wheel on Unix
+ run: |
+ devscripts/CI/ghactions-release
+ env:
+ TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
+ TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
+ if: ${{ runner.os != 'Windows' && startsWith(github.ref, 'refs/tags/') }}
+ - name: Build and publish wheel on w32
+ run: |
+ pip install -U pip setuptools twine wheel
+ python setup.py bdist_wheel
+ twine upload --disable-progress-bar --skip-existing dist\*
+ if: ${{ runner.os == 'Windows' && startsWith(github.ref, 'refs/tags/') }}
+ env:
+ TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
+ TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
+ - name: Publish wheel to Releases
+ uses: ncipollo/release-action@v1
+ with:
+ artifacts: "dist/*"
+ allowUpdates: true
+ bodyFile: "LATEST-CHANGES.rst"
+ omitBodyDuringUpdate: true
+ omitNameDuringUpdate: true
+ omitPrereleaseDuringUpdate: true
+ prerelease: true
+ replacesArtifacts: false
+ skipIfReleaseExists: false
+ updateOnlyUnreleased: false
+ if: ${{ startsWith(github.ref, 'refs/tags/') }}
diff --git a/.gitignore b/.gitignore
index f42d00c..2b1008f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,7 @@
*.so
.eggs/
.tox/
-Cheetah3.egg-info/
+CT3.egg-info/
build
dist
docs/*.html
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 6b34bfc..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,130 +0,0 @@
-os: linux
-
-dist: xenial
-
-language: python
-
-python:
- - "2.7"
-
-cache: pip
-
-addons:
- apt:
- packages:
- - patchelf
-
-matrix:
- include:
- - python: "2.7"
- env: TOXENV=py27
- - python: "2.7"
- arch: arm64-graviton2
- group: edge
- virt: lxd
- env: TOXENV=py27
- - python: "3.5"
- env: TOXENV=py34 TOXPYTHON=/home/travis/virtualenv/python3.4.8/bin/python3.4
- - python: "3.5"
- arch: arm64-graviton2
- group: edge
- virt: lxd
- env: TOXENV=py34 TOXPYTHON=/home/travis/virtualenv/python3.4.10/bin/python3.4
- - python: "3.5"
- env: TOXENV=py35
- - python: "3.5"
- arch: arm64-graviton2
- group: edge
- virt: lxd
- env: TOXENV=py35
- - python: "3.6"
- env: TOXENV=py36
- - python: "3.6"
- arch: arm64-graviton2
- group: edge
- virt: lxd
- env: TOXENV=py36
- - python: "3.7"
- env: TOXENV=py37
- - python: "3.7"
- arch: arm64-graviton2
- group: edge
- virt: lxd
- env: TOXENV=py37
- - python: "3.8"
- env: TOXENV=py38
- - python: "3.8"
- arch: arm64-graviton2
- group: edge
- virt: lxd
- env: TOXENV=py38
- - python: "3.9"
- env: TOXENV=py39
- - python: "3.9"
- arch: arm64-graviton2
- group: edge
- virt: lxd
- env: TOXENV=py39
- - python: "2.7"
- env: TOXENV=py27-flake8
- - python: "3.9"
- env: TOXENV=py39-flake8
- - os: osx
- # No version of Python is available via virtualenv on OS X workers, see https://github.com/travis-ci/travis-ci/issues/2312
- language: generic
- env: TOXENV=py27
- - os: osx
- language: generic
- env: TOXENV=py35
- - os: osx
- language: generic
- env: TOXENV=py36
- - os: osx
- language: generic
- env: TOXENV=py37
- - os: osx
- language: generic
- env: TOXENV=py38
- - os: osx
- language: generic
- env: TOXENV=py39
- - python: "pypy2.7-6.0"
- env: TOXENV=pypy
-
- fast_finish: true
-
-before_install:
- - |
- if [ "$TRAVIS_OS_NAME" = 'osx' -a "$TOXENV" != "py27" ]; then
- curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
- bash Miniconda3-latest-MacOSX-x86_64.sh -b -p "$HOME/miniconda3"
- REQUIRED_PYTHON_VERSION=$(python -c "import os; toxenv = os.environ['TOXENV']; print('.'.join(list(toxenv[2:])))")
- ~/miniconda3/bin/conda create -y -n "$TOXENV" python="$REQUIRED_PYTHON_VERSION"
- . ~/miniconda3/bin/activate "$TOXENV"
- fi
- - |
- if [ "$TRAVIS_OS_NAME" = 'linux' -a "$TOXENV" = "py34" ]; then
- # Manually install Python 3.4 to run tox under Python 3.5 and tests with Python 3.4
- if [ "$TRAVIS_CPU_ARCH" = 'arm64' ]; then
- _UBUNTU_PYTHON_ARCH=aarch64
- else
- _UBUNTU_PYTHON_ARCH=x86_64
- fi
- curl -sSf --retry 5 -o python-3.4.tar.bz2 https://storage.googleapis.com/travis-ci-language-archives/python/binaries/ubuntu/16.04/$_UBUNTU_PYTHON_ARCH/python-3.4.tar.bz2
- sudo tar xjf python-3.4.tar.bz2 --directory /
- fi
-
-install:
- - travis_retry pip install --upgrade "pip<19.2" "setuptools<44" "tox>=3.15" ppu
-
-script:
- - tox
-
-before_cache:
- - remove-old-files.py -o 180 ~/.cache/pip
-
-deploy:
- provider: script
- script: devscripts/CI/travisci-release
- on:
- tags: true
diff --git a/ANNOUNCE.rst b/ANNOUNCE.rst
index 409ecee..d1453f1 100644
--- a/ANNOUNCE.rst
+++ b/ANNOUNCE.rst
@@ -1,37 +1,32 @@
Hello!
-I'm pleased to announce version 3.2.7b1, the 1st beta
-for minor feature release 3.2.7 of branch 3.2 of CheetahTemplate3.
+I'm pleased to announce version 3.3.2b2, the 1st beta release
+of release 3.3.2 of branch 3.3 of CheetahTemplate3.
What's new in CheetahTemplate3
==============================
-The contributors for this release are:
-N Protokowicz, Enzo Conty, Andrea Mennucci, Saiprasad Kale, odidev.
-Many thanks!
-
-Minor features:
-
- - Load from JSON file to searchlist (similar to loading from pickle).
+The contributor for this release is nate.k. Thanks!
Bug fixes:
- - Fix ``filetype`` for Python 2 in ``Template``.
+ - Fixed printing to stdout in ``CheetahWrapper``.
-Build, CI:
+Code style:
- - Build wheels for ``aarch64`` at Travis; publish them at PyPI.
+ - Fixed a ``F811`` warning from ``flake8``:
+ redefinition of unused 'join' in ``ImportManager.py``.
-Tests:
+CI:
- - ``tox.ini``: Limit ``VIRTUALENV_PIP`` version for Python 3.4.
+ - CI(GHActions): Install all Python and PyPy versions from ``conda-forge``.
What is CheetahTemplate3
========================
-Cheetah3 is a free and open source template engine.
+Cheetah3 is a free and open source (MIT) Python template engine.
It's a fork of the original CheetahTemplate library.
Python 2.7 or 3.4+ is required.
@@ -43,11 +38,8 @@ Where is CheetahTemplate3
Site:
https://cheetahtemplate.org/
-Development:
-https://github.com/CheetahTemplate3
-
Download:
-https://pypi.org/project/Cheetah3/3.2.7b1
+https://pypi.org/project/CT3/3.3.2b2
News and changes:
https://cheetahtemplate.org/news.html
@@ -55,10 +47,23 @@ https://cheetahtemplate.org/news.html
StackOverflow:
https://stackoverflow.com/questions/tagged/cheetah
+Mailing lists:
+https://sourceforge.net/p/cheetahtemplate/mailman/
+
+Development:
+https://github.com/CheetahTemplate3
+
+Developer Guide:
+https://cheetahtemplate.org/dev_guide/
+
Example
=======
+Install::
+
+ $ pip install CT3 # (or even "ct3")
+
Below is a simple example of some Cheetah code, as you can see it's practically
Python. You can import, inherit and define methods just like in a regular Python
module, since that's what your Cheetah templates are compiled to :) ::
diff --git a/Cheetah/CacheRegion.py b/Cheetah/CacheRegion.py
index 230e8ba..153aec9 100644
--- a/Cheetah/CacheRegion.py
+++ b/Cheetah/CacheRegion.py
@@ -25,7 +25,7 @@ except ImportError:
from md5 import md5
import time
-import Cheetah.CacheStore
+from . import CacheStore
class CacheItem(object):
@@ -105,7 +105,7 @@ class CacheRegion(object):
self._regionID = regionID
self._templateCacheIdPrefix = templateCacheIdPrefix
if not cacheStore:
- cacheStore = Cheetah.CacheStore.MemoryCacheStore()
+ cacheStore = CacheStore.MemoryCacheStore()
self._cacheStore = cacheStore
self._wrappedCacheDataStore = _CacheDataStoreWrapper(
cacheStore, keyPrefix=templateCacheIdPrefix + ':' + regionID + ':')
diff --git a/Cheetah/CheetahWrapper.py b/Cheetah/CheetahWrapper.py
index a466477..11da748 100755
--- a/Cheetah/CheetahWrapper.py
+++ b/Cheetah/CheetahWrapper.py
@@ -14,11 +14,11 @@ except ImportError: # PY3
import pickle as pickle
from optparse import OptionParser
-from Cheetah.Compiler import DEFAULT_COMPILER_SETTINGS
-from Cheetah.Template import Template
-from Cheetah.Utils.Misc import mkdirsWithPyInitFiles
-from Cheetah.Version import Version
-from Cheetah.compat import PY2
+from .Compiler import DEFAULT_COMPILER_SETTINGS
+from .Template import Template
+from .Utils.Misc import mkdirsWithPyInitFiles
+from .Version import Version
+from .compat import PY2
optionDashesRE = re.compile(R"^-{1,2}")
moduleNameRE = re.compile(R"^[a-zA-Z_][a-zA-Z_0-9]*$")
@@ -227,7 +227,7 @@ Files are %s""", args, pprint.pformat(vars(opts)), files)
if opts.print_settings:
print()
print('>> Available Cheetah compiler settings:')
- from Cheetah.Compiler import _DEFAULT_COMPILER_SETTINGS
+ from .Compiler import _DEFAULT_COMPILER_SETTINGS
listing = _DEFAULT_COMPILER_SETTINGS
listing.sort(key=lambda _l: _l[0][0].lower())
@@ -266,7 +266,7 @@ Files are %s""", args, pprint.pformat(vars(opts)), files)
self._compileOrFill()
def fill(self):
- from Cheetah.ImportHooks import install
+ from .ImportHooks import install
install()
self._compileOrFill()
@@ -291,7 +291,7 @@ you do have write permission to and re-run the tests.""")
os.remove(TEST_WRITE_FILENAME)
# @@MO: End ugly kludge.
import unittest
- from Cheetah.Tests import Test
+ from .Tests import Test
verbosity = 1
if '-q' in self.testOpts:
verbosity = 0
@@ -329,7 +329,8 @@ you do have write permission to and re-run the tests.""")
fprintfMessage(sys.stderr, format, *args)
def error(self, format, *args):
- """Always print a warning message to stderr and exit with an error code.
+ """
+ Always print a warning message to stderr and exit with an error code.
"""
fprintfMessage(sys.stderr, format, *args)
sys.exit(1)
@@ -591,7 +592,7 @@ you do have write permission to and re-run the tests.""")
pysrc = TemplateClass.compile(file=sys.stdin,
compilerSettings=compilerSettings,
returnAClass=False)
- output = pysrc
+ output = pysrc if PY2 else pysrc.decode()
else:
output = str(TemplateClass(file=sys.stdin,
compilerSettings=compilerSettings))
diff --git a/Cheetah/Compiler.py b/Cheetah/Compiler.py
index 9254ed0..61c7468 100644
--- a/Cheetah/Compiler.py
+++ b/Cheetah/Compiler.py
@@ -19,16 +19,16 @@ import warnings
import copy
import codecs
-from Cheetah.Version import Version, VersionTuple
-from Cheetah.SettingsManager import SettingsManager
-from Cheetah.Utils.Indenter import indentize # an undocumented preprocessor
-from Cheetah import NameMapper
-from Cheetah.Parser import Parser, ParseError, specialVarRE, \
+from .Version import Version, VersionTuple
+from .SettingsManager import SettingsManager
+from .Utils.Indenter import indentize # an undocumented preprocessor
+from . import NameMapper
+from .Parser import Parser, ParseError, specialVarRE, \
STATIC_CACHE, REFRESH_CACHE, SET_GLOBAL, SET_MODULE, \
unicodeDirectiveRE, encodingDirectiveRE, escapedNewlineRE
-from Cheetah.compat import PY2, string_type, unicode
+from .compat import PY2, string_type, unicode
-from Cheetah.NameMapper import valueForName, valueFromSearchList, \
+from .NameMapper import valueForName, valueFromSearchList, \
valueFromFrameOrSearchList
VFFSL = valueFromFrameOrSearchList
VFSL = valueFromSearchList
@@ -108,7 +108,7 @@ _DEFAULT_COMPILER_SETTINGS = [
'The filters *must* return the expr or raise an expression, '
'they can modify the expr if needed'),
('templateMetaclass', None,
- 'Strictly optional, only will work with new-style basecalsses as well'),
+ 'Strictly optional, only will work with new-style baseclasses as well'),
('i18NFunctionName', 'self.i18n', ''),
('cheetahVarStartToken', '$', ''),
@@ -136,7 +136,8 @@ DEFAULT_COMPILER_SETTINGS = \
class GenUtils(object):
- """An abstract baseclass for the Compiler classes that provides methods that
+ """
+ An abstract baseclass for the Compiler classes that provides methods that
perform generic utility functions or generate pieces of output code from
information passed in by the Parser baseclass. These methods don't do any
parsing themselves.
@@ -473,7 +474,8 @@ class MethodCompiler(GenUtils):
self._pendingStrConstChunks = [strConst]
def commitStrConst(self):
- """Add the code for outputting the pending strConst without chopping off
+ """
+ Add the code for outputting the pending strConst without chopping off
any whitespace from it.
"""
if not self._pendingStrConstChunks:
@@ -1749,6 +1751,11 @@ class ModuleCompiler(SettingsManager, GenUtils):
self._moduleHeaderLines = []
self._moduleDocStringLines = []
self._specialVars = {}
+ # we might have been moved to be a sub-package
+ if "__spec__" in globals():
+ package = __spec__.parent # noqa: F821 undefined name '__spec__'
+ else:
+ package = __package__
self._importStatements = [
"import sys",
"import os",
@@ -1760,18 +1767,19 @@ class ModuleCompiler(SettingsManager, GenUtils):
"from os.path import getmtime, exists",
"import time",
"import types",
- "from Cheetah.Version import MinCompatibleVersion as "
- "RequiredCheetahVersion",
- "from Cheetah.Version import MinCompatibleVersionTuple "
- "as RequiredCheetahVersionTuple",
- "from Cheetah.Template import Template",
- "from Cheetah.DummyTransaction import *",
- "from Cheetah.NameMapper import NotFound, "
- "valueForName, valueFromSearchList, valueFromFrameOrSearchList",
- "from Cheetah.CacheRegion import CacheRegion",
- "import Cheetah.Filters as Filters",
- "import Cheetah.ErrorCatchers as ErrorCatchers",
- "from Cheetah.compat import unicode",
+ "from %s.Version import MinCompatibleVersion as "
+ "RequiredCheetahVersion" % package,
+ "from %s.Version import MinCompatibleVersionTuple "
+ "as RequiredCheetahVersionTuple" % package,
+ "from %s.Template import Template" % package,
+ "from %s.DummyTransaction import *" % package,
+ "from %s.NameMapper import NotFound, "
+ "valueForName, valueFromSearchList, "
+ "valueFromFrameOrSearchList" % package,
+ "from %s.CacheRegion import CacheRegion" % package,
+ "import %s.Filters as Filters" % package,
+ "import %s.ErrorCatchers as ErrorCatchers" % package,
+ "from %s.compat import unicode" % package,
]
self._importedVarNames = ['sys',
diff --git a/Cheetah/DirectiveAnalyzer.py b/Cheetah/DirectiveAnalyzer.py
index da513a2..5e77c3d 100755
--- a/Cheetah/DirectiveAnalyzer.py
+++ b/Cheetah/DirectiveAnalyzer.py
@@ -3,9 +3,9 @@
import os
import pprint
-from Cheetah import Parser
-from Cheetah import Compiler
-from Cheetah import Template
+from . import Parser
+from . import Compiler
+from . import Template
class Analyzer(Parser.Parser):
diff --git a/Cheetah/Django.py b/Cheetah/Django.py
index f7b2826..882d408 100644
--- a/Cheetah/Django.py
+++ b/Cheetah/Django.py
@@ -1,4 +1,4 @@
-import Cheetah.Template
+from . import Template
def render(template_file, **kwargs):
@@ -13,5 +13,5 @@ def render(template_file, **kwargs):
import django.http
import django.template.loader
source, loader = django.template.loader.find_template_source(template_file)
- t = Cheetah.Template.Template(source, searchList=[kwargs])
+ t = Template.Template(source, searchList=[kwargs])
return django.http.HttpResponse(t.__str__())
diff --git a/Cheetah/DummyTransaction.py b/Cheetah/DummyTransaction.py
index e6c8d1e..23d1619 100644
--- a/Cheetah/DummyTransaction.py
+++ b/Cheetah/DummyTransaction.py
@@ -9,7 +9,7 @@ specific DummyTransaction or DummyResponse behavior
'''
import logging
-from Cheetah.compat import unicode
+from .compat import unicode
class DummyResponseFailure(Exception):
diff --git a/Cheetah/ErrorCatchers.py b/Cheetah/ErrorCatchers.py
index aad302d..655cb78 100644
--- a/Cheetah/ErrorCatchers.py
+++ b/Cheetah/ErrorCatchers.py
@@ -1,6 +1,6 @@
import time
-from Cheetah.NameMapper import NotFound
+from .NameMapper import NotFound
class Error(Exception):
diff --git a/Cheetah/FileUtils.py b/Cheetah/FileUtils.py
index 628b31a..be9c33f 100644
--- a/Cheetah/FileUtils.py
+++ b/Cheetah/FileUtils.py
@@ -4,7 +4,7 @@ import os
import os.path
import re
from tempfile import NamedTemporaryFile
-from Cheetah.compat import string_type
+from .compat import string_type
def _escapeRegexChars(
@@ -23,27 +23,30 @@ def findFiles(*args, **kw):
def replaceStrInFiles(files, theStr, repl):
- """Replace all instances of 'theStr' with 'repl' for each file in the 'files'
+ """
+ Replace all instances of 'theStr' with 'repl' for each file in the 'files'
list. Returns a dictionary with data about the matches found.
This is like string.replace() on a multi-file basis.
This function is a wrapper around the FindAndReplace class. See its
- docstring for more details."""
+ docstring for more details.
+ """
pattern = _escapeRegexChars(theStr)
return FindAndReplace(files, pattern, repl).results()
def replaceRegexInFiles(files, pattern, repl):
-
- """Replace all instances of regex 'pattern' with 'repl' for each file in the
+ """
+ Replace all instances of regex 'pattern' with 'repl' for each file in the
'files' list. Returns a dictionary with data about the matches found.
This is like re.sub on a multi-file basis.
This function is a wrapper around the FindAndReplace class. See its
- docstring for more details."""
+ docstring for more details.
+ """
return FindAndReplace(files, pattern, repl).results()
diff --git a/Cheetah/Filters.py b/Cheetah/Filters.py
index 08e29c1..6d0f600 100755
--- a/Cheetah/Filters.py
+++ b/Cheetah/Filters.py
@@ -6,7 +6,7 @@
#filter results in output filters Cheetah's $placeholders .
#transform results in a filter on the entirety of the output
'''
-from Cheetah.compat import unicode
+from .compat import unicode
# Additional entities WebSafe knows how to transform. No need to include
# '<', '>' or '&' since those will have been done already.
diff --git a/Cheetah/ImportHooks.py b/Cheetah/ImportHooks.py
index c0dadac..68674cf 100644
--- a/Cheetah/ImportHooks.py
+++ b/Cheetah/ImportHooks.py
@@ -22,10 +22,10 @@ except ImportError: # PY2
from threading import RLock
import traceback
-from Cheetah import ImportManager
-from Cheetah.ImportManager import DirOwner
-from Cheetah.Compiler import Compiler
-from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
+from . import ImportManager
+from .ImportManager import DirOwner
+from .Compiler import Compiler
+from .convertTmplPathToModuleName import convertTmplPathToModuleName
_installed = False
@@ -121,7 +121,8 @@ def install(templateFileExtensions=('.tmpl',)):
global _installed
if not _installed:
CheetahDirOwner.templateFileExtensions = templateFileExtensions
- if isinstance(builtin.__import__, types.BuiltinFunctionType):
+ if isinstance(builtin.__import__,
+ (types.BuiltinFunctionType, types.FunctionType)):
global __oldimport__
ImportManager.__oldimport__ = __oldimport__ = builtin.__import__
ImportManager._globalOwnerTypes.insert(0, CheetahDirOwner)
diff --git a/Cheetah/ImportManager.py b/Cheetah/ImportManager.py
index 8117f11..95cab96 100644
--- a/Cheetah/ImportManager.py
+++ b/Cheetah/ImportManager.py
@@ -20,7 +20,7 @@ This is a hacked/documented version of Gordon McMillan's iu.py. I have:
import marshal
import py_compile
import sys
-from Cheetah.compat import PY2, string_type, new_module, get_suffixes, \
+from .compat import PY2, string_type, new_module, get_suffixes, \
load_module_from_file, RecursionError
if PY2:
import imp
@@ -60,14 +60,15 @@ def _os_bootstrap():
elif 'mac' in names:
from mac import stat, getcwd
- def join(a, b):
- if a == '':
- return b
- if ':' not in a:
- a = ':' + a
- if a[-1:] != ':':
- a = a + ':'
- return a + b
+ if join is None:
+ def join(a, b):
+ if a == '':
+ return b
+ if ':' not in a:
+ a = ':' + a
+ if a[-1:] != ':':
+ a = a + ':'
+ return a + b
else:
raise ImportError('no os specific module found')
diff --git a/Cheetah/LoadTemplate.py b/Cheetah/LoadTemplate.py
index ec5ae2b..12b52b7 100644
--- a/Cheetah/LoadTemplate.py
+++ b/Cheetah/LoadTemplate.py
@@ -1,6 +1,6 @@
import os
import sys
-from Cheetah.ImportHooks import CheetahDirOwner
+from .ImportHooks import CheetahDirOwner
def loadTemplateModule(templatePath, debuglevel=0):
diff --git a/Cheetah/NameMapper.py b/Cheetah/NameMapper.py
index 3c16dff..7c09e37 100755
--- a/Cheetah/NameMapper.py
+++ b/Cheetah/NameMapper.py
@@ -142,8 +142,9 @@ been compiled or falls back to the Python version if not.
import inspect
from pprint import pformat
+import sys
-from Cheetah.compat import PY2
+from .compat import PY2
if PY2:
from collections import Mapping
else:
@@ -263,7 +264,9 @@ def hasName(obj, name):
try:
- from Cheetah._namemapper import NotFound, valueForKey, valueForName, \
+ if getattr(sys, '_cheetah_namemapper_pure', False):
+ raise ValueError # Not an error, just a way to skip ``_namemapper``
+ from ._namemapper import NotFound, valueForKey, valueForName, \
valueFromSearchList, valueFromFrameOrSearchList, valueFromFrame
C_VERSION = True
except Exception:
@@ -378,7 +381,8 @@ def example():
'item': 'itemval',
'subDict': {'nestedMethod': a.method3}
}
- # b = 'this is local b'
+
+ b = 'this is local b' # noqa: F841 local variable assigned but never used
print(valueForKey(a.dic, 'subDict'))
print(valueForName(a, 'dic.item'))
diff --git a/Cheetah/Parser.py b/Cheetah/Parser.py
index 5b33783..6b406cf 100644
--- a/Cheetah/Parser.py
+++ b/Cheetah/Parser.py
@@ -13,10 +13,10 @@ import re
import types
import inspect
-from Cheetah.SourceReader import SourceReader
-from Cheetah.Unspecified import Unspecified
-from Cheetah.Macros.I18n import I18n
-from Cheetah.compat import PY2, string_type, unicode
+from .SourceReader import SourceReader
+from .Unspecified import Unspecified
+from .Macros.I18n import I18n
+from .compat import PY2, string_type, unicode
if PY2:
from tokenize import pseudoprog
else:
@@ -893,7 +893,8 @@ class _LowLevelParser(SourceReader):
return varnames
def getCheetahVar(self, plain=False, skipStartToken=False):
- """This is called when parsing inside expressions. Cache tokens are only
+ """
+ This is called when parsing inside expressions. Cache tokens are only
valid in placeholders so this method discards any cache tokens found.
"""
if not skipStartToken:
@@ -2390,7 +2391,7 @@ class _HighLevelParser(_LowLevelParser):
macroSrc,
'%end def'])
- from Cheetah.Template import Template
+ from .Template import Template
templateAPIClass = self.setting('templateAPIClassForDefMacro',
default=Template)
compilerSettings = self.setting('compilerSettingsForDefMacro',
diff --git a/Cheetah/SettingsManager.py b/Cheetah/SettingsManager.py
index ac6e598..fc16df3 100644
--- a/Cheetah/SettingsManager.py
+++ b/Cheetah/SettingsManager.py
@@ -11,7 +11,7 @@ try:
from StringIO import StringIO
except ImportError:
from io import StringIO
-from Cheetah.compat import PY2
+from .compat import PY2
numberRE = re.compile(Number)
@@ -121,7 +121,8 @@ class _SettingsCollector(object):
return self.readSettingsFromModule(module)
def readSettingsFromConfigFileObj(self, inFile, convert=True):
- """Return the settings from a config file that uses the syntax accepted by
+ """
+ Return the settings from a config file that uses the syntax accepted by
Python's standard ConfigParser module (like Windows .ini files).
NOTE:
@@ -203,7 +204,8 @@ class _SettingsCollector(object):
class SettingsManager(_SettingsCollector):
- """A mixin class that provides facilities for managing application settings.
+ """
+ A mixin class that provides facilities for managing application settings.
SettingsManager is designed to work well with nested settings dictionaries
of any depth.
diff --git a/Cheetah/SourceReader.py b/Cheetah/SourceReader.py
index a45f1eb..f2b3683 100644
--- a/Cheetah/SourceReader.py
+++ b/Cheetah/SourceReader.py
@@ -1,7 +1,7 @@
"""SourceReader class for Cheetah's Parser and CodeGenerator
"""
import re
-from Cheetah.compat import unicode
+from .compat import unicode
EOLre = re.compile(r'[ \f\t]*(?:\r\n|\r|\n)')
EOLZre = re.compile(r'(?:\r\n|\r|\n|\Z)')
diff --git a/Cheetah/Template.py b/Cheetah/Template.py
index 3ff156e..4aac607 100644
--- a/Cheetah/Template.py
+++ b/Cheetah/Template.py
@@ -24,24 +24,24 @@ import pprint
import cgi # Used by .webInput() if the template is a CGI script.
import types
-from Cheetah import ErrorCatchers # for placeholder tags
-from Cheetah import Filters # the output filters
-from Cheetah.CacheRegion import CacheRegion
-from Cheetah.CacheStore import MemoryCacheStore # , MemcachedCacheStore
-from Cheetah.Compiler import Compiler
-from Cheetah.NameMapper import NotFound, valueFromSearchList
-from Cheetah.Parser import ParseError, SourceReader
+from . import ErrorCatchers # for placeholder tags
+from . import Filters # the output filters
+from .CacheRegion import CacheRegion
+from .CacheStore import MemoryCacheStore # , MemcachedCacheStore
+from .Compiler import Compiler
+from .NameMapper import NotFound, valueFromSearchList
+from .Parser import ParseError, SourceReader
# Base classes for Template
-from Cheetah.Servlet import Servlet
-from Cheetah.Unspecified import Unspecified
-from Cheetah.Utils.Indenter import Indenter # and for placeholders
-from Cheetah.Utils.WebInputMixin import _Converter, _lookup, \
+from .Servlet import Servlet
+from .Unspecified import Unspecified
+from .Utils.Indenter import Indenter # and for placeholders
+from .Utils.WebInputMixin import _Converter, _lookup, \
NonNumericInputError
-from Cheetah.Version import MinCompatibleVersion
-from Cheetah.Version import convertVersionStringToTuple, \
+from .Version import MinCompatibleVersion
+from .Version import convertVersionStringToTuple, \
MinCompatibleVersionTuple
-from Cheetah.compat import PY2, string_type, unicode
-from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
+from .compat import PY2, string_type, unicode
+from .convertTmplPathToModuleName import convertTmplPathToModuleName
try:
from threading import Lock
@@ -1514,7 +1514,7 @@ class Template(Servlet):
Type 'python yourtemplate.py --help to see what it's capabable of.
"""
- from Cheetah.TemplateCmdLineIface import CmdLineIface
+ from .TemplateCmdLineIface import CmdLineIface
CmdLineIface(templateObj=self).run()
##################################################
diff --git a/Cheetah/TemplateCmdLineIface.py b/Cheetah/TemplateCmdLineIface.py
index e14559a..38c236c 100644
--- a/Cheetah/TemplateCmdLineIface.py
+++ b/Cheetah/TemplateCmdLineIface.py
@@ -9,7 +9,7 @@ except ImportError:
from pickle import load
from json import load as jsonload
-from Cheetah.Version import Version
+from .Version import Version
class Error(Exception):
diff --git a/Cheetah/Templates/_SkeletonPage.py b/Cheetah/Templates/_SkeletonPage.py
index 1e0fcc5..e4590f9 100644
--- a/Cheetah/Templates/_SkeletonPage.py
+++ b/Cheetah/Templates/_SkeletonPage.py
@@ -57,7 +57,8 @@ class _SkeletonPage(Template):
self._bodyTagAttribs = {}
def metaTags(self):
- """Return a formatted vesion of the self._metaTags dictionary, using the
+ """
+ Return a formatted vesion of the self._metaTags dictionary, using the
formatMetaTags function from Cheetah.Macros.HTML"""
return self.formatMetaTags(self._metaTags)
diff --git a/Cheetah/Tests/CheetahWrapper.py b/Cheetah/Tests/CheetahWrapper.py
index a98eb14..70c57b4 100755
--- a/Cheetah/Tests/CheetahWrapper.py
+++ b/Cheetah/Tests/CheetahWrapper.py
@@ -214,11 +214,13 @@ Found %(result)r"""
status, output = self.assertPosixSubprocess(cmd)
if not nonzero:
- self.assertEqual(status, 0, '''Subprocess exited with a non-zero status (%d)
- %s''' % (status, output))
+ self.assertEqual(status, 0,
+ '''Subprocess exited with a non-zero status (%d)
+ %s''' % (status, output))
else:
- self.assertNotEqual(status, 0, '''Subprocess exited with a zero status (%d)
- %s''' % (status, output))
+ self.assertNotEqual(status, 0,
+ '''Subprocess exited with a zero status (%d)
+ %s''' % (status, output))
return output
def go(self, cmd, expectedStatus=0, expectedOutputSubstring=None):
diff --git a/Cheetah/Tests/NameMapper_pure.py b/Cheetah/Tests/NameMapper_pure.py
deleted file mode 100644
index 0bbc7d9..0000000
--- a/Cheetah/Tests/NameMapper_pure.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import sys
-import unittest
-
-try:
- from Cheetah import _namemapper # noqa
-except ImportError:
- # _namemapper hasn't been compiled so Tests/NameMapper.py
- # tests pure-python NameMapper.py; no need to duplicate these tests.
- pass
-
-
-def _setNameMapperFunctions():
- from Cheetah.NameMapper import NotFound, \
- valueForName, valueFromSearchList, valueFromFrame, \
- valueFromFrameOrSearchList
- from Cheetah.Tests import NameMapper
- for func in [
- NotFound, valueForName, valueFromSearchList,
- valueFromFrame, valueFromFrameOrSearchList
- ]:
- setattr(NameMapper, func.__name__, func)
-
-
-def setUpModule():
- if 'Cheetah.NameMapper' in sys.modules:
- del sys.modules['Cheetah.NameMapper']
- sys.modules['Cheetah._namemapper'] = None # emulate absence of the module
- _setNameMapperFunctions()
-
-
-def tearDownModule():
- del sys.modules['Cheetah.NameMapper']
- del sys.modules['Cheetah._namemapper']
- del sys.modules['Cheetah.Tests.NameMapper']
- _setNameMapperFunctions() # restore NameMapper
-
-
-class NameMapperTest(unittest.TestCase):
- def test_valueForName(self):
- from Cheetah.NameMapper import valueForName
- self.assertEqual(valueForName('upper', 'upper', True), 'UPPER')
diff --git a/Cheetah/Tests/SyntaxAndOutput.py b/Cheetah/Tests/SyntaxAndOutput.py
index a2ee63c..0e0f6dd 100755
--- a/Cheetah/Tests/SyntaxAndOutput.py
+++ b/Cheetah/Tests/SyntaxAndOutput.py
@@ -300,7 +300,9 @@ class Backslashes(OutputTest):
"\ \ " + "\n\n\n\n\n\n\n\n\n")
def test8(self):
- """ single line from an apache conf file with single quotes and many NEWLINES
+ """
+ Single line from an apache conf file
+ with single quotes and many NEWLINES
"""
self.verify(
@@ -794,18 +796,18 @@ class UnicodeDirective(OutputTest):
self.verify("#unicode latin-1\n1234",
u"1234")
- self.verify("#unicode latin-1\n1234ü",
- u"1234ü")
- self.verify("#unicode: latin-1\n1234ü",
- u"1234ü")
- self.verify("# unicode : latin-1\n1234ü",
- u"1234ü")
+ self.verify("#unicode latin-1\n1234?",
+ u"1234?")
+ self.verify("#unicode: latin-1\n1234?",
+ u"1234?")
+ self.verify("# unicode : latin-1\n1234?",
+ u"1234?")
- self.verify(u"#unicode latin-1\n1234ü",
- u"1234ü")
+ self.verify(u"#unicode latin-1\n1234?",
+ u"1234?")
- self.verify("#encoding latin-1\n1234ü",
- u"1234ü")
+ self.verify("#encoding latin-1\n1234?",
+ u"1234?")
class Placeholders_Esc(OutputTest):
@@ -2148,7 +2150,8 @@ class SetDirective(OutputTest):
def test5(self):
"""#set with a dictionary"""
- self.verify("""#set $testDict = {'one':'one1','two':'two2','three':'three3'}
+ self.verify("""\
+#set $testDict = {'one':'one1','two':'two2','three':'three3'}
$testDict.one
$testDict.two""",
"one1\ntwo2")
@@ -2820,14 +2823,16 @@ class ExtendsDirective(OutputTest):
def test1(self):
"""#extends Cheetah.Templates._SkeletonPage"""
- self.verify("""#from Cheetah.Templates._SkeletonPage import _SkeletonPage
+ self.verify("""\
+#from Cheetah.Templates._SkeletonPage import _SkeletonPage
#extends _SkeletonPage
#implements respond
$spacer()
""",
'<img src="spacer.gif" width="1" height="1" alt="" />\n')
- self.verify("""#from Cheetah.Templates._SkeletonPage import _SkeletonPage
+ self.verify("""\
+#from Cheetah.Templates._SkeletonPage import _SkeletonPage
#extends _SkeletonPage
#implements respond(foo=1234)
$spacer()$foo
@@ -3050,9 +3055,9 @@ class GetVar(OutputTest): # Template.getVar()
"1234")
def test6(self):
- """$getVar('$') raises ValueError
+ """$getVar('$') raises ValueError or NotFound(LookupError)
"""
- with self.assertRaises(ValueError):
+ with self.assertRaises((ValueError, LookupError)):
self.verify("$getVar('$')", "never get here")
diff --git a/Cheetah/Tests/Test.py b/Cheetah/Tests/Test.py
index 293f88f..08e79d4 100755
--- a/Cheetah/Tests/Test.py
+++ b/Cheetah/Tests/Test.py
@@ -12,43 +12,61 @@ TODO
"""
import sys
-import unittest
-from Cheetah.Tests import Analyzer
-from Cheetah.Tests import CheetahWrapper
-from Cheetah.Tests import Filters
-from Cheetah.Tests import ImportHooks
-from Cheetah.Tests import LoadTemplate
-from Cheetah.Tests import Misc
-from Cheetah.Tests import NameMapper
-from Cheetah.Tests import NameMapper_pure
-from Cheetah.Tests import Parser
-from Cheetah.Tests import Regressions
-from Cheetah.Tests import SyntaxAndOutput
-from Cheetah.Tests import Template
-from Cheetah.Tests import TemplateCmdLineIface
-from Cheetah.Tests import Unicode
+args_l = len(sys.argv)
+if args_l == 1:
+ pass
+elif args_l == 2 and sys.argv[1] == 'test':
+ pass
+elif args_l == 2 and sys.argv[1] == '--namemapper-pure':
+ try:
+ from Cheetah import _namemapper # noqa
+ except ImportError:
+ # _namemapper hasn't been compiled so Tests/NameMapper.py
+ # tests pure-python NameMapper.py; no need to duplicate these tests.
+ print('Ok')
+ sys.exit(0)
+ sys.modules['Cheetah._namemapper'] = None
+ sys._cheetah_namemapper_pure = True
+else:
+ sys.exit('Wrong argument or wrong number of arguments')
+
+import unittest # noqa: E402 module level import not at top of file
+
+from Cheetah.Tests import Analyzer # noqa: E402
+from Cheetah.Tests import CheetahWrapper # noqa: E402
+from Cheetah.Tests import Filters # noqa: E402
+from Cheetah.Tests import ImportHooks # noqa: E402
+from Cheetah.Tests import LoadTemplate # noqa: E402
+from Cheetah.Tests import Misc # noqa: E402
+from Cheetah.Tests import NameMapper # noqa: E402
+from Cheetah.Tests import Parser # noqa: E402
+from Cheetah.Tests import Regressions # noqa: E402
+from Cheetah.Tests import SyntaxAndOutput # noqa: E402
+from Cheetah.Tests import Template # noqa: E402
+from Cheetah.Tests import TemplateCmdLineIface # noqa: E402
+from Cheetah.Tests import Unicode # noqa: E402
SyntaxAndOutput.install_eols()
suites = [
- unittest.findTestCases(Analyzer),
- unittest.findTestCases(Filters),
- unittest.findTestCases(ImportHooks),
- unittest.findTestCases(LoadTemplate),
- unittest.findTestCases(Misc),
- unittest.findTestCases(NameMapper),
- unittest.findTestCases(Parser),
- unittest.findTestCases(Regressions),
- unittest.findTestCases(SyntaxAndOutput),
- unittest.findTestCases(Template),
- unittest.findTestCases(TemplateCmdLineIface),
- unittest.findTestCases(Unicode),
- unittest.findTestCases(NameMapper_pure),
+ unittest.defaultTestLoader.loadTestsFromModule(Analyzer),
+ unittest.defaultTestLoader.loadTestsFromModule(Filters),
+ unittest.defaultTestLoader.loadTestsFromModule(ImportHooks),
+ unittest.defaultTestLoader.loadTestsFromModule(LoadTemplate),
+ unittest.defaultTestLoader.loadTestsFromModule(Misc),
+ unittest.defaultTestLoader.loadTestsFromModule(NameMapper),
+ unittest.defaultTestLoader.loadTestsFromModule(Parser),
+ unittest.defaultTestLoader.loadTestsFromModule(Regressions),
+ unittest.defaultTestLoader.loadTestsFromModule(SyntaxAndOutput),
+ unittest.defaultTestLoader.loadTestsFromModule(Template),
+ unittest.defaultTestLoader.loadTestsFromModule(TemplateCmdLineIface),
+ unittest.defaultTestLoader.loadTestsFromModule(Unicode),
]
if not sys.platform.startswith('java'):
- suites.append(unittest.findTestCases(CheetahWrapper))
+ suites.append(
+ unittest.defaultTestLoader.loadTestsFromModule(CheetahWrapper))
if __name__ == '__main__':
if 'xml' in sys.argv:
diff --git a/Cheetah/Tests/Unicode.py b/Cheetah/Tests/Unicode.py
index bd23933..a60b361 100644
--- a/Cheetah/Tests/Unicode.py
+++ b/Cheetah/Tests/Unicode.py
@@ -1,6 +1,5 @@
# -*- encoding: utf8 -*-
-from glob import glob
import os
from shutil import rmtree
import tempfile
@@ -13,33 +12,28 @@ from Cheetah.compat import PY2, unicode, load_module_from_file
class CommandLineTest(unittest.TestCase):
def createAndCompile(self, source):
- fd, sourcefile = tempfile.mkstemp()
- os.close(fd)
- os.remove(sourcefile)
- sourcefile = sourcefile.replace('-', '_')
-
- if PY2:
- fd = open('%s.tmpl' % sourcefile, 'w')
- else:
- fd = open('%s.tmpl' % sourcefile, 'w', encoding='utf-8')
- fd.write(source)
- fd.close()
-
- wrap = CheetahWrapper.CheetahWrapper()
- wrap.main(['cheetah', 'compile',
- '--encoding=utf-8', '--settings=encoding="utf-8"',
- '--quiet', '--nobackup', sourcefile])
- module_name = os.path.split(sourcefile)[1]
- module = load_module_from_file(
- module_name, module_name, sourcefile + '.py')
- template = getattr(module, module_name)
- os.remove('%s.tmpl' % sourcefile)
- for sourcefile_py in glob('%s.py*' % sourcefile): # *.py[co]
- os.remove(sourcefile_py)
- __pycache__ = os.path.join(os.path.dirname(sourcefile), '__pycache__')
- if os.path.exists(__pycache__): # PY3
- rmtree(__pycache__)
- return template
+ tmpDir = tempfile.mkdtemp()
+ try:
+ sourcefile = os.path.join(tmpDir, "source")
+
+ if PY2:
+ fd = open('%s.tmpl' % sourcefile, 'w')
+ else:
+ fd = open('%s.tmpl' % sourcefile, 'w', encoding='utf-8')
+ fd.write(source)
+ fd.close()
+
+ wrap = CheetahWrapper.CheetahWrapper()
+ wrap.main(['cheetah', 'compile',
+ '--encoding=utf-8', '--settings=encoding="utf-8"',
+ '--quiet', '--nobackup', sourcefile])
+ module_name = os.path.split(sourcefile)[1]
+ module = load_module_from_file(
+ module_name, module_name, sourcefile + '.py')
+ template = getattr(module, module_name)
+ return template
+ finally:
+ rmtree(tmpDir, True)
class JBQ_UTF8_Test1(unittest.TestCase):
diff --git a/Cheetah/Utils/WebInputMixin.py b/Cheetah/Utils/WebInputMixin.py
index 9c06c08..b753bb0 100644
--- a/Cheetah/Utils/WebInputMixin.py
+++ b/Cheetah/Utils/WebInputMixin.py
@@ -2,7 +2,7 @@
transaction variables in bulk. See the docstring of webInput for full details.
"""
-from Cheetah.Utils.Misc import useOrRaise
+from .Misc import useOrRaise
class NonNumericInputError(ValueError):
diff --git a/Cheetah/Utils/htmlDecode.py b/Cheetah/Utils/htmlDecode.py
index 286f1f9..e0e1d4c 100644
--- a/Cheetah/Utils/htmlDecode.py
+++ b/Cheetah/Utils/htmlDecode.py
@@ -4,7 +4,7 @@
"""
-from Cheetah.Utils.htmlEncode import htmlCodesReversed
+from .htmlEncode import htmlCodesReversed
def htmlDecode(s, codes=htmlCodesReversed):
diff --git a/Cheetah/Version.py b/Cheetah/Version.py
index 6802c06..7752a0e 100755
--- a/Cheetah/Version.py
+++ b/Cheetah/Version.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
-Version = '3.2.7b1'
-VersionTuple = (3, 2, 7, 'beta', 1)
+Version = '3.3.2b2'
+VersionTuple = (3, 3, 2, 'beta', 2)
MinCompatibleVersion = '3.0.0a1'
MinCompatibleVersionTuple = (3, 0, 0, 'alpha', 1)
diff --git a/Cheetah/__init__.py b/Cheetah/__init__.py
index 1bd8e47..23d0fbf 100644
--- a/Cheetah/__init__.py
+++ b/Cheetah/__init__.py
@@ -13,4 +13,4 @@ Documentation
https://cheetahtemplate.org/
'''
-from Cheetah.Version import * # noqa
+from .Version import * # noqa
diff --git a/Cheetah/compat.py b/Cheetah/compat.py
index 9f42ba7..7d9b052 100644
--- a/Cheetah/compat.py
+++ b/Cheetah/compat.py
@@ -47,7 +47,7 @@ else:
(s, 'rb', 3) for s in importlib.machinery.EXTENSION_SUFFIXES
]
source = [
- (s, 'rU', 1) for s in importlib.machinery.SOURCE_SUFFIXES
+ (s, 'r', 1) for s in importlib.machinery.SOURCE_SUFFIXES
]
bytecode = [
(s, 'rb', 2) for s in importlib.machinery.BYTECODE_SUFFIXES
diff --git a/Cheetah/convertTmplPathToModuleName.py b/Cheetah/convertTmplPathToModuleName.py
index 2dec2ab..221d76a 100644
--- a/Cheetah/convertTmplPathToModuleName.py
+++ b/Cheetah/convertTmplPathToModuleName.py
@@ -1,6 +1,6 @@
import os.path
import string
-from Cheetah.compat import unicode
+from .compat import unicode
letters = None
try:
diff --git a/LATEST-CHANGES.rst b/LATEST-CHANGES.rst
new file mode 100644
index 0000000..e54d861
--- /dev/null
+++ b/LATEST-CHANGES.rst
@@ -0,0 +1,12 @@
+Bug fixes:
+
+ - Fixed printing to stdout in ``CheetahWrapper``.
+
+Code style:
+
+ - Fixed a ``F811`` warning from ``flake8``:
+ redefinition of unused 'join' in ``ImportManager.py``.
+
+CI:
+
+ - CI(GHActions): Install all Python and PyPy versions from ``conda-forge``.
diff --git a/LICENSE b/LICENSE
index bfaa797..339050f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License
-Copyright (c) 2017-2021, Oleg Broytman and contributors.
+Copyright (c) 2017-2022, Oleg Broytman and contributors.
Copyright (c) 2009-2012, R. Tyler Croy and contributors.
Copyright (c) 2001-2008, The Cheetah Development Team: Tavis Rudd, Mike Orr,
Chuck Esterbrook, Ian Bicking.
diff --git a/MANIFEST.in b/MANIFEST.in
index 387faaa..a1379e3 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,7 +2,7 @@ global-include *.py *.rst *.txt
recursive-include Cheetah *.tmpl *.h *.c
recursive-include bin *
recursive-include docs *.css *.html *.js *.gif *.png
-include .travis.yml BUGS LICENSE MANIFEST.in TODO buildandrun tox.ini
+include BUGS LICENSE MANIFEST.in TODO buildandrun tox.ini
include docs/genapidocs docs/Makefile docs/make.bat docs/rebuild
recursive-exclude devscripts *
recursive-exclude docs/_build *
diff --git a/README.rst b/README.rst
index fe4416a..7a6971e 100644
--- a/README.rst
+++ b/README.rst
@@ -1,56 +1,59 @@
-Cheetah Template 3.2.7b1
+Cheetah Template 3.3.2b2
========================
-Cheetah3 is a free and open source template engine and code generation tool.
+Cheetah3 is a free and open source (MIT) Python template engine.
+It's a fork of the original CheetahTemplate library.
-It can be used standalone or combined with other tools and frameworks. Web
-development is its principle use, but Cheetah is very flexible and is also being
-used to generate C++ game code, Java, sql, form emails and even Python code.
+Python 2.7 or 3.4+ is required.
-It's a fork of the original CheetahTemplate library.
-Documentation
--------------
+Where is CheetahTemplate3
+=========================
+
+Site:
+https://cheetahtemplate.org/
+
+Download:
+https://pypi.org/project/CT3/
-For a high-level introduction to Cheetah please refer to the User's Guide
-at https://cheetahtemplate.org/users_guide/index.html
+News and changes:
+https://cheetahtemplate.org/news.html
-Credits
--------
+StackOverflow:
+https://stackoverflow.com/questions/tagged/cheetah
-https://cheetahtemplate.org/authors.html
+Mailing lists:
+https://sourceforge.net/p/cheetahtemplate/mailman/
-https://github.com/CheetahTemplate3/cheetah3/blob/master/LICENSE
+Development:
+https://github.com/CheetahTemplate3
-Praise
-------
+Developer Guide:
+https://cheetahtemplate.org/dev_guide/
-"I'm enamored with Cheetah" - Sam Ruby, senior member of IBM Emerging
-Technologies Group & director of Apache Software Foundation
-"Give Cheetah a try. You won't regret it. ... Cheetah is a truly powerful
-system. ... Cheetah is a serious contender for the 'best of breed' Python
-templating." - Alex Martelli
+Example
+=======
-"People with a strong PHP background absolutely love Cheetah for being Smarty,
-but much, much better." - Marek Baczynski
+Install::
-"I am using Smarty and I know it very well, but compiled Cheetah Templates with
-its inheritance approach is much powerful and easier to use than Smarty." -
-Jaroslaw Zabiello
+ $ pip install CT3 # (or even "ct3")
-"There is no better solution than Cheetah" - Wilk
+Below is a simple example of some Cheetah code, as you can see it's practically
+Python. You can import, inherit and define methods just like in a regular Python
+module, since that's what your Cheetah templates are compiled to :) ::
-"A cheetah template can inherit from a python class, or a cheetah template, and
-a Python class can inherit from a cheetah template. This brings the full power
-of OO programming facilities to the templating system, and simply blows away
-other templating systems" - Mike Meyer
+ #from Cheetah.Template import Template
+ #extends Template
-"Cheetah has successfully been introduced as a replacement for the overweight
-XSL Templates for code generation. Despite the power of XSL (and notably XPath
-expressions), code generation is better suited to Cheetah as templates are much
-easier to implement and manage." - `The FEAR development team
-<http://fear.sourceforge.net/docs/latest/guide/Build.html#id2550573>`_.
+ #set $people = [{'name' : 'Tom', 'mood' : 'Happy'}, {'name' : 'Dick',
+ 'mood' : 'Sad'}, {'name' : 'Harry', 'mood' : 'Hairy'}]
-"I've used Cheetah quite a bit and it's a very good package" - Kevin Dangoor,
-lead developer of TurboGears.
+ <strong>How are you feeling?</strong>
+ <ul>
+ #for $person in $people
+ <li>
+ $person['name'] is $person['mood']
+ </li>
+ #end for
+ </ul>
diff --git a/SetupConfig.py b/SetupConfig.py
index d3a75d1..e6fccb1 100644
--- a/SetupConfig.py
+++ b/SetupConfig.py
@@ -9,7 +9,8 @@ from Cheetah.compat import PY2
# Cheetah3 has already been taken at PyPI,
# CheetahTemplate3 seems to be too long.
-name = 'Cheetah3'
+# CT3 is just right!
+name = 'CT3'
description = "Cheetah is a template engine and code generation tool"
license = "MIT"
author = "Tavis Rudd"
@@ -57,6 +58,8 @@ classifiers = [line.strip() for line in '''\
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
+ Programming Language :: Python :: 3.10
+ Programming Language :: Python :: 3.11
Topic :: Internet :: WWW/HTTP
Topic :: Internet :: WWW/HTTP :: Dynamic Content
Topic :: Internet :: WWW/HTTP :: Site Management
diff --git a/SetupTools.py b/SetupTools.py
index 1d89680..e7f9bbd 100644
--- a/SetupTools.py
+++ b/SetupTools.py
@@ -17,7 +17,7 @@ if sys.platform == 'win32':
# 2.6's distutils.msvc9compiler can raise an IOError when failing to
# find the compiler
ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError,
- IOError)
+ IOError, TypeError)
else:
ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 5da5e53..0000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,122 +0,0 @@
-version: '{branch}-{build}'
-
-cache:
- - '%LOCALAPPDATA%\pip\Cache'
- # Cache chocolatey-installed packages (PyPy)
- - C:\ProgramData\chocolatey\bin -> appveyor.yml, devscripts\CI\appveyor_install_pypy.cmd
- - C:\ProgramData\chocolatey\lib -> appveyor.yml, devscripts\CI\appveyor_install_pypy.cmd
-
-# Match travis
-clone_depth: 50
-
-environment:
- global:
- # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
- # /E:ON and /V:ON options are not enabled in the batch script intepreter
- # See: http://stackoverflow.com/a/13751649/163740
- CMD_IN_ENV: "cmd /E:ON /V:ON /C devscripts\\CI\\run_with_env.cmd"
-
- matrix:
- - TOXENV: "py27"
- PYTHON_VERSION: "2.7"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\Python27"
- - TOXENV: "py27"
- PYTHON_VERSION: "2.7"
- PYTHON_ARCH: "64"
- PYTHON_HOME: "C:\\Python27-x64"
- - TOXENV: "py34"
- PYTHON_VERSION: "3.5"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\Python35"
- PYTHON34_HOME: "C:\\Python34"
- - TOXENV: "py34"
- PYTHON_VERSION: "3.5"
- PYTHON_ARCH: "64"
- PYTHON_HOME: "C:\\Python35-x64"
- PYTHON34_HOME: "C:\\Python34-x64"
- - TOXENV: "py35"
- PYTHON_VERSION: "3.5"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\Python35"
- - TOXENV: "py35"
- PYTHON_VERSION: "3.5"
- PYTHON_ARCH: "64"
- PYTHON_HOME: "C:\\Python35-x64"
- - TOXENV: "py36"
- PYTHON_VERSION: "3.6"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\Python36"
- - TOXENV: "py36"
- PYTHON_VERSION: "3.6"
- PYTHON_ARCH: "64"
- PYTHON_HOME: "C:\\Python36-x64"
- - TOXENV: "py37"
- PYTHON_VERSION: "3.7"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\Python37"
- - TOXENV: "py37"
- PYTHON_VERSION: "3.7"
- PYTHON_ARCH: "64"
- PYTHON_HOME: "C:\\Python37-x64"
- - TOXENV: "py38"
- PYTHON_VERSION: "3.8"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\Python38"
- - TOXENV: "py38"
- PYTHON_VERSION: "3.8"
- PYTHON_ARCH: "64"
- PYTHON_HOME: "C:\\Python38-x64"
- - TOXENV: "py39"
- PYTHON_VERSION: "3.9"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\Python39"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
- - TOXENV: "py39"
- PYTHON_VERSION: "3.9"
- PYTHON_ARCH: "64"
- PYTHON_HOME: "C:\\Python39-x64"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
- - TOXENV: "pypy"
- PYTHON_VERSION: "2.7"
- PYTHON_ARCH: "32"
- PYTHON_HOME: "C:\\ProgramData\\chocolatey\\lib\\python.pypy\\tools\\pypy2.7-v7.3.1-win32"
-
-install:
- # Ensure we use the right python version
- - "SET PATH=%PYTHON_HOME%;%PYTHON_HOME%\\Scripts;%PATH%"
- - "SET PYTHON=%PYTHON_HOME%\\python.exe"
- - "SET TOXPYTHON=%PYTHON%"
- - if "%TOXENV%" == "py34" SET TOXPYTHON=%PYTHON34_HOME%\python.exe
- - if "%TOXENV%" == "pypy" devscripts\CI\appveyor_install_pypy.cmd
- - if "%TOXENV%" == "pypy" SET PYTHON=%PYTHON_HOME%\pypy.exe
- - if "%TOXENV%" == "pypy" SET TOXPYTHON=%PYTHON%
- - "%PYTHON% --version"
- - "%PYTHON% -c \"import struct; print(struct.calcsize('P') * 8)\""
- - "%PYTHON% -m ensurepip"
- - "%PYTHON% -m pip install --upgrade \"pip<19.2\" \"setuptools<44\""
- - "%PYTHON% -m pip install --upgrade \"tox>=3.15\" ppu"
- - "%PYTHON% -m pip --version"
-
-# No build step - _namemapper extension will be built under tox
-build: false
-
-test_script:
- - "%CMD_IN_ENV% %PYTHON% -m tox"
-
-after_test:
- - remove-old-files.py -o 180 %LOCALAPPDATA%\pip\Cache
-
-deploy_script:
- # If tests are successful and we've tested a tag, deploy binary wheel
- # TWINE_USERNAME / TWINE_PASSWORD / TWINE_REPOSITORY_URL
- # must be set in AppVeyor settings.
- - if "%APPVEYOR_REPO_TAG%" == "true" (
- if "%TOXENV%" == "py34" (
- %TOXPYTHON% -m pip install --upgrade "readme-renderer<25.0" "twine<2.0" "wheel==0.31.1"
- ) else (
- %TOXPYTHON% -m pip install --upgrade twine "wheel==0.34.1"
- ) &&
- %CMD_IN_ENV% %TOXPYTHON% setup.py bdist_wheel &&
- twine upload --skip-existing dist\*.whl
- )
diff --git a/devscripts/CI/appveyor_install_pypy.cmd b/devscripts/CI/appveyor_install_pypy.cmd
deleted file mode 100644
index 12470be..0000000
--- a/devscripts/CI/appveyor_install_pypy.cmd
+++ /dev/null
@@ -1,7 +0,0 @@
-REM curl -fsSL -o pypy2.zip https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.10.0-win32.zip
-REM 7z x pypy2.zip -oc:\
-
-REM Borrowed from https://github.com/pytest-dev/pytest/blob/master/scripts/install-pypy.bat
-REM install pypy using choco
-REM redirect to a file because choco install python.pypy is too noisy. If the command fails, write output to console
-choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1)
diff --git a/devscripts/CI/travisci-release b/devscripts/CI/ghactions-release
index cef5f4d..990f677 100755
--- a/devscripts/CI/travisci-release
+++ b/devscripts/CI/ghactions-release
@@ -1,7 +1,7 @@
#! /usr/bin/env bash
set -e
-[[ "$TOXENV" == *-flake8 || "$TOXENV" == pypy* ]] && exit 0
+[[ "$TOXENV" == pypy* ]] && exit 0
umask 022 &&
chmod -R a+rX . &&
@@ -9,12 +9,7 @@ chmod -R a+rX . &&
py=$(python -c "import sys; print('.'.join(sys.version.split('.')[:2]))")
v=$(echo "$py" | sed 's/\.//') &&
-pip install -U "pip<19.2" "setuptools<44" "readme-renderer<25.0" "twine<2.0" &&
-if [ "$py" == 3.4 ]; then
- pip install -U "wheel==0.31.1"
-else
- pip install -U "wheel==0.34.1"
-fi &&
+pip install -U pip setuptools readme-renderer twine wheel &&
python setup.py sdist &&
if [ -d build ]; then find build -name '*.py[co]' -delete; fi &&
@@ -24,32 +19,33 @@ python -m compileall build &&
python -O -m compileall build &&
python setup.py bdist_wheel &&
-if [ "$TRAVIS_OS_NAME" == 'linux' ]; then
+if [ "$RUNNER_OS" == 'Linux' ]; then
+ # auditwheel 5.2+ require patchelf 0.14+
if [ "$py" == 2.7 ]; then
- pyenv global system 3.6.7 2.7.15
- pip3.6 install -U "auditwheel==3.1.0"
+ pip3.7 install -U "auditwheel<5.2"
elif [ "$py" == 3.4 ]; then
pip install -U typing "auditwheel==2.1.1"
else
- pip install -U "auditwheel==3.1.0"
+ pip install -U "auditwheel<5.2"
fi &&
- for f in dist/Cheetah3-*-cp$v-*-linux*.whl; do
+ for f in dist/CT3-*-cp$v-*-linux*.whl; do
if [ "$py" == 2.7 ]; then
- python3.6 -m auditwheel repair -w dist/ "$f"
+ python3.7 -m auditwheel repair -w dist/ "$f"
else
python -m auditwheel repair -w dist/ "$f"
fi &&
rm -f "$f"
done
-elif [ "$TRAVIS_OS_NAME" == 'osx' ]; then
+elif [ "$RUNNER_OS" == 'macOS' ]; then
+
pip install -U delocate
- for f in dist/Cheetah3-*-cp$v-*-macosx*.whl; do
+ for f in dist/CT3-*-cp$v-*-macosx*.whl; do
delocate-wheel -v "$f"
done
fi &&
# TWINE_USERNAME / TWINE_PASSWORD / TWINE_REPOSITORY_URL
-# must be set in Travis settings.
-exec twine upload --skip-existing dist/*
+# must be set in Github Actions settings.
+exec twine upload --disable-progress-bar --skip-existing dist/*
diff --git a/devscripts/CI/pip-install.py b/devscripts/CI/pip-install.py
deleted file mode 100755
index 1b0bd30..0000000
--- a/devscripts/CI/pip-install.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /usr/bin/env python
-
-import subprocess
-import sys
-
-subprocess.check_call([sys.executable, '-m', 'ensurepip'])
-subprocess.check_call([sys.executable, '-m', 'pip', 'install'] + sys.argv[1:])
diff --git a/devscripts/CI/run_with_env.cmd b/devscripts/CI/run_with_env.cmd
deleted file mode 100644
index 5da547c..0000000
--- a/devscripts/CI/run_with_env.cmd
+++ /dev/null
@@ -1,88 +0,0 @@
-:: To build extensions for 64 bit Python 3, we need to configure environment
-:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
-:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
-::
-:: To build extensions for 64 bit Python 2, we need to configure environment
-:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
-:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
-::
-:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific
-:: environment configurations.
-::
-:: Note: this script needs to be run with the /E:ON and /V:ON flags for the
-:: cmd interpreter, at least for (SDK v7.0)
-::
-:: More details at:
-:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
-:: http://stackoverflow.com/a/13751649/163740
-::
-:: Author: Olivier Grisel
-:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
-::
-:: Notes about batch files for Python people:
-::
-:: Quotes in values are literally part of the values:
-:: SET FOO="bar"
-:: FOO is now five characters long: " b a r "
-:: If you don't want quotes, don't include them on the right-hand side.
-::
-:: The CALL lines at the end of this file look redundant, but if you move them
-:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y
-:: case, I don't know why.
-@ECHO OFF
-
-SET COMMAND_TO_RUN=%*
-SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
-SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf
-
-:: Extract the major and minor versions, and allow for the minor version to be
-:: more than 9. This requires the version number to have two dots in it.
-SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1%
-IF "%PYTHON_VERSION:~3,1%" == "." (
- SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1%
-) ELSE (
- SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2%
-)
-
-:: Based on the Python version, determine what SDK version to use, and whether
-:: to set the SDK for 64-bit.
-IF %MAJOR_PYTHON_VERSION% == 2 (
- SET WINDOWS_SDK_VERSION="v7.0"
- SET SET_SDK_64=Y
-) ELSE (
- IF %MAJOR_PYTHON_VERSION% == 3 (
- SET WINDOWS_SDK_VERSION="v7.1"
- IF %MINOR_PYTHON_VERSION% LEQ 4 (
- SET SET_SDK_64=Y
- ) ELSE (
- SET SET_SDK_64=N
- IF EXIST "%WIN_WDK%" (
- :: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/
- REN "%WIN_WDK%" 0wdf
- )
- )
- ) ELSE (
- ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%"
- EXIT 1
- )
-)
-
-IF %PYTHON_ARCH% == 64 (
- IF %SET_SDK_64% == Y (
- ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture
- SET DISTUTILS_USE_SDK=1
- SET MSSdk=1
- "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
- "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
- ECHO Executing: %COMMAND_TO_RUN%
- call %COMMAND_TO_RUN% || EXIT 1
- ) ELSE (
- ECHO Using default MSVC build environment for 64 bit architecture
- ECHO Executing: %COMMAND_TO_RUN%
- call %COMMAND_TO_RUN% || EXIT 1
- )
-) ELSE (
- ECHO Using default MSVC build environment for 32 bit architecture
- ECHO Executing: %COMMAND_TO_RUN%
- call %COMMAND_TO_RUN% || EXIT 1
-)
diff --git a/devscripts/RELEASE-CHECKLIST b/devscripts/RELEASE-CHECKLIST
index 7b4cc87..56617eb 100644
--- a/devscripts/RELEASE-CHECKLIST
+++ b/devscripts/RELEASE-CHECKLIST
@@ -5,9 +5,10 @@
1a. The script checks out the release branch ('maint' for a bug-fix
release, 'master' for minor or major release) and calls editor; update
version, the list of contributors, the list of changes and download URL
- in ANNOUNCE.rst; if it is a stable release - edit docs/news.rst to set
- release date. Edit Version.py and README.rst in the release branch -
- fix versions. Edit section [egg_info] in setup.cfg - set if it is a
+ in ANNOUNCE.rst; copy the list of changes from ANNOUNCE.rst to
+ LATEST-CHANGES.rst; if it is a stable release - edit docs/news.rst to
+ set release date. Edit Version.py and README.rst in the release branch
+ - fix versions. Edit section [egg_info] in setup.cfg - set if it is a
stable or development release. In SetupConfig.py edit "Development
Status" in trove classifiers; edit dev_tag or download URL: if a
non-stable version - append 'dev' and date stamp, for a stable version
@@ -17,15 +18,10 @@
branch and creates the new tag at the head of the release branch. Push
the branch and the tag to start test/build.
-3. Run devscripts/push-all in the development repository to push all
- branches and tags to the public repositories.
-
-4. Run devscripts/release. This generates and uploads new archives to PyPI.
-
-5. Generate new docs using devscripts/build-all-docs. Upload docs using
+3. Generate new docs using devscripts/build-all-docs. Upload docs using
devscripts/publish-docs.
-6. Run devscripts/postrelease. The script checks out master and null-merge
+4. Run devscripts/postrelease. The script checks out master and null-merge
maint. The script restores ANNOUNCE.rst from the previous commit
(HEAD~). It calls editor; update next version, remove the list of
contributors and the list of changes, edit download URL in ANNOUNCE.rst.
@@ -34,8 +30,8 @@
edit "Development Status" in trove classifiers; edit dev_tag or download
URL. Commit. Verify. Fast-forward next to master.
-7. Send announcement to the Cheetah mailing list. For a stable release send
+5. Send announcement to the Cheetah mailing list. For a stable release send
announcements to python and python-announce mailing lists.
-8. Announce new release at Wikipedia
+6. Announce new release at Wikipedia
(https://en.wikipedia.org/wiki/CheetahTemplate).
diff --git a/devscripts/build-all-docs b/devscripts/build-all-docs
index 3f4b8bf..422b1e7 100755
--- a/devscripts/build-all-docs
+++ b/devscripts/build-all-docs
@@ -5,7 +5,7 @@ PROG_DIR="`pwd`" &&
cd .. &&
devscripts/build-docs &&
-rsync -ahP --del --exclude=/.git --exclude=/.nojekyll \
+rsync -ahPv --del --exclude=/.git --exclude=/.nojekyll \
--exclude=/CNAME --exclude=/robots.txt \
docs/html/ ../cheetahtemplate3.github.io/ &&
diff --git a/devscripts/postrelease b/devscripts/postrelease
index c60c856..0837c5b 100755
--- a/devscripts/postrelease
+++ b/devscripts/postrelease
@@ -5,7 +5,7 @@ tag="`python setup.py --version`" &&
. `dirname $0`/split_tag.sh &&
split_tag $tag
-if [ $micro -eq 0 -a $state = final ] &&
+if [ $micro -eq 0 -a \( $state = final -o $state = post \) ] &&
git branch --merged master | grep -Fqw maint; then
git checkout maint &&
git merge --ff-only master &&
@@ -18,5 +18,5 @@ fi &&
git checkout $tag~ ANNOUNCE.rst &&
-`git var GIT_EDITOR` ANNOUNCE.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py &&
-exec git commit --message="Build: Prepare for the next release" --message="[skip ci]" ANNOUNCE.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py
+`git var GIT_EDITOR` ANNOUNCE.rst LATEST-CHANGES.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py &&
+exec git commit --message="Build: Prepare for the next release" --message="[skip ci]" ANNOUNCE.rst LATEST-CHANGES.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py
diff --git a/devscripts/prerelease b/devscripts/prerelease
index 92c116e..97cba02 100755
--- a/devscripts/prerelease
+++ b/devscripts/prerelease
@@ -10,11 +10,18 @@ fi
. `dirname $0`/split_tag.sh &&
split_tag $tag
-if [ $micro -eq 0 -o $state != final ]; then
+if [ $micro -eq 0 -o $state != final -o $state != post ]; then
git checkout master
else
git checkout maint
fi &&
-`git var GIT_EDITOR` ANNOUNCE.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py &&
-exec git commit --message="Release $tag" ANNOUNCE.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py
+if [ $state = final -o $state = post ]; then
+ ghr_prerelease=false
+else
+ ghr_prerelease=true
+fi &&
+sed -Ei "s/(^ +prerelease): .*\$/\1: $ghr_prerelease/" .github/workflows/test-publish.yaml &&
+
+`git var GIT_EDITOR` ANNOUNCE.rst LATEST-CHANGES.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py &&
+exec git commit --message="Release $tag" ANNOUNCE.rst LATEST-CHANGES.rst docs/news.rst Cheetah/Version.py README.rst setup.cfg SetupConfig.py .github/workflows/test-publish.yaml
diff --git a/devscripts/prerelease-tag b/devscripts/prerelease-tag
index 99513b1..75777f3 100755
--- a/devscripts/prerelease-tag
+++ b/devscripts/prerelease-tag
@@ -10,7 +10,7 @@ fi
. `dirname $0`/split_tag.sh &&
split_tag $tag
-if [ $micro -eq 0 -o $state != final ]; then
+if [ $micro -eq 0 -o $state != final -o $state != post ]; then
git checkout master
else
git checkout maint
diff --git a/devscripts/push-all b/devscripts/push-all
deleted file mode 100755
index 90d99d5..0000000
--- a/devscripts/push-all
+++ /dev/null
@@ -1,4 +0,0 @@
-#! /bin/sh
-
- git push --all origin &&
-exec git push --tags origin
diff --git a/devscripts/release b/devscripts/release
deleted file mode 100755
index 561d37f..0000000
--- a/devscripts/release
+++ /dev/null
@@ -1,34 +0,0 @@
-#! /bin/sh
-
-cd "`dirname \"$0\"`"/.. &&
-umask 022 &&
-chmod -R a+rX . &&
-
-set-commit-date.py &&
-devscripts/build-docs &&
-
-if [ ! -d build ]; then mkdir build; fi &&
-python setup.py sdist &&
-
-for py in 2.7 3.4 3.5 3.6 3.7 3.8 3.9; do
- find build -name '*.py[co]' -delete &&
- python$py setup.py build_ext &&
- python$py setup.py build --executable '/usr/bin/env python' &&
- python$py -m compileall build &&
- python$py -O -m compileall build &&
- python$py setup.py bdist_wheel &&
- cd dist &&
- v="`echo $py | sed 's/\.//'`" &&
- for f in Cheetah3-*-cp$v-*-linux_*.whl; do
- if [ $py = 2.7 ]; then
- python3.6 -m auditwheel repair -w . $f
- else
- python$py -m auditwheel repair -w . $f
- fi &&
- rm $f
- done &&
- cd ..
-done &&
-
-twine upload --skip-existing dist/* &&
-exec rm -rf build dist docs/html Cheetah3.egg-info
diff --git a/devscripts/requirements/requirements.txt b/devscripts/requirements/requirements.txt
index 5d2aba7..e69de29 100644
--- a/devscripts/requirements/requirements.txt
+++ b/devscripts/requirements/requirements.txt
@@ -1 +0,0 @@
---install-option=-O2
diff --git a/devscripts/requirements/requirements_dev.txt b/devscripts/requirements/requirements_dev.txt
index e794101..5ccac49 100644
--- a/devscripts/requirements/requirements_dev.txt
+++ b/devscripts/requirements/requirements_dev.txt
@@ -1,5 +1,6 @@
-r requirements.txt
auditwheel
-wheel==0.31.1
+wheel==0.31.1; python_version == '2.7' or python_version == '3.4'
+wheel==0.34.1; python_version >= '3.5'
twine
diff --git a/devscripts/requirements/requirements_tox.txt b/devscripts/requirements/requirements_tox.txt
index 8b5960b..b72a322 100644
--- a/devscripts/requirements/requirements_tox.txt
+++ b/devscripts/requirements/requirements_tox.txt
@@ -1 +1 @@
-tox >= 3.15
+tox >= 3.15, < 4
diff --git a/devscripts/setup b/devscripts/setup
deleted file mode 100755
index 271f497..0000000
--- a/devscripts/setup
+++ /dev/null
@@ -1,10 +0,0 @@
-#! /bin/sh
-
-umask 022 # -rwxr-xr-x
-cd "`dirname \"$0\"`"/.. &&
-
-for py_ver in 2.7 3.4 3.5 3.6 3.7 3.8 3.9; do
- python$py_ver -m pip install --install-option=-O2 --upgrade .
-done &&
-
-exec rm -rf build dist Cheetah3.egg-info MANIFEST *.egg
diff --git a/devscripts/test-cheetah.cmd b/devscripts/test-cheetah.cmd
index 900bdb8..8df0447 100644
--- a/devscripts/test-cheetah.cmd
+++ b/devscripts/test-cheetah.cmd
@@ -3,7 +3,7 @@
SetLocal EnableDelayedExpansion
set SavePATH=%PATH%
-for %%V in (27 34 35 36 37 38 39) do (
+for %%V in (27 34 35 36 37 38 39 310 311) do (
for %%s in (32 64) do (
set PATH=C:\Python%%V-%%s;C:\Python%%V-%%s\Scripts;!SavePATH!
set TOXPYTHON=C:\Python%%V-%%s\python.exe
diff --git a/docs/api/Cheetah.Tests.NameMapper_pure.rst b/docs/api/Cheetah.Tests.NameMapper_pure.rst
deleted file mode 100644
index 927661f..0000000
--- a/docs/api/Cheetah.Tests.NameMapper_pure.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-Cheetah\.Tests\.NameMapper\_pure module
-=======================================
-
-.. automodule:: Cheetah.Tests.NameMapper_pure
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/docs/authors.rst b/docs/authors.rst
index 944cedc..1aba337 100644
--- a/docs/authors.rst
+++ b/docs/authors.rst
@@ -39,4 +39,7 @@ Contributions have been made by:
* Enzo Conty <contact at enzoconty.dev>
* Andrea Mennucci <mennucc1@debian.org>
* odidev <odidev at puresoftware.com>
+* Pierre Ossman <ossman at cendio.se>
+* Michael Gorny <mgorny at gentoo.org>
+* nate.k <nate.k at onetrueloan.com>
* Oleg Broytman <phd@phdru.name>
diff --git a/docs/developers.rst b/docs/developers.rst
index 7f7d328..38191ae 100644
--- a/docs/developers.rst
+++ b/docs/developers.rst
@@ -27,9 +27,9 @@ Anyone and everyone is encouraged to submit patches at any time, but as far
as bugs or feature requests go, we try to file those *first* in the `Cheetah3 Bug Tracker <https://github.com/CheetahTemplate3/cheetah3/issues>`_
and then they can be organized into particular releases as is necessary.
-In addition to the bug tracker, Cheetah uses Travis CI for automating builds
-and test runs (see: `Cheetah at Travis
-<https://travis-ci.com/github/CheetahTemplate3/cheetah3>`_).
+In addition to the bug tracker, Cheetah uses Github Actions
+for automating builds and test runs (see: `Github Actions for Cheetah
+<https://github.com/CheetahTemplate3/cheetah3/actions>`_).
Prior to the tarballing of a release, **all** tests must be passing before the
**next** branch is merged down to the Git **master** branch where the release
diff --git a/docs/download.rst b/docs/download.rst
index 8c318d7..668cc1b 100644
--- a/docs/download.rst
+++ b/docs/download.rst
@@ -2,7 +2,7 @@ Downloading Cheetah
===================
You can download wheels, eggs and tarballs of Cheetah from the `Python
-Package Index <http://pypi.org/project/Cheetah3/>`_.
+Package Index <http://pypi.org/project/CT3/>`_.
You can keep up to date with release candidates or other downloads of
Cheetah by visiting the `CheetahTemplate GitHub page
diff --git a/docs/news.rst b/docs/news.rst
index 0705216..f737cee 100644
--- a/docs/news.rst
+++ b/docs/news.rst
@@ -1,6 +1,95 @@
News
====
+Development (master)
+--------------------
+
+Bug fixes:
+
+ - Fixed printing to stdout in ``CheetahWrapper``.
+
+Code style:
+
+ - Fixed a ``F811`` warning from ``flake8``:
+ redefinition of unused 'join' in ``ImportManager.py``.
+
+CI:
+
+ - CI(GHActions): Install all Python and PyPy versions from ``conda-forge``.
+
+3.3.1 (2022-12-25)
+------------------
+
+Bug fixes:
+
+ - Fixed ``ImportHooks`` under PyPy3.
+
+Tests:
+
+ - Run tests with PyPy3.
+
+CI:
+
+ - Use ``conda`` to install older Pythons
+
+ Ubuntu >= 22 and ``setup-python`` dropped Pythons < 3.7.
+ Use ``s-weigand/setup-conda`` instead of ``setup-python``.
+
+3.3.0.post1 (2022-11-26)
+------------------------
+
+Tests:
+
+ - Run tests with Python 3.11.
+
+ - Fix DeprecationWarning: ``unittest.findTestCases()`` is deprecated. Use
+ ``unittest.TestLoader.loadTestsFromModule()`` instead.
+
+CI:
+
+ - Publish wheels at Github Releases.
+
+3.3.0 (2022-10-10)
+------------------
+
+Great move:
+
+ - PyPI has wrongfully classified project ``Cheetah3`` as "critical".
+ This puts a burden to use 2FA to manage the project at PyPI. To
+ avoid the burden the project is renamed to ``CT3`` at PyPI.
+ There will be no updates for ``Cheetah3``.
+ Sorry for the inconvenience!
+
+Minor features:
+
+ - Use relative imports everywhere.
+
+Tests:
+
+ - Run pure-python ``NameMapper`` tests in a separate process.
+
+ - Fixed a bug in tests with pure-python ``NameMapper``.
+
+ - Add Python 3.10 to ``tox.ini``.
+
+CI:
+
+ - Migrated to GitHub Actions.
+
+ Due to the absent of Python 3.4 at GH Actions tests are not run and
+ wheels are not built. Installation from sources should work.
+
+ Due to GH Actions lacking old compilers for w32/w64 releases for old
+ Python versions (currently 2.7) are packaged without compiled
+ _namemapper.pyd extension. Cheetah can be used without compiled
+ _namemapper.pyd extension. A pure-python replacement should work;
+ ``Cheetah`` imports it automatically if the compiled extension is
+ not available.
+
+ - Stop testing at Travis CI.
+
+ - Stop testing at AppVeyor.
+
3.2.7b1 (2021-07-25)
--------------------
diff --git a/docs/rebuild b/docs/rebuild
index 2161873..e12d662 100755
--- a/docs/rebuild
+++ b/docs/rebuild
@@ -1,4 +1,4 @@
#! /bin/sh
PYTHONPATH=.. make html &&
-exec rsync -ahP --del --exclude=.buildinfo --exclude=objects.inv _build/html .
+exec rsync -ahPv --del --exclude=.buildinfo --exclude=objects.inv _build/html .
diff --git a/docs/users_guide/gettingStarted.rst b/docs/users_guide/gettingStarted.rst
index a094445..d1a9d56 100644
--- a/docs/users_guide/gettingStarted.rst
+++ b/docs/users_guide/gettingStarted.rst
@@ -29,7 +29,7 @@ To install Cheetah in your system-wide Python library:
command is normally 'su root'. On non-POSIX systems such as Windows
NT, login as an administrator.
-#. Run {pip install Cheetah3} at the command prompt.
+#. Run {pip install CT3} at the command prompt.
#. Or download source code and run {python setup.py install}.
@@ -39,7 +39,7 @@ To install Cheetah in your system-wide Python library:
#. If you cannot login as as an administrator install Cheetah as user to your
own home directory: add option {--user} to commands: either
- {pip install --user Cheetah3} or {python setup.py install --user}.
+ {pip install --user CT3} or {python setup.py install --user}.
Cheetah's installation is managed by Python's Distribution
Utilities ('distutils'). There are many options for customization.
diff --git a/tox.ini b/tox.ini
index 307ca53..8449a00 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,37 +1,25 @@
[tox]
minversion = 3.15
-envlist = py27,py3{4,5,6,7,8,9},pypy,py{27,38,39}-flake8
+envlist = py27,py3{4,5,6,7,8,9,10,11},pypy,pypy3,py{27,36,311}-flake8
[testenv]
-basepython =
- py27: {env:TOXPYTHON:python2.7}
- py34: {env:TOXPYTHON:python3.4}
- py35: {env:TOXPYTHON:python3.5}
- py36: {env:TOXPYTHON:python3.6}
- py37: {env:TOXPYTHON:python3.7}
- py38: {env:TOXPYTHON:python3.8}
- py39: {env:TOXPYTHON:python3.9}
- pypy: {env:TOXPYTHON:pypy}
commands =
{envpython} --version
{envpython} -c "import struct; print(struct.calcsize('P') * 8)"
deps =
- pip < 19.2
- setuptools < 44
- Markdown >= 2.0.1, < 3.2
+ Markdown
pygments
-install_command = {envpython} {toxinidir}{/}devscripts{/}CI{/}pip-install.py {opts} {packages}
-passenv = CI TRAVIS TRAVIS_* APPVEYOR DISTUTILS_USE_SDK MSSdk INCLUDE LIB WINDIR
+passenv = CI DISTUTILS_USE_SDK MSSdk INCLUDE LIB WINDIR
setenv =
LC_CTYPE = en_US.UTF-8
- VIRTUALENV_PIP = 19.1.1
-[testenv:{py27,py34,py35,py36,py37,py38,py39,pypy}]
+[testenv:py{27,34,35,36,37,38,39,310,311,py,py3}]
commands =
{[testenv]commands}
{envpython} {envsitepackagesdir}/Cheetah/Tests/Test.py
+ {envpython} {envsitepackagesdir}/Cheetah/Tests/Test.py --namemapper-pure
-[testenv:{py27,py34,py35,py36,py37,py38,py39}-flake8]
+[testenv:py{27,34,35,36,37,38,39,310,311}-flake8]
deps =
flake8
commands =