Cheetah Template Portable

Overview

Cheetah Template Portable is an open source Python-based template engine and code generation framework. It's packaged with a PortableApps.com launcher so you can use it from a cloud folder, portable drive, or local folder without needing to install it on each PC. Learn more about Cheetah Template

Components in this release (3.2.6.post1 Dev Test 1):

Cheetah Template 3.2.6.post1 (64 bit) (https://cheetahtemplate.org/)

Python 3.8.10 (64 bit) (https://github.com/winpython)

PortableAppsFormat 3.5 (https://portableapps.com/)

Bootstrap 4.6.1 (https://github.com/twbs/bootstrap)

jQuery JavaScript Library v2.2.4 (https://jquery.com/)

tether 2.0.0 (https://github.com/shipshapecode/tether)

theme_styles.html (modified) from https://github.com/bofeng/

All of the above components have been integrated and packaged with a PortableApps.com launcher with the appropriate PortableAppsFormat as listed above.

Bootstrap is included with theme_styles.html along with jQuery(jquery.js) and tether(tether.min.js).

Cheetah Template works with Python distribution as mentioned above. As with Cheetah Template Python is also in PortableAppsFormat.

Cheetah Template: Python PortableAppsFormat

Although the Python distribution is derived from WinPython, only Python itself is used. By using the PortableApps.com launcher, a Python shell launches with environment variables configured for Cheetah Template but Python is actually at its core. Here is a snippet of the shell:

__ ____________ __

\ \/ \/ /

\/ * * \/ CHEETAH 3.2.6.post1 Command-Line Tool

\ | /

\ ==----== / by Tavis Rudd <tavis@damnsimple.com>

\__________/ and Mike Orr <sluggoster@gmail.com>

USAGE:

------

cheetah compile [options] [FILES ...] : Compile template definitions

cheetah fill [options] [FILES ...] : Fill template definitions

cheetah help : Print this help message

cheetah options : Print options help message

cheetah test [options] : Run Cheetah's regression tests

: (same as for unittest)

cheetah version : Print Cheetah version number

You may abbreviate the command to the first letter; e.g., 'h' == 'help'.

If FILES is a single "-", read standard input and write standard output.

Run "cheetah options" for the list of valid options.

python –h:

usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...

Options and arguments (and corresponding environment variables):

-b : issue warnings about str(bytes_instance), str(bytearray_instance)

and comparing bytes/bytearray with str. (-bb: issue errors)

-B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x

-c cmd : program passed in as string (terminates option list)

-d : debug output from parser; also PYTHONDEBUG=x

-E : ignore PYTHON* environment variables (such as PYTHONPATH)

-h : print this help message and exit (also --help)

-i : inspect interactively after running script; forces a prompt even

if stdin does not appear to be a terminal; also PYTHONINSPECT=x

-I : isolate Python from the user's environment (implies -E and -s)

-m mod : run library module as a script (terminates option list)

-O : remove assert and __debug__-dependent statements; add .opt-1 before

.pyc extension; also PYTHONOPTIMIZE=x

-OO : do -O changes and also discard docstrings; add .opt-2 before

.pyc extension

-q : don't print version and copyright messages on interactive startup

-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE

-S : don't imply 'import site' on initialization

-u : force the stdout and stderr streams to be unbuffered;

this option has no effect on stdin; also PYTHONUNBUFFERED=x

-v : verbose (trace import statements); also PYTHONVERBOSE=x

can be supplied multiple times to increase verbosity

-V : print the Python version number and exit (also --version)

when given twice, print more information about the build

-W arg : warning control; arg is action:message:category:module:lineno

also PYTHONWARNINGS=arg

-x : skip first line of source, allowing use of non-Unix forms of #!cmd

-X opt : set implementation-specific option. The following options are available

:

-X faulthandler: enable faulthandler

-X showrefcount: output the total reference count and number of used

memory blocks when the program finishes or after each statement in

the

interactive interpreter. This only works on debug builds

-X tracemalloc: start tracing Python memory allocations using the

tracemalloc module. By default, only the most recent frame is store

d in a

traceback of a trace. Use -X tracemalloc=NFRAME to start tracing wi

th a

traceback limit of NFRAME frames

-X showalloccount: output the total count of allocated objects for each

type when the program finishes. This only works when Python was bui

lt with

COUNT_ALLOCS defined

-X importtime: show how long each import takes. It shows module name,

cumulative time (including nested imports) and self time (excluding

nested imports). Note that its output may be broken in multi-thread

ed

application. Typical usage is python3 -X importtime -c 'import asyn

cio'

-X dev: enable CPython's "development mode", introducing additional run

time

checks which are too expensive to be enabled by default. Effect of

the

developer mode:

* Add default warning filter, as -W default

* Install debug hooks on memory allocators: see the PyMem_SetupD

ebugHooks() C function

* Enable the faulthandler module to dump the Python traceback on

a crash

* Enable asyncio debug mode

* Set the dev_mode attribute of sys.flags to True

* io.IOBase destructor logs close() exceptions

-X utf8: enable UTF-8 mode for operating system interfaces, overriding

the default

locale-aware mode. -X utf8=0 explicitly disables UTF-8 mode (even w

hen it would

otherwise activate automatically)

-X pycache_prefix=PATH: enable writing .pyc files to a parallel tree ro

oted at the

given directory instead of to the code tree

--check-hash-based-pycs always|default|never:

control how Python invalidates hash-based .pyc files

file : program read from script file

- : program read from stdin (default; interactive mode if a tty)

arg ...: arguments passed to program in sys.argv[1:]

Other environment variables:

PYTHONSTARTUP: file executed on interactive startup (no default)

PYTHONPATH : ';'-separated list of directories prefixed to the

default module search path. The result is sys.path.

PYTHONHOME : alternate <prefix> directory (or <prefix>;<exec_prefix>).

The default module search path uses <prefix>\python{major}{minor}

.

PYTHONCASEOK : ignore case in 'import' statements (Windows).

PYTHONUTF8: if set to 1, enable the UTF-8 mode.

PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.

PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.

PYTHONHASHSEED: if this variable is set to 'random', a random value is used

to seed the hashes of str and bytes objects. It can also be set to an

integer in the range [0,4294967295] to get hash values with a

predictable seed.

PYTHONMALLOC: set the Python memory allocators and/or install debug hooks

on Python memory allocators. Use PYTHONMALLOC=debug to install debug

hooks.

PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale

coercion behavior. Use PYTHONCOERCECLOCALE=warn to request display of

locale coercion and locale compatibility warnings on stderr.

PYTHONBREAKPOINT: if this variable is set to 0, it disables the default

debugger. It can be set to the callable of your debugger of choice.

PYTHONDEVMODE: enable the development mode.

PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.

Cheetah Template: Cheetah Fill & Cheetah Compile

theme_styles.html

The theme_styles.html exposes the most commonly used Bootstrap components which makes it useful to further customizations.

To create a Cheetah template file theme_styles.tmpl cheetah fill is used. The cheetah command is actually a subcommand of Python (i.e. python cheetah).

cheetah fill

So, the syntax of cheetah fill in the current working directory (without changing directory):

cheetah fill --idir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --odir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --iext=.html --oext=.tmpl theme_styles.html

As an example above the directories specified are provided as samples. Your directory structure might be different as you can always move portable app around as you see fit.

The above automatically creates theme_styles.tmpl in the output directory specified. Note that the encoding is utf-8.

theme_styles.tmpl

With the template definition at hand, it can be altered to store constant values and use inheritance to arrange the template in a hierarchy. Depending on your purpose, you can go with the containment approach.

cheetah compile

To compile theme_styles.tmpl into theme_styles.py, cheetah compile is used. The syntax for cheetah compile in the current working directory (without changing directory):

cheetah compile --idir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --odir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap theme_styles.tmpl

As it is the case again, the above directory structure maybe very different from yours. Again, note the encoding is utf-8.

theme_styles.py

With success in compiling to a Python module and a class, it is very useful that the Python module can be modified to your hearts desired. It is very flexible so you can even integrated at this point to other frameworks for many purposes.

Here is a snippet of the class:

##################################################

## CLASSES

class theme_styles(Template):

##################################################

## CHEETAH GENERATED METHODS

def __init__(self, *args, **KWs):

super(theme_styles, self).__init__(*args, **KWs)

if not self._CHEETAH__instanceInitialized:

cheetahKWArgs = {}

allowedKWs = 'searchList namespaces filter filtersLib errorCatcher'.split()

for k,v in KWs.items():

if k in allowedKWs: cheetahKWArgs[k] = v

self._initCheetahInstance(**cheetahKWArgs)

Cheetah Template: Cheetah Test

Executing cheetah test runs 2177 tests. Most of the tests are very useful to determine the state of the Cheetah Template feature set. With some caveats, the Cheetah Template in PortableAppsFormat passed all tests. The completion of tests is display as:

.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

----------------------------------------------------------------------

Ran 2177 tests in 126.242s

OK

What are the caveats? The next sections will cover all those Cheetah Template and Python configurations, workarounds, and code changes for this release.

Cheetah Template: Python & Cheetah Configurations, Workarounds, Code Changes, Et Cetera

Python & Cheetah Configurations

To start, Cheetah.pth file was placed in site-packages which takes care of cheetah cheetah-compile Scripts path for python.

The cheetah and python shell is configured properly when the PortableApps.com launcher runs. When everything is up you land on the working directory. Of course as long as you are in the shell environment variables are present. You can even launch python interactive mode and all its environment variables are also present.

Workarounds

It is when you change directory in the same shell when things do not work as reliable as it should be. Even though all the environment variables are still valid the cheetah command no longer work and error messages like “Fatal error in launcher: Unable to create process using '"python" or some similar error messages. Recall in previous sections that was mentioned that cheetah is actually a subcommand (i.e. python cheetah). Out of roughly ninety-nine times, one time the shell work as it should but only when manually repeating the shell configurations again even though it was fine. Of course changing back to the working directory everything works as before. A lot of research was put into this issue so some stuff came out from it.

There were many cases of similar and different platforms having similar error issues and so on. Python has so many features at its core including the ability to run multiple versions of Python on the same platform/OS using many methods (i.e. directly executing each Python version, using some virtual environments venv/pyvenv and more). So, one of the workaround is to stay at the current working directory as launched and then specifying the input and out directory as cheetah supports that. As mentioned previously and here again,

cheetah fill --idir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --odir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --iext=.html --oext=.tmpl theme_styles.html

cheetah compile --idir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --odir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap theme_styles.tmpl

As you see, --idir and --odir, would allow sidestepping all that changing working directory stuff. Another workaround is to feed all the Cheetah Template sources to another framework and work from there but that is for another topic entirely. It is not necessary as the cheetah subcommand in a shell works fine if stay within its current limits for this release.

Code Changes

Before getting into code changes, have a read under the headline “Testing your installation” at https://cheetahtemplate.org/users_guide/gettingStarted.html. Remember, “Certain test failures are insignificant.” After examining the source and in the interest of getting cheetah test to pass all tests, code changes were made.

In site-packages\Cheetah\Tests\SyntaxAndOutput.py,

'includeFileName': '..\\..\\Data\\CheetahTemplatePortable64bitTemp\\parseTest.txt',

fp = open('..\\..\\Data\\CheetahTemplatePortable64bitTemp\\backslashes.txt', 'w')

Or do searches for “parseTest.txt” and “backslashes.txt” and you will find them all.

Otherwise, there are many error messages and error codes and not included here.

In site-packages\Cheetah\Tests\CheetahWrapper.py:

##################################################

# TEST CASE CLASSES

class OneFile(CFBase):

"""

substitute 'cheetah' with complete direct path to python.exe and complete direct path to cheetah.exe

at the present time as of january 1, 2022

'cheetah' subcommand = python.exe cheetah.exe

until function calls replace subcommands the crude method of substituting 'cheetah' as mentioned above

works

"""

The above comments say it all. In this release, function calls have not replace subcommands yet. Again, lots of error messages and error codes if the comments above were not followed and again those error messages and error codes are not included here.

Cheetah Template: Compile Codecs Encoding

This is a case of encoding issue with available codecs use by cheetah compile. For some reason every time this is executed,

cheetah compile --idir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --odir=C:\alpha_beta\beta\CheetahTemplatePortable\Other\bootstrap --encoding=utf-8 theme_styles.tmpl

This came up,

UnicodeEncodeError: 'ascii' codec can't encode characters in position 37265-3726

6: ordinal not in range(128)

Eventually it was determined that the encoding compiler setting was not picked up from commandline so a forced utf-8 default setting in the source still did not work. Finally, a code change in site-packages\Cheetah\Compiler.py (self._moduleEncoding) was necessary.

def _setupCompilerState(self):

self._activeClassesList = []

self._finishedClassesList = [] # listed by ordered

self._finishedClassIndex = {} # listed by name

self._moduleDef = None

self._moduleShBang = '#!/usr/bin/env python'

self._moduleEncoding = 'utf-8'

According to many sources including official Python documentations, utf-8 was default for Python beginning with version 3. Again, if another framework were to just take the Cheetah Template source and work with it then the encoding setting is already set elsewhere. Again, this is another topic entirely.

Cheetah Template: PortableAppsFormat Portability Notes

Cheetah Template (and Python) uses %APPDATA% to store its settings and data. Specifically,

\Users\<username>\AppData\Local\Temp\CheetahTemplatePortable64bitTemp

and

\Users\<username>\AppData\Local\pip

are use.

To make the app portable, the PortableApps.com launcher App\AppInfo\Launcher\CheetahTemplatePortable64bit.ini has the

[DirectoriesMove]

CheetahTemplatePortable64bitTemp=%APPDATA%\CheetahTemplatePortable64bitTemp

pip=%APPDATA%\pip

which puts the settings and data in the Data\CheetahTemplatePortable64bitTemp and Data\pip inside the portable app directory.

A word about cheetah test: As long as you do not modify site-packages\Cheetah\Tests\CheetahWrapper.py,

DELETE = True # True to clean up after ourselves, False for debugging.

OUTPUT = False # Normally False, True for debugging.

and turn on debugging, then the temporary directories such as tmp_hr9hz5b, tmp_hr9hz5b\SRC, and so on will be cleaned up after completion of tests.

Besides meeting the portable app definition at https://portableapps.com/about/what_is_a_portable_app, it is very workable in other OS/platform such as Linux, UNIX, BSD, etc. via Wine (winehq.org) & Mac OS X via CrossOver, Wineskin, WineBottler, PlayOnMac.

Finally, “Why PortableApps.com Format and a PortableApps.com Installer?” Perhaps, a read at https://portableapps.com/about/what_is_a_portable_app#whypaf would suffice.