summaryrefslogtreecommitdiffstats
path: root/cobbler
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2007-02-19 15:40:20 -0500
committerJim Meyering <jim@meyering.net>2007-02-19 15:40:20 -0500
commit2bb24f6178d3d930f10906a0e80c7d5f272668f0 (patch)
treee3049895ae7d104d3c7870787bb77056f8bdc1c8 /cobbler
parent4a2197efaa111af43ebfcc4455112a2ce2a89ea7 (diff)
downloadthird_party-cobbler-2bb24f6178d3d930f10906a0e80c7d5f272668f0.tar.gz
third_party-cobbler-2bb24f6178d3d930f10906a0e80c7d5f272668f0.tar.xz
third_party-cobbler-2bb24f6178d3d930f10906a0e80c7d5f272668f0.zip
Removing Cheetah, RHEL4/Centos users can find an RPM, so that's fair.
Diffstat (limited to 'cobbler')
-rw-r--r--cobbler/Cheetah/CacheRegion.py138
-rw-r--r--cobbler/Cheetah/CacheStore.py108
-rw-r--r--cobbler/Cheetah/CheetahWrapper.py589
-rw-r--r--cobbler/Cheetah/DummyTransaction.py58
-rw-r--r--cobbler/Cheetah/ErrorCatchers.py63
-rw-r--r--cobbler/Cheetah/FileUtils.py374
-rw-r--r--cobbler/Cheetah/Filters.py290
-rw-r--r--cobbler/Cheetah/ImportHooks.py139
-rw-r--r--cobbler/Cheetah/ImportManager.py562
-rw-r--r--cobbler/Cheetah/Macros/I18n.py67
-rw-r--r--cobbler/Cheetah/Macros/__init__.py1
-rw-r--r--cobbler/Cheetah/NameMapper.py355
-rw-r--r--cobbler/Cheetah/Parser.py2558
-rw-r--r--cobbler/Cheetah/Servlet.py126
-rw-r--r--cobbler/Cheetah/SettingsManager.py623
-rw-r--r--cobbler/Cheetah/SourceReader.py305
-rw-r--r--cobbler/Cheetah/Template.py1858
-rw-r--r--cobbler/Cheetah/TemplateCmdLineIface.py108
-rw-r--r--cobbler/Cheetah/Templates/SkeletonPage.py273
-rw-r--r--cobbler/Cheetah/Templates/SkeletonPage.tmpl44
-rw-r--r--cobbler/Cheetah/Templates/_SkeletonPage.py216
-rw-r--r--cobbler/Cheetah/Templates/__init__.py1
-rw-r--r--cobbler/Cheetah/Tests/CheetahWrapper.py596
-rw-r--r--cobbler/Cheetah/Tests/FileRefresh.py55
-rw-r--r--cobbler/Cheetah/Tests/NameMapper.py539
-rw-r--r--cobbler/Cheetah/Tests/SyntaxAndOutput.py3170
-rw-r--r--cobbler/Cheetah/Tests/Template.py312
-rw-r--r--cobbler/Cheetah/Tests/Test.py70
-rw-r--r--cobbler/Cheetah/Tests/__init__.py1
-rw-r--r--cobbler/Cheetah/Tests/unittest_local_copy.py977
-rw-r--r--cobbler/Cheetah/Tools/CGITemplate.py78
-rw-r--r--cobbler/Cheetah/Tools/MondoReport.py464
-rw-r--r--cobbler/Cheetah/Tools/MondoReportDoc.txt391
-rw-r--r--cobbler/Cheetah/Tools/RecursiveNull.py23
-rw-r--r--cobbler/Cheetah/Tools/SiteHierarchy.py183
-rw-r--r--cobbler/Cheetah/Tools/__init__.py8
-rw-r--r--cobbler/Cheetah/Unspecified.py9
-rw-r--r--cobbler/Cheetah/Utils/Indenter.py135
-rw-r--r--cobbler/Cheetah/Utils/Misc.py82
-rw-r--r--cobbler/Cheetah/Utils/VerifyType.py82
-rw-r--r--cobbler/Cheetah/Utils/WebInputMixin.py103
-rw-r--r--cobbler/Cheetah/Utils/__init__.py1
-rw-r--r--cobbler/Cheetah/Utils/htmlDecode.py14
-rw-r--r--cobbler/Cheetah/Utils/htmlEncode.py21
-rw-r--r--cobbler/Cheetah/Utils/memcache.py625
-rw-r--r--cobbler/Cheetah/Utils/optik/__init__.py32
-rw-r--r--cobbler/Cheetah/Utils/optik/errors.py52
-rw-r--r--cobbler/Cheetah/Utils/optik/option.py354
-rw-r--r--cobbler/Cheetah/Utils/optik/option_parser.py667
-rw-r--r--cobbler/Cheetah/Version.py58
-rw-r--r--cobbler/Cheetah/__init__.py27
-rwxr-xr-xcobbler/Cheetah/_namemapper.sobin10144 -> 0 bytes
-rw-r--r--cobbler/Cheetah/convertTmplPathToModuleName.py15
53 files changed, 0 insertions, 18000 deletions
diff --git a/cobbler/Cheetah/CacheRegion.py b/cobbler/Cheetah/CacheRegion.py
deleted file mode 100644
index 16de188..0000000
--- a/cobbler/Cheetah/CacheRegion.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# $Id: CacheRegion.py,v 1.3 2006/01/28 04:19:30 tavis_rudd Exp $
-"""Cache holder classes for Cheetah:
-
-Cache regions are defined using the #cache Cheetah directive. Each
-cache region can be viewed as a dictionary (keyed by cacheRegionID)
-handling at least one cache item (the default one). It's possible to add
-cacheItems in a region by using the `varyBy` #cache directive parameter as
-in the following example::
- #def getArticle
- this is the article content.
- #end def
-
- #cache varyBy=$getArticleID()
- $getArticle($getArticleID())
- #end cache
-
-The code above will generate a CacheRegion and add new cacheItem for each value
-of $getArticleID().
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com> and Philippe Normand <phil@base-art.net>
-Version: $Revision: 1.3 $
-Start Date: 2005/06/20
-Last Revision Date: $Date: 2006/01/28 04:19:30 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com> and Philippe Normand <phil@base-art.net>"
-__revision__ = "$Revision: 1.3 $"[11:-2]
-
-import md5
-from time import time as currentTime
-from Cheetah.CacheStore import MemoryCacheStore
-
-class CacheItem:
- """A CacheItem is a container storing:
-
- - cacheID (string)
- - refreshTime (timestamp or None) : last time the cache was refreshed
- - data (string) : the content of the cache
- """
-
- def __init__(self, cacheItemID, cacheStore):
- self._cacheItemID = cacheItemID
- self._cacheStore = cacheStore
- self._refreshTime = None
- self._expiryTime = 0
-
- def hasExpired(self):
- return (self._expiryTime and currentTime() > self._expiryTime)
-
- def setExpiryTime(self, time):
- self._expiryTime = time
-
- def getExpiryTime(self):
- return self._expiryTime
-
- def setData(self, data):
- self._refreshTime = currentTime()
- self._cacheStore.set(self._cacheItemID, data, self._expiryTime)
-
- def getRefreshTime(self):
- return self._refreshTime
-
- def getData(self):
- assert self._refreshTime
- return self._cacheStore.get(self._cacheItemID)
-
- def renderOutput(self):
- """Can be overridden to implement edge-caching"""
- return self.getData() or ""
-
- def clear(self):
- self._cacheStore.delete(self._cacheItemID)
- self._refreshTime = None
-
-class _CacheDataStoreWrapper:
- def __init__(self, dataStore, keyPrefix):
- self._dataStore = dataStore
- self._keyPrefix = keyPrefix
-
- def get(self, key):
- return self._dataStore.get(self._keyPrefix+key)
-
- def delete(self, key):
- self._dataStore.delete(self._keyPrefix+key)
-
- def set(self, key, val, time=0):
- self._dataStore.set(self._keyPrefix+key, val, time=time)
-
-class CacheRegion:
- """ A `CacheRegion` stores some `CacheItem` instances.
-
- This implementation stores the data in the memory of the current process.
- If you need a more advanced data store, create a cacheStore class that works
- with Cheetah's CacheStore protocol and provide it as the cacheStore argument
- to __init__. For example you could use
- Cheetah.CacheStore.MemcachedCacheStore, a wrapper around the Python
- memcached API (http://www.danga.com/memcached).
- """
- _cacheItemClass = CacheItem
-
- def __init__(self, regionID, templateCacheIdPrefix='', cacheStore=None):
- self._isNew = True
- self._regionID = regionID
- self._templateCacheIdPrefix = templateCacheIdPrefix
- if not cacheStore:
- cacheStore = MemoryCacheStore()
- self._cacheStore = cacheStore
- self._wrappedCacheDataStore = _CacheDataStoreWrapper(
- cacheStore, keyPrefix=templateCacheIdPrefix+':'+regionID+':')
- self._cacheItems = {}
-
- def isNew(self):
- return self._isNew
-
- def clear(self):
- " drop all the caches stored in this cache region "
- for cacheItemId in self._cacheItems.keys():
- cacheItem = self._cacheItems[cacheItemId]
- cacheItem.clear()
- del self._cacheItems[cacheItemId]
-
- def getCacheItem(self, cacheItemID):
- """ Lazy access to a cacheItem
-
- Try to find a cache in the stored caches. If it doesn't
- exist, it's created.
-
- Returns a `CacheItem` instance.
- """
- cacheItemID = md5.new(str(cacheItemID)).hexdigest()
-
- if not self._cacheItems.has_key(cacheItemID):
- cacheItem = self._cacheItemClass(
- cacheItemID=cacheItemID, cacheStore=self._wrappedCacheDataStore)
- self._cacheItems[cacheItemID] = cacheItem
- self._isNew = False
- return self._cacheItems[cacheItemID]
diff --git a/cobbler/Cheetah/CacheStore.py b/cobbler/Cheetah/CacheStore.py
deleted file mode 100644
index f1a1840..0000000
--- a/cobbler/Cheetah/CacheStore.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""Provides several CacheStore backends for Cheetah's caching framework. The
-methods provided by these classes have the same semantics as those in the
-python-memcached API, except for their return values:
-
-set(key, val, time=0)
- set the value unconditionally
-add(key, val, time=0)
- set only if the server doesn't already have this key
-replace(key, val, time=0)
- set only if the server already have this key
-get(key, val)
- returns val or raises a KeyError
-delete(key)
- deletes or raises a KeyError
-
-"""
-from time import time as currentTime
-
-from Cheetah.Utils.memcache import Client as MemcachedClient
-
-class Error(Exception):
- pass
-
-class AbstractCacheStore(object):
-
- def set(self, key, val, time=None):
- raise NotImplementedError
-
- def add(self, key, val, time=None):
- raise NotImplementedError
-
- def replace(self, key, val, time=None):
- raise NotImplementedError
-
- def delete(self, key):
- raise NotImplementedError
-
- def get(self, key):
- raise NotImplementedError
-
-class MemoryCacheStore(AbstractCacheStore):
- def __init__(self):
- self._data = {}
-
- def set(self, key, val, time=0):
- self._data[key] = (val, time)
-
- def add(self, key, val, time=0):
- if self._data.has_key(key):
- raise Error('a value for key %r is already in the cache'%key)
- self._data[key] = (val, time)
-
- def replace(self, key, val, time=0):
- if self._data.has_key(key):
- raise Error('a value for key %r is already in the cache'%key)
- self._data[key] = (val, time)
-
- def delete(self, key):
- del self._data[key]
-
- def get(self, key):
- (val, exptime) = self._data[key]
- if exptime and currentTime() > exptime:
- del self._data[key]
- raise KeyError(key)
- else:
- return val
-
- def clear(self):
- self._data.clear()
-
-class MemcachedCacheStore(AbstractCacheStore):
- servers = ('127.0.0.1:11211')
- def __init__(self, servers=None, debug=False):
- if servers is None:
- servers = self.servers
-
- self._client = MemcachedClient(servers, debug)
-
- def set(self, key, val, time=0):
- self._client.set(key, val, time)
-
- def add(self, key, val, time=0):
- res = self._client.add(key, val, time)
- if not res:
- raise Error('a value for key %r is already in the cache'%key)
- self._data[key] = (val, time)
-
- def replace(self, key, val, time=0):
- res = self._client.replace(key, val, time)
- if not res:
- raise Error('a value for key %r is already in the cache'%key)
- self._data[key] = (val, time)
-
- def delete(self, key):
- res = self._client.delete(key, time=0)
- if not res:
- raise KeyError(key)
-
- def get(self, key):
- val = self._client.get(key)
- if val is None:
- raise KeyError(key)
- else:
- return val
-
- def clear(self):
- self._client.flush_all()
diff --git a/cobbler/Cheetah/CheetahWrapper.py b/cobbler/Cheetah/CheetahWrapper.py
deleted file mode 100644
index 68a8598..0000000
--- a/cobbler/Cheetah/CheetahWrapper.py
+++ /dev/null
@@ -1,589 +0,0 @@
-#!/usr/bin/env python
-# $Id: CheetahWrapper.py,v 1.25 2006/02/04 00:59:46 tavis_rudd Exp $
-"""Cheetah command-line interface.
-
-2002-09-03 MSO: Total rewrite.
-2002-09-04 MSO: Bugfix, compile command was using wrong output ext.
-2002-11-08 MSO: Another rewrite.
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com> and Mike Orr <iron@mso.oz.net>
-Version: $Revision: 1.25 $
-Start Date: 2001/03/30
-Last Revision Date: $Date: 2006/02/04 00:59:46 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com> and Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.25 $"[11:-2]
-
-import getopt, glob, os, pprint, re, shutil, sys
-import cPickle as pickle
-
-from Cheetah.Version import Version
-from Cheetah.Template import Template, DEFAULT_COMPILER_SETTINGS
-from Cheetah.Utils.Misc import mkdirsWithPyInitFiles
-from Cheetah.Utils.optik import OptionParser
-
-optionDashesRE = re.compile( R"^-{1,2}" )
-moduleNameRE = re.compile( R"^[a-zA-Z_][a-zA-Z_0-9]*$" )
-
-def fprintfMessage(stream, format, *args):
- if format[-1:] == '^':
- format = format[:-1]
- else:
- format += '\n'
- if args:
- message = format % args
- else:
- message = format
- stream.write(message)
-
-class Error(Exception):
- pass
-
-
-class Bundle:
- """Wrap the source, destination and backup paths in one neat little class.
- Used by CheetahWrapper.getBundles().
- """
- def __init__(self, **kw):
- self.__dict__.update(kw)
-
- def __repr__(self):
- return "<Bundle %r>" % self.__dict__
-
-
-class MyOptionParser(OptionParser):
- standard_option_list = [] # We use commands for Optik's standard options.
-
- def error(self, msg):
- """Print our usage+error page."""
- usage(HELP_PAGE2, msg)
-
- def print_usage(self, file=None):
- """Our usage+error page already has this."""
- pass
-
-
-##################################################
-## USAGE FUNCTION & MESSAGES
-
-def usage(usageMessage, errorMessage="", out=sys.stderr):
- """Write help text, an optional error message, and abort the program.
- """
- out.write(WRAPPER_TOP)
- out.write(usageMessage)
- exitStatus = 0
- if errorMessage:
- out.write('\n')
- out.write("*** USAGE ERROR ***: %s\n" % errorMessage)
- exitStatus = 1
- sys.exit(exitStatus)
-
-
-WRAPPER_TOP = """\
- __ ____________ __
- \ \/ \/ /
- \/ * * \/ CHEETAH %(Version)s Command-Line Tool
- \ | /
- \ ==----== / by Tavis Rudd <tavis@damnsimple.com>
- \__________/ and Mike Orr <iron@mso.oz.net>
-
-""" % globals()
-
-
-HELP_PAGE1 = """\
-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.
-"""
-
-HELP_PAGE2 = """\
-OPTIONS FOR "compile" AND "fill":
----------------------------------
- --idir DIR, --odir DIR : input/output directories (default: current dir)
- --iext EXT, --oext EXT : input/output filename extensions
- (default for compile: tmpl/py, fill: tmpl/html)
- -R : recurse subdirectories looking for input files
- --debug : print lots of diagnostic output to standard error
- --env : put the environment in the searchList
- --flat : no destination subdirectories
- --nobackup : don't make backups
- --pickle FILE : unpickle FILE and put that object in the searchList
- --stdout, -p : output to standard output (pipe)
- --settings : a string representing the compiler settings to use
- e.g. --settings='useNameMapper=False,useFilters=False'
- This string is eval'd in Python so it should contain
- valid Python syntax.
- --templateAPIClass : a string representing a subclass of
- Cheetah.Template:Template to use for compilation
-
-Run "cheetah help" for the main help screen.
-"""
-
-##################################################
-## CheetahWrapper CLASS
-
-class CheetahWrapper:
- MAKE_BACKUPS = True
- BACKUP_SUFFIX = ".bak"
- _templateClass = None
- _compilerSettings = None
-
- def __init__(self):
- self.progName = None
- self.command = None
- self.opts = None
- self.pathArgs = None
- self.sourceFiles = []
- self.searchList = []
-
- ##################################################
- ## MAIN ROUTINE
-
- def main(self, argv=None):
- """The main program controller."""
-
- if argv is None:
- argv = sys.argv
-
- # Step 1: Determine the command and arguments.
- try:
- self.progName = progName = os.path.basename(argv[0])
- self.command = command = optionDashesRE.sub("", argv[1])
- if command == 'test':
- self.testOpts = argv[2:]
- else:
- self.parseOpts(argv[2:])
- except IndexError:
- usage(HELP_PAGE1, "not enough command-line arguments")
-
- # Step 2: Call the command
- meths = (self.compile, self.fill, self.help, self.options,
- self.test, self.version)
- for meth in meths:
- methName = meth.__name__
- # Or meth.im_func.func_name
- # Or meth.func_name (Python >= 2.1 only, sometimes works on 2.0)
- methInitial = methName[0]
- if command in (methName, methInitial):
- sys.argv[0] += (" " + methName)
- # @@MO: I don't necessarily agree sys.argv[0] should be
- # modified.
- meth()
- return
- # If none of the commands matched.
- usage(HELP_PAGE1, "unknown command '%s'" % command)
-
- def parseOpts(self, args):
- C, D, W = self.chatter, self.debug, self.warn
- self.isCompile = isCompile = self.command[0] == 'c'
- defaultOext = isCompile and ".py" or ".html"
- parser = MyOptionParser()
- pao = parser.add_option
- pao("--idir", action="store", dest="idir", default="")
- pao("--odir", action="store", dest="odir", default="")
- pao("--iext", action="store", dest="iext", default=".tmpl")
- pao("--oext", action="store", dest="oext", default=defaultOext)
- pao("-R", action="store_true", dest="recurse", default=False)
- pao("--stdout", "-p", action="store_true", dest="stdout", default=False)
- pao("--debug", action="store_true", dest="debug", default=False)
- pao("--env", action="store_true", dest="env", default=False)
- pao("--pickle", action="store", dest="pickle", default="")
- pao("--flat", action="store_true", dest="flat", default=False)
- pao("--nobackup", action="store_true", dest="nobackup", default=False)
- pao("--settings", action="store", dest="compilerSettingsString", default=None)
- pao("--templateAPIClass", action="store", dest="templateClassName", default=None)
-
- self.opts, self.pathArgs = opts, files = parser.parse_args(args)
- D("""\
-cheetah compile %s
-Options are
-%s
-Files are %s""", args, pprint.pformat(vars(opts)), files)
-
-
- #cleanup trailing path separators
- seps = [sep for sep in [os.sep, os.altsep] if sep]
- for attr in ['idir', 'odir']:
- for sep in seps:
- path = getattr(opts, attr, None)
- if path and path.endswith(sep):
- path = path[:-len(sep)]
- setattr(opts, attr, path)
- break
-
- self._fixExts()
- if opts.env:
- self.searchList.insert(0, os.environ)
- if opts.pickle:
- f = open(opts.pickle, 'rb')
- unpickled = pickle.load(f)
- f.close()
- self.searchList.insert(0, unpickled)
- opts.verbose = not opts.stdout
-
- ##################################################
- ## COMMAND METHODS
-
- def compile(self):
- self._compileOrFill()
-
- def fill(self):
- from Cheetah.ImportHooks import install
- install()
- self._compileOrFill()
-
- def help(self):
- usage(HELP_PAGE1, "", sys.stdout)
-
- def options(self):
- usage(HELP_PAGE2, "", sys.stdout)
-
- def test(self):
- # @@MO: Ugly kludge.
- TEST_WRITE_FILENAME = 'cheetah_test_file_creation_ability.tmp'
- try:
- f = open(TEST_WRITE_FILENAME, 'w')
- except:
- sys.exit("""\
-Cannot run the tests because you don't have write permission in the current
-directory. The tests need to create temporary files. Change to a directory
-you do have write permission to and re-run the tests.""")
- else:
- f.close()
- os.remove(TEST_WRITE_FILENAME)
- # @@MO: End ugly kludge.
- from Cheetah.Tests import Test
- import Cheetah.Tests.unittest_local_copy as unittest
- del sys.argv[1:] # Prevent unittest from misinterpreting options.
- sys.argv.extend(self.testOpts)
- #unittest.main(testSuite=Test.testSuite)
- #unittest.main(testSuite=Test.testSuite)
- unittest.main(module=Test)
-
- def version(self):
- print Version
-
- # If you add a command, also add it to the 'meths' variable in main().
-
- ##################################################
- ## LOGGING METHODS
-
- def chatter(self, format, *args):
- """Print a verbose message to stdout. But don't if .opts.stdout is
- true or .opts.verbose is false.
- """
- if self.opts.stdout or not self.opts.verbose:
- return
- fprintfMessage(sys.stdout, format, *args)
-
-
- def debug(self, format, *args):
- """Print a debugging message to stderr, but don't if .debug is
- false.
- """
- if self.opts.debug:
- fprintfMessage(sys.stderr, format, *args)
-
- def warn(self, format, *args):
- """Always print a warning message to stderr.
- """
- fprintfMessage(sys.stderr, format, *args)
-
- def error(self, format, *args):
- """Always print a warning message to stderr and exit with an error code.
- """
- fprintfMessage(sys.stderr, format, *args)
- sys.exit(1)
-
- ##################################################
- ## HELPER METHODS
-
-
- def _fixExts(self):
- assert self.opts.oext, "oext is empty!"
- iext, oext = self.opts.iext, self.opts.oext
- if iext and not iext.startswith("."):
- self.opts.iext = "." + iext
- if oext and not oext.startswith("."):
- self.opts.oext = "." + oext
-
-
-
- def _compileOrFill(self):
- C, D, W = self.chatter, self.debug, self.warn
- opts, files = self.opts, self.pathArgs
- if files == ["-"]:
- self._compileOrFillStdin()
- return
- elif not files and opts.recurse:
- which = opts.idir and "idir" or "current"
- C("Drilling down recursively from %s directory.", which)
- sourceFiles = []
- dir = os.path.join(self.opts.idir, os.curdir)
- os.path.walk(dir, self._expandSourceFilesWalk, sourceFiles)
- elif not files:
- usage(HELP_PAGE1, "Neither files nor -R specified!")
- else:
- sourceFiles = self._expandSourceFiles(files, opts.recurse, True)
- sourceFiles = [os.path.normpath(x) for x in sourceFiles]
- D("All source files found: %s", sourceFiles)
- bundles = self._getBundles(sourceFiles)
- D("All bundles: %s", pprint.pformat(bundles))
- if self.opts.flat:
- self._checkForCollisions(bundles)
- for b in bundles:
- self._compileOrFillBundle(b)
-
- def _checkForCollisions(self, bundles):
- """Check for multiple source paths writing to the same destination
- path.
- """
- C, D, W = self.chatter, self.debug, self.warn
- isError = False
- dstSources = {}
- for b in bundles:
- if dstSources.has_key(b.dst):
- dstSources[b.dst].append(b.src)
- else:
- dstSources[b.dst] = [b.src]
- keys = dstSources.keys()
- keys.sort()
- for dst in keys:
- sources = dstSources[dst]
- if len(sources) > 1:
- isError = True
- sources.sort()
- fmt = "Collision: multiple source files %s map to one destination file %s"
- W(fmt, sources, dst)
- if isError:
- what = self.isCompile and "Compilation" or "Filling"
- sys.exit("%s aborted due to collisions" % what)
-
-
- def _expandSourceFilesWalk(self, arg, dir, files):
- """Recursion extension for .expandSourceFiles().
- This method is a callback for os.path.walk().
- 'arg' is a list to which successful paths will be appended.
- """
- iext = self.opts.iext
- for f in files:
- path = os.path.join(dir, f)
- if path.endswith(iext) and os.path.isfile(path):
- arg.append(path)
- elif os.path.islink(path) and os.path.isdir(path):
- os.path.walk(path, self._expandSourceFilesWalk, arg)
- # If is directory, do nothing; 'walk' will eventually get it.
-
-
- def _expandSourceFiles(self, files, recurse, addIextIfMissing):
- """Calculate source paths from 'files' by applying the
- command-line options.
- """
- C, D, W = self.chatter, self.debug, self.warn
- idir = self.opts.idir
- iext = self.opts.iext
- files = []
- for f in self.pathArgs:
- oldFilesLen = len(files)
- D("Expanding %s", f)
- path = os.path.join(idir, f)
- pathWithExt = path + iext # May or may not be valid.
- if os.path.isdir(path):
- if recurse:
- os.path.walk(path, self._expandSourceFilesWalk, files)
- else:
- raise Error("source file '%s' is a directory" % path)
- elif os.path.isfile(path):
- files.append(path)
- elif (addIextIfMissing and not path.endswith(iext) and
- os.path.isfile(pathWithExt)):
- files.append(pathWithExt)
- # Do not recurse directories discovered by iext appending.
- elif os.path.exists(path):
- W("Skipping source file '%s', not a plain file.", path)
- else:
- W("Skipping source file '%s', not found.", path)
- if len(files) > oldFilesLen:
- D(" ... found %s", files[oldFilesLen:])
- return files
-
-
- def _getBundles(self, sourceFiles):
- flat = self.opts.flat
- idir = self.opts.idir
- iext = self.opts.iext
- nobackup = self.opts.nobackup
- odir = self.opts.odir
- oext = self.opts.oext
- idirSlash = idir + os.sep
- bundles = []
- for src in sourceFiles:
- # 'base' is the subdirectory plus basename.
- base = src
- if idir and src.startswith(idirSlash):
- base = src[len(idirSlash):]
- if iext and base.endswith(iext):
- base = base[:-len(iext)]
- basename = os.path.basename(base)
- if flat:
- dst = os.path.join(odir, basename + oext)
- else:
- dbn = basename
- if odir and base.startswith(os.sep):
- odd = odir
- while odd != '':
- idx = base.find(odd)
- if idx == 0:
- dbn = base[len(odd):]
- if dbn[0] == '/':
- dbn = dbn[1:]
- break
- odd = os.path.dirname(odd)
- if odd == '/':
- break
- dst = os.path.join(odir, dbn + oext)
- else:
- dst = os.path.join(odir, base + oext)
- bak = dst + self.BACKUP_SUFFIX
- b = Bundle(src=src, dst=dst, bak=bak, base=base, basename=basename)
- bundles.append(b)
- return bundles
-
-
- def _getTemplateClass(self):
- C, D, W = self.chatter, self.debug, self.warn
- modname = None
- if self._templateClass:
- return self._templateClass
-
- modname = self.opts.templateClassName
-
- if not modname:
- return Template
- p = modname.rfind('.')
- if ':' not in modname:
- self.error('The value of option --templateAPIClass is invalid\n'
- 'It must be in the form "module:class", '
- 'e.g. "Cheetah.Template:Template"')
-
- modname, classname = modname.split(':')
-
- C('using --templateAPIClass=%s:%s'%(modname, classname))
-
- if p >= 0:
- mod = getattr(__import__(modname[:p], {}, {}, [modname[p+1:]]), modname[p+1:])
- else:
- mod = __import__(modname, {}, {}, [])
-
- klass = getattr(mod, classname, None)
- if klass:
- self._templateClass = klass
- return klass
- else:
- self.error('**Template class specified in option --templateAPIClass not found\n'
- '**Falling back on Cheetah.Template:Template')
-
-
- def _getCompilerSettings(self):
- if self._compilerSettings:
- return self._compilerSettings
-
- def getkws(**kws):
- return kws
- if self.opts.compilerSettingsString:
- try:
- exec 'settings = getkws(%s)'%self.opts.compilerSettingsString
- except:
- self.error("There's an error in your --settings option."
- "It must be valid Python syntax.\n"
- +" --settings='%s'\n"%self.opts.compilerSettingsString
- +" %s: %s"%sys.exc_info()[:2]
- )
-
- validKeys = DEFAULT_COMPILER_SETTINGS.keys()
- if [k for k in settings.keys() if k not in validKeys]:
- self.error(
- 'The --setting "%s" is not a valid compiler setting name.'%k)
-
- self._compilerSettings = settings
- return settings
- else:
- return {}
-
- def _compileOrFillStdin(self):
- TemplateClass = self._getTemplateClass()
- compilerSettings = self._getCompilerSettings()
- if self.isCompile:
- pysrc = TemplateClass.compile(file=sys.stdin,
- compilerSettings=compilerSettings,
- returnAClass=False)
- output = pysrc
- else:
- output = str(TemplateClass(file=sys.stdin, compilerSettings=compilerSettings))
- sys.stdout.write(output)
-
- def _compileOrFillBundle(self, b):
- C, D, W = self.chatter, self.debug, self.warn
- TemplateClass = self._getTemplateClass()
- compilerSettings = self._getCompilerSettings()
- src = b.src
- dst = b.dst
- base = b.base
- basename = b.basename
- dstDir = os.path.dirname(dst)
- what = self.isCompile and "Compiling" or "Filling"
- C("%s %s -> %s^", what, src, dst) # No trailing newline.
- if os.path.exists(dst) and not self.opts.nobackup:
- bak = b.bak
- C(" (backup %s)", bak) # On same line as previous message.
- else:
- bak = None
- C("")
- if self.isCompile:
- if not moduleNameRE.match(basename):
- tup = basename, src
- raise Error("""\
-%s: base name %s contains invalid characters. It must
-be named according to the same rules as Python modules.""" % tup)
- pysrc = TemplateClass.compile(file=src, returnAClass=False,
- moduleName=basename,
- className=basename,
- compilerSettings=compilerSettings)
- output = pysrc
- else:
- #output = str(TemplateClass(file=src, searchList=self.searchList))
- tclass = TemplateClass.compile(file=src, compilerSettings=compilerSettings)
- output = str(tclass(searchList=self.searchList))
-
- if bak:
- shutil.copyfile(dst, bak)
- if dstDir and not os.path.exists(dstDir):
- if self.isCompile:
- mkdirsWithPyInitFiles(dstDir)
- else:
- os.makedirs(dstDir)
- if self.opts.stdout:
- sys.stdout.write(output)
- else:
- f = open(dst, 'w')
- f.write(output)
- f.close()
-
-
-##################################################
-## if run from the command line
-if __name__ == '__main__': CheetahWrapper().main()
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/DummyTransaction.py b/cobbler/Cheetah/DummyTransaction.py
deleted file mode 100644
index 8ebe33d..0000000
--- a/cobbler/Cheetah/DummyTransaction.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python
-# $Id: DummyTransaction.py,v 1.13 2005/11/13 01:12:13 tavis_rudd Exp $
-
-"""Provides dummy Transaction and Response classes is used by Cheetah in place
-of real Webware transactions when the Template obj is not used directly as a
-Webware servlet.
-
-Meta-Data
-==========
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.13 $
-Start Date: 2001/08/30
-Last Revision Date: $Date: 2005/11/13 01:12:13 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.13 $"[11:-2]
-
-def flush():
- pass
-
-class DummyResponse:
-
- """A dummy Response class is used by Cheetah in place of real Webware
- Response objects when the Template obj is not used directly as a Webware
- servlet. """
-
-
- def __init__(self):
- self._outputChunks = outputChunks = []
- self.write = write = outputChunks.append
- def getvalue(outputChunks=outputChunks):
- return ''.join(outputChunks)
- self.getvalue = getvalue
-
- def writeln(txt):
- write(txt)
- write('\n')
- self.writeln = writeln
- self.flush = flush
-
- def writelines(self, *lines):
- ## not used
- [self.writeln(ln) for ln in lines]
-
-class DummyTransaction:
-
- """A dummy Transaction class is used by Cheetah in place of real Webware
- transactions when the Template obj is not used directly as a Webware
- servlet.
-
- It only provides a response object and method. All other methods and
- attributes make no sense in this context.
- """
-
- def __init__(self, DummyResponse=DummyResponse):
- def response(resp=DummyResponse()):
- return resp
- self.response = response
diff --git a/cobbler/Cheetah/ErrorCatchers.py b/cobbler/Cheetah/ErrorCatchers.py
deleted file mode 100644
index d33b979..0000000
--- a/cobbler/Cheetah/ErrorCatchers.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python
-# $Id: ErrorCatchers.py,v 1.7 2005/01/03 19:59:07 tavis_rudd Exp $
-"""ErrorCatcher class for Cheetah Templates
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.7 $
-Start Date: 2001/08/01
-Last Revision Date: $Date: 2005/01/03 19:59:07 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.7 $"[11:-2]
-
-import time
-from Cheetah.NameMapper import NotFound
-
-class Error(Exception):
- pass
-
-class ErrorCatcher:
- _exceptionsToCatch = (NotFound,)
-
- def __init__(self, templateObj):
- pass
-
- def exceptions(self):
- return self._exceptionsToCatch
-
- def warn(self, exc_val, code, rawCode, lineCol):
- return rawCode
-## make an alias
-Echo = ErrorCatcher
-
-class BigEcho(ErrorCatcher):
- def warn(self, exc_val, code, rawCode, lineCol):
- return "="*15 + "&lt;" + rawCode + " could not be found&gt;" + "="*15
-
-class KeyError(ErrorCatcher):
- def warn(self, exc_val, code, rawCode, lineCol):
- raise KeyError("no '%s' in this Template Object's Search List" % rawCode)
-
-class ListErrors(ErrorCatcher):
- """Accumulate a list of errors."""
- _timeFormat = "%c"
-
- def __init__(self, templateObj):
- ErrorCatcher.__init__(self, templateObj)
- self._errors = []
-
- def warn(self, exc_val, code, rawCode, lineCol):
- dict = locals().copy()
- del dict['self']
- dict['time'] = time.strftime(self._timeFormat,
- time.localtime(time.time()))
- self._errors.append(dict)
- return rawCode
-
- def listErrors(self):
- """Return the list of errors."""
- return self._errors
-
-
diff --git a/cobbler/Cheetah/FileUtils.py b/cobbler/Cheetah/FileUtils.py
deleted file mode 100644
index c3749f5..0000000
--- a/cobbler/Cheetah/FileUtils.py
+++ /dev/null
@@ -1,374 +0,0 @@
-#!/usr/bin/env python
-# $Id: FileUtils.py,v 1.12 2005/11/02 22:26:07 tavis_rudd Exp $
-"""File utitilies for Python:
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.12 $
-Start Date: 2001/09/26
-Last Revision Date: $Date: 2005/11/02 22:26:07 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.12 $"[11:-2]
-
-
-from glob import glob
-import os
-from os import listdir
-import os.path
-import re
-from types import StringType
-from tempfile import mktemp
-
-def _escapeRegexChars(txt,
- escapeRE=re.compile(r'([\$\^\*\+\.\?\{\}\[\]\(\)\|\\])')):
- return escapeRE.sub(r'\\\1' , txt)
-
-def findFiles(*args, **kw):
- """Recursively find all the files matching a glob pattern.
-
- This function is a wrapper around the FileFinder class. See its docstring
- for details about the accepted arguments, etc."""
-
- return FileFinder(*args, **kw).files()
-
-def replaceStrInFiles(files, theStr, repl):
-
- """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."""
-
- 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
- '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."""
-
- return FindAndReplace(files, pattern, repl).results()
-
-
-##################################################
-## CLASSES
-
-class FileFinder:
-
- """Traverses a directory tree and finds all files in it that match one of
- the specified glob patterns."""
-
- def __init__(self, rootPath,
- globPatterns=('*',),
- ignoreBasenames=('CVS','.svn'),
- ignoreDirs=(),
- ):
-
- self._rootPath = rootPath
- self._globPatterns = globPatterns
- self._ignoreBasenames = ignoreBasenames
- self._ignoreDirs = ignoreDirs
- self._files = []
-
- self.walkDirTree(rootPath)
-
- def walkDirTree(self, dir='.',
-
- listdir=os.listdir,
- isdir=os.path.isdir,
- join=os.path.join,
- ):
-
- """Recursively walk through a directory tree and find matching files."""
- processDir = self.processDir
- filterDir = self.filterDir
-
- pendingDirs = [dir]
- addDir = pendingDirs.append
- getDir = pendingDirs.pop
-
- while pendingDirs:
- dir = getDir()
- ## process this dir
- processDir(dir)
-
- ## and add sub-dirs
- for baseName in listdir(dir):
- fullPath = join(dir, baseName)
- if isdir(fullPath):
- if filterDir(baseName, fullPath):
- addDir( fullPath )
-
- def filterDir(self, baseName, fullPath):
-
- """A hook for filtering out certain dirs. """
-
- return not (baseName in self._ignoreBasenames or
- fullPath in self._ignoreDirs)
-
- def processDir(self, dir, glob=glob):
- extend = self._files.extend
- for pattern in self._globPatterns:
- extend( glob(os.path.join(dir, pattern)) )
-
- def files(self):
- return self._files
-
-class _GenSubberFunc:
-
- """Converts a 'sub' string in the form that one feeds to re.sub (backrefs,
- groups, etc.) into a function that can be used to do the substitutions in
- the FindAndReplace class."""
-
- backrefRE = re.compile(r'\\([1-9][0-9]*)')
- groupRE = re.compile(r'\\g<([a-zA-Z_][a-zA-Z_]*)>')
-
- def __init__(self, replaceStr):
- self._src = replaceStr
- self._pos = 0
- self._codeChunks = []
- self.parse()
-
- def src(self):
- return self._src
-
- def pos(self):
- return self._pos
-
- def setPos(self, pos):
- self._pos = pos
-
- def atEnd(self):
- return self._pos >= len(self._src)
-
- def advance(self, offset=1):
- self._pos += offset
-
- def readTo(self, to, start=None):
- if start == None:
- start = self._pos
- self._pos = to
- if self.atEnd():
- return self._src[start:]
- else:
- return self._src[start:to]
-
- ## match and get methods
-
- def matchBackref(self):
- return self.backrefRE.match(self.src(), self.pos())
-
- def getBackref(self):
- m = self.matchBackref()
- self.setPos(m.end())
- return m.group(1)
-
- def matchGroup(self):
- return self.groupRE.match(self.src(), self.pos())
-
- def getGroup(self):
- m = self.matchGroup()
- self.setPos(m.end())
- return m.group(1)
-
- ## main parse loop and the eat methods
-
- def parse(self):
- while not self.atEnd():
- if self.matchBackref():
- self.eatBackref()
- elif self.matchGroup():
- self.eatGroup()
- else:
- self.eatStrConst()
-
- def eatStrConst(self):
- startPos = self.pos()
- while not self.atEnd():
- if self.matchBackref() or self.matchGroup():
- break
- else:
- self.advance()
- strConst = self.readTo(self.pos(), start=startPos)
- self.addChunk(repr(strConst))
-
- def eatBackref(self):
- self.addChunk( 'm.group(' + self.getBackref() + ')' )
-
- def eatGroup(self):
- self.addChunk( 'm.group("' + self.getGroup() + '")' )
-
- def addChunk(self, chunk):
- self._codeChunks.append(chunk)
-
- ## code wrapping methods
-
- def codeBody(self):
- return ', '.join(self._codeChunks)
-
- def code(self):
- return "def subber(m):\n\treturn ''.join([%s])\n" % (self.codeBody())
-
- def subberFunc(self):
- exec self.code()
- return subber
-
-
-class FindAndReplace:
-
- """Find and replace all instances of 'patternOrRE' with 'replacement' for
- each file in the 'files' list. This is a multi-file version of re.sub().
-
- 'patternOrRE' can be a raw regex pattern or
- a regex object as generated by the re module. 'replacement' can be any
- string that would work with patternOrRE.sub(replacement, fileContents).
- """
-
- def __init__(self, files, patternOrRE, replacement,
- recordResults=True):
-
-
- if type(patternOrRE) == StringType:
- self._regex = re.compile(patternOrRE)
- else:
- self._regex = patternOrRE
- if type(replacement) == StringType:
- self._subber = _GenSubberFunc(replacement).subberFunc()
- else:
- self._subber = replacement
-
- self._pattern = pattern = self._regex.pattern
- self._files = files
- self._results = {}
- self._recordResults = recordResults
-
- ## see if we should use pgrep to do the file matching
- self._usePgrep = False
- if (os.popen3('pgrep')[2].read()).startswith('Usage:'):
- ## now check to make sure pgrep understands the pattern
- tmpFile = mktemp()
- open(tmpFile, 'w').write('#')
- if not (os.popen3('pgrep "' + pattern + '" ' + tmpFile)[2].read()):
- # it didn't print an error msg so we're ok
- self._usePgrep = True
- os.remove(tmpFile)
-
- self._run()
-
- def results(self):
- return self._results
-
- def _run(self):
- regex = self._regex
- subber = self._subDispatcher
- usePgrep = self._usePgrep
- pattern = self._pattern
- for file in self._files:
- if not os.path.isfile(file):
- continue # skip dirs etc.
-
- self._currFile = file
- found = False
- if locals().has_key('orig'):
- del orig
- if self._usePgrep:
- if os.popen('pgrep "' + pattern + '" ' + file ).read():
- found = True
- else:
- orig = open(file).read()
- if regex.search(orig):
- found = True
- if found:
- if not locals().has_key('orig'):
- orig = open(file).read()
- new = regex.sub(subber, orig)
- open(file, 'w').write(new)
-
- def _subDispatcher(self, match):
- if self._recordResults:
- if not self._results.has_key(self._currFile):
- res = self._results[self._currFile] = {}
- res['count'] = 0
- res['matches'] = []
- else:
- res = self._results[self._currFile]
- res['count'] += 1
- res['matches'].append({'contents':match.group(),
- 'start':match.start(),
- 'end':match.end(),
- }
- )
- return self._subber(match)
-
-
-class SourceFileStats:
-
- """
- """
-
- _fileStats = None
-
- def __init__(self, files):
- self._fileStats = stats = {}
- for file in files:
- stats[file] = self.getFileStats(file)
-
- def rawStats(self):
- return self._fileStats
-
- def summary(self):
- codeLines = 0
- blankLines = 0
- commentLines = 0
- totalLines = 0
- for fileStats in self.rawStats().values():
- codeLines += fileStats['codeLines']
- blankLines += fileStats['blankLines']
- commentLines += fileStats['commentLines']
- totalLines += fileStats['totalLines']
-
- stats = {'codeLines':codeLines,
- 'blankLines':blankLines,
- 'commentLines':commentLines,
- 'totalLines':totalLines,
- }
- return stats
-
- def printStats(self):
- pass
-
- def getFileStats(self, fileName):
- codeLines = 0
- blankLines = 0
- commentLines = 0
- commentLineRe = re.compile(r'\s#.*$')
- blankLineRe = re.compile('\s$')
- lines = open(fileName).read().splitlines()
- totalLines = len(lines)
-
- for line in lines:
- if commentLineRe.match(line):
- commentLines += 1
- elif blankLineRe.match(line):
- blankLines += 1
- else:
- codeLines += 1
-
- stats = {'codeLines':codeLines,
- 'blankLines':blankLines,
- 'commentLines':commentLines,
- 'totalLines':totalLines,
- }
-
- return stats
diff --git a/cobbler/Cheetah/Filters.py b/cobbler/Cheetah/Filters.py
deleted file mode 100644
index 2bf4784..0000000
--- a/cobbler/Cheetah/Filters.py
+++ /dev/null
@@ -1,290 +0,0 @@
-#!/usr/bin/env python
-# $Id: Filters.py,v 1.28 2006/06/16 20:15:24 hierro Exp $
-"""Filters for the #filter directive; output filters Cheetah's $placeholders .
-
-Filters may now be used standalone, for debugging or for use outside Cheetah.
-Class DummyTemplate, instance _dummyTemplateObj and class NoDefault exist only
-for this, to provide a default argument for the filter constructors (which
-would otherwise require a real template object).
-
-The default filter is now RawOrEncodedUnicode. Please use this as a base class instead of Filter because it handles non-ASCII characters better.
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.28 $
-Start Date: 2001/08/01
-Last Revision Date: $Date: 2006/06/16 20:15:24 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.28 $"[11:-2]
-
-from StringIO import StringIO # not cStringIO because of unicode support
-
-# Additional entities WebSafe knows how to transform. No need to include
-# '<', '>' or '&' since those will have been done already.
-webSafeEntities = {' ': '&nbsp;', '"': '&quot;'}
-
-class Error(Exception):
- pass
-
-class NoDefault:
- pass
-
-
-class DummyTemplate:
- """Fake template class to allow filters to be used standalone.
-
- This is provides only the level of Template compatibility required by the
- standard filters. Namely, the get-settings interface works but there are
- no settings. Other aspects of Template are not implemented.
- """
- def setting(self, name, default=NoDefault):
- if default is NoDefault:
- raise KeyError(name)
- else:
- return default
-
- def settings(self):
- return {}
-
-_dummyTemplateObj = DummyTemplate()
-
-
-##################################################
-## BASE CLASS
-
-class Filter(object):
- """A baseclass for the Cheetah Filters."""
-
- def __init__(self, templateObj=_dummyTemplateObj):
- """Setup a ref to the templateObj. Subclasses should call this method.
- """
- if hasattr(templateObj, 'setting'):
- self.setting = templateObj.setting
- else:
- self.setting = lambda k: None
-
- if hasattr(templateObj, 'settings'):
- self.settings = templateObj.settings
- else:
- self.settings = lambda: {}
-
- def generateAutoArgs(self):
-
- """This hook allows the filters to generate an arg-list that will be
- appended to the arg-list of a $placeholder tag when it is being
- translated into Python code during the template compilation process. See
- the 'Pager' filter class for an example."""
-
- return ''
-
- def filter(self, val, **kw):
-
- """Reimplement this method if you want more advanced filterting."""
-
- return str(val)
-
-
-##################################################
-## ENHANCED FILTERS
-
-#####
-class ReplaceNone(Filter):
- def filter(self, val, **kw):
-
- """Replace None with an empty string. Reimplement this method if you
- want more advanced filterting."""
-
- if val is None:
- return ''
- return str(val)
-#####
-class EncodeUnicode(Filter):
- def filter(self, val,
- encoding='utf8',
- str=str, type=type, unicodeType=type(u''),
- **kw):
- """Encode Unicode strings, by default in UTF-8.
-
- >>> import Cheetah.Template
- >>> t = Cheetah.Template.Template('''
- ... $myvar
- ... ${myvar, encoding='utf16'}
- ... ''', searchList=[{'myvar': u'Asni\xe8res'}],
- ... filter='EncodeUnicode')
- >>> print t
- """
- if type(val)==unicodeType:
- filtered = val.encode(encoding)
- elif val is None:
- filtered = ''
- else:
- filtered = str(val)
- return filtered
-
-class RawOrEncodedUnicode(Filter):
- def filter(self, val,
- #encoding='utf8',
- encoding=None,
- str=str, type=type, unicodeType=type(u''),
- **kw):
- """Pass Unicode strings through unmolested, unless an encoding is specified.
- """
- if type(val)==unicodeType:
- if encoding:
- filtered = val.encode(encoding)
- else:
- filtered = val
- elif val is None:
- filtered = ''
- else:
- filtered = str(val)
- return filtered
-
-#####
-class MaxLen(RawOrEncodedUnicode):
- def filter(self, val, **kw):
- """Replace None with '' and cut off at maxlen."""
-
- output = super(MaxLen, self).filter(val, **kw)
- if kw.has_key('maxlen') and len(output) > kw['maxlen']:
- return output[:kw['maxlen']]
- return output
-
-
-#####
-class Pager(RawOrEncodedUnicode):
- def __init__(self, templateObj=_dummyTemplateObj):
- Filter.__init__(self, templateObj)
- self._IDcounter = 0
-
- def buildQString(self,varsDict, updateDict):
- finalDict = varsDict.copy()
- finalDict.update(updateDict)
- qString = '?'
- for key, val in finalDict.items():
- qString += str(key) + '=' + str(val) + '&'
- return qString
-
- def generateAutoArgs(self):
- ID = str(self._IDcounter)
- self._IDcounter += 1
- return ', trans=trans, ID=' + ID
-
- def filter(self, val, **kw):
- """Replace None with '' and cut off at maxlen."""
- output = super(Pager, self).filter(val, **kw)
- if kw.has_key('trans') and kw['trans']:
- ID = kw['ID']
- marker = kw.get('marker', '<split>')
- req = kw['trans'].request()
- URI = req.environ()['SCRIPT_NAME'] + req.environ()['PATH_INFO']
- queryVar = 'pager' + str(ID) + '_page'
- fields = req.fields()
- page = int(fields.get( queryVar, 1))
- pages = output.split(marker)
- output = pages[page-1]
- output += '<BR>'
- if page > 1:
- output +='<A HREF="' + URI + self.buildQString(fields, {queryVar:max(page-1,1)}) + \
- '">Previous Page</A>&nbsp;&nbsp;&nbsp;'
- if page < len(pages):
- output += '<A HREF="' + URI + self.buildQString(
- fields,
- {queryVar:
- min(page+1,len(pages))}) + \
- '">Next Page</A>'
-
- return output
- return output
-
-
-#####
-class WebSafe(RawOrEncodedUnicode):
- """Escape HTML entities in $placeholders.
- """
- def filter(self, val, **kw):
- s = super(WebSafe, self).filter(val, **kw)
- # These substitutions are copied from cgi.escape().
- s = s.replace("&", "&amp;") # Must be done first!
- s = s.replace("<", "&lt;")
- s = s.replace(">", "&gt;")
- # Process the additional transformations if any.
- if kw.has_key('also'):
- also = kw['also']
- entities = webSafeEntities # Global variable.
- for k in also:
- if entities.has_key(k):
- v = entities[k]
- else:
- v = "&#%s;" % ord(k)
- s = s.replace(k, v)
- # Return the puppy.
- return s
-
-
-#####
-class Strip(RawOrEncodedUnicode):
- """Strip leading/trailing whitespace but preserve newlines.
-
- This filter goes through the value line by line, removing leading and
- trailing whitespace on each line. It does not strip newlines, so every
- input line corresponds to one output line, with its trailing newline intact.
-
- We do not use val.split('\n') because that would squeeze out consecutive
- blank lines. Instead, we search for each newline individually. This
- makes us unable to use the fast C .split method, but it makes the filter
- much more widely useful.
-
- This filter is intended to be usable both with the #filter directive and
- with the proposed #sed directive (which has not been ratified yet.)
- """
- def filter(self, val, **kw):
- s = super(Strip, self).filter(val, **kw)
- result = []
- start = 0 # The current line will be s[start:end].
- while 1: # Loop through each line.
- end = s.find('\n', start) # Find next newline.
- if end == -1: # If no more newlines.
- break
- chunk = s[start:end].strip()
- result.append(chunk)
- result.append('\n')
- start = end + 1
- # Write the unfinished portion after the last newline, if any.
- chunk = s[start:].strip()
- result.append(chunk)
- return "".join(result)
-
-#####
-class StripSqueeze(RawOrEncodedUnicode):
- """Canonicalizes every chunk of whitespace to a single space.
-
- Strips leading/trailing whitespace. Removes all newlines, so multi-line
- input is joined into one ling line with NO trailing newline.
- """
- def filter(self, val, **kw):
- s = super(StripSqueeze, self).filter(val, **kw)
- s = s.split()
- return " ".join(s)
-
-##################################################
-## MAIN ROUTINE -- testing
-
-def test():
- s1 = "abc <=> &"
- s2 = " asdf \n\t 1 2 3\n"
- print "WebSafe INPUT:", `s1`
- print " WebSafe:", `WebSafe().filter(s1)`
-
- print
- print " Strip INPUT:", `s2`
- print " Strip:", `Strip().filter(s2)`
- print "StripSqueeze:", `StripSqueeze().filter(s2)`
-
- print "Unicode:", `EncodeUnicode().filter(u'aoeu12345\u1234')`
-
-if __name__ == "__main__": test()
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/ImportHooks.py b/cobbler/Cheetah/ImportHooks.py
deleted file mode 100644
index 9d50119..0000000
--- a/cobbler/Cheetah/ImportHooks.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/env python
-# $Id: ImportHooks.py,v 1.25 2006/06/20 19:23:27 tavis_rudd Exp $
-
-"""Provides some import hooks to allow Cheetah's .tmpl files to be imported
-directly like Python .py modules.
-
-To use these:
- import Cheetah.ImportHooks
- Cheetah.ImportHooks.install()
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.25 $
-Start Date: 2001/03/30
-Last Revision Date: $Date: 2006/06/20 19:23:27 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.25 $"[11:-2]
-
-import sys
-import os.path
-import types
-import __builtin__
-import new
-import imp
-from threading import Lock
-import string
-import traceback
-from Cheetah import ImportManager
-from Cheetah.ImportManager import DirOwner
-from Cheetah.Compiler import Compiler
-from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
-
-_installed = False
-
-##################################################
-## HELPER FUNCS
-
-_cacheDir = []
-def setCacheDir(cacheDir):
- global _cacheDir
- _cacheDir.append(cacheDir)
-
-##################################################
-## CLASSES
-
-class CheetahDirOwner(DirOwner):
- _lock = Lock()
- _acquireLock = _lock.acquire
- _releaseLock = _lock.release
-
- templateFileExtensions = ('.tmpl',)
-
- def getmod(self, name):
- try:
- self._acquireLock()
- mod = DirOwner.getmod(self, name)
- if mod:
- return mod
-
- for ext in self.templateFileExtensions:
- tmplPath = os.path.join(self.path, name + ext)
- if os.path.exists(tmplPath):
- try:
- return self._compile(name, tmplPath)
- except:
- # @@TR: log the error
- exc_txt = traceback.format_exc()
- exc_txt =' '+(' \n'.join(exc_txt.splitlines()))
- raise ImportError(
- 'Error while compiling Cheetah module'
- ' %(name)s, original traceback follows:\n%(exc_txt)s'%locals())
- ##
- return None
-
- finally:
- self._releaseLock()
-
- def _compile(self, name, tmplPath):
- ## @@ consider adding an ImportError raiser here
- code = str(Compiler(file=tmplPath, moduleName=name,
- mainClassName=name))
- if _cacheDir:
- __file__ = os.path.join(_cacheDir[0],
- convertTmplPathToModuleName(tmplPath)) + '.py'
- try:
- open(__file__, 'w').write(code)
- except OSError:
- ## @@ TR: need to add some error code here
- traceback.print_exc(file=sys.stderr)
- __file__ = tmplPath
- else:
- __file__ = tmplPath
- co = compile(code+'\n', __file__, 'exec')
-
- mod = imp.new_module(name)
- mod.__file__ = co.co_filename
- if _cacheDir:
- mod.__orig_file__ = tmplPath # @@TR: this is used in the WebKit
- # filemonitoring code
- mod.__co__ = co
- return mod
-
-
-##################################################
-## FUNCTIONS
-
-def install(templateFileExtensions=('.tmpl',)):
- """Install the Cheetah Import Hooks"""
-
- global _installed
- if not _installed:
- CheetahDirOwner.templateFileExtensions = templateFileExtensions
- import __builtin__
- if type(__builtin__.__import__) == types.BuiltinFunctionType:
- global __oldimport__
- __oldimport__ = __builtin__.__import__
- ImportManager._globalOwnerTypes.insert(0, CheetahDirOwner)
- #ImportManager._globalOwnerTypes.append(CheetahDirOwner)
- global _manager
- _manager=ImportManager.ImportManager()
- _manager.setThreaded()
- _manager.install()
-
-def uninstall():
- """Uninstall the Cheetah Import Hooks"""
- global _installed
- if not _installed:
- import __builtin__
- if type(__builtin__.__import__) == types.MethodType:
- __builtin__.__import__ = __oldimport__
- global _manager
- del _manager
-
-if __name__ == '__main__':
- install()
diff --git a/cobbler/Cheetah/ImportManager.py b/cobbler/Cheetah/ImportManager.py
deleted file mode 100644
index 3ff1dbe..0000000
--- a/cobbler/Cheetah/ImportManager.py
+++ /dev/null
@@ -1,562 +0,0 @@
-#!/usr/bin/env python
-# $Id: ImportManager.py,v 1.5 2006/01/27 19:00:20 tavis_rudd Exp $
-
-"""Provides an emulator/replacement for Python's standard import system.
-
-@@TR: Be warned that Import Hooks are in the deepest, darkest corner of Python's
-jungle. If you need to start hacking with this, be prepared to get lost for a
-while. Also note, this module predates the newstyle import hooks in Python 2.3
-http://www.python.org/peps/pep-0302.html.
-
-
-This is a hacked/documented version of Gordon McMillan's iu.py. I have:
-
- - made it a little less terse
-
- - added docstrings and explanatations
-
- - standardized the variable naming scheme
-
- - reorganized the code layout to enhance readability
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com> based on Gordon McMillan's iu.py
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.5 $
-Start Date: 2001/03/30
-Last Revision Date: $Date: 2006/01/27 19:00:20 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.5 $"[11:-2]
-
-##################################################
-## DEPENDENCIES
-
-import sys
-import imp
-import marshal
-
-##################################################
-## CONSTANTS & GLOBALS
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-_installed = False
-
-STRINGTYPE = type('')
-
-# _globalOwnerTypes is defined at the bottom of this file
-
-_os_stat = _os_path_join = _os_getcwd = _os_path_dirname = None
-
-##################################################
-## FUNCTIONS
-
-def _os_bootstrap():
- """Set up 'os' module replacement functions for use during import bootstrap."""
-
- names = sys.builtin_module_names
-
- join = dirname = None
- if 'posix' in names:
- sep = '/'
- from posix import stat, getcwd
- elif 'nt' in names:
- sep = '\\'
- from nt import stat, getcwd
- elif 'dos' in names:
- sep = '\\'
- from dos import stat, getcwd
- elif 'os2' in names:
- sep = '\\'
- from os2 import stat, getcwd
- elif 'mac' in names:
- from mac import stat, getcwd
- def join(a, b):
- if a == '':
- return b
- path = s
- if ':' not in a:
- a = ':' + a
- if a[-1:] != ':':
- a = a + ':'
- return a + b
- else:
- raise ImportError, 'no os specific module found'
-
- if join is None:
- def join(a, b, sep=sep):
- if a == '':
- return b
- lastchar = a[-1:]
- if lastchar == '/' or lastchar == sep:
- return a + b
- return a + sep + b
-
- if dirname is None:
- def dirname(a, sep=sep):
- for i in range(len(a)-1, -1, -1):
- c = a[i]
- if c == '/' or c == sep:
- return a[:i]
- return ''
-
- global _os_stat
- _os_stat = stat
-
- global _os_path_join
- _os_path_join = join
-
- global _os_path_dirname
- _os_path_dirname = dirname
-
- global _os_getcwd
- _os_getcwd = getcwd
-
-_os_bootstrap()
-
-def packageName(s):
- for i in range(len(s)-1, -1, -1):
- if s[i] == '.':
- break
- else:
- return ''
- return s[:i]
-
-def nameSplit(s):
- rslt = []
- i = j = 0
- for j in range(len(s)):
- if s[j] == '.':
- rslt.append(s[i:j])
- i = j+1
- if i < len(s):
- rslt.append(s[i:])
- return rslt
-
-def getPathExt(fnm):
- for i in range(len(fnm)-1, -1, -1):
- if fnm[i] == '.':
- return fnm[i:]
- return ''
-
-def pathIsDir(pathname):
- "Local replacement for os.path.isdir()."
- try:
- s = _os_stat(pathname)
- except OSError:
- return None
- return (s[0] & 0170000) == 0040000
-
-def getDescr(fnm):
- ext = getPathExt(fnm)
- for (suffix, mode, typ) in imp.get_suffixes():
- if suffix == ext:
- return (suffix, mode, typ)
-
-##################################################
-## CLASSES
-
-class Owner:
-
- """An Owner does imports from a particular piece of turf That is, there's
- an Owner for each thing on sys.path There are owners for directories and
- .pyz files. There could be owners for zip files, or even URLs. A
- shadowpath (a dictionary mapping the names in sys.path to their owners) is
- used so that sys.path (or a package's __path__) is still a bunch of strings,
- """
-
- def __init__(self, path):
- self.path = path
-
- def __str__(self):
- return self.path
-
- def getmod(self, nm):
- return None
-
-class DirOwner(Owner):
-
- def __init__(self, path):
- if path == '':
- path = _os_getcwd()
- if not pathIsDir(path):
- raise ValueError, "%s is not a directory" % path
- Owner.__init__(self, path)
-
- def getmod(self, nm,
- getsuffixes=imp.get_suffixes, loadco=marshal.loads, newmod=imp.new_module):
-
- pth = _os_path_join(self.path, nm)
-
- possibles = [(pth, 0, None)]
- if pathIsDir(pth):
- possibles.insert(0, (_os_path_join(pth, '__init__'), 1, pth))
- py = pyc = None
- for pth, ispkg, pkgpth in possibles:
- for ext, mode, typ in getsuffixes():
- attempt = pth+ext
- try:
- st = _os_stat(attempt)
- except:
- pass
- else:
- if typ == imp.C_EXTENSION:
- fp = open(attempt, 'rb')
- mod = imp.load_module(nm, fp, attempt, (ext, mode, typ))
- mod.__file__ = attempt
- return mod
- elif typ == imp.PY_SOURCE:
- py = (attempt, st)
- else:
- pyc = (attempt, st)
- if py or pyc:
- break
- if py is None and pyc is None:
- return None
- while 1:
- if pyc is None or py and pyc[1][8] < py[1][8]:
- try:
- co = compile(open(py[0], 'r').read()+'\n', py[0], 'exec')
- break
- except SyntaxError, e:
- print "Invalid syntax in %s" % py[0]
- print e.args
- raise
- elif pyc:
- stuff = open(pyc[0], 'rb').read()
- try:
- co = loadco(stuff[8:])
- break
- except (ValueError, EOFError):
- pyc = None
- else:
- return None
- mod = newmod(nm)
- mod.__file__ = co.co_filename
- if ispkg:
- mod.__path__ = [pkgpth]
- subimporter = PathImportDirector(mod.__path__)
- mod.__importsub__ = subimporter.getmod
- mod.__co__ = co
- return mod
-
-
-class ImportDirector(Owner):
- """ImportDirectors live on the metapath There's one for builtins, one for
- frozen modules, and one for sys.path Windows gets one for modules gotten
- from the Registry Mac would have them for PY_RESOURCE modules etc. A
- generalization of Owner - their concept of 'turf' is broader"""
-
- pass
-
-class BuiltinImportDirector(ImportDirector):
- """Directs imports of builtin modules"""
- def __init__(self):
- self.path = 'Builtins'
-
- def getmod(self, nm, isbuiltin=imp.is_builtin):
- if isbuiltin(nm):
- mod = imp.load_module(nm, None, nm, ('','',imp.C_BUILTIN))
- return mod
- return None
-
-class FrozenImportDirector(ImportDirector):
- """Directs imports of frozen modules"""
-
- def __init__(self):
- self.path = 'FrozenModules'
-
- def getmod(self, nm,
- isFrozen=imp.is_frozen, loadMod=imp.load_module):
- if isFrozen(nm):
- mod = loadMod(nm, None, nm, ('','',imp.PY_FROZEN))
- if hasattr(mod, '__path__'):
- mod.__importsub__ = lambda name, pname=nm, owner=self: owner.getmod(pname+'.'+name)
- return mod
- return None
-
-
-class RegistryImportDirector(ImportDirector):
- """Directs imports of modules stored in the Windows Registry"""
-
- def __init__(self):
- self.path = "WindowsRegistry"
- self.map = {}
- try:
- import win32api
- ## import win32con
- except ImportError:
- pass
- else:
- HKEY_CURRENT_USER = -2147483647
- HKEY_LOCAL_MACHINE = -2147483646
- KEY_ALL_ACCESS = 983103
- subkey = r"Software\Python\PythonCore\%s\Modules" % sys.winver
- for root in (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE):
- try:
- hkey = win32api.RegOpenKeyEx(root, subkey, 0, KEY_ALL_ACCESS)
- except:
- pass
- else:
- numsubkeys, numvalues, lastmodified = win32api.RegQueryInfoKey(hkey)
- for i in range(numsubkeys):
- subkeyname = win32api.RegEnumKey(hkey, i)
- hskey = win32api.RegOpenKeyEx(hkey, subkeyname, 0, KEY_ALL_ACCESS)
- val = win32api.RegQueryValueEx(hskey, '')
- desc = getDescr(val[0])
- self.map[subkeyname] = (val[0], desc)
- hskey.Close()
- hkey.Close()
- break
-
- def getmod(self, nm):
- stuff = self.map.get(nm)
- if stuff:
- fnm, desc = stuff
- fp = open(fnm, 'rb')
- mod = imp.load_module(nm, fp, fnm, desc)
- mod.__file__ = fnm
- return mod
- return None
-
-class PathImportDirector(ImportDirector):
- """Directs imports of modules stored on the filesystem."""
-
- def __init__(self, pathlist=None, importers=None, ownertypes=None):
- if pathlist is None:
- self.path = sys.path
- else:
- self.path = pathlist
- if ownertypes == None:
- self._ownertypes = _globalOwnerTypes
- else:
- self._ownertypes = ownertypes
- if importers:
- self._shadowPath = importers
- else:
- self._shadowPath = {}
- self._inMakeOwner = False
- self._building = {}
-
- def getmod(self, nm):
- mod = None
- for thing in self.path:
- if type(thing) is STRINGTYPE:
- owner = self._shadowPath.get(thing, -1)
- if owner == -1:
- owner = self._shadowPath[thing] = self._makeOwner(thing)
- if owner:
- mod = owner.getmod(nm)
- else:
- mod = thing.getmod(nm)
- if mod:
- break
- return mod
-
- def _makeOwner(self, path):
- if self._building.get(path):
- return None
- self._building[path] = 1
- owner = None
- for klass in self._ownertypes:
- try:
- # this may cause an import, which may cause recursion
- # hence the protection
- owner = klass(path)
- except:
- pass
- else:
- break
- del self._building[path]
- return owner
-
-#=================ImportManager============================#
-# The one-and-only ImportManager
-# ie, the builtin import
-
-UNTRIED = -1
-
-class ImportManager:
- # really the equivalent of builtin import
- def __init__(self):
- self.metapath = [
- BuiltinImportDirector(),
- FrozenImportDirector(),
- RegistryImportDirector(),
- PathImportDirector()
- ]
- self.threaded = 0
- self.rlock = None
- self.locker = None
- self.setThreaded()
-
- def setThreaded(self):
- thread = sys.modules.get('thread', None)
- if thread and not self.threaded:
- self.threaded = 1
- self.rlock = thread.allocate_lock()
- self._get_ident = thread.get_ident
-
- def install(self):
- import __builtin__
- __builtin__.__import__ = self.importHook
- __builtin__.reload = self.reloadHook
-
- def importHook(self, name, globals=None, locals=None, fromlist=None):
- # first see if we could be importing a relative name
- #print "importHook(%s, %s, locals, %s)" % (name, globals['__name__'], fromlist)
- _sys_modules_get = sys.modules.get
- contexts = [None]
- if globals:
- importernm = globals.get('__name__', '')
- if importernm:
- if hasattr(_sys_modules_get(importernm), '__path__'):
- contexts.insert(0,importernm)
- else:
- pkgnm = packageName(importernm)
- if pkgnm:
- contexts.insert(0,pkgnm)
- # so contexts is [pkgnm, None] or just [None]
- # now break the name being imported up so we get:
- # a.b.c -> [a, b, c]
- nmparts = nameSplit(name)
- _self_doimport = self.doimport
- threaded = self.threaded
- for context in contexts:
- ctx = context
- for i in range(len(nmparts)):
- nm = nmparts[i]
- #print " importHook trying %s in %s" % (nm, ctx)
- if ctx:
- fqname = ctx + '.' + nm
- else:
- fqname = nm
- if threaded:
- self._acquire()
- mod = _sys_modules_get(fqname, UNTRIED)
- if mod is UNTRIED:
- mod = _self_doimport(nm, ctx, fqname)
- if threaded:
- self._release()
- if mod:
- ctx = fqname
- else:
- break
- else:
- # no break, point i beyond end
- i = i + 1
- if i:
- break
-
- if i<len(nmparts):
- if ctx and hasattr(sys.modules[ctx], nmparts[i]):
- #print "importHook done with %s %s %s (case 1)" % (name, globals['__name__'], fromlist)
- return sys.modules[nmparts[0]]
- del sys.modules[fqname]
- raise ImportError, "No module named %s" % fqname
- if fromlist is None:
- #print "importHook done with %s %s %s (case 2)" % (name, globals['__name__'], fromlist)
- if context:
- return sys.modules[context+'.'+nmparts[0]]
- return sys.modules[nmparts[0]]
- bottommod = sys.modules[ctx]
- if hasattr(bottommod, '__path__'):
- fromlist = list(fromlist)
- i = 0
- while i < len(fromlist):
- nm = fromlist[i]
- if nm == '*':
- fromlist[i:i+1] = list(getattr(bottommod, '__all__', []))
- if i >= len(fromlist):
- break
- nm = fromlist[i]
- i = i + 1
- if not hasattr(bottommod, nm):
- if self.threaded:
- self._acquire()
- mod = self.doimport(nm, ctx, ctx+'.'+nm)
- if self.threaded:
- self._release()
- if not mod:
- raise ImportError, "%s not found in %s" % (nm, ctx)
- #print "importHook done with %s %s %s (case 3)" % (name, globals['__name__'], fromlist)
- return bottommod
-
- def doimport(self, nm, parentnm, fqname):
- # Not that nm is NEVER a dotted name at this point
- #print "doimport(%s, %s, %s)" % (nm, parentnm, fqname)
- if parentnm:
- parent = sys.modules[parentnm]
- if hasattr(parent, '__path__'):
- importfunc = getattr(parent, '__importsub__', None)
- if not importfunc:
- subimporter = PathImportDirector(parent.__path__)
- importfunc = parent.__importsub__ = subimporter.getmod
- mod = importfunc(nm)
- if mod:
- setattr(parent, nm, mod)
- else:
- #print "..parent not a package"
- return None
- else:
- # now we're dealing with an absolute import
- for director in self.metapath:
- mod = director.getmod(nm)
- if mod:
- break
- if mod:
- mod.__name__ = fqname
- sys.modules[fqname] = mod
- if hasattr(mod, '__co__'):
- co = mod.__co__
- del mod.__co__
- exec co in mod.__dict__
- if fqname == 'thread' and not self.threaded:
-## print "thread detected!"
- self.setThreaded()
- else:
- sys.modules[fqname] = None
- #print "..found %s" % mod
- return mod
-
- def reloadHook(self, mod):
- fqnm = mod.__name__
- nm = nameSplit(fqnm)[-1]
- parentnm = packageName(fqnm)
- newmod = self.doimport(nm, parentnm, fqnm)
- mod.__dict__.update(newmod.__dict__)
-## return newmod
-
- def _acquire(self):
- if self.rlock.locked():
- if self.locker == self._get_ident():
- self.lockcount = self.lockcount + 1
-## print "_acquire incrementing lockcount to", self.lockcount
- return
- self.rlock.acquire()
- self.locker = self._get_ident()
- self.lockcount = 0
-## print "_acquire first time!"
-
- def _release(self):
- if self.lockcount:
- self.lockcount = self.lockcount - 1
-## print "_release decrementing lockcount to", self.lockcount
- else:
- self.rlock.release()
-## print "_release releasing lock!"
-
-
-##################################################
-## MORE CONSTANTS & GLOBALS
-
-_globalOwnerTypes = [
- DirOwner,
- Owner,
-]
diff --git a/cobbler/Cheetah/Macros/I18n.py b/cobbler/Cheetah/Macros/I18n.py
deleted file mode 100644
index 7c2b1ef..0000000
--- a/cobbler/Cheetah/Macros/I18n.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import gettext
-_ = gettext.gettext
-class I18n(object):
- def __init__(self, parser):
- pass
-
-## junk I'm playing with to test the macro framework
-# def parseArgs(self, parser, startPos):
-# parser.getWhiteSpace()
-# args = parser.getExpression(useNameMapper=False,
-# pyTokensToBreakAt=[':']).strip()
-# return args
-#
-# def convertArgStrToDict(self, args, parser=None, startPos=None):
-# def getArgs(*pargs, **kws):
-# return pargs, kws
-# exec 'positionalArgs, kwArgs = getArgs(%(args)s)'%locals()
-# return kwArgs
-
- def __call__(self,
- src, # aka message,
- plural=None,
- n=None, # should be a string representing the name of the
- # '$var' rather than $var itself
- id=None,
- domain=None,
- source=None,
- target=None,
- comment=None,
-
- # args that are automatically supplied by the parser when the
- # macro is called:
- parser=None,
- macros=None,
- isShortForm=False,
- EOLCharsInShortForm=None,
- startPos=None,
- endPos=None,
- ):
- """This is just a stub at this time.
-
- plural = the plural form of the message
- n = a sized argument to distinguish between single and plural forms
-
- id = msgid in the translation catalog
- domain = translation domain
- source = source lang
- target = a specific target lang
- comment = a comment to the translation team
-
- See the following for some ideas
- http://www.zope.org/DevHome/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport
-
- Other notes:
- - There is no need to replicate the i18n:name attribute from plone / PTL,
- as cheetah placeholders serve the same purpose
-
-
- """
-
- #print macros['i18n']
- src = _(src)
- if isShortForm and endPos<len(parser):
- return src+EOLCharsInShortForm
- else:
- return src
-
diff --git a/cobbler/Cheetah/Macros/__init__.py b/cobbler/Cheetah/Macros/__init__.py
deleted file mode 100644
index 792d600..0000000
--- a/cobbler/Cheetah/Macros/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/cobbler/Cheetah/NameMapper.py b/cobbler/Cheetah/NameMapper.py
deleted file mode 100644
index 2d6d953..0000000
--- a/cobbler/Cheetah/NameMapper.py
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/env python
-# $Id: NameMapper.py,v 1.29 2006/01/15 20:27:42 tavis_rudd Exp $
-
-"""This module supports Cheetah's optional NameMapper syntax.
-
-Overview
-================================================================================
-
-NameMapper provides a simple syntax for accessing Python data structures,
-functions, and methods from Cheetah. It's called NameMapper because it 'maps'
-simple 'names' in Cheetah templates to possibly more complex syntax in Python.
-
-Its purpose is to make working with Cheetah easy for non-programmers.
-Specifically, non-programmers using Cheetah should NOT need to be taught (a)
-what the difference is between an object and a dictionary, (b) what functions
-and methods are, and (c) what 'self' is. A further aim (d) is to buffer the
-code in Cheetah templates from changes in the implementation of the Python data
-structures behind them.
-
-Consider this scenario:
-
-You are building a customer information system. The designers with you want to
-use information from your system on the client's website --AND-- they want to
-understand the display code and so they can maintian it themselves.
-
-You write a UI class with a 'customers' method that returns a dictionary of all
-the customer objects. Each customer object has an 'address' method that returns
-the a dictionary with information about the customer's address. The designers
-want to be able to access that information.
-
-Using PSP, the display code for the website would look something like the
-following, assuming your servlet subclasses the class you created for managing
-customer information:
-
- <%= self.customer()[ID].address()['city'] %> (42 chars)
-
-Using Cheetah's NameMapper syntax it could be any of the following:
-
- $self.customers()[$ID].address()['city'] (39 chars)
- --OR--
- $customers()[$ID].address()['city']
- --OR--
- $customers()[$ID].address().city
- --OR--
- $customers()[$ID].address.city
- --OR--
- $customers()[$ID].address.city
- --OR--
- $customers[$ID].address.city (27 chars)
-
-
-Which of these would you prefer to explain to the designers, who have no
-programming experience? The last form is 15 characters shorter than the PSP
-and, conceptually, is far more accessible. With PHP or ASP, the code would be
-even messier than the PSP
-
-This is a rather extreme example and, of course, you could also just implement
-'$getCustomer($ID).city' and obey the Law of Demeter (search Google for more on that).
-But good object orientated design isn't the point here.
-
-Details
-================================================================================
-The parenthesized letters below correspond to the aims in the second paragraph.
-
-DICTIONARY ACCESS (a)
----------------------
-
-NameMapper allows access to items in a dictionary using the same dotted notation
-used to access object attributes in Python. This aspect of NameMapper is known
-as 'Unified Dotted Notation'.
-
-For example, with Cheetah it is possible to write:
- $customers()['kerr'].address() --OR-- $customers().kerr.address()
-where the second form is in NameMapper syntax.
-
-This only works with dictionary keys that are also valid python identifiers:
- regex = '[a-zA-Z_][a-zA-Z_0-9]*'
-
-
-AUTOCALLING (b,d)
------------------
-
-NameMapper automatically detects functions and methods in Cheetah $vars and calls
-them if the parentheses have been left off.
-
-For example if 'a' is an object, 'b' is a method
- $a.b
-is equivalent to
- $a.b()
-
-If b returns a dictionary, then following variations are possible
- $a.b.c --OR-- $a.b().c --OR-- $a.b()['c']
-where 'c' is a key in the dictionary that a.b() returns.
-
-Further notes:
-* NameMapper autocalls the function or method without any arguments. Thus
-autocalling can only be used with functions or methods that either have no
-arguments or have default values for all arguments.
-
-* NameMapper only autocalls functions and methods. Classes and callable object instances
-will not be autocalled.
-
-* Autocalling can be disabled using Cheetah's 'useAutocalling' setting.
-
-LEAVING OUT 'self' (c,d)
-------------------------
-
-NameMapper makes it possible to access the attributes of a servlet in Cheetah
-without needing to include 'self' in the variable names. See the NAMESPACE
-CASCADING section below for details.
-
-NAMESPACE CASCADING (d)
---------------------
-...
-
-Implementation details
-================================================================================
-
-* NameMapper's search order is dictionary keys then object attributes
-
-* NameMapper.NotFound is raised if a value can't be found for a name.
-
-Performance and the C version
-================================================================================
-
-Cheetah comes with both a C version and a Python version of NameMapper. The C
-version is significantly faster and the exception tracebacks are much easier to
-read. It's still slower than standard Python syntax, but you won't notice the
-difference in realistic usage scenarios.
-
-Cheetah uses the optimized C version (_namemapper.c) if it has
-been compiled or falls back to the Python version if not.
-
-Meta-Data
-================================================================================
-Authors: Tavis Rudd <tavis@damnsimple.com>,
- Chuck Esterbrook <echuck@mindspring.com>
-Version: $Revision: 1.29 $
-Start Date: 2001/04/03
-Last Revision Date: $Date: 2006/01/15 20:27:42 $
-"""
-from __future__ import generators
-__author__ = "Tavis Rudd <tavis@damnsimple.com>," +\
- "\nChuck Esterbrook <echuck@mindspring.com>"
-__revision__ = "$Revision: 1.29 $"[11:-2]
-import types
-from types import StringType, InstanceType, ClassType, TypeType
-from pprint import pformat
-import inspect
-
-_INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS = False
-_ALLOW_WRAPPING_OF_NOTFOUND_EXCEPTIONS = True
-__all__ = ['NotFound',
- 'hasKey',
- 'valueForKey',
- 'valueForName',
- 'valueFromSearchList',
- 'valueFromFrameOrSearchList',
- 'valueFromFrame',
- ]
-
-
-## N.B. An attempt is made at the end of this module to import C versions of
-## these functions. If _namemapper.c has been compiled succesfully and the
-## import goes smoothly, the Python versions defined here will be replaced with
-## the C versions.
-
-class NotFound(LookupError):
- pass
-
-def _raiseNotFoundException(key, namespace):
- excString = "cannot find '%s'"%key
- if _INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS:
- excString += ' in the namespace %s'%pformat(namespace)
- raise NotFound(excString)
-
-def _wrapNotFoundException(exc, fullName, namespace):
- if not _ALLOW_WRAPPING_OF_NOTFOUND_EXCEPTIONS:
- raise
- else:
- excStr = exc.args[0]
- if excStr.find('while searching')==-1: # only wrap once!
- excStr +=" while searching for '%s'"%fullName
- if _INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS:
- excString += ' in the namespace %s'%pformat(namespace)
- exc.args = (excStr,)
- raise
-
-def hasKey(obj, key):
- """Determine if 'obj' has 'key' """
- if hasattr(obj,'has_key') and obj.has_key(key):
- return True
- elif hasattr(obj, key):
- return True
- else:
- return False
-
-def valueForKey(obj, key):
- if hasattr(obj, 'has_key') and obj.has_key(key):
- return obj[key]
- elif hasattr(obj, key):
- return getattr(obj, key)
- else:
- _raiseNotFoundException(key, obj)
-
-def _valueForName(obj, name, executeCallables=False):
- nameChunks=name.split('.')
- for i in range(len(nameChunks)):
- key = nameChunks[i]
- if hasattr(obj, 'has_key') and obj.has_key(key):
- nextObj = obj[key]
- elif hasattr(obj, key):
- nextObj = getattr(obj, key)
- else:
- _raiseNotFoundException(key, obj)
-
- if (executeCallables and callable(nextObj)
- and (type(nextObj) not in (InstanceType, ClassType))):
- obj = nextObj()
- else:
- obj = nextObj
- return obj
-
-def valueForName(obj, name, executeCallables=False):
- try:
- return _valueForName(obj, name, executeCallables)
- except NotFound, e:
- _wrapNotFoundException(e, fullName=name, namespace=obj)
-
-def valueFromSearchList(searchList, name, executeCallables=False):
- key = name.split('.')[0]
- for namespace in searchList:
- if hasKey(namespace, key):
- return _valueForName(namespace, name,
- executeCallables=executeCallables)
- _raiseNotFoundException(key, searchList)
-
-def _namespaces(callerFrame, searchList=None):
- yield callerFrame.f_locals
- if searchList:
- for namespace in searchList:
- yield namespace
- yield callerFrame.f_globals
- yield __builtins__
-
-def valueFromFrameOrSearchList(searchList, name, executeCallables=False,
- frame=None):
- def __valueForName():
- try:
- return _valueForName(namespace, name, executeCallables=executeCallables)
- except NotFound, e:
- _wrapNotFoundException(e, fullName=name, namespace=searchList)
- try:
- if not frame:
- frame = inspect.stack()[1][0]
- key = name.split('.')[0]
- for namespace in _namespaces(frame, searchList):
- if hasKey(namespace, key): return __valueForName()
- _raiseNotFoundException(key, searchList)
- finally:
- del frame
-
-def valueFromFrame(name, executeCallables=False, frame=None):
- # @@TR consider implementing the C version the same way
- # at the moment it provides a seperate but mirror implementation
- # to valueFromFrameOrSearchList
- try:
- if not frame:
- frame = inspect.stack()[1][0]
- return valueFromFrameOrSearchList(searchList=None,
- name=name,
- executeCallables=executeCallables,
- frame=frame)
- finally:
- del frame
-
-def hasName(obj, name):
- #Not in the C version
- """Determine if 'obj' has the 'name' """
- key = name.split('.')[0]
- if not hasKey(obj, key):
- return False
- try:
- valueForName(obj, name)
- return True
- except NotFound:
- return False
-try:
- from _namemapper import NotFound, valueForKey, valueForName, \
- valueFromSearchList, valueFromFrameOrSearchList, valueFromFrame
- # it is possible with Jython or Windows, for example, that _namemapper.c hasn't been compiled
- C_VERSION = True
-except:
- C_VERSION = False
-
-##################################################
-## CLASSES
-
-class Mixin:
- """@@ document me"""
- def valueForName(self, name):
- return valueForName(self, name)
-
- def valueForKey(self, key):
- return valueForKey(self, key)
-
-##################################################
-## if run from the command line ##
-
-def example():
- class A(Mixin):
- classVar = 'classVar val'
- def method(self,arg='method 1 default arg'):
- return arg
-
- def method2(self, arg='meth 2 default arg'):
- return {'item1':arg}
-
- def method3(self, arg='meth 3 default'):
- return arg
-
- class B(A):
- classBvar = 'classBvar val'
-
- a = A()
- a.one = 'valueForOne'
- def function(whichOne='default'):
- values = {
- 'default': 'default output',
- 'one': 'output option one',
- 'two': 'output option two'
- }
- return values[whichOne]
-
- a.dic = {
- 'func': function,
- 'method': a.method3,
- 'item': 'itemval',
- 'subDict': {'nestedMethod':a.method3}
- }
- b = 'this is local b'
-
- print valueForKey(a.dic,'subDict')
- print valueForName(a, 'dic.item')
- print valueForName(vars(), 'b')
- print valueForName(__builtins__, 'dir')()
- print valueForName(vars(), 'a.classVar')
- print valueForName(vars(), 'a.dic.func', executeCallables=True)
- print valueForName(vars(), 'a.method2.item1', executeCallables=True)
-
-if __name__ == '__main__':
- example()
-
-
-
diff --git a/cobbler/Cheetah/Parser.py b/cobbler/Cheetah/Parser.py
deleted file mode 100644
index a72e702..0000000
--- a/cobbler/Cheetah/Parser.py
+++ /dev/null
@@ -1,2558 +0,0 @@
-#!/usr/bin/env python
-# $Id: Parser.py,v 1.130 2006/06/21 23:49:14 tavis_rudd Exp $
-"""Parser classes for Cheetah's Compiler
-
-Classes:
- ParseError( Exception )
- _LowLevelParser( Cheetah.SourceReader.SourceReader ), basically a lexer
- _HighLevelParser( _LowLevelParser )
- Parser === _HighLevelParser (an alias)
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.130 $
-Start Date: 2001/08/01
-Last Revision Date: $Date: 2006/06/21 23:49:14 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.130 $"[11:-2]
-
-import os
-import sys
-import re
-from re import DOTALL, MULTILINE
-from types import StringType, ListType, TupleType, ClassType, TypeType
-import time
-from tokenize import pseudoprog
-import inspect
-import new
-import traceback
-
-from Cheetah.SourceReader import SourceReader
-from Cheetah import Filters
-from Cheetah import ErrorCatchers
-from Cheetah.Unspecified import Unspecified
-
-# re tools
-def escapeRegexChars(txt,
- escapeRE=re.compile(r'([\$\^\*\+\.\?\{\}\[\]\(\)\|\\])')):
-
- """Return a txt with all special regular expressions chars escaped."""
-
- return escapeRE.sub(r'\\\1' , txt)
-
-def group(*choices): return '(' + '|'.join(choices) + ')'
-def nongroup(*choices): return '(?:' + '|'.join(choices) + ')'
-def namedGroup(name, *choices): return '(P:<' + name +'>' + '|'.join(choices) + ')'
-def any(*choices): return apply(group, choices) + '*'
-def maybe(*choices): return apply(group, choices) + '?'
-
-##################################################
-## CONSTANTS & GLOBALS ##
-
-NO_CACHE = 0
-STATIC_CACHE = 1
-REFRESH_CACHE = 2
-
-SET_LOCAL = 0
-SET_GLOBAL = 1
-SET_MODULE = 2
-
-##################################################
-## Tokens for the parser ##
-
-#generic
-identchars = "abcdefghijklmnopqrstuvwxyz" \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
-namechars = identchars + "0123456789"
-
-#operators
-powerOp = '**'
-unaryArithOps = ('+', '-', '~')
-binaryArithOps = ('+', '-', '/', '//','%')
-shiftOps = ('>>','<<')
-bitwiseOps = ('&','|','^')
-assignOp = '='
-augAssignOps = ('+=','-=','/=','*=', '**=','^=','%=',
- '>>=','<<=','&=','|=', )
-assignmentOps = (assignOp,) + augAssignOps
-
-compOps = ('<','>','==','!=','<=','>=', '<>', 'is', 'in',)
-booleanOps = ('and','or','not')
-operators = (powerOp,) + unaryArithOps + binaryArithOps \
- + shiftOps + bitwiseOps + assignmentOps \
- + compOps + booleanOps
-
-delimeters = ('(',')','{','}','[',']',
- ',','.',':',';','=','`') + augAssignOps
-
-
-keywords = ('and', 'del', 'for', 'is', 'raise',
- 'assert', 'elif', 'from', 'lambda', 'return',
- 'break', 'else', 'global', 'not', 'try',
- 'class', 'except', 'if', 'or', 'while',
- 'continue', 'exec', 'import', 'pass',
- 'def', 'finally', 'in', 'print',
- )
-
-single3 = "'''"
-double3 = '"""'
-
-tripleQuotedStringStarts = ("'''", '"""',
- "r'''", 'r"""', "R'''", 'R"""',
- "u'''", 'u"""', "U'''", 'U"""',
- "ur'''", 'ur"""', "Ur'''", 'Ur"""',
- "uR'''", 'uR"""', "UR'''", 'UR"""')
-
-tripleQuotedStringPairs = {"'''": single3, '"""': double3,
- "r'''": single3, 'r"""': double3,
- "u'''": single3, 'u"""': double3,
- "ur'''": single3, 'ur"""': double3,
- "R'''": single3, 'R"""': double3,
- "U'''": single3, 'U"""': double3,
- "uR'''": single3, 'uR"""': double3,
- "Ur'''": single3, 'Ur"""': double3,
- "UR'''": single3, 'UR"""': double3,
- }
-
-closurePairs= {')':'(',']':'[','}':'{'}
-closurePairsRev= {'(':')','[':']','{':'}'}
-
-##################################################
-## Regex chunks for the parser ##
-
-tripleQuotedStringREs = {}
-def makeTripleQuoteRe(start, end):
- start = escapeRegexChars(start)
- end = escapeRegexChars(end)
- return re.compile(r'(?:' + start + r').*?' + r'(?:' + end + r')', re.DOTALL)
-
-for start, end in tripleQuotedStringPairs.items():
- tripleQuotedStringREs[start] = makeTripleQuoteRe(start, end)
-
-WS = r'[ \f\t]*'
-EOL = r'\r\n|\n|\r'
-EOLZ = EOL + r'|\Z'
-escCharLookBehind = nongroup(r'(?<=\A)',r'(?<!\\)')
-nameCharLookAhead = r'(?=[A-Za-z_])'
-identRE=re.compile(r'[a-zA-Z_][a-zA-Z_0-9]*')
-EOLre=re.compile(r'(?:\r\n|\r|\n)')
-
-specialVarRE=re.compile(r'([a-zA-z_]+)@') # for matching specialVar comments
-# e.g. ##author@ Tavis Rudd
-
-directiveNamesAndParsers = {
- # importing and inheritance
- 'import':None,
- 'from':None,
- 'extends': 'eatExtends',
- 'implements': 'eatImplements',
-
- # output, filtering, and caching
- 'slurp': 'eatSlurp',
- 'raw': 'eatRaw',
- 'include': 'eatInclude',
- 'cache': 'eatCache',
- 'filter': 'eatFilter',
- 'echo': None,
- 'silent': None,
-
- 'call': 'eatCall',
- 'arg': 'eatCallArg',
-
- 'capture': 'eatCapture',
-
- # declaration, assignment, and deletion
- 'attr': 'eatAttr',
- 'def': 'eatDef',
- 'block': 'eatBlock',
- '@': 'eatDecorator',
- 'defmacro': 'eatDefMacro',
-
- 'closure': 'eatClosure',
-
- 'set': 'eatSet',
- 'del': None,
-
- # flow control
- 'if': 'eatIf',
- 'while': None,
- 'for': None,
- 'else': None,
- 'elif': None,
- 'pass': None,
- 'break': None,
- 'continue': None,
- 'stop': None,
- 'return': None,
- 'yield': None,
-
- # little wrappers
- 'repeat': None,
- 'unless': None,
-
- # error handling
- 'assert': None,
- 'raise': None,
- 'try': None,
- 'except': None,
- 'finally': None,
- 'errorCatcher': 'eatErrorCatcher',
-
- # intructions to the parser and compiler
- 'breakpoint': 'eatBreakPoint',
- 'compiler': 'eatCompiler',
- 'compiler-settings': 'eatCompilerSettings',
-
- # misc
- 'shBang': 'eatShbang',
- 'encoding': 'eatEncoding',
-
- 'end': 'eatEndDirective',
- }
-
-endDirectiveNamesAndHandlers = {
- 'def': 'handleEndDef', # has short-form
- 'block': None, # has short-form
- 'closure': None, # has short-form
- 'cache': None, # has short-form
- 'call': None, # has short-form
- 'capture': None, # has short-form
- 'filter': None,
- 'errorCatcher':None,
- 'while': None, # has short-form
- 'for': None, # has short-form
- 'if': None, # has short-form
- 'try': None, # has short-form
- 'repeat': None, # has short-form
- 'unless': None, # has short-form
- }
-
-##################################################
-## CLASSES ##
-
-# @@TR: SyntaxError doesn't call exception.__str__ for some reason!
-#class ParseError(SyntaxError):
-class ParseError(ValueError):
- def __init__(self, stream, msg='Invalid Syntax', extMsg='', lineno=None, col=None):
- self.stream = stream
- if stream.pos() >= len(stream):
- stream.setPos(len(stream) -1)
- self.msg = msg
- self.extMsg = extMsg
- self.lineno = lineno
- self.col = col
-
- def __str__(self):
- return self.report()
-
- def report(self):
- stream = self.stream
- if stream.filename():
- f = " in file %s" % stream.filename()
- else:
- f = ''
- report = ''
- if self.lineno:
- lineno = self.lineno
- row, col, line = (lineno, (self.col or 0),
- self.stream.splitlines()[lineno-1])
- else:
- row, col, line = self.stream.getRowColLine()
-
- ## get the surrounding lines
- lines = stream.splitlines()
- prevLines = [] # (rowNum, content)
- for i in range(1,4):
- if row-1-i <=0:
- break
- prevLines.append( (row-i,lines[row-1-i]) )
-
- nextLines = [] # (rowNum, content)
- for i in range(1,4):
- if not row-1+i < len(lines):
- break
- nextLines.append( (row+i,lines[row-1+i]) )
- nextLines.reverse()
-
- ## print the main message
- report += "\n\n%s\n" %self.msg
- report += "Line %i, column %i%s\n\n" % (row, col, f)
- report += 'Line|Cheetah Code\n'
- report += '----|-------------------------------------------------------------\n'
- while prevLines:
- lineInfo = prevLines.pop()
- report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
- report += "%(row)-4d|%(line)s\n"% {'row':row, 'line':line}
- report += ' '*5 +' '*(col-1) + "^\n"
-
- while nextLines:
- lineInfo = nextLines.pop()
- report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
- ## add the extra msg
- if self.extMsg:
- report += self.extMsg + '\n'
-
- return report
-
-class ForbiddenSyntax(ParseError): pass
-class ForbiddenExpression(ForbiddenSyntax): pass
-class ForbiddenDirective(ForbiddenSyntax): pass
-
-class CheetahVariable:
- def __init__(self, nameChunks, useNameMapper=True, cacheToken=None,
- rawSource=None):
- self.nameChunks = nameChunks
- self.useNameMapper = useNameMapper
- self.cacheToken = cacheToken
- self.rawSource = rawSource
-
-class Placeholder(CheetahVariable): pass
-
-class ArgList:
- """Used by _LowLevelParser.getArgList()"""
-
- def __init__(self):
- self.argNames = []
- self.defVals = []
- self.i = 0
-
- def addArgName(self, name):
- self.argNames.append( name )
- self.defVals.append( None )
-
- def next(self):
- self.i += 1
-
- def addToDefVal(self, token):
- i = self.i
- if self.defVals[i] == None:
- self.defVals[i] = ''
- self.defVals[i] += token
-
- def merge(self):
- defVals = self.defVals
- for i in range(len(defVals)):
- if type(defVals[i]) == StringType:
- defVals[i] = defVals[i].strip()
-
- return map(None, [i.strip() for i in self.argNames], defVals)
-
- def __str__(self):
- return str(self.merge())
-
-class _LowLevelParser(SourceReader):
- """This class implements the methods to match or extract ('get*') the basic
- elements of Cheetah's grammar. It does NOT handle any code generation or
- state management.
- """
-
- _settingsManager = None
-
- def setSettingsManager(self, settingsManager):
- self._settingsManager = settingsManager
-
- def setting(self, key, default=Unspecified):
- if default is Unspecified:
- return self._settingsManager.setting(key)
- else:
- return self._settingsManager.setting(key, default=default)
-
- def setSetting(self, key, val):
- self._settingsManager.setSetting(key, val)
-
- def settings(self):
- return self._settingsManager.settings()
-
- def updateSettings(self, settings):
- self._settingsManager.updateSettings(settings)
-
- def _initializeSettings(self):
- self._settingsManager._initializeSettings()
-
- def configureParser(self):
- """Is called by the Compiler instance after the parser has had a
- settingsManager assigned with self.setSettingsManager()
- """
- self._makeCheetahVarREs()
- self._makeCommentREs()
- self._makeDirectiveREs()
- self._makePspREs()
- self._possibleNonStrConstantChars = (
- self.setting('commentStartToken')[0] +
- self.setting('multiLineCommentStartToken')[0] +
- self.setting('cheetahVarStartToken')[0] +
- self.setting('directiveStartToken')[0] +
- self.setting('PSPStartToken')[0])
- self._nonStrConstMatchers = [
- self.matchCommentStartToken,
- self.matchMultiLineCommentStartToken,
- self.matchVariablePlaceholderStart,
- self.matchExpressionPlaceholderStart,
- self.matchDirective,
- self.matchPSPStartToken,
- self.matchEOLSlurpToken,
- ]
-
- ## regex setup ##
-
- def _makeCheetahVarREs(self):
-
- """Setup the regexs for Cheetah $var parsing."""
-
- num = r'[0-9\.]+'
- interval = (r'(?P<interval>' +
- num + r's|' +
- num + r'm|' +
- num + r'h|' +
- num + r'd|' +
- num + r'w|' +
- num + ')'
- )
-
- cacheToken = (r'(?:' +
- r'(?P<REFRESH_CACHE>\*' + interval + '\*)'+
- '|' +
- r'(?P<STATIC_CACHE>\*)' +
- '|' +
- r'(?P<NO_CACHE>)' +
- ')')
- self.cacheTokenRE = re.compile(cacheToken)
-
- silentPlaceholderToken = (r'(?:' +
- r'(?P<SILENT>' +escapeRegexChars('!')+')'+
- '|' +
- r'(?P<NOT_SILENT>)' +
- ')')
- self.silentPlaceholderTokenRE = re.compile(silentPlaceholderToken)
-
- self.cheetahVarStartRE = re.compile(
- escCharLookBehind +
- r'(?P<startToken>'+escapeRegexChars(self.setting('cheetahVarStartToken'))+')'+
- r'(?P<silenceToken>'+silentPlaceholderToken+')'+
- r'(?P<cacheToken>'+cacheToken+')'+
- r'(?P<enclosure>|(?:(?:\{|\(|\[)[ \t\f]*))' + # allow WS after enclosure
- r'(?=[A-Za-z_])')
- validCharsLookAhead = r'(?=[A-Za-z_\*!\{\(\[])'
- self.cheetahVarStartToken = self.setting('cheetahVarStartToken')
- self.cheetahVarStartTokenRE = re.compile(
- escCharLookBehind +
- escapeRegexChars(self.setting('cheetahVarStartToken'))
- +validCharsLookAhead
- )
-
- self.cheetahVarInExpressionStartTokenRE = re.compile(
- escapeRegexChars(self.setting('cheetahVarStartToken'))
- +r'(?=[A-Za-z_])'
- )
-
- self.expressionPlaceholderStartRE = re.compile(
- escCharLookBehind +
- r'(?P<startToken>' + escapeRegexChars(self.setting('cheetahVarStartToken')) + ')' +
- r'(?P<cacheToken>' + cacheToken + ')' +
- #r'\[[ \t\f]*'
- r'(?:\{|\(|\[)[ \t\f]*'
- + r'(?=[^\)\}\]])'
- )
-
- if self.setting('EOLSlurpToken'):
- self.EOLSlurpRE = re.compile(
- escapeRegexChars(self.setting('EOLSlurpToken'))
- + r'[ \t\f]*'
- + r'(?:'+EOL+')'
- )
- else:
- self.EOLSlurpRE = None
-
-
- def _makeCommentREs(self):
- """Construct the regex bits that are used in comment parsing."""
- startTokenEsc = escapeRegexChars(self.setting('commentStartToken'))
- self.commentStartTokenRE = re.compile(escCharLookBehind + startTokenEsc)
- del startTokenEsc
-
- startTokenEsc = escapeRegexChars(
- self.setting('multiLineCommentStartToken'))
- endTokenEsc = escapeRegexChars(
- self.setting('multiLineCommentEndToken'))
- self.multiLineCommentTokenStartRE = re.compile(escCharLookBehind +
- startTokenEsc)
- self.multiLineCommentEndTokenRE = re.compile(escCharLookBehind +
- endTokenEsc)
-
- def _makeDirectiveREs(self):
- """Construct the regexs that are used in directive parsing."""
- startToken = self.setting('directiveStartToken')
- endToken = self.setting('directiveEndToken')
- startTokenEsc = escapeRegexChars(startToken)
- endTokenEsc = escapeRegexChars(endToken)
- validSecondCharsLookAhead = r'(?=[A-Za-z_@])'
- reParts = [escCharLookBehind, startTokenEsc]
- if self.setting('allowWhitespaceAfterDirectiveStartToken'):
- reParts.append('[ \t]*')
- reParts.append(validSecondCharsLookAhead)
- self.directiveStartTokenRE = re.compile(''.join(reParts))
- self.directiveEndTokenRE = re.compile(escCharLookBehind + endTokenEsc)
-
- def _makePspREs(self):
- """Setup the regexs for PSP parsing."""
- startToken = self.setting('PSPStartToken')
- startTokenEsc = escapeRegexChars(startToken)
- self.PSPStartTokenRE = re.compile(escCharLookBehind + startTokenEsc)
- endToken = self.setting('PSPEndToken')
- endTokenEsc = escapeRegexChars(endToken)
- self.PSPEndTokenRE = re.compile(escCharLookBehind + endTokenEsc)
-
-
- def isLineClearToStartToken(self, pos=None):
- return self.isLineClearToPos(pos)
-
- def matchTopLevelToken(self):
- """Returns the first match found from the following methods:
- self.matchCommentStartToken
- self.matchMultiLineCommentStartToken
- self.matchVariablePlaceholderStart
- self.matchExpressionPlaceholderStart
- self.matchDirective
- self.matchPSPStartToken
- self.matchEOLSlurpToken
-
- Returns None if no match.
- """
- match = None
- if self.peek() in self._possibleNonStrConstantChars:
- for matcher in self._nonStrConstMatchers:
- match = matcher()
- if match:
- break
- return match
-
- def matchPyToken(self):
- match = pseudoprog.match(self.src(), self.pos())
-
- if match and match.group() in tripleQuotedStringStarts:
- TQSmatch = tripleQuotedStringREs[match.group()].match(self.src(), self.pos())
- if TQSmatch:
- return TQSmatch
- return match
-
- def getPyToken(self):
- match = self.matchPyToken()
- if match is None:
- raise ParseError(self)
- elif match.group() in tripleQuotedStringStarts:
- raise ParseError(self, msg='Malformed triple-quoted string')
- return self.readTo(match.end())
-
- def matchEOLSlurpToken(self):
- if self.EOLSlurpRE:
- return self.EOLSlurpRE.match(self.src(), self.pos())
-
- def getEOLSlurpToken(self):
- match = self.matchEOLSlurpToken()
- if not match:
- raise ParseError(self, msg='Invalid EOL slurp token')
- return self.readTo(match.end())
-
- def matchCommentStartToken(self):
- return self.commentStartTokenRE.match(self.src(), self.pos())
-
- def getCommentStartToken(self):
- match = self.matchCommentStartToken()
- if not match:
- raise ParseError(self, msg='Invalid single-line comment start token')
- return self.readTo(match.end())
-
- def matchMultiLineCommentStartToken(self):
- return self.multiLineCommentTokenStartRE.match(self.src(), self.pos())
-
- def getMultiLineCommentStartToken(self):
- match = self.matchMultiLineCommentStartToken()
- if not match:
- raise ParseError(self, msg='Invalid multi-line comment start token')
- return self.readTo(match.end())
-
- def matchMultiLineCommentEndToken(self):
- return self.multiLineCommentEndTokenRE.match(self.src(), self.pos())
-
- def getMultiLineCommentEndToken(self):
- match = self.matchMultiLineCommentEndToken()
- if not match:
- raise ParseError(self, msg='Invalid multi-line comment end token')
- return self.readTo(match.end())
-
- def getDottedName(self):
- srcLen = len(self)
- nameChunks = []
-
- if not self.peek() in identchars:
- raise ParseError(self)
-
- while self.pos() < srcLen:
- c = self.peek()
- if c in namechars:
- nameChunk = self.getIdentifier()
- nameChunks.append(nameChunk)
- elif c == '.':
- if self.pos()+1 <srcLen and self.peek(1) in identchars:
- nameChunks.append(self.getc())
- else:
- break
- else:
- break
-
- return ''.join(nameChunks)
-
- def matchIdentifier(self):
- return identRE.match(self.src(), self.pos())
-
- def getIdentifier(self):
- match = self.matchIdentifier()
- if not match:
- raise ParseError(self, msg='Invalid identifier')
- return self.readTo(match.end())
-
- def matchOperator(self):
- match = self.matchPyToken()
- if match and match.group() not in operators:
- match = None
- return match
-
- def getOperator(self):
- match = self.matchOperator()
- if not match:
- raise ParseError(self, msg='Expected operator')
- return self.readTo( match.end() )
-
- def matchAssignmentOperator(self):
- match = self.matchPyToken()
- if match and match.group() not in assignmentOps:
- match = None
- return match
-
- def getAssignmentOperator(self):
- match = self.matchAssignmentOperator()
- if not match:
- raise ParseError(self, msg='Expected assignment operator')
- return self.readTo( match.end() )
-
- def matchDirective(self):
- """Returns False or the name of the directive matched.
- """
- startPos = self.pos()
- if not self.matchDirectiveStartToken():
- return False
- self.getDirectiveStartToken()
- directiveName = self.matchDirectiveName()
- self.setPos(startPos)
- return directiveName
-
- def matchDirectiveName(self, directiveNameChars=identchars+'0123456789-@'):
- startPos = self.pos()
- directives = self._directiveNamesAndParsers.keys()
- possibleMatches = []
- name = ''
- while not self.atEnd():
- c = self.getc()
- if not c in directiveNameChars:
- break
- name += c
- if name in directives:
- possibleMatches.append(name)
-
- possibleMatches.sort()
- possibleMatches.reverse() # longest match first
-
- directiveName = False
- if possibleMatches:
- directiveName = possibleMatches[0]
-
- self.setPos(startPos)
- return directiveName
-
- def matchDirectiveStartToken(self):
- return self.directiveStartTokenRE.match(self.src(), self.pos())
-
- def getDirectiveStartToken(self):
- match = self.matchDirectiveStartToken()
- if not match:
- raise ParseError(self, msg='Invalid directive start token')
- return self.readTo(match.end())
-
- def matchDirectiveEndToken(self):
- return self.directiveEndTokenRE.match(self.src(), self.pos())
-
- def getDirectiveEndToken(self):
- match = self.matchDirectiveEndToken()
- if not match:
- raise ParseError(self, msg='Invalid directive end token')
- return self.readTo(match.end())
-
-
- def matchColonForSingleLineShortFormDirective(self):
- if not self.atEnd() and self.peek()==':':
- restOfLine = self[self.pos()+1:self.findEOL()]
- restOfLine = restOfLine.strip()
- if not restOfLine:
- return False
- elif self.commentStartTokenRE.match(restOfLine):
- return False
- else: # non-whitespace, non-commment chars found
- return True
- return False
-
- def matchPSPStartToken(self):
- return self.PSPStartTokenRE.match(self.src(), self.pos())
-
- def matchPSPEndToken(self):
- return self.PSPEndTokenRE.match(self.src(), self.pos())
-
- def getPSPStartToken(self):
- match = self.matchPSPStartToken()
- if not match:
- raise ParseError(self, msg='Invalid psp start token')
- return self.readTo(match.end())
-
- def getPSPEndToken(self):
- match = self.matchPSPEndToken()
- if not match:
- raise ParseError(self, msg='Invalid psp end token')
- return self.readTo(match.end())
-
- def matchCheetahVarStart(self):
- """includes the enclosure and cache token"""
- return self.cheetahVarStartRE.match(self.src(), self.pos())
-
- def matchCheetahVarStartToken(self):
- """includes the enclosure and cache token"""
- return self.cheetahVarStartTokenRE.match(self.src(), self.pos())
-
- def matchCheetahVarInExpressionStartToken(self):
- """no enclosures or cache tokens allowed"""
- return self.cheetahVarInExpressionStartTokenRE.match(self.src(), self.pos())
-
- def matchVariablePlaceholderStart(self):
- """includes the enclosure and cache token"""
- return self.cheetahVarStartRE.match(self.src(), self.pos())
-
- def matchExpressionPlaceholderStart(self):
- """includes the enclosure and cache token"""
- return self.expressionPlaceholderStartRE.match(self.src(), self.pos())
-
- def getCheetahVarStartToken(self):
- """just the start token, not the enclosure or cache token"""
- match = self.matchCheetahVarStartToken()
- if not match:
- raise ParseError(self, msg='Expected Cheetah $var start token')
- return self.readTo( match.end() )
-
-
- def getCacheToken(self):
- try:
- token = self.cacheTokenRE.match(self.src(), self.pos())
- self.setPos( token.end() )
- return token.group()
- except:
- raise ParseError(self, msg='Expected cache token')
-
- def getSilentPlaceholderToken(self):
- try:
- token = self.silentPlaceholderTokenRE.match(self.src(), self.pos())
- self.setPos( token.end() )
- return token.group()
- except:
- raise ParseError(self, msg='Expected silent placeholder token')
-
-
-
- def getTargetVarsList(self):
- varnames = []
- while not self.atEnd():
- if self.peek() in ' \t\f':
- self.getWhiteSpace()
- elif self.peek() in '\r\n':
- break
- elif self.startswith(','):
- self.advance()
- elif self.startswith('in ') or self.startswith('in\t'):
- break
- #elif self.matchCheetahVarStart():
- elif self.matchCheetahVarInExpressionStartToken():
- self.getCheetahVarStartToken()
- self.getSilentPlaceholderToken()
- self.getCacheToken()
- varnames.append( self.getDottedName() )
- elif self.matchIdentifier():
- varnames.append( self.getDottedName() )
- else:
- break
- return varnames
-
- def getCheetahVar(self, plain=False, skipStartToken=False):
- """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:
- self.getCheetahVarStartToken()
- self.getSilentPlaceholderToken()
- self.getCacheToken()
- return self.getCheetahVarBody(plain=plain)
-
- def getCheetahVarBody(self, plain=False):
- # @@TR: this should be in the compiler
- return self._compiler.genCheetahVar(self.getCheetahVarNameChunks(), plain=plain)
-
- def getCheetahVarNameChunks(self):
-
- """
- nameChunks = list of Cheetah $var subcomponents represented as tuples
- [ (namemapperPart,autoCall,restOfName),
- ]
- where:
- namemapperPart = the dottedName base
- autocall = where NameMapper should use autocalling on namemapperPart
- restOfName = any arglist, index, or slice
-
- If restOfName contains a call arglist (e.g. '(1234)') then autocall is
- False, otherwise it defaults to True.
-
- EXAMPLE
- ------------------------------------------------------------------------
-
- if the raw CheetahVar is
- $a.b.c[1].d().x.y.z
-
- nameChunks is the list
- [ ('a.b.c',True,'[1]'),
- ('d',False,'()'),
- ('x.y.z',True,''),
- ]
-
- """
-
- chunks = []
- while self.pos() < len(self):
- rest = ''
- autoCall = True
- if not self.peek() in identchars + '.':
- break
- elif self.peek() == '.':
-
- if self.pos()+1 < len(self) and self.peek(1) in identchars:
- self.advance() # discard the period as it isn't needed with NameMapper
- else:
- break
-
- dottedName = self.getDottedName()
- if not self.atEnd() and self.peek() in '([':
- if self.peek() == '(':
- rest = self.getCallArgString()
- else:
- rest = self.getExpression(enclosed=True)
-
- period = max(dottedName.rfind('.'), 0)
- if period:
- chunks.append( (dottedName[:period], autoCall, '') )
- dottedName = dottedName[period+1:]
- if rest and rest[0]=='(':
- autoCall = False
- chunks.append( (dottedName, autoCall, rest) )
-
- return chunks
-
-
- def getCallArgString(self,
- enclosures=[], # list of tuples (char, pos), where char is ({ or [
- useNameMapper=Unspecified):
-
- """ Get a method/function call argument string.
-
- This method understands *arg, and **kw
- """
-
- # @@TR: this settings mangling should be removed
- if useNameMapper is not Unspecified:
- useNameMapper_orig = self.setting('useNameMapper')
- self.setSetting('useNameMapper', useNameMapper)
-
- if enclosures:
- pass
- else:
- if not self.peek() == '(':
- raise ParseError(self, msg="Expected '('")
- startPos = self.pos()
- self.getc()
- enclosures = [('(', startPos),
- ]
-
- argStringBits = ['(']
- addBit = argStringBits.append
-
- while 1:
- if self.atEnd():
- open = enclosures[-1][0]
- close = closurePairsRev[open]
- self.setPos(enclosures[-1][1])
- raise ParseError(
- self, msg="EOF was reached before a matching '" + close +
- "' was found for the '" + open + "'")
-
- c = self.peek()
- if c in ")}]": # get the ending enclosure and break
- if not enclosures:
- raise ParseError(self)
- c = self.getc()
- open = closurePairs[c]
- if enclosures[-1][0] == open:
- enclosures.pop()
- addBit(')')
- break
- else:
- raise ParseError(self)
- elif c in " \t\f\r\n":
- addBit(self.getc())
- elif self.matchCheetahVarInExpressionStartToken():
- startPos = self.pos()
- codeFor1stToken = self.getCheetahVar()
- WS = self.getWhiteSpace()
- if not self.atEnd() and self.peek() == '=':
- nextToken = self.getPyToken()
- if nextToken == '=':
- endPos = self.pos()
- self.setPos(startPos)
- codeFor1stToken = self.getCheetahVar(plain=True)
- self.setPos(endPos)
-
- ## finally
- addBit( codeFor1stToken + WS + nextToken )
- else:
- addBit( codeFor1stToken + WS)
- elif self.matchCheetahVarStart():
- # it has syntax that is only valid at the top level
- self._raiseErrorAboutInvalidCheetahVarSyntaxInExpr()
- else:
- beforeTokenPos = self.pos()
- token = self.getPyToken()
- if token in ('{','(','['):
- self.rev()
- token = self.getExpression(enclosed=True)
- token = self.transformToken(token, beforeTokenPos)
- addBit(token)
-
- if useNameMapper is not Unspecified:
- self.setSetting('useNameMapper', useNameMapper_orig) # @@TR: see comment above
-
- return ''.join(argStringBits)
-
- def getDefArgList(self, exitPos=None, useNameMapper=False):
-
- """ Get an argument list. Can be used for method/function definition
- argument lists or for #directive argument lists. Returns a list of
- tuples in the form (argName, defVal=None) with one tuple for each arg
- name.
-
- These defVals are always strings, so (argName, defVal=None) is safe even
- with a case like (arg1, arg2=None, arg3=1234*2), which would be returned as
- [('arg1', None),
- ('arg2', 'None'),
- ('arg3', '1234*2'),
- ]
-
- This method understands *arg, and **kw
-
- """
-
- if self.peek() == '(':
- self.advance()
- else:
- exitPos = self.findEOL() # it's a directive so break at the EOL
- argList = ArgList()
- onDefVal = False
-
- # @@TR: this settings mangling should be removed
- useNameMapper_orig = self.setting('useNameMapper')
- self.setSetting('useNameMapper', useNameMapper)
-
- while 1:
- if self.atEnd():
- self.setPos(enclosures[-1][1])
- raise ParseError(
- self, msg="EOF was reached before a matching ')'"+
- " was found for the '('")
-
- if self.pos() == exitPos:
- break
-
- c = self.peek()
- if c == ")" or self.matchDirectiveEndToken():
- break
- elif c == ":":
- break
- elif c in " \t\f\r\n":
- if onDefVal:
- argList.addToDefVal(c)
- self.advance()
- elif c == '=':
- onDefVal = True
- self.advance()
- elif c == ",":
- argList.next()
- onDefVal = False
- self.advance()
- elif self.startswith(self.cheetahVarStartToken) and not onDefVal:
- self.advance(len(self.cheetahVarStartToken))
- elif self.matchIdentifier() and not onDefVal:
- argList.addArgName( self.getIdentifier() )
- elif onDefVal:
- if self.matchCheetahVarInExpressionStartToken():
- token = self.getCheetahVar()
- elif self.matchCheetahVarStart():
- # it has syntax that is only valid at the top level
- self._raiseErrorAboutInvalidCheetahVarSyntaxInExpr()
- else:
- beforeTokenPos = self.pos()
- token = self.getPyToken()
- if token in ('{','(','['):
- self.rev()
- token = self.getExpression(enclosed=True)
- token = self.transformToken(token, beforeTokenPos)
- argList.addToDefVal(token)
- elif c == '*' and not onDefVal:
- varName = self.getc()
- if self.peek() == '*':
- varName += self.getc()
- if not self.matchIdentifier():
- raise ParseError(self)
- varName += self.getIdentifier()
- argList.addArgName(varName)
- else:
- raise ParseError(self)
-
-
- self.setSetting('useNameMapper', useNameMapper_orig) # @@TR: see comment above
- return argList.merge()
-
- def getExpressionParts(self,
- enclosed=False,
- enclosures=None, # list of tuples (char, pos), where char is ({ or [
- pyTokensToBreakAt=None, # only works if not enclosed
- useNameMapper=Unspecified,
- ):
-
- """ Get a Cheetah expression that includes $CheetahVars and break at
- directive end tokens, the end of an enclosure, or at a specified
- pyToken.
- """
-
- if useNameMapper is not Unspecified:
- useNameMapper_orig = self.setting('useNameMapper')
- self.setSetting('useNameMapper', useNameMapper)
-
- if enclosures is None:
- enclosures = []
-
- srcLen = len(self)
- exprBits = []
- while 1:
- if self.atEnd():
- if enclosures:
- open = enclosures[-1][0]
- close = closurePairsRev[open]
- self.setPos(enclosures[-1][1])
- raise ParseError(
- self, msg="EOF was reached before a matching '" + close +
- "' was found for the '" + open + "'")
- else:
- break
-
- c = self.peek()
- if c in "{([":
- exprBits.append(c)
- enclosures.append( (c, self.pos()) )
- self.advance()
- elif enclosed and not enclosures:
- break
- elif c in "])}":
- if not enclosures:
- raise ParseError(self)
- open = closurePairs[c]
- if enclosures[-1][0] == open:
- enclosures.pop()
- exprBits.append(c)
- else:
- open = enclosures[-1][0]
- close = closurePairsRev[open]
- row, col = self.getRowCol()
- self.setPos(enclosures[-1][1])
- raise ParseError(
- self, msg= "A '" + c + "' was found at line " + str(row) +
- ", col " + str(col) +
- " before a matching '" + close +
- "' was found\nfor the '" + open + "'")
- self.advance()
-
- elif c in " \f\t":
- exprBits.append(self.getWhiteSpace())
- elif self.matchDirectiveEndToken() and not enclosures:
- break
- elif c == "\\" and self.pos()+1 < srcLen:
- eolMatch = EOLre.match(self.src(), self.pos()+1)
- if not eolMatch:
- self.advance()
- raise ParseError(self, msg='Line ending expected')
- self.setPos( eolMatch.end() )
- elif c in '\r\n':
- if enclosures:
- self.advance()
- else:
- break
- elif self.matchCheetahVarInExpressionStartToken():
- expr = self.getCheetahVar()
- exprBits.append(expr)
- elif self.matchCheetahVarStart():
- # it has syntax that is only valid at the top level
- self._raiseErrorAboutInvalidCheetahVarSyntaxInExpr()
- else:
- beforeTokenPos = self.pos()
- token = self.getPyToken()
- if (not enclosures
- and pyTokensToBreakAt
- and token in pyTokensToBreakAt):
-
- self.setPos(beforeTokenPos)
- break
-
- token = self.transformToken(token, beforeTokenPos)
-
- exprBits.append(token)
- if identRE.match(token):
- if token == 'for':
- expr = self.getExpression(useNameMapper=False, pyTokensToBreakAt=['in'])
- exprBits.append(expr)
- else:
- exprBits.append(self.getWhiteSpace())
- if not self.atEnd() and self.peek() == '(':
- exprBits.append(self.getCallArgString())
- ##
- if useNameMapper is not Unspecified:
- self.setSetting('useNameMapper', useNameMapper_orig) # @@TR: see comment above
- return exprBits
-
- def getExpression(self,
- enclosed=False,
- enclosures=None, # list of tuples (char, pos), where # char is ({ or [
- pyTokensToBreakAt=None,
- useNameMapper=Unspecified,
- ):
- """Returns the output of self.getExpressionParts() as a concatenated
- string rather than as a list.
- """
- return ''.join(self.getExpressionParts(
- enclosed=enclosed, enclosures=enclosures,
- pyTokensToBreakAt=pyTokensToBreakAt,
- useNameMapper=useNameMapper))
-
-
- def transformToken(self, token, beforeTokenPos):
- """Takes a token from the expression being parsed and performs and
- special transformations required by Cheetah.
-
- At the moment only Cheetah's c'$placeholder strings' are transformed.
- """
- if token=='c' and not self.atEnd() and self.peek() in '\'"':
- nextToken = self.getPyToken()
- token = nextToken.upper()
- theStr = eval(token)
- endPos = self.pos()
- if not theStr:
- return
-
- if token.startswith(single3) or token.startswith(double3):
- startPosIdx = 3
- else:
- startPosIdx = 1
- #print 'CHEETAH STRING', nextToken, theStr, startPosIdx
- self.setPos(beforeTokenPos+startPosIdx+1)
- outputExprs = []
- strConst = ''
- while self.pos() < (endPos-startPosIdx):
- if self.matchCheetahVarStart() or self.matchExpressionPlaceholderStart():
- if strConst:
- outputExprs.append(repr(strConst))
- strConst = ''
- placeholderExpr = self.getPlaceholder()
- outputExprs.append('str('+placeholderExpr+')')
- else:
- strConst += self.getc()
- self.setPos(endPos)
- if strConst:
- outputExprs.append(repr(strConst))
- #if not self.atEnd() and self.matches('.join('):
- # print 'DEBUG***'
- token = "''.join(["+','.join(outputExprs)+"])"
- return token
-
- def _raiseErrorAboutInvalidCheetahVarSyntaxInExpr(self):
- match = self.matchCheetahVarStart()
- groupdict = match.groupdict()
- if groupdict.get('cacheToken'):
- raise ParseError(
- self,
- msg='Cache tokens are not valid inside expressions. '
- 'Use them in top-level $placeholders only.')
- elif groupdict.get('enclosure'):
- raise ParseError(
- self,
- msg='Long-form placeholders - ${}, $(), $[], etc. are not valid inside expressions. '
- 'Use them in top-level $placeholders only.')
- else:
- raise ParseError(
- self,
- msg='This form of $placeholder syntax is not valid here.')
-
-
- def getPlaceholder(self, allowCacheTokens=False, plain=False, returnEverything=False):
- # filtered
- for callback in self.setting('preparsePlaceholderHooks'):
- callback(parser=self)
-
- startPos = self.pos()
- lineCol = self.getRowCol(startPos)
- startToken = self.getCheetahVarStartToken()
- silentPlaceholderToken = self.getSilentPlaceholderToken()
- if silentPlaceholderToken:
- isSilentPlaceholder = True
- else:
- isSilentPlaceholder = False
-
-
- if allowCacheTokens:
- cacheToken = self.getCacheToken()
- cacheTokenParts = self.cacheTokenRE.match(cacheToken).groupdict()
- else:
- cacheTokenParts = {}
-
- if self.peek() in '({[':
- pos = self.pos()
- enclosureOpenChar = self.getc()
- enclosures = [ (enclosureOpenChar, pos) ]
- self.getWhiteSpace()
- else:
- enclosures = []
-
- filterArgs = None
- if self.matchIdentifier():
- nameChunks = self.getCheetahVarNameChunks()
- expr = self._compiler.genCheetahVar(nameChunks[:], plain=plain)
- restOfExpr = None
- if enclosures:
- WS = self.getWhiteSpace()
- expr += WS
- if self.setting('allowPlaceholderFilterArgs') and self.peek()==',':
- filterArgs = self.getCallArgString(enclosures=enclosures)[1:-1]
- else:
- if self.peek()==closurePairsRev[enclosureOpenChar]:
- self.getc()
- else:
- restOfExpr = self.getExpression(enclosed=True, enclosures=enclosures)
- if restOfExpr[-1] == closurePairsRev[enclosureOpenChar]:
- restOfExpr = restOfExpr[:-1]
- expr += restOfExpr
- rawPlaceholder = self[startPos: self.pos()]
- else:
- expr = self.getExpression(enclosed=True, enclosures=enclosures)
- if expr[-1] == closurePairsRev[enclosureOpenChar]:
- expr = expr[:-1]
- rawPlaceholder=self[startPos: self.pos()]
-
- expr = self._applyExpressionFilters(expr,'placeholder',
- rawExpr=rawPlaceholder,startPos=startPos)
- for callback in self.setting('postparsePlaceholderHooks'):
- callback(parser=self)
-
- if returnEverything:
- return (expr, rawPlaceholder, lineCol, cacheTokenParts,
- filterArgs, isSilentPlaceholder)
- else:
- return expr
-
-
-class _HighLevelParser(_LowLevelParser):
- """This class is a StateMachine for parsing Cheetah source and
- sending state dependent code generation commands to
- Cheetah.Compiler.Compiler.
- """
- def __init__(self, src, filename=None, breakPoint=None, compiler=None):
- _LowLevelParser.__init__(self, src, filename=filename, breakPoint=breakPoint)
- self.setSettingsManager(compiler)
- self._compiler = compiler
- self.setupState()
- self.configureParser()
-
- def setupState(self):
- self._macros = {}
- self._macroDetails = {}
- self._openDirectivesStack = []
-
- def cleanup(self):
- """Cleanup to remove any possible reference cycles
- """
- self._macros.clear()
- for macroname, macroDetails in self._macroDetails.items():
- macroDetails.template.shutdown()
- del macroDetails.template
- self._macroDetails.clear()
-
- def configureParser(self):
- _LowLevelParser.configureParser(self)
- self._initDirectives()
-
- def _initDirectives(self):
- def normalizeParserVal(val):
- if isinstance(val, (str,unicode)):
- handler = getattr(self, val)
- elif type(val) in (ClassType, TypeType):
- handler = val(self)
- elif callable(val):
- handler = val
- elif val is None:
- handler = val
- else:
- raise Exception('Invalid parser/handler value %r for %s'%(val, name))
- return handler
-
- normalizeHandlerVal = normalizeParserVal
-
- _directiveNamesAndParsers = directiveNamesAndParsers.copy()
- customNamesAndParsers = self.setting('directiveNamesAndParsers',{})
- _directiveNamesAndParsers.update(customNamesAndParsers)
-
- _endDirectiveNamesAndHandlers = endDirectiveNamesAndHandlers.copy()
- customNamesAndHandlers = self.setting('endDirectiveNamesAndHandlers',{})
- _endDirectiveNamesAndHandlers.update(customNamesAndHandlers)
-
- self._directiveNamesAndParsers = {}
- for name, val in _directiveNamesAndParsers.items():
- if val in (False, 0):
- continue
- self._directiveNamesAndParsers[name] = normalizeParserVal(val)
-
- self._endDirectiveNamesAndHandlers = {}
- for name, val in _endDirectiveNamesAndHandlers.items():
- if val in (False, 0):
- continue
- self._endDirectiveNamesAndHandlers[name] = normalizeHandlerVal(val)
-
- self._closeableDirectives = ['def','block','closure','defmacro',
- 'call',
- 'capture',
- 'cache',
- 'filter',
- 'if','unless',
- 'for','while','repeat',
- 'try',
- ]
- for directiveName in self.setting('closeableDirectives',[]):
- self._closeableDirectives.append(directiveName)
-
-
-
- macroDirectives = self.setting('macroDirectives',{})
- from Cheetah.Macros.I18n import I18n
- macroDirectives['i18n'] = I18n
-
-
- for macroName, callback in macroDirectives.items():
- if type(callback) in (ClassType, TypeType):
- callback = callback(parser=self)
- assert callback
- self._macros[macroName] = callback
- self._directiveNamesAndParsers[macroName] = self.eatMacroCall
-
- def _applyExpressionFilters(self, expr, exprType, rawExpr=None, startPos=None):
- """Pipes cheetah expressions through a set of optional filter hooks.
-
- The filters are functions which may modify the expressions or raise
- a ForbiddenExpression exception if the expression is not allowed. They
- are defined in the compiler setting 'expressionFilterHooks'.
-
- Some intended use cases:
-
- - to implement 'restricted execution' safeguards in cases where you
- can't trust the author of the template.
-
- - to enforce style guidelines
-
- filter call signature: (parser, expr, exprType, rawExpr=None, startPos=None)
- - parser is the Cheetah parser
- - expr is the expression to filter. In some cases the parser will have
- already modified it from the original source code form. For example,
- placeholders will have been translated into namemapper calls. If you
- need to work with the original source, see rawExpr.
- - exprType is the name of the directive, 'psp', or 'placeholder'. All
- lowercase. @@TR: These will eventually be replaced with a set of
- constants.
- - rawExpr is the original source string that Cheetah parsed. This
- might be None in some cases.
- - startPos is the character position in the source string/file
- where the parser started parsing the current expression.
-
- @@TR: I realize this use of the term 'expression' is a bit wonky as many
- of the 'expressions' are actually statements, but I haven't thought of
- a better name yet. Suggestions?
- """
- for callback in self.setting('expressionFilterHooks'):
- expr = callback(parser=self, expr=expr, exprType=exprType,
- rawExpr=rawExpr, startPos=startPos)
- return expr
-
- def _filterDisabledDirectives(self, directiveName):
- directiveName = directiveName.lower()
- if (directiveName in self.setting('disabledDirectives')
- or (self.setting('enabledDirectives')
- and directiveName not in self.setting('enabledDirectives'))):
- for callback in self.setting('disabledDirectiveHooks'):
- callback(parser=self, directiveName=directiveName)
- raise ForbiddenDirective(self, msg='This %r directive is disabled'%directiveName)
-
- ## main parse loop
-
- def parse(self, breakPoint=None, assertEmptyStack=True):
- if breakPoint:
- origBP = self.breakPoint()
- self.setBreakPoint(breakPoint)
- assertEmptyStack = False
-
- while not self.atEnd():
- if self.matchCommentStartToken():
- self.eatComment()
- elif self.matchMultiLineCommentStartToken():
- self.eatMultiLineComment()
- elif self.matchVariablePlaceholderStart():
- self.eatPlaceholder()
- elif self.matchExpressionPlaceholderStart():
- self.eatPlaceholder()
- elif self.matchDirective():
- self.eatDirective()
- elif self.matchPSPStartToken():
- self.eatPSP()
- elif self.matchEOLSlurpToken():
- self.eatEOLSlurpToken()
- else:
- self.eatPlainText()
- if assertEmptyStack:
- self.assertEmptyOpenDirectivesStack()
- if breakPoint:
- self.setBreakPoint(origBP)
-
- ## non-directive eat methods
-
- def eatPlainText(self):
- startPos = self.pos()
- match = None
- while not self.atEnd():
- match = self.matchTopLevelToken()
- if match:
- break
- else:
- self.advance()
- strConst = self.readTo(self.pos(), start=startPos)
- self._compiler.addStrConst(strConst)
- return match
-
- def eatComment(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- if isLineClearToStartToken:
- self._compiler.handleWSBeforeDirective()
- self.getCommentStartToken()
- comm = self.readToEOL(gobble=isLineClearToStartToken)
- self._compiler.addComment(comm)
-
- def eatMultiLineComment(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
-
- self.getMultiLineCommentStartToken()
- endPos = startPos = self.pos()
- level = 1
- while 1:
- endPos = self.pos()
- if self.atEnd():
- break
- if self.matchMultiLineCommentStartToken():
- self.getMultiLineCommentStartToken()
- level += 1
- elif self.matchMultiLineCommentEndToken():
- self.getMultiLineCommentEndToken()
- level -= 1
- if not level:
- break
- self.advance()
- comm = self.readTo(endPos, start=startPos)
-
- if not self.atEnd():
- self.getMultiLineCommentEndToken()
-
- if (not self.atEnd()) and self.setting('gobbleWhitespaceAroundMultiLineComments'):
- restOfLine = self[self.pos():self.findEOL()]
- if not restOfLine.strip(): # WS only to EOL
- self.readToEOL(gobble=isLineClearToStartToken)
-
- if isLineClearToStartToken and (self.atEnd() or self.pos() > endOfFirstLine):
- self._compiler.handleWSBeforeDirective()
-
- self._compiler.addComment(comm)
-
- def eatPlaceholder(self):
- (expr, rawPlaceholder,
- lineCol, cacheTokenParts,
- filterArgs, isSilentPlaceholder) = self.getPlaceholder(
- allowCacheTokens=True, returnEverything=True)
-
- self._compiler.addPlaceholder(
- expr,
- filterArgs=filterArgs,
- rawPlaceholder=rawPlaceholder,
- cacheTokenParts=cacheTokenParts,
- lineCol=lineCol,
- silentMode=isSilentPlaceholder)
- return
-
- def eatPSP(self):
- # filtered
- self._filterDisabledDirectives(directiveName='psp')
- self.getPSPStartToken()
- endToken = self.setting('PSPEndToken')
- startPos = self.pos()
- while not self.atEnd():
- if self.peek() == endToken[0]:
- if self.matchPSPEndToken():
- break
- self.advance()
- pspString = self.readTo(self.pos(), start=startPos).strip()
- pspString = self._applyExpressionFilters(pspString, 'psp', startPos=startPos)
- self._compiler.addPSP(pspString)
- self.getPSPEndToken()
-
- ## generic directive eat methods
- _simpleIndentingDirectives = '''
- else elif for while repeat unless try except finally'''.split()
- _simpleExprDirectives = '''
- pass continue stop return yield break
- del assert raise
- silent echo
- import from'''.split()
- _directiveHandlerNames = {'import':'addImportStatement',
- 'from':'addImportStatement', }
- def eatDirective(self):
- directiveName = self.matchDirective()
- self._filterDisabledDirectives(directiveName)
-
- for callback in self.setting('preparseDirectiveHooks'):
- callback(parser=self, directiveName=directiveName)
-
- # subclasses can override the default behaviours here by providing an
- # eater method in self._directiveNamesAndParsers[directiveName]
- directiveParser = self._directiveNamesAndParsers.get(directiveName)
- if directiveParser:
- directiveParser()
- elif directiveName in self._simpleIndentingDirectives:
- handlerName = self._directiveHandlerNames.get(directiveName)
- if not handlerName:
- handlerName = 'add'+directiveName.capitalize()
- handler = getattr(self._compiler, handlerName)
- self.eatSimpleIndentingDirective(directiveName, callback=handler)
- elif directiveName in self._simpleExprDirectives:
- handlerName = self._directiveHandlerNames.get(directiveName)
- if not handlerName:
- handlerName = 'add'+directiveName.capitalize()
- handler = getattr(self._compiler, handlerName)
- if directiveName in ('silent', 'echo'):
- includeDirectiveNameInExpr = False
- else:
- includeDirectiveNameInExpr = True
- expr = self.eatSimpleExprDirective(
- directiveName,
- includeDirectiveNameInExpr=includeDirectiveNameInExpr)
- handler(expr)
- ##
- for callback in self.setting('postparseDirectiveHooks'):
- callback(parser=self, directiveName=directiveName)
-
- def _eatRestOfDirectiveTag(self, isLineClearToStartToken, endOfFirstLinePos):
- foundComment = False
- if self.matchCommentStartToken():
- pos = self.pos()
- self.advance()
- if not self.matchDirective():
- self.setPos(pos)
- foundComment = True
- self.eatComment() # this won't gobble the EOL
- else:
- self.setPos(pos)
-
- if not foundComment and self.matchDirectiveEndToken():
- self.getDirectiveEndToken()
- elif isLineClearToStartToken and (not self.atEnd()) and self.peek() in '\r\n':
- # still gobble the EOL if a comment was found.
- self.readToEOL(gobble=True)
-
- if isLineClearToStartToken and (self.atEnd() or self.pos() > endOfFirstLinePos):
- self._compiler.handleWSBeforeDirective()
-
- def _eatToThisEndDirective(self, directiveName):
- finalPos = endRawPos = startPos = self.pos()
- directiveChar = self.setting('directiveStartToken')[0]
- isLineClearToStartToken = False
- while not self.atEnd():
- if self.peek() == directiveChar:
- if self.matchDirective() == 'end':
- endRawPos = self.pos()
- self.getDirectiveStartToken()
- self.advance(len('end'))
- self.getWhiteSpace()
- if self.startswith(directiveName):
- if self.isLineClearToStartToken(endRawPos):
- isLineClearToStartToken = True
- endRawPos = self.findBOL(endRawPos)
- self.advance(len(directiveName)) # to end of directiveName
- self.getWhiteSpace()
- finalPos = self.pos()
- break
- self.advance()
- finalPos = endRawPos = self.pos()
-
- textEaten = self.readTo(endRawPos, start=startPos)
- self.setPos(finalPos)
-
- endOfFirstLinePos = self.findEOL()
-
- if self.matchDirectiveEndToken():
- self.getDirectiveEndToken()
- elif isLineClearToStartToken and (not self.atEnd()) and self.peek() in '\r\n':
- self.readToEOL(gobble=True)
-
- if isLineClearToStartToken and self.pos() > endOfFirstLinePos:
- self._compiler.handleWSBeforeDirective()
- return textEaten
-
-
- def eatSimpleExprDirective(self, directiveName, includeDirectiveNameInExpr=True):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
- self.getDirectiveStartToken()
- if not includeDirectiveNameInExpr:
- self.advance(len(directiveName))
- startPos = self.pos()
- expr = self.getExpression().strip()
- directiveName = expr.split()[0]
- expr = self._applyExpressionFilters(expr, directiveName, startPos=startPos)
- if directiveName in self._closeableDirectives:
- self.pushToOpenDirectivesStack(directiveName)
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
- return expr
-
- def eatSimpleIndentingDirective(self, directiveName, callback,
- includeDirectiveNameInExpr=False):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- lineCol = self.getRowCol()
- self.getDirectiveStartToken()
- if directiveName not in 'else elif for while try except finally'.split():
- self.advance(len(directiveName))
- startPos = self.pos()
-
- self.getWhiteSpace()
-
- expr = self.getExpression(pyTokensToBreakAt=[':'])
- expr = self._applyExpressionFilters(expr, directiveName, startPos=startPos)
- if self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- if directiveName in 'else elif except finally'.split():
- callback(expr, dedent=False, lineCol=lineCol)
- else:
- callback(expr, lineCol=lineCol)
-
- self.getWhiteSpace(max=1)
- self.parse(breakPoint=self.findEOL(gobble=True))
- self._compiler.commitStrConst()
- self._compiler.dedent()
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- if directiveName in self._closeableDirectives:
- self.pushToOpenDirectivesStack(directiveName)
- callback(expr, lineCol=lineCol)
-
- def eatEndDirective(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- self.getDirectiveStartToken()
- self.advance(3) # to end of 'end'
- self.getWhiteSpace()
- pos = self.pos()
- directiveName = False
- for key in self._endDirectiveNamesAndHandlers.keys():
- if self.find(key, pos) == pos:
- directiveName = key
- break
- if not directiveName:
- raise ParseError(self, msg='Invalid end directive')
-
- endOfFirstLinePos = self.findEOL()
- self.getExpression() # eat in any extra comment-like crap
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- if directiveName in self._closeableDirectives:
- self.popFromOpenDirectivesStack(directiveName)
-
- # subclasses can override the default behaviours here by providing an
- # end-directive handler in self._endDirectiveNamesAndHandlers[directiveName]
- if self._endDirectiveNamesAndHandlers.get(directiveName):
- handler = self._endDirectiveNamesAndHandlers[directiveName]
- handler()
- elif directiveName in 'block capture cache call filter errorCatcher'.split():
- if key == 'block':
- self._compiler.closeBlock()
- elif key == 'capture':
- self._compiler.endCaptureRegion()
- elif key == 'cache':
- self._compiler.endCacheRegion()
- elif key == 'call':
- self._compiler.endCallRegion()
- elif key == 'filter':
- self._compiler.closeFilterBlock()
- elif key == 'errorCatcher':
- self._compiler.turnErrorCatcherOff()
- elif directiveName in 'while for if try repeat unless'.split():
- self._compiler.commitStrConst()
- self._compiler.dedent()
- elif directiveName=='closure':
- self._compiler.commitStrConst()
- self._compiler.dedent()
- # @@TR: temporary hack of useSearchList
- self.setSetting('useSearchList', self._useSearchList_orig)
-
- ## specific directive eat methods
-
- def eatBreakPoint(self):
- """Tells the parser to stop parsing at this point and completely ignore
- everything else.
-
- This is a debugging tool.
- """
- self.setBreakPoint(self.pos())
-
- def eatShbang(self):
- # filtered
- self.getDirectiveStartToken()
- self.advance(len('shBang'))
- self.getWhiteSpace()
- startPos = self.pos()
- shBang = self.readToEOL()
- shBang = self._applyExpressionFilters(shBang, 'shbang', startPos=startPos)
- self._compiler.setShBang(shBang.strip())
-
- def eatEncoding(self):
- # filtered
- self.getDirectiveStartToken()
- self.advance(len('encoding'))
- self.getWhiteSpace()
- startPos = self.pos()
- encoding = self.readToEOL()
- encoding = self._applyExpressionFilters(encoding, 'encoding', startPos=startPos)
- self._compiler.setModuleEncoding(encoding.strip())
-
- def eatCompiler(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
- startPos = self.pos()
- self.getDirectiveStartToken()
- self.advance(len('compiler')) # to end of 'compiler'
- self.getWhiteSpace()
-
- startPos = self.pos()
- settingName = self.getIdentifier()
-
- if settingName.lower() == 'reset':
- self.getExpression() # gobble whitespace & junk
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
- self._initializeSettings()
- self.configureParser()
- return
-
- self.getWhiteSpace()
- if self.peek() == '=':
- self.advance()
- else:
- raise ParserError(self)
- valueExpr = self.getExpression()
- endPos = self.pos()
-
- # @@TR: it's unlikely that anyone apply filters would have left this
- # directive enabled:
- # @@TR: fix up filtering, regardless
- self._applyExpressionFilters('%s=%r'%(settingName, valueExpr),
- 'compiler', startPos=startPos)
-
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
- try:
- self._compiler.setCompilerSetting(settingName, valueExpr)
- except:
- out = sys.stderr
- print >> out, 'An error occurred while processing the following #compiler directive.'
- print >> out, '-'*80
- print >> out, self[startPos:endPos]
- print >> out, '-'*80
- print >> out, 'Please check the syntax of these settings.'
- print >> out, 'A full Python exception traceback follows.'
- raise
-
-
- def eatCompilerSettings(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(len('compiler-settings')) # to end of 'settings'
-
- keywords = self.getTargetVarsList()
- self.getExpression() # gobble any garbage
-
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
-
- if 'reset' in keywords:
- self._compiler._initializeSettings()
- self.configureParser()
- # @@TR: this implies a single-line #compiler-settings directive, and
- # thus we should parse forward for an end directive.
- # Subject to change in the future
- return
- startPos = self.pos()
- settingsStr = self._eatToThisEndDirective('compiler-settings')
- settingsStr = self._applyExpressionFilters(settingsStr, 'compilerSettings',
- startPos=startPos)
- try:
- self._compiler.setCompilerSettings(keywords=keywords, settingsStr=settingsStr)
- except:
- out = sys.stderr
- print >> out, 'An error occurred while processing the following compiler settings.'
- print >> out, '-'*80
- print >> out, settingsStr.strip()
- print >> out, '-'*80
- print >> out, 'Please check the syntax of these settings.'
- print >> out, 'A full Python exception traceback follows.'
- raise
-
- def eatAttr(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- startPos = self.pos()
- self.getDirectiveStartToken()
- self.advance(len('attr'))
- self.getWhiteSpace()
- startPos = self.pos()
- if self.matchCheetahVarStart():
- self.getCheetahVarStartToken()
- attribName = self.getIdentifier()
- self.getWhiteSpace()
- self.getAssignmentOperator()
- expr = self.getExpression()
- expr = self._applyExpressionFilters(expr, 'attr', startPos=startPos)
- self._compiler.addAttribute(attribName, expr)
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
-
- def eatDecorator(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- startPos = self.pos()
- self.getDirectiveStartToken()
- #self.advance() # eat @
- startPos = self.pos()
- decoratorExpr = self.getExpression()
- decoratorExpr = self._applyExpressionFilters(decoratorExpr, 'decorator', startPos=startPos)
- self._compiler.addDecorator(decoratorExpr)
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- self.getWhiteSpace()
-
- directiveName = self.matchDirective()
- if not directiveName or directiveName not in ('def', 'block', 'closure'):
- raise ParseError(self, msg='Expected #def, #block or #closure')
- self.eatDirective()
-
- def eatDef(self):
- # filtered
- self._eatDefOrBlock('def')
-
- def eatBlock(self):
- # filtered
- startPos = self.pos()
- methodName, rawSignature = self._eatDefOrBlock('block')
- self._compiler._blockMetaData[methodName] = {
- 'raw':rawSignature,
- 'lineCol':self.getRowCol(startPos),
- }
-
- def eatClosure(self):
- # filtered
- self._eatDefOrBlock('closure')
-
- def _eatDefOrBlock(self, directiveName):
- # filtered
- assert directiveName in ('def','block','closure')
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- startPos = self.pos()
- self.getDirectiveStartToken()
- self.advance(len(directiveName))
- self.getWhiteSpace()
- if self.matchCheetahVarStart():
- self.getCheetahVarStartToken()
- methodName = self.getIdentifier()
- self.getWhiteSpace()
- if self.peek() == '(':
- argsList = self.getDefArgList()
- self.advance() # past the closing ')'
- if argsList and argsList[0][0] == 'self':
- del argsList[0]
- else:
- argsList=[]
-
- def includeBlockMarkers():
- if self.setting('includeBlockMarkers'):
- startMarker = self.setting('blockMarkerStart')
- self._compiler.addStrConst(startMarker[0] + methodName + startMarker[1])
-
- # @@TR: fix up filtering
- self._applyExpressionFilters(self[startPos:self.pos()], 'def', startPos=startPos)
-
- if self.matchColonForSingleLineShortFormDirective():
- isNestedDef = (self.setting('allowNestedDefScopes')
- and [name for name in self._openDirectivesStack if name=='def'])
- self.getc()
- rawSignature = self[startPos:endOfFirstLinePos]
- self._eatSingleLineDef(directiveName=directiveName,
- methodName=methodName,
- argsList=argsList,
- startPos=startPos,
- endPos=endOfFirstLinePos)
- if directiveName == 'def' and not isNestedDef:
- #@@TR: must come before _eatRestOfDirectiveTag ... for some reason
- self._compiler.closeDef()
- elif directiveName == 'block':
- includeBlockMarkers()
- self._compiler.closeBlock()
- elif directiveName == 'closure' or isNestedDef:
- self._compiler.dedent()
-
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- else:
- if self.peek()==':':
- self.getc()
- self.pushToOpenDirectivesStack(directiveName)
- rawSignature = self[startPos:self.pos()]
- self._eatMultiLineDef(directiveName=directiveName,
- methodName=methodName,
- argsList=argsList,
- startPos=startPos,
- isLineClearToStartToken=isLineClearToStartToken)
- if directiveName == 'block':
- includeBlockMarkers()
-
- return methodName, rawSignature
-
- def _eatMultiLineDef(self, directiveName, methodName, argsList, startPos,
- isLineClearToStartToken=False):
- # filtered in calling method
- self.getExpression() # slurp up any garbage left at the end
- signature = self[startPos:self.pos()]
- endOfFirstLinePos = self.findEOL()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- parserComment = ('## CHEETAH: generated from ' + signature +
- ' at line %s, col %s' % self.getRowCol(startPos)
- + '.')
-
- isNestedDef = (self.setting('allowNestedDefScopes')
- and len([name for name in self._openDirectivesStack if name=='def'])>1)
- if directiveName=='block' or (directiveName=='def' and not isNestedDef):
- self._compiler.startMethodDef(methodName, argsList, parserComment)
- else: #closure
- self._useSearchList_orig = self.setting('useSearchList')
- self.setSetting('useSearchList', False)
- self._compiler.addClosure(methodName, argsList, parserComment)
-
- return methodName
-
- def _eatSingleLineDef(self, directiveName, methodName, argsList, startPos, endPos):
- # filtered in calling method
- fullSignature = self[startPos:endPos]
- parserComment = ('## Generated from ' + fullSignature +
- ' at line %s, col %s' % self.getRowCol(startPos)
- + '.')
- isNestedDef = (self.setting('allowNestedDefScopes')
- and [name for name in self._openDirectivesStack if name=='def'])
- if directiveName=='block' or (directiveName=='def' and not isNestedDef):
- self._compiler.startMethodDef(methodName, argsList, parserComment)
- else: #closure
- # @@TR: temporary hack of useSearchList
- useSearchList_orig = self.setting('useSearchList')
- self.setSetting('useSearchList', False)
- self._compiler.addClosure(methodName, argsList, parserComment)
-
- self.getWhiteSpace(max=1)
- self.parse(breakPoint=endPos)
- if directiveName=='closure' or isNestedDef: # @@TR: temporary hack of useSearchList
- self.setSetting('useSearchList', useSearchList_orig)
-
- def eatExtends(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(len('extends'))
- self.getWhiteSpace()
- startPos = self.pos()
- if self.setting('allowExpressionsInExtendsDirective'):
- baseName = self.getExpression()
- else:
- baseName = self.getDottedName()
-
- baseName = self._applyExpressionFilters(baseName, 'extends', startPos=startPos)
- self._compiler.setBaseClass(baseName) # in compiler
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
-
- def eatImplements(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(len('implements'))
- self.getWhiteSpace()
- startPos = self.pos()
- methodName = self.getIdentifier()
- if not self.atEnd() and self.peek() == '(':
- argsList = self.getDefArgList()
- self.advance() # past the closing ')'
- if argsList and argsList[0][0] == 'self':
- del argsList[0]
- else:
- argsList=[]
-
- # @@TR: need to split up filtering of the methodname and the args
- #methodName = self._applyExpressionFilters(methodName, 'implements', startPos=startPos)
- self._applyExpressionFilters(self[startPos:self.pos()], 'implements', startPos=startPos)
-
- self._compiler.setMainMethodName(methodName)
- self._compiler.setMainMethodArgs(argsList)
-
- self.getExpression() # throw away and unwanted crap that got added in
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
-
- def eatSet(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(3)
- self.getWhiteSpace()
- style = SET_LOCAL
- if self.startswith('local'):
- self.getIdentifier()
- self.getWhiteSpace()
- elif self.startswith('global'):
- self.getIdentifier()
- self.getWhiteSpace()
- style = SET_GLOBAL
- elif self.startswith('module'):
- self.getIdentifier()
- self.getWhiteSpace()
- style = SET_MODULE
-
- startsWithDollar = self.matchCheetahVarStart()
- startPos = self.pos()
- LVALUE = self.getExpression(pyTokensToBreakAt=assignmentOps, useNameMapper=False).strip()
- OP = self.getAssignmentOperator()
- RVALUE = self.getExpression()
- expr = LVALUE + ' ' + OP + ' ' + RVALUE.strip()
-
- expr = self._applyExpressionFilters(expr, 'set', startPos=startPos)
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
-
- class Components: pass # used for 'set global'
- exprComponents = Components()
- exprComponents.LVALUE = LVALUE
- exprComponents.OP = OP
- exprComponents.RVALUE = RVALUE
- self._compiler.addSet(expr, exprComponents, style)
-
- def eatSlurp(self):
- if self.isLineClearToStartToken():
- self._compiler.handleWSBeforeDirective()
- self._compiler.commitStrConst()
- self.readToEOL(gobble=True)
-
- def eatEOLSlurpToken(self):
- if self.isLineClearToStartToken():
- self._compiler.handleWSBeforeDirective()
- self._compiler.commitStrConst()
- self.readToEOL(gobble=True)
-
- def eatRaw(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(len('raw'))
- self.getWhiteSpace()
- if self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- self.getWhiteSpace(max=1)
- rawBlock = self.readToEOL(gobble=False)
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- rawBlock = self._eatToThisEndDirective('raw')
- self._compiler.addRawText(rawBlock)
-
- def eatInclude(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(len('include'))
-
- self.getWhiteSpace()
- includeFrom = 'file'
- isRaw = False
- if self.startswith('raw'):
- self.advance(3)
- isRaw=True
-
- self.getWhiteSpace()
- if self.startswith('source'):
- self.advance(len('source'))
- includeFrom = 'str'
- self.getWhiteSpace()
- if not self.peek() == '=':
- raise ParseError(self)
- self.advance()
- startPos = self.pos()
- sourceExpr = self.getExpression()
- sourceExpr = self._applyExpressionFilters(sourceExpr, 'include', startPos=startPos)
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- self._compiler.addInclude(sourceExpr, includeFrom, isRaw)
-
-
- def eatDefMacro(self):
- # @@TR: not filtered yet
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(len('defmacro'))
-
- self.getWhiteSpace()
- if self.matchCheetahVarStart():
- self.getCheetahVarStartToken()
- macroName = self.getIdentifier()
- self.getWhiteSpace()
- if self.peek() == '(':
- argsList = self.getDefArgList(useNameMapper=False)
- self.advance() # past the closing ')'
- if argsList and argsList[0][0] == 'self':
- del argsList[0]
- else:
- argsList=[]
-
- assert not self._directiveNamesAndParsers.has_key(macroName)
- argsList.insert(0, ('src',None))
- argsList.append(('parser','None'))
- argsList.append(('macros','None'))
- argsList.append(('compilerSettings','None'))
- argsList.append(('isShortForm','None'))
- argsList.append(('EOLCharsInShortForm','None'))
- argsList.append(('startPos','None'))
- argsList.append(('endPos','None'))
-
- if self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- self.getWhiteSpace(max=1)
- macroSrc = self.readToEOL(gobble=False)
- self.readToEOL(gobble=True)
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- macroSrc = self._eatToThisEndDirective('defmacro')
-
- #print argsList
- normalizedMacroSrc = ''.join(
- ['%def callMacro('+','.join([defv and '%s=%s'%(n,defv) or n
- for n,defv in argsList])
- +')\n',
- macroSrc,
- '%end def'])
-
-
- from Cheetah.Template import Template
- templateAPIClass = self.setting('templateAPIClassForDefMacro', default=Template)
- compilerSettings = self.setting('compilerSettingsForDefMacro', default={})
- searchListForMacros = self.setting('searchListForDefMacro', default=[])
- searchListForMacros = list(searchListForMacros) # copy to avoid mutation bugs
- searchListForMacros.append({'macros':self._macros,
- 'parser':self,
- 'compilerSettings':self.settings(),
- })
-
- templateAPIClass._updateSettingsWithPreprocessTokens(
- compilerSettings, placeholderToken='@', directiveToken='%')
- macroTemplateClass = templateAPIClass.compile(source=normalizedMacroSrc,
- compilerSettings=compilerSettings)
- #print normalizedMacroSrc
- #t = macroTemplateClass()
- #print t.callMacro('src')
- #print t.generatedClassCode()
-
- class MacroDetails: pass
- macroDetails = MacroDetails()
- macroDetails.macroSrc = macroSrc
- macroDetails.argsList = argsList
- macroDetails.template = macroTemplateClass(searchList=searchListForMacros)
-
- self._macroDetails[macroName] = macroDetails
- self._macros[macroName] = macroDetails.template.callMacro
- self._directiveNamesAndParsers[macroName] = self.eatMacroCall
-
- def eatMacroCall(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- startPos = self.pos()
- self.getDirectiveStartToken()
- macroName = self.getIdentifier()
- macro = self._macros[macroName]
- if hasattr(macro, 'parse'):
- return macro.parse(parser=self, startPos=startPos)
-
- if hasattr(macro, 'parseArgs'):
- args = macro.parseArgs(parser=self, startPos=startPos)
- else:
- self.getWhiteSpace()
- args = self.getExpression(useNameMapper=False,
- pyTokensToBreakAt=[':']).strip()
-
- if self.matchColonForSingleLineShortFormDirective():
- isShortForm = True
- self.advance() # skip over :
- self.getWhiteSpace(max=1)
- srcBlock = self.readToEOL(gobble=False)
- EOLCharsInShortForm = self.readToEOL(gobble=True)
- #self.readToEOL(gobble=False)
- else:
- isShortForm = False
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- srcBlock = self._eatToThisEndDirective(macroName)
-
-
- if hasattr(macro, 'convertArgStrToDict'):
- kwArgs = macro.convertArgStrToDict(args, parser=self, startPos=startPos)
- else:
- def getArgs(*pargs, **kws):
- return pargs, kws
- exec 'positionalArgs, kwArgs = getArgs(%(args)s)'%locals()
-
- assert not kwArgs.has_key('src')
- kwArgs['src'] = srcBlock
-
- if type(macro)==new.instancemethod:
- co = macro.im_func.func_code
- elif (hasattr(macro, '__call__')
- and hasattr(macro.__call__, 'im_func')):
- co = macro.__call__.im_func.func_code
- else:
- co = macro.func_code
- availableKwArgs = inspect.getargs(co)[0]
-
- if 'parser' in availableKwArgs:
- kwArgs['parser'] = self
- if 'macros' in availableKwArgs:
- kwArgs['macros'] = self._macros
- if 'compilerSettings' in availableKwArgs:
- kwArgs['compilerSettings'] = self.settings()
- if 'isShortForm' in availableKwArgs:
- kwArgs['isShortForm'] = isShortForm
- if isShortForm and 'EOLCharsInShortForm' in availableKwArgs:
- kwArgs['EOLCharsInShortForm'] = EOLCharsInShortForm
-
- if 'startPos' in availableKwArgs:
- kwArgs['startPos'] = startPos
- if 'endPos' in availableKwArgs:
- kwArgs['endPos'] = self.pos()
-
- srcFromMacroOutput = macro(**kwArgs)
-
- origParseSrc = self._src
- origBreakPoint = self.breakPoint()
- origPos = self.pos()
- # add a comment to the output about the macro src that is being parsed
- # or add a comment prefix to all the comments added by the compiler
- self._src = srcFromMacroOutput
- self.setPos(0)
- self.setBreakPoint(len(srcFromMacroOutput))
-
- self.parse(assertEmptyStack=False)
-
- self._src = origParseSrc
- self.setBreakPoint(origBreakPoint)
- self.setPos(origPos)
-
-
- #self._compiler.addRawText('end')
-
- def eatCache(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- lineCol = self.getRowCol()
- self.getDirectiveStartToken()
- self.advance(len('cache'))
-
- startPos = self.pos()
- argList = self.getDefArgList(useNameMapper=True)
- argList = self._applyExpressionFilters(argList, 'cache', startPos=startPos)
-
- def startCache():
- cacheInfo = self._compiler.genCacheInfoFromArgList(argList)
- self._compiler.startCacheRegion(cacheInfo, lineCol)
-
- if self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- self.getWhiteSpace(max=1)
- startCache()
- self.parse(breakPoint=self.findEOL(gobble=True))
- self._compiler.endCacheRegion()
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- self.pushToOpenDirectivesStack('cache')
- startCache()
-
- def eatCall(self):
- # @@TR: need to enable single line version of this
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- lineCol = self.getRowCol()
- self.getDirectiveStartToken()
- self.advance(len('call'))
- startPos = self.pos()
-
- useAutocallingOrig = self.setting('useAutocalling')
- self.setSetting('useAutocalling', False)
- self.getWhiteSpace()
- if self.matchCheetahVarStart():
- functionName = self.getCheetahVar()
- else:
- functionName = self.getCheetahVar(plain=True, skipStartToken=True)
- self.setSetting('useAutocalling', useAutocallingOrig)
- # @@TR: fix up filtering
- self._applyExpressionFilters(self[startPos:self.pos()], 'call', startPos=startPos)
-
- self.getWhiteSpace()
- args = self.getExpression(pyTokensToBreakAt=[':']).strip()
- if self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- self._compiler.startCallRegion(functionName, args, lineCol)
- self.getWhiteSpace(max=1)
- self.parse(breakPoint=self.findEOL(gobble=False))
- self._compiler.endCallRegion()
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self.pushToOpenDirectivesStack("call")
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- self._compiler.startCallRegion(functionName, args, lineCol)
-
- def eatCallArg(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- lineCol = self.getRowCol()
- self.getDirectiveStartToken()
-
- self.advance(len('arg'))
- startPos = self.pos()
- self.getWhiteSpace()
- argName = self.getIdentifier()
- self.getWhiteSpace()
- argName = self._applyExpressionFilters(argName, 'arg', startPos=startPos)
- self._compiler.setCallArg(argName, lineCol)
- if self.peek() == ':':
- self.getc()
- else:
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
-
- def eatFilter(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
-
- self.getDirectiveStartToken()
- self.advance(len('filter'))
- self.getWhiteSpace()
- startPos = self.pos()
- if self.matchCheetahVarStart():
- isKlass = True
- theFilter = self.getExpression(pyTokensToBreakAt=[':'])
- else:
- isKlass = False
- theFilter = self.getIdentifier()
- self.getWhiteSpace()
- theFilter = self._applyExpressionFilters(theFilter, 'filter', startPos=startPos)
-
- if self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- self.getWhiteSpace(max=1)
- self._compiler.setFilter(theFilter, isKlass)
- self.parse(breakPoint=self.findEOL(gobble=False))
- self._compiler.closeFilterBlock()
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self.pushToOpenDirectivesStack("filter")
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- self._compiler.setFilter(theFilter, isKlass)
-
- def eatErrorCatcher(self):
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- self.getDirectiveStartToken()
- self.advance(len('errorCatcher'))
- self.getWhiteSpace()
- startPos = self.pos()
- errorCatcherName = self.getIdentifier()
- errorCatcherName = self._applyExpressionFilters(
- errorCatcherName, 'errorcatcher', startPos=startPos)
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- self._compiler.setErrorCatcher(errorCatcherName)
-
- def eatCapture(self):
- # @@TR: this could be refactored to use the code in eatSimpleIndentingDirective
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLinePos = self.findEOL()
- lineCol = self.getRowCol()
-
- self.getDirectiveStartToken()
- self.advance(len('capture'))
- startPos = self.pos()
- self.getWhiteSpace()
-
- expr = self.getExpression(pyTokensToBreakAt=[':'])
- expr = self._applyExpressionFilters(expr, 'capture', startPos=startPos)
- if self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- self._compiler.startCaptureRegion(assignTo=expr, lineCol=lineCol)
- self.getWhiteSpace(max=1)
- self.parse(breakPoint=self.findEOL(gobble=False))
- self._compiler.endCaptureRegion()
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
- self.pushToOpenDirectivesStack("capture")
- self._compiler.startCaptureRegion(assignTo=expr, lineCol=lineCol)
-
-
- def eatIf(self):
- # filtered
- isLineClearToStartToken = self.isLineClearToStartToken()
- endOfFirstLine = self.findEOL()
- lineCol = self.getRowCol()
- self.getDirectiveStartToken()
- startPos = self.pos()
-
- expressionParts = self.getExpressionParts(pyTokensToBreakAt=[':'])
- expr = ''.join(expressionParts).strip()
- expr = self._applyExpressionFilters(expr, 'if', startPos=startPos)
-
- isTernaryExpr = ('then' in expressionParts and 'else' in expressionParts)
- if isTernaryExpr:
- conditionExpr = []
- trueExpr = []
- falseExpr = []
- currentExpr = conditionExpr
- for part in expressionParts:
- if part.strip()=='then':
- currentExpr = trueExpr
- elif part.strip()=='else':
- currentExpr = falseExpr
- else:
- currentExpr.append(part)
-
- conditionExpr = ''.join(conditionExpr)
- trueExpr = ''.join(trueExpr)
- falseExpr = ''.join(falseExpr)
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
- self._compiler.addTernaryExpr(conditionExpr, trueExpr, falseExpr, lineCol=lineCol)
- elif self.matchColonForSingleLineShortFormDirective():
- self.advance() # skip over :
- self._compiler.addIf(expr, lineCol=lineCol)
- self.getWhiteSpace(max=1)
- self.parse(breakPoint=self.findEOL(gobble=True))
- self._compiler.commitStrConst()
- self._compiler.dedent()
- else:
- if self.peek()==':':
- self.advance()
- self.getWhiteSpace()
- self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
- self.pushToOpenDirectivesStack('if')
- self._compiler.addIf(expr, lineCol=lineCol)
-
- ## end directive handlers
- def handleEndDef(self):
- isNestedDef = (self.setting('allowNestedDefScopes')
- and [name for name in self._openDirectivesStack if name=='def'])
- if not isNestedDef:
- self._compiler.closeDef()
- else:
- # @@TR: temporary hack of useSearchList
- self.setSetting('useSearchList', self._useSearchList_orig)
- self._compiler.commitStrConst()
- self._compiler.dedent()
- ###
-
- def pushToOpenDirectivesStack(self, directiveName):
- assert directiveName in self._closeableDirectives
- self._openDirectivesStack.append(directiveName)
-
- def popFromOpenDirectivesStack(self, directiveName):
- if not self._openDirectivesStack:
- raise ParseError(self, msg="#end found, but nothing to end")
-
- if self._openDirectivesStack[-1] == directiveName:
- del self._openDirectivesStack[-1]
- else:
- raise ParseError(self, msg="#end %s found, expected #end %s" %(
- directiveName, self._openDirectivesStack[-1]))
-
- def assertEmptyOpenDirectivesStack(self):
- if self._openDirectivesStack:
- errorMsg = (
- "Some #directives are missing their corresponding #end ___ tag: %s" %(
- ', '.join(self._openDirectivesStack)))
- raise ParseError(self, msg=errorMsg)
-
-##################################################
-## Make an alias to export
-Parser = _HighLevelParser
diff --git a/cobbler/Cheetah/Servlet.py b/cobbler/Cheetah/Servlet.py
deleted file mode 100644
index 5295d30..0000000
--- a/cobbler/Cheetah/Servlet.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-# $Id: Servlet.py,v 1.40 2006/02/04 23:06:15 tavis_rudd Exp $
-"""Provides an abstract Servlet baseclass for Cheetah's Template class
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.40 $
-Start Date: 2001/10/03
-Last Revision Date: $Date: 2006/02/04 23:06:15 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.40 $"[11:-2]
-
-import sys
-import os.path
-
-isWebwareInstalled = False
-try:
- if 'ds.appserver' in sys.modules.keys():
- from ds.appserver.Servlet import Servlet as BaseServlet
- else:
- from WebKit.Servlet import Servlet as BaseServlet
- isWebwareInstalled = True
-
- if not issubclass(BaseServlet, object):
- class NewStyleBaseServlet(BaseServlet, object): pass
- BaseServlet = NewStyleBaseServlet
-except:
- class BaseServlet(object):
- _reusable = 1
- _threadSafe = 0
-
- def __init__(self):
- pass
-
- def awake(self, transaction):
- pass
-
- def sleep(self, transaction):
- pass
-
- def shutdown(self):
- pass
-
-##################################################
-## CLASSES
-
-class Servlet(BaseServlet):
-
- """This class is an abstract baseclass for Cheetah.Template.Template.
-
- It wraps WebKit.Servlet and provides a few extra convenience methods that
- are also found in WebKit.Page. It doesn't do any of the HTTP method
- resolution that is done in WebKit.HTTPServlet
- """
-
- transaction = None
- application = None
- request = None
- session = None
-
- def __init__(self):
- BaseServlet.__init__(self)
-
- # this default will be changed by the .awake() method
- self._CHEETAH__isControlledByWebKit = False
-
- ## methods called by Webware during the request-response
-
- def awake(self, transaction):
- BaseServlet.awake(self, transaction)
-
- # a hack to signify that the servlet is being run directly from WebKit
- self._CHEETAH__isControlledByWebKit = True
-
- self.transaction = transaction
- #self.application = transaction.application
- self.response = response = transaction.response
- self.request = transaction.request
-
- # Temporary hack to accomodate bug in
- # WebKit.Servlet.Servlet.serverSidePath: it uses
- # self._request even though this attribute does not exist.
- # This attribute WILL disappear in the future.
- self._request = transaction.request()
-
-
- self.session = transaction.session
- self.write = response().write
- #self.writeln = response.writeln
-
- def respond(self, trans=None):
- raise NotImplementedError("""\
-couldn't find the template's main method. If you are using #extends
-without #implements, try adding '#implements respond' to your template
-definition.""")
-
- def sleep(self, transaction):
- BaseServlet.sleep(self, transaction)
- self.session = None
- self.request = None
- self._request = None
- self.response = None
- self.transaction = None
-
- def shutdown(self):
- pass
-
- def serverSidePath(self, path=None,
- normpath=os.path.normpath,
- abspath=os.path.abspath
- ):
-
- if self._CHEETAH__isControlledByWebKit:
- return BaseServlet.serverSidePath(self, path)
- elif path:
- return normpath(abspath(path.replace("\\",'/')))
- elif hasattr(self, '_filePath') and self._filePath:
- return normpath(abspath(self._filePath))
- else:
- return None
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/SettingsManager.py b/cobbler/Cheetah/SettingsManager.py
deleted file mode 100644
index 0967155..0000000
--- a/cobbler/Cheetah/SettingsManager.py
+++ /dev/null
@@ -1,623 +0,0 @@
-#!/usr/bin/env python
-
-"""Provides a mixin/base class for collecting and managing application settings
-
-Meta-Data
-==========
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.28 $
-Start Date: 2001/05/30
-Last Revision Date: $Date: 2006/01/29 07:19:12 $
-"""
-
-# $Id: SettingsManager.py,v 1.28 2006/01/29 07:19:12 tavis_rudd Exp $
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.28 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import sys
-import os.path
-import copy as copyModule
-from ConfigParser import ConfigParser
-import re
-from tokenize import Intnumber, Floatnumber, Number
-from types import *
-import types
-import new
-import tempfile
-import imp
-import time
-
-from StringIO import StringIO # not cStringIO because of unicode support
-
-import imp # used by SettingsManager.updateSettingsFromPySrcFile()
-
-try:
- import threading
- from threading import Lock # used for thread lock on sys.path manipulations
-except:
- ## provide a dummy for non-threading Python systems
- class Lock:
- def acquire(self):
- pass
- def release(self):
- pass
-
-class BaseErrorClass: pass
-
-##################################################
-## CONSTANTS & GLOBALS ##
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-numberRE = re.compile(Number)
-complexNumberRE = re.compile('[\(]*' +Number + r'[ \t]*\+[ \t]*' + Number + '[\)]*')
-
-convertableToStrTypes = (StringType, IntType, FloatType,
- LongType, ComplexType, NoneType,
- UnicodeType)
-
-##################################################
-## FUNCTIONS ##
-
-def mergeNestedDictionaries(dict1, dict2, copy=False, deepcopy=False):
-
- """Recursively merge the values of dict2 into dict1.
-
- This little function is very handy for selectively overriding settings in a
- settings dictionary that has a nested structure.
- """
-
- if copy:
- dict1 = copyModule.copy(dict1)
- elif deepcopy:
- dict1 = copyModule.deepcopy(dict1)
-
- for key,val in dict2.items():
- if dict1.has_key(key) and type(val) == types.DictType and \
- type(dict1[key]) == types.DictType:
-
- dict1[key] = mergeNestedDictionaries(dict1[key], val)
- else:
- dict1[key] = val
- return dict1
-
-def stringIsNumber(S):
-
- """Return True if theString represents a Python number, False otherwise.
- This also works for complex numbers and numbers with +/- in front."""
-
- S = S.strip()
-
- if S[0] in '-+' and len(S) > 1:
- S = S[1:].strip()
-
- match = complexNumberRE.match(S)
- if not match:
- match = numberRE.match(S)
- if not match or (match.end() != len(S)):
- return False
- else:
- return True
-
-def convStringToNum(theString):
-
- """Convert a string representation of a Python number to the Python version"""
-
- if not stringIsNumber(theString):
- raise Error(theString + ' cannot be converted to a Python number')
- return eval(theString, {}, {})
-
-
-
-######
-
-ident = r'[_a-zA-Z][_a-zA-Z0-9]*'
-firstChunk = r'^(?P<indent>\s*)(?P<class>[_a-zA-Z][_a-zA-Z0-9]*)'
-customClassRe = re.compile(firstChunk + r'\s*:')
-baseClasses = r'(?P<bases>\(\s*([_a-zA-Z][_a-zA-Z0-9]*\s*(,\s*[_a-zA-Z][_a-zA-Z0-9]*\s*)*)\))'
-customClassWithBasesRe = re.compile(firstChunk + baseClasses + '\s*:')
-
-def translateClassBasedConfigSyntax(src):
-
- """Compiles a config file in the custom class-based SettingsContainer syntax
- to Vanilla Python
-
- # WebKit.config
- Applications:
- MyApp:
- Dirs:
- ROOT = '/home/www/Home'
- Products = '/home/www/Products'
- becomes:
- # WebKit.config
- from Cheetah.SettingsManager import SettingsContainer
- class Applications(SettingsContainer):
- class MyApp(SettingsContainer):
- class Dirs(SettingsContainer):
- ROOT = '/home/www/Home'
- Products = '/home/www/Products'
- """
-
- outputLines = []
- for line in src.splitlines():
- if customClassRe.match(line) and \
- line.strip().split(':')[0] not in ('else','try', 'except', 'finally'):
-
- line = customClassRe.sub(
- r'\g<indent>class \g<class>(SettingsContainer):', line)
-
- elif customClassWithBasesRe.match(line) and not line.strip().startswith('except'):
- line = customClassWithBasesRe.sub(
- r'\g<indent>class \g<class>\g<bases>:', line)
-
- outputLines.append(line)
-
- ## prepend this to the first line to make sure that tracebacks report the right line nums
- if outputLines[0].find('class ') == -1:
- initLine = 'from Cheetah.SettingsManager import SettingsContainer; True, False = 1, 0; '
- else:
- initLine = 'from Cheetah.SettingsManager import SettingsContainer; True, False = 1, 0\n'
- return initLine + '\n'.join(outputLines) + '\n'
-
-
-##################################################
-## CLASSES ##
-
-class Error(BaseErrorClass):
- pass
-
-class NoDefault:
- pass
-
-class ConfigParserCaseSensitive(ConfigParser):
-
- """A case sensitive version of the standard Python ConfigParser."""
-
- def optionxform(self, optionstr):
-
- """Don't change the case as is done in the default implemenation."""
-
- return optionstr
-
-class SettingsContainer:
- """An abstract base class for 'classes' that are used to house settings."""
- pass
-
-
-class _SettingsCollector:
-
- """An abstract base class that provides the methods SettingsManager uses to
- collect settings from config files and SettingsContainers.
-
- This class only collects settings it doesn't modify the _settings dictionary
- of SettingsManager instances in any way.
-
- SettingsCollector is designed to:
- - be able to read settings from Python src files (or strings) so that
- complex Python objects can be stored in the application's settings
- dictionary. For example, you might want to store references to various
- classes that are used by the application and plugins to the application
- might want to substitute one class for another.
- - be able to read/write .ini style config files (or strings)
- - allow sections in .ini config files to be extended by settings in Python
- src files
- - allow python literals to be used values in .ini config files
- - maintain the case of setting names, unlike the ConfigParser module
-
- """
-
- _sysPathLock = Lock() # used by the updateSettingsFromPySrcFile() method
- _ConfigParserClass = ConfigParserCaseSensitive
-
-
- def __init__(self):
- pass
-
- def normalizePath(self, path):
-
- """A hook for any neccessary path manipulations.
-
- For example, when this is used with WebKit servlets all relative paths
- must be converted so they are relative to the servlet's directory rather
- than relative to the program's current working dir.
-
- The default implementation just normalizes the path for the current
- operating system."""
-
- return os.path.normpath(path.replace("\\",'/'))
-
-
- def readSettingsFromContainer(self, container, ignoreUnderscored=True):
-
- """Returns all settings from a SettingsContainer or Python
- module.
-
- This method is recursive.
- """
-
- S = {}
- if type(container) == ModuleType:
- attrs = vars(container)
- else:
- attrs = self._getAllAttrsFromContainer(container)
-
- for k, v in attrs.items():
- if (ignoreUnderscored and k.startswith('_')) or v is SettingsContainer:
- continue
- if self._isContainer(v):
- S[k] = self.readSettingsFromContainer(v)
- else:
- S[k] = v
- return S
-
- # provide an alias
- readSettingsFromModule = readSettingsFromContainer
-
- def _isContainer(self, thing):
-
- """Check if 'thing' is a Python module or a subclass of
- SettingsContainer."""
-
- return type(thing) == ModuleType or (
- type(thing) == ClassType and issubclass(thing, SettingsContainer)
- )
-
- def _getAllAttrsFromContainer(self, container):
- """Extract all the attributes of a SettingsContainer subclass.
-
- The 'container' is a class, so extracting all attributes from it, an
- instance of it, and all its base classes.
-
- This method is not recursive.
- """
-
- attrs = container.__dict__.copy()
- # init an instance of the container and get all attributes
- attrs.update( container().__dict__ )
-
- for base in container.__bases__:
- for k, v in base.__dict__.items():
- if not attrs.has_key(k):
- attrs[k] = v
- return attrs
-
- def readSettingsFromPySrcFile(self, path):
-
- """Return new settings dict from variables in a Python source file.
-
- This method will temporarily add the directory of src file to sys.path so
- that import statements relative to that dir will work properly."""
-
- path = self.normalizePath(path)
- dirName = os.path.dirname(path)
- tmpPath = tempfile.mkstemp('webware_temp')
-
- pySrc = translateClassBasedConfigSyntax(open(path).read())
- modName = path.replace('.','_').replace('/','_').replace('\\','_')
- open(tmpPath, 'w').write(pySrc)
- try:
- fp = open(tmpPath)
- self._sysPathLock.acquire()
- sys.path.insert(0, dirName)
- module = imp.load_source(modName, path, fp)
- newSettings = self.readSettingsFromModule(module)
- del sys.path[0]
- self._sysPathLock.release()
- return newSettings
- finally:
- fp.close()
- try:
- os.remove(tmpPath)
- except:
- pass
- if os.path.exists(tmpPath + 'c'):
- try:
- os.remove(tmpPath + 'c')
- except:
- pass
- if os.path.exists(path + 'c'):
- try:
- os.remove(path + 'c')
- except:
- pass
-
-
- def readSettingsFromPySrcStr(self, theString):
-
- """Return a dictionary of the settings in a Python src string."""
-
- globalsDict = {'True':1,
- 'False':0,
- 'SettingsContainer':SettingsContainer,
- }
- newSettings = {'self':self}
- exec theString in globalsDict, newSettings
- del newSettings['self'], newSettings['True'], newSettings['False']
- module = new.module('temp_settings_module')
- module.__dict__.update(newSettings)
- return self.readSettingsFromModule(module)
-
- def readSettingsFromConfigFile(self, path, convert=True):
- path = self.normalizePath(path)
- fp = open(path)
- settings = self.readSettingsFromConfigFileObj(fp, convert=convert)
- fp.close()
- return settings
-
- def readSettingsFromConfigFileObj(self, inFile, convert=True):
-
- """Return the settings from a config file that uses the syntax accepted by
- Python's standard ConfigParser module (like Windows .ini files).
-
- NOTE:
- this method maintains case unlike the ConfigParser module, unless this
- class was initialized with the 'caseSensitive' keyword set to False.
-
- All setting values are initially parsed as strings. However, If the
- 'convert' arg is True this method will do the following value
- conversions:
-
- * all Python numeric literals will be coverted from string to number
-
- * The string 'None' will be converted to the Python value None
-
- * The string 'True' will be converted to a Python truth value
-
- * The string 'False' will be converted to a Python false value
-
- * Any string starting with 'python:' will be treated as a Python literal
- or expression that needs to be eval'd. This approach is useful for
- declaring lists and dictionaries.
-
- If a config section titled 'Globals' is present the options defined
- under it will be treated as top-level settings.
- """
-
- p = self._ConfigParserClass()
- p.readfp(inFile)
- sects = p.sections()
- newSettings = {}
-
- sects = p.sections()
- newSettings = {}
-
- for s in sects:
- newSettings[s] = {}
- for o in p.options(s):
- if o != '__name__':
- newSettings[s][o] = p.get(s,o)
-
- ## loop through new settings -> deal with global settings, numbers,
- ## booleans and None ++ also deal with 'importSettings' commands
-
- for sect, subDict in newSettings.items():
- for key, val in subDict.items():
- if convert:
- if val.lower().startswith('python:'):
- subDict[key] = eval(val[7:],{},{})
- if val.lower() == 'none':
- subDict[key] = None
- if val.lower() == 'true':
- subDict[key] = True
- if val.lower() == 'false':
- subDict[key] = False
- if stringIsNumber(val):
- subDict[key] = convStringToNum(val)
-
- ## now deal with any 'importSettings' commands
- if key.lower() == 'importsettings':
- if val.find(';') < 0:
- importedSettings = self.readSettingsFromPySrcFile(val)
- else:
- path = val.split(';')[0]
- rest = ''.join(val.split(';')[1:]).strip()
- parentDict = self.readSettingsFromPySrcFile(path)
- importedSettings = eval('parentDict["' + rest + '"]')
-
- subDict.update(mergeNestedDictionaries(subDict,
- importedSettings))
-
- if sect.lower() == 'globals':
- newSettings.update(newSettings[sect])
- del newSettings[sect]
-
- return newSettings
-
-
-class SettingsManager(_SettingsCollector):
-
- """A mixin class that provides facilities for managing application settings.
-
- SettingsManager is designed to work well with nested settings dictionaries
- of any depth.
- """
-
- ## init methods
-
- def __init__(self):
- """MUST BE CALLED BY SUBCLASSES"""
- _SettingsCollector.__init__(self)
- self._settings = {}
- self._initializeSettings()
-
- def _defaultSettings(self):
- return {}
-
- def _initializeSettings(self):
-
- """A hook that allows for complex setting initialization sequences that
- involve references to 'self' or other settings. For example:
- self._settings['myCalcVal'] = self._settings['someVal'] * 15
- This method should be called by the class' __init__() method when needed.
- The dummy implementation should be reimplemented by subclasses.
- """
-
- pass
-
- ## core post startup methods
-
- def setting(self, name, default=NoDefault):
-
- """Get a setting from self._settings, with or without a default value."""
-
- if default is NoDefault:
- return self._settings[name]
- else:
- return self._settings.get(name, default)
-
-
- def hasSetting(self, key):
- """True/False"""
- return self._settings.has_key(key)
-
- def setSetting(self, name, value):
- """Set a setting in self._settings."""
- self._settings[name] = value
-
- def settings(self):
- """Return a reference to the settings dictionary"""
- return self._settings
-
- def copySettings(self):
- """Returns a shallow copy of the settings dictionary"""
- return copy(self._settings)
-
- def deepcopySettings(self):
- """Returns a deep copy of the settings dictionary"""
- return deepcopy(self._settings)
-
- def updateSettings(self, newSettings, merge=True):
-
- """Update the settings with a selective merge or a complete overwrite."""
-
- if merge:
- mergeNestedDictionaries(self._settings, newSettings)
- else:
- self._settings.update(newSettings)
-
-
-
-
- ## source specific update methods
-
- def updateSettingsFromPySrcStr(self, theString, merge=True):
-
- """Update the settings from a code in a Python src string."""
-
- newSettings = self.readSettingsFromPySrcStr(theString)
- self.updateSettings(newSettings,
- merge=newSettings.get('mergeSettings',merge) )
-
- def updateSettingsFromPySrcFile(self, path, merge=True):
-
- """Update the settings from variables in a Python source file.
-
- This method will temporarily add the directory of src file to sys.path so
- that import statements relative to that dir will work properly."""
-
- newSettings = self.readSettingsFromPySrcFile(path)
- self.updateSettings(newSettings,
- merge=newSettings.get('mergeSettings',merge) )
-
-
- def updateSettingsFromConfigFile(self, path, **kw):
-
- """Update the settings from a text file using the syntax accepted by
- Python's standard ConfigParser module (like Windows .ini files).
- """
-
- path = self.normalizePath(path)
- fp = open(path)
- self.updateSettingsFromConfigFileObj(fp, **kw)
- fp.close()
-
-
- def updateSettingsFromConfigFileObj(self, inFile, convert=True, merge=True):
-
- """See the docstring for .updateSettingsFromConfigFile()
-
- The caller of this method is responsible for closing the inFile file
- object."""
-
- newSettings = self.readSettingsFromConfigFileObj(inFile, convert=convert)
- self.updateSettings(newSettings,
- merge=newSettings.get('mergeSettings',merge))
-
- def updateSettingsFromConfigStr(self, configStr, convert=True, merge=True):
-
- """See the docstring for .updateSettingsFromConfigFile()
- """
-
- configStr = '[globals]\n' + configStr
- inFile = StringIO(configStr)
- newSettings = self.readSettingsFromConfigFileObj(inFile, convert=convert)
- self.updateSettings(newSettings,
- merge=newSettings.get('mergeSettings',merge))
-
-
- ## methods for output representations of the settings
-
- def _createConfigFile(self, outFile=None):
-
- """
- Write all the settings that can be represented as strings to an .ini
- style config string.
-
- This method can only handle one level of nesting and will only work with
- numbers, strings, and None.
- """
-
- if outFile is None:
- outFile = StringIO()
- iniSettings = {'Globals':{}}
- globals = iniSettings['Globals']
-
- for key, theSetting in self.settings().items():
- if type(theSetting) in convertableToStrTypes:
- globals[key] = theSetting
- if type(theSetting) is DictType:
- iniSettings[key] = {}
- for subKey, subSetting in theSetting.items():
- if type(subSetting) in convertableToStrTypes:
- iniSettings[key][subKey] = subSetting
-
- sections = iniSettings.keys()
- sections.sort()
- outFileWrite = outFile.write # short-cut namebinding for efficiency
- for section in sections:
- outFileWrite("[" + section + "]\n")
- sectDict = iniSettings[section]
-
- keys = sectDict.keys()
- keys.sort()
- for key in keys:
- if key == "__name__":
- continue
- outFileWrite("%s = %s\n" % (key, sectDict[key]))
- outFileWrite("\n")
-
- return outFile
-
- def writeConfigFile(self, path):
-
- """Write all the settings that can be represented as strings to an .ini
- style config file."""
-
- path = self.normalizePath(path)
- fp = open(path,'w')
- self._createConfigFile(fp)
- fp.close()
-
- def getConfigString(self):
- """Return a string with the settings in .ini file format."""
-
- return self._createConfigFile().getvalue()
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/SourceReader.py b/cobbler/Cheetah/SourceReader.py
deleted file mode 100644
index e91c200..0000000
--- a/cobbler/Cheetah/SourceReader.py
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/usr/bin/env python
-# $Id: SourceReader.py,v 1.14 2006/01/18 03:16:59 tavis_rudd Exp $
-"""SourceReader class for Cheetah's Parser and CodeGenerator
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.14 $
-Start Date: 2001/09/19
-Last Revision Date: $Date: 2006/01/18 03:16:59 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.14 $"[11:-2]
-
-import re
-import sys
-
-EOLre = re.compile(r'[ \f\t]*(?:\r\n|\r|\n)')
-EOLZre = re.compile(r'(?:\r\n|\r|\n|\Z)')
-ENCODINGsearch = re.compile("coding[=:]\s*([-\w.]+)").search
-
-class Error(Exception):
- pass
-
-class SourceReader:
- def __init__(self, src, filename=None, breakPoint=None, encoding=None):
-
- ## @@TR 2005-01-17: the following comes from a patch Terrel Shumway
- ## contributed to add unicode support to the reading of Cheetah source
- ## files with dynamically compiled templates. All the existing unit
- ## tests pass but, it needs more testing and some test cases of its
- ## own. My instinct is to move this up into the code that passes in the
- ## src string rather than leaving it here. As implemented here it
- ## forces all src strings to unicode, which IMO is not what we want.
- # if encoding is None:
- # # peek at the encoding in the first two lines
- # m = EOLZre.search(src)
- # pos = m.end()
- # if pos<len(src):
- # m = EOLZre.search(src,pos)
- # pos = m.end()
- # m = ENCODINGsearch(src,0,pos)
- # if m:
- # encoding = m.group(1)
- # else:
- # encoding = sys.getfilesystemencoding()
- # self._encoding = encoding
- # if type(src) is not unicode:
- # src = src.decode(encoding)
- ## end of Terrel's patch
-
- self._src = src
- self._filename = filename
-
- self._srcLen = len(src)
- if breakPoint == None:
- self._breakPoint = self._srcLen
- else:
- self.setBreakPoint(breakPoint)
- self._pos = 0
- self._bookmarks = {}
- self._posTobookmarkMap = {}
-
- ## collect some meta-information
- self._EOLs = []
- pos = 0
- while pos < len(self):
- EOLmatch = EOLZre.search(src, pos)
- self._EOLs.append(EOLmatch.start())
- pos = EOLmatch.end()
-
- self._BOLs = []
- for pos in self._EOLs:
- BOLpos = self.findBOL(pos)
- self._BOLs.append(BOLpos)
-
- def src(self):
- return self._src
-
- def filename(self):
- return self._filename
-
- def __len__(self):
- return self._breakPoint
-
- def __getitem__(self, i):
- self.checkPos(i)
- return self._src[i]
-
- def __getslice__(self, i, j):
- i = max(i, 0); j = max(j, 0)
- return self._src[i:j]
-
- def splitlines(self):
- if not hasattr(self, '_srcLines'):
- self._srcLines = self._src.splitlines()
- return self._srcLines
-
- def lineNum(self, pos=None):
- if pos == None:
- pos = self._pos
-
- for i in range(len(self._BOLs)):
- if pos >= self._BOLs[i] and pos <= self._EOLs[i]:
- return i
-
- def getRowCol(self, pos=None):
- if pos == None:
- pos = self._pos
- lineNum = self.lineNum(pos)
- BOL, EOL = self._BOLs[lineNum], self._EOLs[lineNum]
- return lineNum+1, pos-BOL+1
-
- def getRowColLine(self, pos=None):
- if pos == None:
- pos = self._pos
- row, col = self.getRowCol(pos)
- return row, col, self.splitlines()[row-1]
-
- def getLine(self, pos):
- if pos == None:
- pos = self._pos
- lineNum = self.lineNum(pos)
- return self.splitlines()[lineNum]
-
- def pos(self):
- return self._pos
-
- def setPos(self, pos):
- self.checkPos(pos)
- self._pos = pos
-
-
- def validPos(self, pos):
- return pos <= self._breakPoint and pos >=0
-
- def checkPos(self, pos):
- if not pos <= self._breakPoint:
- raise Error("pos (" + str(pos) + ") is invalid: beyond the stream's end (" +
- str(self._breakPoint-1) + ")" )
- elif not pos >=0:
- raise Error("pos (" + str(pos) + ") is invalid: less than 0" )
-
- def breakPoint(self):
- return self._breakPoint
-
- def setBreakPoint(self, pos):
- if pos > self._srcLen:
- raise Error("New breakpoint (" + str(pos) +
- ") is invalid: beyond the end of stream's source string (" +
- str(self._srcLen) + ")" )
- elif not pos >= 0:
- raise Error("New breakpoint (" + str(pos) + ") is invalid: less than 0" )
-
- self._breakPoint = pos
-
- def setBookmark(self, name):
- self._bookmarks[name] = self._pos
- self._posTobookmarkMap[self._pos] = name
-
- def hasBookmark(self, name):
- return self._bookmarks.has_key(name)
-
- def gotoBookmark(self, name):
- if not self.hasBookmark(name):
- raise Error("Invalid bookmark (" + name + ', '+
- str(pos) + ") is invalid: does not exist" )
- pos = self._bookmarks[name]
- if not self.validPos(pos):
- raise Error("Invalid bookmark (" + name + ', '+
- str(pos) + ") is invalid: pos is out of range" )
- self._pos = pos
-
- def atEnd(self):
- return self._pos >= self._breakPoint
-
- def atStart(self):
- return self._pos == 0
-
- def peek(self, offset=0):
- self.checkPos(self._pos+offset)
- pos = self._pos + offset
- return self._src[pos]
-
- def getc(self):
- pos = self._pos
- if self.validPos(pos+1):
- self._pos += 1
- return self._src[pos]
-
- def ungetc(self, c=None):
- if not self.atStart():
- raise Error('Already at beginning of stream')
-
- self._pos -= 1
- if not c==None:
- self._src[self._pos] = c
-
- def advance(self, offset=1):
- self.checkPos(self._pos + offset)
- self._pos += offset
-
- def rev(self, offset=1):
- self.checkPos(self._pos - offset)
- self._pos -= offset
-
- def read(self, offset):
- self.checkPos(self._pos + offset)
- start = self._pos
- self._pos += offset
- return self._src[start:self._pos]
-
- def readTo(self, to, start=None):
- self.checkPos(to)
- if start == None:
- start = self._pos
- self._pos = to
- return self._src[start:to]
-
-
- def readToEOL(self, start=None, gobble=True):
- EOLmatch = EOLZre.search(self.src(), self.pos())
- if gobble:
- pos = EOLmatch.end()
- else:
- pos = EOLmatch.start()
- return self.readTo(to=pos, start=start)
-
-
- def find(self, it, pos=None):
- if pos == None:
- pos = self._pos
- return self._src.find(it, pos )
-
- def startswith(self, it, pos=None):
- if self.find(it, pos) == self.pos():
- return True
- else:
- return False
-
- def rfind(self, it, pos):
- if pos == None:
- pos = self._pos
- return self._src.rfind(it, pos)
-
- def findBOL(self, pos=None):
- if pos == None:
- pos = self._pos
- src = self.src()
- return max(src.rfind('\n',0,pos)+1, src.rfind('\r',0,pos)+1, 0)
-
- def findEOL(self, pos=None, gobble=False):
- if pos == None:
- pos = self._pos
-
- match = EOLZre.search(self.src(), pos)
- if gobble:
- return match.end()
- else:
- return match.start()
-
- def isLineClearToPos(self, pos=None):
- if pos == None:
- pos = self.pos()
- self.checkPos(pos)
- src = self.src()
- BOL = self.findBOL()
- return BOL == pos or src[BOL:pos].isspace()
-
- def matches(self, strOrRE):
- if isinstance(strOrRE, (str, unicode)):
- return self.startswith(strOrRE, pos=self.pos())
- else: # assume an re object
- return strOrRE.match(self.src(), self.pos())
-
- def matchWhiteSpace(self, WSchars=' \f\t'):
- return (not self.atEnd()) and self.peek() in WSchars
-
- def getWhiteSpace(self, max=None, WSchars=' \f\t'):
- if not self.matchWhiteSpace(WSchars):
- return ''
- start = self.pos()
- breakPoint = self.breakPoint()
- if max is not None:
- breakPoint = min(breakPoint, self.pos()+max)
- while self.pos() < breakPoint:
- self.advance()
- if not self.matchWhiteSpace(WSchars):
- break
- return self.src()[start:self.pos()]
-
- def matchNonWhiteSpace(self, WSchars=' \f\t\n\r'):
- return self.atEnd() or not self.peek() in WSchars
-
- def getNonWhiteSpace(self, WSchars=' \f\t\n\r'):
- if not self.matchNonWhiteSpace(WSchars):
- return ''
- start = self.pos()
- while self.pos() < self.breakPoint():
- self.advance()
- if not self.matchNonWhiteSpace(WSchars):
- break
- return self.src()[start:self.pos()]
diff --git a/cobbler/Cheetah/Template.py b/cobbler/Cheetah/Template.py
deleted file mode 100644
index 0185b50..0000000
--- a/cobbler/Cheetah/Template.py
+++ /dev/null
@@ -1,1858 +0,0 @@
-#!/usr/bin/env python
-# $Id: Template.py,v 1.181 2006/06/22 20:25:16 hierro Exp $
-"""Provides the core API for Cheetah.
-
-See the docstring in the Template class and the Users' Guide for more information
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.181 $
-Start Date: 2001/03/30
-Last Revision Date: $Date: 2006/06/22 20:25:16 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.181 $"[11:-2]
-
-################################################################################
-## DEPENDENCIES
-import sys # used in the error handling code
-import re # used to define the internal delims regex
-import new # used to bind methods and create dummy modules
-import string
-import os.path
-import time # used in the cache refresh code
-from random import randrange
-import imp
-import inspect
-import StringIO
-import traceback
-import pprint
-import cgi # Used by .webInput() if the template is a CGI script.
-import types
-from types import StringType, ClassType
-try:
- from types import StringTypes
-except ImportError:
- StringTypes = (types.StringType,types.UnicodeType)
-try:
- from types import BooleanType
- boolTypeAvailable = True
-except ImportError:
- boolTypeAvailable = False
-
-try:
- from threading import Lock
-except ImportError:
- class Lock:
- def acquire(self): pass
- def release(self): pass
-
-from Cheetah.Version import convertVersionStringToTuple, MinCompatibleVersionTuple
-from Cheetah.Version import MinCompatibleVersion
-# Base classes for Template
-from Cheetah.Servlet import Servlet
-# More intra-package imports ...
-from Cheetah.Parser import ParseError, SourceReader
-from Cheetah.Compiler import Compiler, DEFAULT_COMPILER_SETTINGS
-from Cheetah import ErrorCatchers # for placeholder tags
-from Cheetah import Filters # the output filters
-from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
-from Cheetah.Utils import VerifyType # Used in Template.__init__
-from Cheetah.Utils.Misc import checkKeywords # Used in Template.__init__
-from Cheetah.Utils.Indenter import Indenter # Used in Template.__init__ and for
- # placeholders
-from Cheetah.NameMapper import NotFound, valueFromSearchList
-from Cheetah.CacheStore import MemoryCacheStore, MemcachedCacheStore
-from Cheetah.CacheRegion import CacheRegion
-from Cheetah.Utils.WebInputMixin import _Converter, _lookup, NonNumericInputError
-
-from Cheetah.Unspecified import Unspecified
-
-class Error(Exception): pass
-class PreprocessError(Error): pass
-
-def hashList(l):
- hashedList = []
- for v in l:
- if isinstance(v, dict):
- v = hashDict(v)
- elif isinstance(v, list):
- v = hashList(v)
- hashedList.append(v)
- return hash(tuple(hashedList))
-
-def hashDict(d):
- items = d.items()
- items.sort()
- hashedList = []
- for k, v in items:
- if isinstance(v, dict):
- v = hashDict(v)
- elif isinstance(v, list):
- v = hashList(v)
- hashedList.append((k,v))
- return hash(tuple(hashedList))
-
-################################################################################
-## MODULE GLOBALS AND CONSTANTS
-
-def _genUniqueModuleName(baseModuleName):
- """The calling code is responsible for concurrency locking.
- """
- if baseModuleName not in sys.modules:
- finalName = baseModuleName
- else:
- finalName = ('cheetah_'+baseModuleName
- +'_'
- +''.join(map(lambda x: '%02d' % x, time.localtime(time.time())[:6]))
- + str(randrange(10000, 99999)))
- return finalName
-
-# Cache of a cgi.FieldStorage() instance, maintained by .webInput().
-# This is only relavent to templates used as CGI scripts.
-_formUsedByWebInput = None
-
-# used in Template.compile()
-def valOrDefault(val, default):
- if val is not Unspecified: return val
- else: return default
-
-
-class CompileCacheItem:
- pass
-
-class TemplatePreprocessor:
- """This is used with the preprocessors argument to Template.compile().
-
- See the docstring for Template.compile
-
- ** Preprocessors are an advanced topic **
- """
- def __init__(self, settings):
- self._settings = settings
-
- def preprocess(self, source, file):
- """Create an intermediate template and return the source code
- it outputs
- """
- settings = self._settings
- if not source: # @@TR: this needs improving
- if isinstance(file, (str, unicode)): # it's a filename.
- f = open(file)
- source = f.read()
- f.close()
- elif hasattr(file, 'read'):
- source = file.read()
- file = None
-
- templateAPIClass = settings.templateAPIClass
- possibleKwArgs = [
- arg for arg in
- inspect.getargs(templateAPIClass.compile.im_func.func_code)[0]
- if arg not in ('klass', 'source', 'file',)]
-
- compileKwArgs = {}
- for arg in possibleKwArgs:
- if hasattr(settings, arg):
- compileKwArgs[arg] = getattr(settings, arg)
-
- tmplClass = templateAPIClass.compile(source=source, file=file, **compileKwArgs)
- tmplInstance = tmplClass(**settings.templateInitArgs)
- outputSource = settings.outputTransformer(tmplInstance)
- outputFile = None
- return outputSource, outputFile
-
-class Template(Servlet):
- """This class provides a) methods used by templates at runtime and b)
- methods for compiling Cheetah source code into template classes.
-
- This documentation assumes you already know Python and the basics of object
- oriented programming. If you don't know Python, see the sections of the
- Cheetah Users' Guide for non-programmers. It also assumes you have read
- about Cheetah's syntax in the Users' Guide.
-
- The following explains how to use Cheetah from within Python programs or via
- the interpreter. If you statically compile your templates on the command
- line using the 'cheetah' script, this is not relevant to you. Statically
- compiled Cheetah template modules/classes (e.g. myTemplate.py:
- MyTemplateClasss) are just like any other Python module or class. Also note,
- most Python web frameworks (Webware, Aquarium, mod_python, Turbogears,
- CherryPy, Quixote, etc.) provide plugins that handle Cheetah compilation for
- you.
-
- There are several possible usage patterns:
- 1) tclass = Template.compile(src)
- t1 = tclass() # or tclass(namespaces=[namespace,...])
- t2 = tclass() # or tclass(namespaces=[namespace2,...])
- outputStr = str(t1) # or outputStr = t1.aMethodYouDefined()
-
- Template.compile provides a rich and very flexible API via its
- optional arguments so there are many possible variations of this
- pattern. One example is:
- tclass = Template.compile('hello $name from $caller', baseclass=dict)
- print tclass(name='world', caller='me')
- See the Template.compile() docstring for more details.
-
- 2) tmplInstance = Template(src)
- # or Template(src, namespaces=[namespace,...])
- outputStr = str(tmplInstance) # or outputStr = tmplInstance.aMethodYouDefined(...args...)
-
- Notes on the usage patterns:
-
- usage pattern 1)
- This is the most flexible, but it is slightly more verbose unless you
- write a wrapper function to hide the plumbing. Under the hood, all
- other usage patterns are based on this approach. Templates compiled
- this way can #extend (subclass) any Python baseclass: old-style or
- new-style (based on object or a builtin type).
-
- usage pattern 2)
- This was Cheetah's original usage pattern. It returns an instance,
- but you can still access the generated class via
- tmplInstance.__class__. If you want to use several different
- namespace 'searchLists' with a single template source definition,
- you're better off with Template.compile (1).
-
- Limitations (use pattern 1 instead):
- - Templates compiled this way can only #extend subclasses of the
- new-style 'object' baseclass. Cheetah.Template is a subclass of
- 'object'. You also can not #extend dict, list, or other builtin
- types.
- - If your template baseclass' __init__ constructor expects args there
- is currently no way to pass them in.
-
- If you need to subclass a dynamically compiled Cheetah class, do something like this:
- from Cheetah.Template import Template
- T1 = Template.compile('$meth1 #def meth1: this is meth1 in T1')
- T2 = Template.compile('#implements meth1\nthis is meth1 redefined in T2', baseclass=T1)
- print T1, T1()
- print T2, T2()
-
-
- Note about class and instance attribute names:
- Attributes used by Cheetah have a special prefix to avoid confusion with
- the attributes of the templates themselves or those of template
- baseclasses.
-
- Class attributes which are used in class methods look like this:
- klass._CHEETAH_useCompilationCache (_CHEETAH_xxx)
-
- Instance attributes look like this:
- klass._CHEETAH__globalSetVars (_CHEETAH__xxx with 2 underscores)
- """
-
- # this is used by ._addCheetahPlumbingCodeToClass()
- _CHEETAH_requiredCheetahMethods = (
- '_initCheetahInstance',
- 'searchList',
- 'errorCatcher',
- 'getVar',
- 'varExists',
- 'getFileContents',
- 'i18n',
- 'runAsMainProgram',
- 'respond',
- 'shutdown',
- 'webInput',
- 'serverSidePath',
- 'generatedClassCode',
- 'generatedModuleCode',
-
- '_getCacheStore',
- '_getCacheStoreIdPrefix',
- '_createCacheRegion',
- 'getCacheRegion',
- 'getCacheRegions',
- 'refreshCache',
-
- '_handleCheetahInclude',
- '_getTemplateAPIClassForIncludeDirectiveCompilation',
- )
- _CHEETAH_requiredCheetahClassMethods = ('subclass',)
- _CHEETAH_requiredCheetahClassAttributes = ('cacheRegionClass','cacheStore',
- 'cacheStoreIdPrefix','cacheStoreClass')
-
- ## the following are used by .compile(). Most are documented in its docstring.
- _CHEETAH_cacheModuleFilesForTracebacks = False
- _CHEETAH_cacheDirForModuleFiles = None # change to a dirname
-
- _CHEETAH_compileCache = dict() # cache store for compiled code and classes
- # To do something other than simple in-memory caching you can create an
- # alternative cache store. It just needs to support the basics of Python's
- # mapping/dict protocol. E.g.:
- # class AdvCachingTemplate(Template):
- # _CHEETAH_compileCache = MemoryOrFileCache()
- _CHEETAH_compileLock = Lock() # used to prevent race conditions
- _CHEETAH_defaultMainMethodName = None
- _CHEETAH_compilerSettings = None
- _CHEETAH_compilerClass = Compiler
- _CHEETAH_cacheCompilationResults = True
- _CHEETAH_useCompilationCache = True
- _CHEETAH_keepRefToGeneratedCode = True
- _CHEETAH_defaultBaseclassForTemplates = None
- _CHEETAH_defaultClassNameForTemplates = None
- # defaults to DEFAULT_COMPILER_SETTINGS['mainMethodName']:
- _CHEETAH_defaultMainMethodNameForTemplates = None
- _CHEETAH_defaultModuleNameForTemplates = 'DynamicallyCompiledCheetahTemplate'
- _CHEETAH_defaultModuleGlobalsForTemplates = None
- _CHEETAH_preprocessors = None
- _CHEETAH_defaultPreprocessorClass = TemplatePreprocessor
-
- ## The following attributes are used by instance methods:
- _CHEETAH_generatedModuleCode = None
- NonNumericInputError = NonNumericInputError
- _CHEETAH_cacheRegionClass = CacheRegion
- _CHEETAH_cacheStoreClass = MemoryCacheStore
- #_CHEETAH_cacheStoreClass = MemcachedCacheStore
- _CHEETAH_cacheStore = None
- _CHEETAH_cacheStoreIdPrefix = None
-
- def _getCompilerClass(klass, source=None, file=None):
- return klass._CHEETAH_compilerClass
- _getCompilerClass = classmethod(_getCompilerClass)
-
- def _getCompilerSettings(klass, source=None, file=None):
- return klass._CHEETAH_compilerSettings
- _getCompilerSettings = classmethod(_getCompilerSettings)
-
- def compile(klass, source=None, file=None,
- returnAClass=True,
-
- compilerSettings=Unspecified,
- compilerClass=Unspecified,
- moduleName=None,
- className=Unspecified,
- mainMethodName=Unspecified,
- baseclass=Unspecified,
- moduleGlobals=Unspecified,
- cacheCompilationResults=Unspecified,
- useCache=Unspecified,
- preprocessors=Unspecified,
- cacheModuleFilesForTracebacks=Unspecified,
- cacheDirForModuleFiles=Unspecified,
-
- keepRefToGeneratedCode=Unspecified,
- ):
-
- """
- The core API for compiling Cheetah source code into template classes.
-
- This class method compiles Cheetah source code and returns a python
- class. You then create template instances using that class. All
- Cheetah's other compilation API's use this method under the hood.
-
- Internally, this method a) parses the Cheetah source code and generates
- Python code defining a module with a single class in it, b) dynamically
- creates a module object with a unique name, c) execs the generated code
- in that module's namespace then inserts the module into sys.modules, and
- d) returns a reference to the generated class. If you want to get the
- generated python source code instead, pass the argument
- returnAClass=False.
-
- It caches generated code and classes. See the descriptions of the
- arguments'cacheCompilationResults' and 'useCache' for details. This
- doesn't mean that templates will automatically recompile themselves when
- the source file changes. Rather, if you call Template.compile(src) or
- Template.compile(file=path) repeatedly it will attempt to return a
- cached class definition instead of recompiling.
-
- Hooks are provided template source preprocessing. See the notes on the
- 'preprocessors' arg.
-
- If you are an advanced user and need to customize the way Cheetah parses
- source code or outputs Python code, you should check out the
- compilerSettings argument.
-
- Arguments:
- You must provide either a 'source' or 'file' arg, but not both:
- - source (string or None)
- - file (string path, file-like object, or None)
-
- The rest of the arguments are strictly optional. All but the first
- have defaults in attributes of the Template class which can be
- overridden in subclasses of this class. Working with most of these is
- an advanced topic.
-
- - returnAClass=True
- If false, return the generated module code rather than a class.
-
- - compilerSettings (a dict)
- Default: Template._CHEETAH_compilerSettings=None
-
- a dictionary of settings to override those defined in
- DEFAULT_COMPILER_SETTINGS. These can also be overridden in your
- template source code with the #compiler or #compiler-settings
- directives.
-
- - compilerClass (a class)
- Default: Template._CHEETAH_compilerClass=Cheetah.Compiler.Compiler
-
- a subclass of Cheetah.Compiler.Compiler. Mucking with this is a
- very advanced topic.
-
- - moduleName (a string)
- Default:
- Template._CHEETAH_defaultModuleNameForTemplates
- ='DynamicallyCompiledCheetahTemplate'
-
- What to name the generated Python module. If the provided value is
- None and a file arg was given, the moduleName is created from the
- file path. In all cases if the moduleName provided is already in
- sys.modules it is passed through a filter that generates a unique
- variant of the name.
-
-
- - className (a string)
- Default: Template._CHEETAH_defaultClassNameForTemplates=None
-
- What to name the generated Python class. If the provided value is
- None, the moduleName is use as the class name.
-
- - mainMethodName (a string)
- Default:
- Template._CHEETAH_defaultMainMethodNameForTemplates
- =None (and thus DEFAULT_COMPILER_SETTINGS['mainMethodName'])
-
- What to name the main output generating method in the compiled
- template class.
-
- - baseclass (a string or a class)
- Default: Template._CHEETAH_defaultBaseclassForTemplates=None
-
- Specifies the baseclass for the template without manually
- including an #extends directive in the source. The #extends
- directive trumps this arg.
-
- If the provided value is a string you must make sure that a class
- reference by that name is available to your template, either by
- using an #import directive or by providing it in the arg
- 'moduleGlobals'.
-
- If the provided value is a class, Cheetah will handle all the
- details for you.
-
- - moduleGlobals (a dict)
- Default: Template._CHEETAH_defaultModuleGlobalsForTemplates=None
-
- A dict of vars that will be added to the global namespace of the
- module the generated code is executed in, prior to the execution
- of that code. This should be Python values, not code strings!
-
- - cacheCompilationResults (True/False)
- Default: Template._CHEETAH_cacheCompilationResults=True
-
- Tells Cheetah to cache the generated code and classes so that they
- can be reused if Template.compile() is called multiple times with
- the same source and options.
-
- - useCache (True/False)
- Default: Template._CHEETAH_useCompilationCache=True
-
- Should the compilation cache be used? If True and a previous
- compilation created a cached template class with the same source
- code, compiler settings and other options, the cached template
- class will be returned.
-
- - cacheModuleFilesForTracebacks (True/False)
- Default: Template._CHEETAH_cacheModuleFilesForTracebacks=False
-
- In earlier versions of Cheetah tracebacks from exceptions that
- were raised inside dynamically compiled Cheetah templates were
- opaque because Python didn't have access to a python source file
- to use in the traceback:
-
- File "xxxx.py", line 192, in getTextiledContent
- content = str(template(searchList=searchList))
- File "cheetah_yyyy.py", line 202, in __str__
- File "cheetah_yyyy.py", line 187, in respond
- File "cheetah_yyyy.py", line 139, in writeBody
- ZeroDivisionError: integer division or modulo by zero
-
- It is now possible to keep those files in a cache dir and allow
- Python to include the actual source lines in tracebacks and makes
- them much easier to understand:
-
- File "xxxx.py", line 192, in getTextiledContent
- content = str(template(searchList=searchList))
- File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 202, in __str__
- def __str__(self): return self.respond()
- File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 187, in respond
- self.writeBody(trans=trans)
- File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 139, in writeBody
- __v = 0/0 # $(0/0)
- ZeroDivisionError: integer division or modulo by zero
-
- - cacheDirForModuleFiles (a string representing a dir path)
- Default: Template._CHEETAH_cacheDirForModuleFiles=None
-
- See notes on cacheModuleFilesForTracebacks.
-
- - preprocessors
- Default: Template._CHEETAH_preprocessors=None
-
- ** THIS IS A VERY ADVANCED TOPIC **
-
- These are used to transform the source code prior to compilation.
- They provide a way to use Cheetah as a code generator for Cheetah
- code. In other words, you use one Cheetah template to output the
- source code for another Cheetah template.
-
- The major expected use cases are:
-
- a) 'compile-time caching' aka 'partial template binding',
- wherein an intermediate Cheetah template is used to output
- the source for the final Cheetah template. The intermediate
- template is a mix of a modified Cheetah syntax (the
- 'preprocess syntax') and standard Cheetah syntax. The
- preprocessor syntax is executed at compile time and outputs
- Cheetah code which is then compiled in turn. This approach
- allows one to completely soft-code all the elements in the
- template which are subject to change yet have it compile to
- extremely efficient Python code with everything but the
- elements that must be variable at runtime (per browser
- request, etc.) compiled as static strings. Examples of this
- usage pattern will be added to the Cheetah Users' Guide.
-
- The'preprocess syntax' is just Cheetah's standard one with
- alternatives for the $ and # tokens:
-
- e.g. '@' and '%' for code like this
- @aPreprocessVar $aRuntimeVar
- %if aCompileTimeCondition then yyy else zzz
- %% preprocessor comment
-
- #if aRunTimeCondition then aaa else bbb
- ## normal comment
- $aRuntimeVar
-
- b) adding #import and #extends directives dynamically based on
- the source
-
- If preprocessors are provided, Cheetah pipes the source code
- through each one in the order provided. Each preprocessor should
- accept the args (source, file) and should return a tuple (source,
- file).
-
- The argument value should be a list, but a single non-list value
- is acceptable and will automatically be converted into a list.
- Each item in the list will be passed through
- Template._normalizePreprocessor(). The items should either match
- one of the following forms:
-
- - an object with a .preprocess(source, file) method
- - a callable with the following signature:
- source, file = f(source, file)
-
- or one of the forms below:
-
- - a single string denoting the 2 'tokens' for the preprocess
- syntax. The tokens should be in the order (placeholderToken,
- directiveToken) and should separated with a space:
- e.g. '@ %'
- klass = Template.compile(src, preprocessors='@ %')
- # or
- klass = Template.compile(src, preprocessors=['@ %'])
-
- - a dict with the following keys or an object with the
- following attributes (all are optional, but nothing will
- happen if you don't provide at least one):
- - tokens: same as the single string described above. You can
- also provide a tuple of 2 strings.
- - searchList: the searchList used for preprocess $placeholders
- - compilerSettings: used in the compilation of the intermediate
- template
- - templateAPIClass: an optional subclass of `Template`
- - outputTransformer: a simple hook for passing in a callable
- which can do further transformations of the preprocessor
- output, or do something else like debug logging. The
- default is str().
- + any keyword arguments to Template.compile which you want to
- provide for the compilation of the intermediate template.
-
- klass = Template.compile(src,
- preprocessors=[ dict(tokens='@ %', searchList=[...]) ] )
-
- """
- ##################################################
- ## normalize and validate args
- try:
- vt = VerifyType.VerifyType
- vtc = VerifyType.VerifyTypeClass
- N = types.NoneType; S = types.StringType; U = types.UnicodeType
- D = types.DictType; F = types.FileType
- C = types.ClassType; M = types.ModuleType
- I = types.IntType
-
- if boolTypeAvailable:
- B = types.BooleanType
-
- vt(source, 'source', [N,S,U], 'string or None')
- vt(file, 'file',[N,S,U,F], 'string, file-like object, or None')
-
- baseclass = valOrDefault(baseclass, klass._CHEETAH_defaultBaseclassForTemplates)
- if isinstance(baseclass, Template):
- baseclass = baseclass.__class__
- vt(baseclass, 'baseclass', [N,S,C,type], 'string, class or None')
-
- cacheCompilationResults = valOrDefault(
- cacheCompilationResults, klass._CHEETAH_cacheCompilationResults)
- if boolTypeAvailable:
- vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
-
- useCache = valOrDefault(useCache, klass._CHEETAH_useCompilationCache)
- if boolTypeAvailable:
- vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
-
- compilerSettings = valOrDefault(
- compilerSettings, klass._getCompilerSettings(source, file) or {})
- vt(compilerSettings, 'compilerSettings', [D], 'dictionary')
-
- compilerClass = valOrDefault(compilerClass, klass._getCompilerClass(source, file))
-
- preprocessors = valOrDefault(preprocessors, klass._CHEETAH_preprocessors)
-
- keepRefToGeneratedCode = valOrDefault(
- keepRefToGeneratedCode, klass._CHEETAH_keepRefToGeneratedCode)
- if boolTypeAvailable:
- vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
-
- vt(moduleName, 'moduleName', [N,S], 'string or None')
- __orig_file__ = None
- if not moduleName:
- if file and type(file) in StringTypes:
- moduleName = convertTmplPathToModuleName(file)
- __orig_file__ = file
- else:
- moduleName = klass._CHEETAH_defaultModuleNameForTemplates
-
- className = valOrDefault(
- className, klass._CHEETAH_defaultClassNameForTemplates)
- vt(className, 'className', [N,S], 'string or None')
- className = className or moduleName
-
- mainMethodName = valOrDefault(
- mainMethodName, klass._CHEETAH_defaultMainMethodNameForTemplates)
- vt(mainMethodName, 'mainMethodName', [N,S], 'string or None')
-
- moduleGlobals = valOrDefault(
- moduleGlobals, klass._CHEETAH_defaultModuleGlobalsForTemplates)
-
- cacheModuleFilesForTracebacks = valOrDefault(
- cacheModuleFilesForTracebacks, klass._CHEETAH_cacheModuleFilesForTracebacks)
- if boolTypeAvailable:
- vt(cacheModuleFilesForTracebacks, 'cacheModuleFilesForTracebacks', [I,B], 'boolean')
-
- cacheDirForModuleFiles = valOrDefault(
- cacheDirForModuleFiles, klass._CHEETAH_cacheDirForModuleFiles)
- vt(cacheDirForModuleFiles, 'cacheDirForModuleFiles', [N,S], 'string or None')
-
- except TypeError, reason:
- raise TypeError(reason)
-
- ##################################################
- ## handle any preprocessors
- if preprocessors:
- origSrc = source
- source, file = klass._preprocessSource(source, file, preprocessors)
-
- ##################################################
- ## compilation, using cache if requested/possible
- baseclassValue = None
- baseclassName = None
- if baseclass:
- if type(baseclass) in StringTypes:
- baseclassName = baseclass
- elif type(baseclass) in (ClassType, type):
- # @@TR: should soft-code this
- baseclassName = 'CHEETAH_dynamicallyAssignedBaseClass_'+baseclass.__name__
- baseclassValue = baseclass
-
-
- cacheHash = None
- cacheItem = None
- if source or isinstance(file, (str, unicode)):
- compilerSettingsHash = None
- if compilerSettings:
- compilerSettingsHash = hashDict(compilerSettings)
-
- moduleGlobalsHash = None
- if moduleGlobals:
- moduleGlobalsHash = hashDict(moduleGlobals)
-
- fileHash = None
- if file:
- fileHash = str(hash(file))+str(os.path.getmtime(file))
-
- try:
- cacheHash = ''.join([str(v) for v in
- [hash(source),
- fileHash,
- className,
- moduleName,
- mainMethodName,
- hash(compilerClass),
- hash(baseclass),
- compilerSettingsHash,
- moduleGlobalsHash,
- hash(cacheDirForModuleFiles),
- ]])
- except:
- #@@TR: should add some logging to this
- pass
- if useCache and cacheHash and klass._CHEETAH_compileCache.has_key(cacheHash):
- cacheItem = klass._CHEETAH_compileCache[cacheHash]
- generatedModuleCode = cacheItem.code
- #print 'DEBUG: found cached copy'
- else:
- compiler = compilerClass(source, file,
- moduleName=moduleName,
- mainClassName=className,
- baseclassName=baseclassName,
- mainMethodName=mainMethodName,
- settings=(compilerSettings or {}))
- compiler.compile()
- generatedModuleCode = compiler.getModuleCode()
-
- if not returnAClass:
- return generatedModuleCode
- else:
- if cacheItem:
- cacheItem.lastCheckoutTime = time.time()
- return cacheItem.klass
-
- def updateLinecache(filename, src):
- import linecache
- size = len(src)
- mtime = time.time()
- lines = src.splitlines()
- fullname = filename
- linecache.cache[filename] = size, mtime, lines, fullname
-
-
- try:
- klass._CHEETAH_compileLock.acquire()
- uniqueModuleName = _genUniqueModuleName(moduleName)
- __file__ = uniqueModuleName+'.py' # relative file path with no dir part
- mod = new.module(uniqueModuleName)
- sys.modules[uniqueModuleName] = mod
- finally:
- klass._CHEETAH_compileLock.release()
-
- try:
- if cacheModuleFilesForTracebacks:
- if not os.path.exists(cacheDirForModuleFiles):
- raise Exception('%s does not exist'%
- cacheDirForModuleFiles)
-
- __file__ = os.path.join(cacheDirForModuleFiles, __file__)
- try:
- klass._CHEETAH_compileLock.acquire()
- # @@TR: might want to assert that it doesn't already exist
- try:
- open(__file__, 'w').write(generatedModuleCode)
- # @@TR: should probably restrict the perms, etc.
- except OSError:
- # @@ TR: should this optionally raise?
- traceback.print_exc(file=sys.stderr)
- finally:
- klass._CHEETAH_compileLock.release()
-
- if moduleGlobals:
- for k, v in moduleGlobals.items():
- setattr(mod, k, v)
- mod.__file__ = __file__
- if __orig_file__ and os.path.exists(__orig_file__):
- # this is used in the WebKit filemonitoring code
- mod.__orig_file__ = __orig_file__
-
- if baseclass and baseclassValue:
- setattr(mod, baseclassName, baseclassValue)
-
- try:
- co = compile(generatedModuleCode, __file__, 'exec')
- exec co in mod.__dict__
- except SyntaxError, e:
- try:
- parseError = genParserErrorFromPythonException(
- source, file, generatedModuleCode, exception=e)
- except:
- traceback.print_exc()
- updateLinecache(__file__, generatedModuleCode)
- e.generatedModuleCode = generatedModuleCode
- raise e
- else:
- raise parseError
- except Exception, e:
- updateLinecache(__file__, generatedModuleCode)
- e.generatedModuleCode = generatedModuleCode
- raise
-
- except:
- del sys.modules[uniqueModuleName]
- raise
-
- templateClass = getattr(mod, className)
-
- if (cacheCompilationResults
- and cacheHash
- and not klass._CHEETAH_compileCache.has_key(cacheHash)):
-
- cacheItem = CompileCacheItem()
- cacheItem.cacheTime = cacheItem.lastCheckoutTime = time.time()
- cacheItem.code = generatedModuleCode
- cacheItem.klass = templateClass
- templateClass._CHEETAH_isInCompilationCache = True
- klass._CHEETAH_compileCache[cacheHash] = cacheItem
- else:
- templateClass._CHEETAH_isInCompilationCache = False
-
- if keepRefToGeneratedCode or cacheCompilationResults:
- templateClass._CHEETAH_generatedModuleCode = generatedModuleCode
-
- return templateClass
- compile = classmethod(compile)
-
- def subclass(klass, *args, **kws):
- """Takes the same args as the .compile() classmethod and returns a
- template that is a subclass of the template this method is called from.
-
- T1 = Template.compile(' foo - $meth1 - bar\n#def meth1: this is T1.meth1')
- T2 = T1.subclass('#implements meth1\n this is T2.meth1')
- """
- kws['baseclass'] = klass
- if isinstance(klass, Template):
- templateAPIClass = klass
- else:
- templateAPIClass = Template
- return templateAPIClass.compile(*args, **kws)
- subclass = classmethod(subclass)
-
- def _preprocessSource(klass, source, file, preprocessors):
- """Iterates through the .compile() classmethod's preprocessors argument
- and pipes the source code through each each preprocessor.
-
- It returns the tuple (source, file) which is then used by
- Template.compile to finish the compilation.
- """
- if not isinstance(preprocessors, (list, tuple)):
- preprocessors = [preprocessors]
- for preprocessor in preprocessors:
- preprocessor = klass._normalizePreprocessorArg(preprocessor)
- source, file = preprocessor.preprocess(source, file)
- return source, file
- _preprocessSource = classmethod(_preprocessSource)
-
- def _normalizePreprocessorArg(klass, arg):
- """Used to convert the items in the .compile() classmethod's
- preprocessors argument into real source preprocessors. This permits the
- use of several shortcut forms for defining preprocessors.
- """
-
- if hasattr(arg, 'preprocess'):
- return arg
- elif callable(arg):
- class WrapperPreprocessor:
- def preprocess(self, source, file):
- return arg(source, file)
- return WrapperPreprocessor()
- else:
- class Settings(object):
- placeholderToken = None
- directiveToken = None
- settings = Settings()
- if isinstance(arg, str) or isinstance(arg, (list, tuple)):
- settings.tokens = arg
- elif isinstance(arg, dict):
- for k, v in arg.items():
- setattr(settings, k, v)
- else:
- settings = arg
-
- settings = klass._normalizePreprocessorSettings(settings)
- return klass._CHEETAH_defaultPreprocessorClass(settings)
-
- _normalizePreprocessorArg = classmethod(_normalizePreprocessorArg)
-
- def _normalizePreprocessorSettings(klass, settings):
- settings.keepRefToGeneratedCode = True
-
- def normalizeSearchList(searchList):
- if not isinstance(searchList, (list, tuple)):
- searchList = [searchList]
- return searchList
-
- def normalizeTokens(tokens):
- if isinstance(tokens, str):
- return tokens.split() # space delimited string e.g.'@ %'
- elif isinstance(tokens, (list, tuple)):
- return tokens
- else:
- raise PreprocessError('invalid tokens argument: %r'%tokens)
-
- if hasattr(settings, 'tokens'):
- (settings.placeholderToken,
- settings.directiveToken) = normalizeTokens(settings.tokens)
-
- if (not getattr(settings,'compilerSettings', None)
- and not getattr(settings, 'placeholderToken', None) ):
-
- raise TypeError(
- 'Preprocessor requires either a "tokens" or a "compilerSettings" arg.'
- ' Neither was provided.')
-
- if not hasattr(settings, 'templateInitArgs'):
- settings.templateInitArgs = {}
- if 'searchList' not in settings.templateInitArgs:
- if not hasattr(settings, 'searchList') and hasattr(settings, 'namespaces'):
- settings.searchList = settings.namespaces
- elif not hasattr(settings, 'searchList'):
- settings.searchList = []
- settings.templateInitArgs['searchList'] = settings.searchList
- settings.templateInitArgs['searchList'] = (
- normalizeSearchList(settings.templateInitArgs['searchList']))
-
- if not hasattr(settings, 'outputTransformer'):
- settings.outputTransformer = unicode
-
- if not hasattr(settings, 'templateAPIClass'):
- class PreprocessTemplateAPIClass(klass): pass
- settings.templateAPIClass = PreprocessTemplateAPIClass
-
- if not hasattr(settings, 'compilerSettings'):
- settings.compilerSettings = {}
-
- klass._updateSettingsWithPreprocessTokens(
- compilerSettings=settings.compilerSettings,
- placeholderToken=settings.placeholderToken,
- directiveToken=settings.directiveToken
- )
- return settings
- _normalizePreprocessorSettings = classmethod(_normalizePreprocessorSettings)
-
- def _updateSettingsWithPreprocessTokens(
- klass, compilerSettings, placeholderToken, directiveToken):
-
- if (placeholderToken and 'cheetahVarStartToken' not in compilerSettings):
- compilerSettings['cheetahVarStartToken'] = placeholderToken
- if directiveToken:
- if 'directiveStartToken' not in compilerSettings:
- compilerSettings['directiveStartToken'] = directiveToken
- if 'directiveEndToken' not in compilerSettings:
- compilerSettings['directiveEndToken'] = directiveToken
- if 'commentStartToken' not in compilerSettings:
- compilerSettings['commentStartToken'] = directiveToken*2
- if 'multiLineCommentStartToken' not in compilerSettings:
- compilerSettings['multiLineCommentStartToken'] = (
- directiveToken+'*')
- if 'multiLineCommentEndToken' not in compilerSettings:
- compilerSettings['multiLineCommentEndToken'] = (
- '*'+directiveToken)
- if 'EOLSlurpToken' not in compilerSettings:
- compilerSettings['EOLSlurpToken'] = directiveToken
- _updateSettingsWithPreprocessTokens = classmethod(_updateSettingsWithPreprocessTokens)
-
- def _addCheetahPlumbingCodeToClass(klass, concreteTemplateClass):
- """If concreteTemplateClass is not a subclass of Cheetah.Template, add
- the required cheetah methods and attributes to it.
-
- This is called on each new template class after it has been compiled.
- If concreteTemplateClass is not a subclass of Cheetah.Template but
- already has method with the same name as one of the required cheetah
- methods, this will skip that method.
- """
- for methodname in klass._CHEETAH_requiredCheetahMethods:
- if not hasattr(concreteTemplateClass, methodname):
- method = getattr(Template, methodname)
- newMethod = new.instancemethod(method.im_func, None, concreteTemplateClass)
- #print methodname, method
- setattr(concreteTemplateClass, methodname, newMethod)
-
- for classMethName in klass._CHEETAH_requiredCheetahClassMethods:
- if not hasattr(concreteTemplateClass, classMethName):
- meth = getattr(klass, classMethName)
- setattr(concreteTemplateClass, classMethName, classmethod(meth.im_func))
-
- for attrname in klass._CHEETAH_requiredCheetahClassAttributes:
- attrname = '_CHEETAH_'+attrname
- if not hasattr(concreteTemplateClass, attrname):
- attrVal = getattr(klass, attrname)
- setattr(concreteTemplateClass, attrname, attrVal)
-
- if (not hasattr(concreteTemplateClass, '__str__')
- or concreteTemplateClass.__str__ is object.__str__):
-
- mainMethNameAttr = '_mainCheetahMethod_for_'+concreteTemplateClass.__name__
- mainMethName = getattr(concreteTemplateClass,mainMethNameAttr, None)
- if mainMethName:
- def __str__(self): return getattr(self, mainMethName)()
- elif (hasattr(concreteTemplateClass, 'respond')
- and concreteTemplateClass.respond!=Servlet.respond):
- def __str__(self): return self.respond()
- else:
- def __str__(self):
- if hasattr(self, mainMethNameAttr):
- return getattr(self,mainMethNameAttr)()
- elif hasattr(self, 'respond'):
- return self.respond()
- else:
- return super(self.__class__, self).__str__()
-
- __str__ = new.instancemethod(__str__, None, concreteTemplateClass)
- setattr(concreteTemplateClass, '__str__', __str__)
-
- _addCheetahPlumbingCodeToClass = classmethod(_addCheetahPlumbingCodeToClass)
-
- ## end classmethods ##
-
- def __init__(self, source=None,
-
- namespaces=None, searchList=None,
- # use either or. They are aliases for the same thing.
-
- file=None,
- filter='RawOrEncodedUnicode', # which filter from Cheetah.Filters
- filtersLib=Filters,
- errorCatcher=None,
-
- compilerSettings=Unspecified, # control the behaviour of the compiler
- _globalSetVars=None, # used internally for #include'd templates
- _preBuiltSearchList=None # used internally for #include'd templates
- ):
- """a) compiles a new template OR b) instantiates an existing template.
-
- Read this docstring carefully as there are two distinct usage patterns.
- You should also read this class' main docstring.
-
- a) to compile a new template:
- t = Template(source=aSourceString)
- # or
- t = Template(file='some/path')
- # or
- t = Template(file=someFileObject)
- # or
- namespaces = [{'foo':'bar'}]
- t = Template(source=aSourceString, namespaces=namespaces)
- # or
- t = Template(file='some/path', namespaces=namespaces)
-
- print t
-
- b) to create an instance of an existing, precompiled template class:
- ## i) first you need a reference to a compiled template class:
- tclass = Template.compile(source=src) # or just Template.compile(src)
- # or
- tclass = Template.compile(file='some/path')
- # or
- tclass = Template.compile(file=someFileObject)
- # or
- # if you used the command line compiler or have Cheetah's ImportHooks
- # installed your template class is also available via Python's
- # standard import mechanism:
- from ACompileTemplate import AcompiledTemplate as tclass
-
- ## ii) then you create an instance
- t = tclass(namespaces=namespaces)
- # or
- t = tclass(namespaces=namespaces, filter='RawOrEncodedUnicode')
- print t
-
- Arguments:
- for usage pattern a)
- If you are compiling a new template, you must provide either a
- 'source' or 'file' arg, but not both:
- - source (string or None)
- - file (string path, file-like object, or None)
-
- Optional args (see below for more) :
- - compilerSettings
- Default: Template._CHEETAH_compilerSettings=None
-
- a dictionary of settings to override those defined in
- DEFAULT_COMPILER_SETTINGS. See
- Cheetah.Template.DEFAULT_COMPILER_SETTINGS and the Users' Guide
- for details.
-
- You can pass the source arg in as a positional arg with this usage
- pattern. Use keywords for all other args.
-
- for usage pattern b)
- Do not use positional args with this usage pattern, unless your
- template subclasses something other than Cheetah.Template and you
- want to pass positional args to that baseclass. E.g.:
- dictTemplate = Template.compile('hello $name from $caller', baseclass=dict)
- tmplvars = dict(name='world', caller='me')
- print dictTemplate(tmplvars)
- This usage requires all Cheetah args to be passed in as keyword args.
-
- optional args for both usage patterns:
-
- - namespaces (aka 'searchList')
- Default: None
-
- an optional list of namespaces (dictionaries, objects, modules,
- etc.) which Cheetah will search through to find the variables
- referenced in $placeholders.
-
- If you provide a single namespace instead of a list, Cheetah will
- automatically convert it into a list.
-
- NOTE: Cheetah does NOT force you to use the namespaces search list
- and related features. It's on by default, but you can turn if off
- using the compiler settings useSearchList=False or
- useNameMapper=False.
-
- - filter
- Default: 'EncodeUnicode'
-
- Which filter should be used for output filtering. This should
- either be a string which is the name of a filter in the
- 'filtersLib' or a subclass of Cheetah.Filters.Filter. . See the
- Users' Guide for more details.
-
- - filtersLib
- Default: Cheetah.Filters
-
- A module containing subclasses of Cheetah.Filters.Filter. See the
- Users' Guide for more details.
-
- - errorCatcher
- Default: None
-
- This is a debugging tool. See the Users' Guide for more details.
- Do not use this or the #errorCatcher diretive with live
- production systems.
-
- Do NOT mess with the args _globalSetVars or _preBuiltSearchList!
-
- """
-
- ##################################################
- ## Verify argument keywords and types
-
- S = types.StringType; U = types.UnicodeType
- L = types.ListType; T = types.TupleType
- D = types.DictType; F = types.FileType
- C = types.ClassType; M = types.ModuleType
- N = types.NoneType
- vt = VerifyType.VerifyType
- vtc = VerifyType.VerifyTypeClass
- try:
- vt(source, 'source', [N,S,U], 'string or None')
- vt(file, 'file', [N,S,U,F], 'string, file open for reading, or None')
- vtc(filter, 'filter', [S,C,type], 'string or class',
- Filters.Filter,
- '(if class, must be subclass of Cheetah.Filters.Filter)')
- vt(filtersLib, 'filtersLib', [S,M], 'string or module',
- '(if module, must contain subclasses of Cheetah.Filters.Filter)')
- vtc(errorCatcher, 'errorCatcher', [N,S,C,type], 'string, class or None',
- ErrorCatchers.ErrorCatcher,
- '(if class, must be subclass of Cheetah.ErrorCatchers.ErrorCatcher)')
- if compilerSettings is not Unspecified:
- vt(compilerSettings, 'compilerSettings', [D], 'dictionary')
-
- except TypeError, reason:
- # Re-raise the exception here so that the traceback will end in
- # this function rather than in some utility function.
- raise TypeError(reason)
-
- if source is not None and file is not None:
- raise TypeError("you must supply either a source string or the" +
- " 'file' keyword argument, but not both")
-
- ##################################################
- ## Do superclass initialization.
- Servlet.__init__(self)
-
- ##################################################
- ## Do required version check
- if not hasattr(self, '_CHEETAH_versionTuple'):
- try:
- mod = sys.modules[self.__class__.__module__]
- compiledVersion = mod.__CHEETAH_version__
- compiledVersionTuple = convertVersionStringToTuple(compiledVersion)
- if compiledVersionTuple < MinCompatibleVersionTuple:
- raise AssertionError(
- 'This template was compiled with Cheetah version'
- ' %s. Templates compiled before version %s must be recompiled.'%(
- compiledVersion, MinCompatibleVersion))
- except AssertionError:
- raise
- except:
- pass
-
- ##################################################
- ## Setup instance state attributes used during the life of template
- ## post-compile
-
- self._initCheetahInstance(
- searchList=searchList, namespaces=namespaces,
- filter=filter, filtersLib=filtersLib,
- errorCatcher=errorCatcher,
- _globalSetVars=_globalSetVars,
- _preBuiltSearchList=_preBuiltSearchList)
-
- ##################################################
- ## Now, compile if we're meant to
- if (source is not None) or (file is not None):
- self._compile(source, file, compilerSettings=compilerSettings)
-
- def generatedModuleCode(self):
- """Return the module code the compiler generated, or None if no
- compilation took place.
- """
-
- return self._CHEETAH_generatedModuleCode
-
- def generatedClassCode(self):
- """Return the class code the compiler generated, or None if no
- compilation took place.
- """
-
- return self._CHEETAH_generatedModuleCode[
- self._CHEETAH_generatedModuleCode.find('\nclass '):
- self._CHEETAH_generatedModuleCode.find('\n## END CLASS DEFINITION')]
-
- def searchList(self):
- """Return a reference to the searchlist
- """
- return self._CHEETAH__searchList
-
- def errorCatcher(self):
- """Return a reference to the current errorCatcher
- """
- return self._CHEETAH__errorCatcher
-
- ## cache methods ##
- def _getCacheStore(self):
- if not self._CHEETAH__cacheStore:
- if self._CHEETAH_cacheStore is not None:
- self._CHEETAH__cacheStore = self._CHEETAH_cacheStore
- else:
- # @@TR: might want to provide a way to provide init args
- self._CHEETAH__cacheStore = self._CHEETAH_cacheStoreClass()
-
- return self._CHEETAH__cacheStore
-
- def _getCacheStoreIdPrefix(self):
- if self._CHEETAH_cacheStoreIdPrefix is not None:
- return self._CHEETAH_cacheStoreIdPrefix
- else:
- return str(id(self))
-
- def _createCacheRegion(self, regionID):
- return self._CHEETAH_cacheRegionClass(
- regionID=regionID,
- templateCacheIdPrefix=self._getCacheStoreIdPrefix(),
- cacheStore=self._getCacheStore())
-
- def getCacheRegion(self, regionID, cacheInfo=None, create=True):
- cacheRegion = self._CHEETAH__cacheRegions.get(regionID)
- if not cacheRegion and create:
- cacheRegion = self._createCacheRegion(regionID)
- self._CHEETAH__cacheRegions[regionID] = cacheRegion
- return cacheRegion
-
- def getCacheRegions(self):
- """Returns a dictionary of the 'cache regions' initialized in a
- template.
-
- Each #cache directive block or $*cachedPlaceholder is a separate 'cache
- region'.
- """
- # returns a copy to prevent users mucking it up
- return self._CHEETAH__cacheRegions.copy()
-
- def refreshCache(self, cacheRegionId=None, cacheItemId=None):
- """Refresh a cache region or a specific cache item within a region.
- """
-
- if not cacheRegionId:
- for key, cregion in self.getCacheRegions():
- cregion.clear()
- else:
- cregion = self._CHEETAH__cacheRegions.get(cacheRegionId)
- if not cregion:
- return
- if not cacheItemId: # clear the desired region and all its cacheItems
- cregion.clear()
- else: # clear one specific cache of a specific region
- cache = cregion.getCacheItem(cacheItemId)
- if cache:
- cache.clear()
-
- ## end cache methods ##
-
- def shutdown(self):
- """Break reference cycles before discarding a servlet.
- """
- try:
- Servlet.shutdown(self)
- except:
- pass
- self._CHEETAH__searchList = None
- self.__dict__ = {}
-
- ## utility functions ##
-
- def getVar(self, varName, default=Unspecified, autoCall=True):
- """Get a variable from the searchList. If the variable can't be found
- in the searchList, it returns the default value if one was given, or
- raises NameMapper.NotFound.
- """
-
- try:
- return valueFromSearchList(self.searchList(), varName.replace('$',''), autoCall)
- except NotFound:
- if default is not Unspecified:
- return default
- else:
- raise
-
- def varExists(self, varName, autoCall=True):
- """Test if a variable name exists in the searchList.
- """
- try:
- valueFromSearchList(self.searchList(), varName.replace('$',''), autoCall)
- return True
- except NotFound:
- return False
-
-
- hasVar = varExists
-
-
- def i18n(self, message,
- plural=None,
- n=None,
-
- id=None,
- domain=None,
- source=None,
- target=None,
- comment=None
- ):
- """This is just a stub at this time.
-
- plural = the plural form of the message
- n = a sized argument to distinguish between single and plural forms
-
- id = msgid in the translation catalog
- domain = translation domain
- source = source lang
- target = a specific target lang
- comment = a comment to the translation team
-
- See the following for some ideas
- http://www.zope.org/DevHome/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport
-
- Other notes:
- - There is no need to replicate the i18n:name attribute from plone / PTL,
- as cheetah placeholders serve the same purpose
-
-
- """
-
- return message
-
- def getFileContents(self, path):
- """A hook for getting the contents of a file. The default
- implementation just uses the Python open() function to load local files.
- This method could be reimplemented to allow reading of remote files via
- various protocols, as PHP allows with its 'URL fopen wrapper'
- """
-
- fp = open(path,'r')
- output = fp.read()
- fp.close()
- return output
-
- def runAsMainProgram(self):
- """Allows the Template to function as a standalone command-line program
- for static page generation.
-
- Type 'python yourtemplate.py --help to see what it's capabable of.
- """
-
- from TemplateCmdLineIface import CmdLineIface
- CmdLineIface(templateObj=self).run()
-
- ##################################################
- ## internal methods -- not to be called by end-users
-
- def _initCheetahInstance(self,
- searchList=None,
- namespaces=None,
- filter='RawOrEncodedUnicode', # which filter from Cheetah.Filters
- filtersLib=Filters,
- errorCatcher=None,
- _globalSetVars=None,
- _preBuiltSearchList=None):
- """Sets up the instance attributes that cheetah templates use at
- run-time.
-
- This is automatically called by the __init__ method of compiled
- templates.
-
- Note that the names of instance attributes used by Cheetah are prefixed
- with '_CHEETAH__' (2 underscores), where class attributes are prefixed
- with '_CHEETAH_' (1 underscore).
- """
- if getattr(self, '_CHEETAH__instanceInitialized', False):
- return
-
- if namespaces is not None:
- assert searchList is None, (
- 'Provide "namespaces" or "searchList", not both!')
- searchList = namespaces
- if searchList is not None and not isinstance(searchList, (list, tuple)):
- searchList = [searchList]
-
- self._CHEETAH__globalSetVars = {}
- if _globalSetVars is not None:
- # this is intended to be used internally by Nested Templates in #include's
- self._CHEETAH__globalSetVars = _globalSetVars
-
- if _preBuiltSearchList is not None:
- # happens with nested Template obj creation from #include's
- self._CHEETAH__searchList = list(_preBuiltSearchList)
- self._CHEETAH__searchList.append(self)
- else:
- # create our own searchList
- self._CHEETAH__searchList = [self._CHEETAH__globalSetVars]
- if searchList is not None:
- self._CHEETAH__searchList.extend(list(searchList))
- self._CHEETAH__searchList.append( self )
- self._CHEETAH__cheetahIncludes = {}
- self._CHEETAH__cacheRegions = {}
- self._CHEETAH__indenter = Indenter()
- self._CHEETAH__filtersLib = filtersLib
- self._CHEETAH__filters = {}
- if type(filter) in StringTypes:
- filterName = filter
- klass = getattr(self._CHEETAH__filtersLib, filterName)
- else:
- klass = filter
- filterName = klass.__name__
- self._CHEETAH__currentFilter = self._CHEETAH__filters[filterName] = klass(self).filter
- self._CHEETAH__initialFilter = self._CHEETAH__currentFilter
- self._CHEETAH__errorCatchers = {}
- if errorCatcher:
- if type(errorCatcher) in StringTypes:
- errorCatcherClass = getattr(ErrorCatchers, errorCatcher)
- elif type(errorCatcher) == ClassType:
- errorCatcherClass = errorCatcher
-
- self._CHEETAH__errorCatcher = ec = errorCatcherClass(self)
- self._CHEETAH__errorCatchers[errorCatcher.__class__.__name__] = ec
-
- else:
- self._CHEETAH__errorCatcher = None
- self._CHEETAH__initErrorCatcher = self._CHEETAH__errorCatcher
-
- if not hasattr(self, 'transaction'):
- self.transaction = None
- self._CHEETAH__instanceInitialized = True
- self._CHEETAH__isBuffering = False
- self._CHEETAH__isControlledByWebKit = False
-
- self._CHEETAH__cacheStore = None
- if self._CHEETAH_cacheStore is not None:
- self._CHEETAH__cacheStore = self._CHEETAH_cacheStore
-
- def _compile(self, source=None, file=None, compilerSettings=Unspecified,
- moduleName=None, mainMethodName=None):
- """Compile the template. This method is automatically called by
- Template.__init__ it is provided with 'file' or 'source' args.
-
- USERS SHOULD *NEVER* CALL THIS METHOD THEMSELVES. Use Template.compile
- instead.
- """
- if compilerSettings is Unspecified:
- compilerSettings = self._getCompilerSettings(source, file) or {}
- mainMethodName = mainMethodName or self._CHEETAH_defaultMainMethodName
- self._fileMtime = None
- self._fileDirName = None
- self._fileBaseName = None
- if file and type(file) in StringTypes:
- file = self.serverSidePath(file)
- self._fileMtime = os.path.getmtime(file)
- self._fileDirName, self._fileBaseName = os.path.split(file)
- self._filePath = file
- templateClass = self.compile(source, file,
- moduleName=moduleName,
- mainMethodName=mainMethodName,
- compilerSettings=compilerSettings,
- keepRefToGeneratedCode=True)
- self.__class__ = templateClass
- # must initialize it so instance attributes are accessible
- templateClass.__init__(self,
- #_globalSetVars=self._CHEETAH__globalSetVars,
- #_preBuiltSearchList=self._CHEETAH__searchList
- )
- if not hasattr(self, 'transaction'):
- self.transaction = None
-
- def _handleCheetahInclude(self, srcArg, trans=None, includeFrom='file', raw=False):
- """Called at runtime to handle #include directives.
- """
- _includeID = srcArg
- if not self._CHEETAH__cheetahIncludes.has_key(_includeID):
- if not raw:
- if includeFrom == 'file':
- source = None
- if type(srcArg) in StringTypes:
- if hasattr(self, 'serverSidePath'):
- file = path = self.serverSidePath(srcArg)
- else:
- file = path = os.path.normpath(srcArg)
- else:
- file = srcArg ## a file-like object
- else:
- source = srcArg
- file = None
- # @@TR: might want to provide some syntax for specifying the
- # Template class to be used for compilation so compilerSettings
- # can be changed.
- compiler = self._getTemplateAPIClassForIncludeDirectiveCompilation(source, file)
- nestedTemplateClass = compiler.compile(source=source,file=file)
- nestedTemplate = nestedTemplateClass(_preBuiltSearchList=self.searchList(),
- _globalSetVars=self._CHEETAH__globalSetVars)
- self._CHEETAH__cheetahIncludes[_includeID] = nestedTemplate
- else:
- if includeFrom == 'file':
- path = self.serverSidePath(srcArg)
- self._CHEETAH__cheetahIncludes[_includeID] = self.getFileContents(path)
- else:
- self._CHEETAH__cheetahIncludes[_includeID] = srcArg
- ##
- if not raw:
- self._CHEETAH__cheetahIncludes[_includeID].respond(trans)
- else:
- trans.response().write(self._CHEETAH__cheetahIncludes[_includeID])
-
- def _getTemplateAPIClassForIncludeDirectiveCompilation(self, source, file):
- """Returns the subclass of Template which should be used to compile
- #include directives.
-
- This abstraction allows different compiler settings to be used in the
- included template than were used in the parent.
- """
- if issubclass(self.__class__, Template):
- return self.__class__
- else:
- return Template
-
- ## functions for using templates as CGI scripts
- def webInput(self, names, namesMulti=(), default='', src='f',
- defaultInt=0, defaultFloat=0.00, badInt=0, badFloat=0.00, debug=False):
- """Method for importing web transaction variables in bulk.
-
- This works for GET/POST fields both in Webware servlets and in CGI
- scripts, and for cookies and session variables in Webware servlets. If
- you try to read a cookie or session variable in a CGI script, you'll get
- a RuntimeError. 'In a CGI script' here means 'not running as a Webware
- servlet'. If the CGI environment is not properly set up, Cheetah will
- act like there's no input.
-
- The public method provided is:
-
- def webInput(self, names, namesMulti=(), default='', src='f',
- defaultInt=0, defaultFloat=0.00, badInt=0, badFloat=0.00, debug=False):
-
- This method places the specified GET/POST fields, cookies or session
- variables into a dictionary, which is both returned and put at the
- beginning of the searchList. It handles:
-
- * single vs multiple values
- * conversion to integer or float for specified names
- * default values/exceptions for missing or bad values
- * printing a snapshot of all values retrieved for debugging
-
- All the 'default*' and 'bad*' arguments have 'use or raise' behavior,
- meaning that if they're a subclass of Exception, they're raised. If
- they're anything else, that value is substituted for the missing/bad
- value.
-
-
- The simplest usage is:
-
- #silent $webInput(['choice'])
- $choice
-
- dic = self.webInput(['choice'])
- write(dic['choice'])
-
- Both these examples retrieves the GET/POST field 'choice' and print it.
- If you leave off the'#silent', all the values would be printed too. But
- a better way to preview the values is
-
- #silent $webInput(['name'], $debug=1)
-
- because this pretty-prints all the values inside HTML <PRE> tags.
-
- ** KLUDGE: 'debug' is supposed to insert into the template output, but it
- wasn't working so I changed it to a'print' statement. So the debugging
- output will appear wherever standard output is pointed, whether at the
- terminal, in a Webware log file, or whatever. ***
-
- Since we didn't specify any coversions, the value is a string. It's a
- 'single' value because we specified it in 'names' rather than
- 'namesMulti'. Single values work like this:
-
- * If one value is found, take it.
- * If several values are found, choose one arbitrarily and ignore the rest.
- * If no values are found, use or raise the appropriate 'default*' value.
-
- Multi values work like this:
- * If one value is found, put it in a list.
- * If several values are found, leave them in a list.
- * If no values are found, use the empty list ([]). The 'default*'
- arguments are *not* consulted in this case.
-
- Example: assume 'days' came from a set of checkboxes or a multiple combo
- box on a form, and the user chose'Monday', 'Tuesday' and 'Thursday'.
-
- #silent $webInput([], ['days'])
- The days you chose are: #slurp
- #for $day in $days
- $day #slurp
- #end for
-
- dic = self.webInput([], ['days'])
- write('The days you chose are: ')
- for day in dic['days']:
- write(day + ' ')
-
- Both these examples print: 'The days you chose are: Monday Tuesday Thursday'.
-
- By default, missing strings are replaced by '' and missing/bad numbers
- by zero. (A'bad number' means the converter raised an exception for
- it, usually because of non-numeric characters in the value.) This
- mimics Perl/PHP behavior, and simplifies coding for many applications
- where missing/bad values *should* be blank/zero. In those relatively
- few cases where you must distinguish between empty-string/zero on the
- one hand and missing/bad on the other, change the appropriate
- 'default*' and 'bad*' arguments to something like:
-
- * None
- * another constant value
- * $NonNumericInputError/self.NonNumericInputError
- * $ValueError/ValueError
-
- (NonNumericInputError is defined in this class and is useful for
- distinguishing between bad input vs a TypeError/ValueError thrown for
- some other rason.)
-
- Here's an example using multiple values to schedule newspaper
- deliveries. 'checkboxes' comes from a form with checkboxes for all the
- days of the week. The days the user previously chose are preselected.
- The user checks/unchecks boxes as desired and presses Submit. The value
- of 'checkboxes' is a list of checkboxes that were checked when Submit
- was pressed. Our task now is to turn on the days the user checked, turn
- off the days he unchecked, and leave on or off the days he didn't
- change.
-
- dic = self.webInput([], ['dayCheckboxes'])
- wantedDays = dic['dayCheckboxes'] # The days the user checked.
- for day, on in self.getAllValues():
- if not on and wantedDays.has_key(day):
- self.TurnOn(day)
- # ... Set a flag or insert a database record ...
- elif on and not wantedDays.has_key(day):
- self.TurnOff(day)
- # ... Unset a flag or delete a database record ...
-
- 'source' allows you to look up the variables from a number of different
- sources:
- 'f' fields (CGI GET/POST parameters)
- 'c' cookies
- 's' session variables
- 'v' 'values', meaning fields or cookies
-
- In many forms, you're dealing only with strings, which is why the
- 'default' argument is third and the numeric arguments are banished to
- the end. But sometimes you want automatic number conversion, so that
- you can do numeric comparisions in your templates without having to
- write a bunch of conversion/exception handling code. Example:
-
- #silent $webInput(['name', 'height:int'])
- $name is $height cm tall.
- #if $height >= 300
- Wow, you're tall!
- #else
- Pshaw, you're short.
- #end if
-
- dic = self.webInput(['name', 'height:int'])
- name = dic[name]
- height = dic[height]
- write('%s is %s cm tall.' % (name, height))
- if height > 300:
- write('Wow, you're tall!')
- else:
- write('Pshaw, you're short.')
-
- To convert a value to a number, suffix ':int' or ':float' to the name.
- The method will search first for a 'height:int' variable and then for a
- 'height' variable. (It will be called 'height' in the final
- dictionary.) If a numeric conversion fails, use or raise 'badInt' or
- 'badFloat'. Missing values work the same way as for strings, except the
- default is 'defaultInt' or 'defaultFloat' instead of 'default'.
-
- If a name represents an uploaded file, the entire file will be read into
- memory. For more sophistocated file-upload handling, leave that name
- out of the list and do your own handling, or wait for
- Cheetah.Utils.UploadFileMixin.
-
- This only in a subclass that also inherits from Webware's Servlet or
- HTTPServlet. Otherwise you'll get an AttributeError on 'self.request'.
-
- EXCEPTIONS: ValueError if 'source' is not one of the stated characters.
- TypeError if a conversion suffix is not ':int' or ':float'.
-
- FUTURE EXPANSION: a future version of this method may allow source
- cascading; e.g., 'vs' would look first in 'values' and then in session
- variables.
-
- Meta-Data
- ================================================================================
- Author: Mike Orr <iron@mso.oz.net>
- License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
- Version: $Revision: 1.181 $
- Start Date: 2002/03/17
- Last Revision Date: $Date: 2006/06/22 20:25:16 $
- """
- src = src.lower()
- isCgi = not self._CHEETAH__isControlledByWebKit
- if isCgi and src in ('f', 'v'):
- global _formUsedByWebInput
- if _formUsedByWebInput is None:
- _formUsedByWebInput = cgi.FieldStorage()
- source, func = 'field', _formUsedByWebInput.getvalue
- elif isCgi and src == 'c':
- raise RuntimeError("can't get cookies from a CGI script")
- elif isCgi and src == 's':
- raise RuntimeError("can't get session variables from a CGI script")
- elif isCgi and src == 'v':
- source, func = 'value', self.request().value
- elif isCgi and src == 's':
- source, func = 'session', self.request().session().value
- elif src == 'f':
- source, func = 'field', self.request().field
- elif src == 'c':
- source, func = 'cookie', self.request().cookie
- elif src == 'v':
- source, func = 'value', self.request().value
- elif src == 's':
- source, func = 'session', self.request().session().value
- else:
- raise TypeError("arg 'src' invalid")
- sources = source + 's'
- converters = {
- '' : _Converter('string', None, default, default ),
- 'int' : _Converter('int', int, defaultInt, badInt ),
- 'float': _Converter('float', float, defaultFloat, badFloat), }
- #pprint.pprint(locals()); return {}
- dic = {} # Destination.
- for name in names:
- k, v = _lookup(name, func, False, converters)
- dic[k] = v
- for name in namesMulti:
- k, v = _lookup(name, func, True, converters)
- dic[k] = v
- # At this point, 'dic' contains all the keys/values we want to keep.
- # We could split the method into a superclass
- # method for Webware/WebwareExperimental and a subclass for Cheetah.
- # The superclass would merely 'return dic'. The subclass would
- # 'dic = super(ThisClass, self).webInput(names, namesMulti, ...)'
- # and then the code below.
- if debug:
- print "<PRE>\n" + pprint.pformat(dic) + "\n</PRE>\n\n"
- self.searchList().insert(0, dic)
- return dic
-
-T = Template # Short and sweet for debugging at the >>> prompt.
-
-
-def genParserErrorFromPythonException(source, file, generatedPyCode, exception):
-
- #print dir(exception)
-
- filename = isinstance(file, (str, unicode)) and file or None
-
- sio = StringIO.StringIO()
- traceback.print_exc(1, sio)
- formatedExc = sio.getvalue()
-
- if hasattr(exception, 'lineno'):
- pyLineno = exception.lineno
- else:
- pyLineno = int(re.search('[ \t]*File.*line (\d+)', formatedExc).group(1))
-
- lines = generatedPyCode.splitlines()
-
- prevLines = [] # (i, content)
- for i in range(1,4):
- if pyLineno-i <=0:
- break
- prevLines.append( (pyLineno+1-i,lines[pyLineno-i]) )
-
- nextLines = [] # (i, content)
- for i in range(1,4):
- if not pyLineno+i < len(lines):
- break
- nextLines.append( (pyLineno+i,lines[pyLineno+i]) )
- nextLines.reverse()
- report = 'Line|Python Code\n'
- report += '----|-------------------------------------------------------------\n'
- while prevLines:
- lineInfo = prevLines.pop()
- report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
-
- if hasattr(exception, 'offset'):
- report += ' '*(3+exception.offset) + '^\n'
-
- while nextLines:
- lineInfo = nextLines.pop()
- report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
-
-
- message = [
- "Error in the Python code which Cheetah generated for this template:",
- '='*80,
- '',
- str(exception),
- '',
- report,
- '='*80,
- ]
- cheetahPosMatch = re.search('line (\d+), col (\d+)', formatedExc)
- if cheetahPosMatch:
- lineno = int(cheetahPosMatch.group(1))
- col = int(cheetahPosMatch.group(2))
- #if hasattr(exception, 'offset'):
- # col = exception.offset
- message.append('\nHere is the corresponding Cheetah code:\n')
- else:
- lineno = None
- col = None
- cheetahPosMatch = re.search('line (\d+), col (\d+)',
- '\n'.join(lines[max(pyLineno-2, 0):]))
- if cheetahPosMatch:
- lineno = int(cheetahPosMatch.group(1))
- col = int(cheetahPosMatch.group(2))
- message.append('\nHere is the corresponding Cheetah code.')
- message.append('** I had to guess the line & column numbers,'
- ' so they are probably incorrect:\n')
-
-
- message = '\n'.join(message)
- reader = SourceReader(source, filename=filename)
- return ParseError(reader, message, lineno=lineno,col=col)
-
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/TemplateCmdLineIface.py b/cobbler/Cheetah/TemplateCmdLineIface.py
deleted file mode 100644
index abd8ae2..0000000
--- a/cobbler/Cheetah/TemplateCmdLineIface.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-# $Id: TemplateCmdLineIface.py,v 1.13 2006/01/10 20:34:35 tavis_rudd Exp $
-
-"""Provides a command line interface to compiled Cheetah template modules.
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.13 $
-Start Date: 2001/12/06
-Last Revision Date: $Date: 2006/01/10 20:34:35 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.13 $"[11:-2]
-
-import sys
-import os
-import getopt
-import os.path
-try:
- from cPickle import load
-except ImportError:
- from pickle import load
-
-from Cheetah.Version import Version
-
-class Error(Exception):
- pass
-
-class CmdLineIface:
- """A command line interface to compiled Cheetah template modules."""
-
- def __init__(self, templateObj,
- scriptName=os.path.basename(sys.argv[0]),
- cmdLineArgs=sys.argv[1:]):
-
- self._template = templateObj
- self._scriptName = scriptName
- self._cmdLineArgs = cmdLineArgs
-
- def run(self):
- """The main program controller."""
-
- self._processCmdLineArgs()
- print self._template
-
- def _processCmdLineArgs(self):
- try:
- self._opts, self._args = getopt.getopt(
- self._cmdLineArgs, 'h', ['help',
- 'env',
- 'pickle=',
- ])
-
- except getopt.GetoptError, v:
- # print help information and exit:
- print v
- print self.usage()
- sys.exit(2)
-
- for o, a in self._opts:
- if o in ('-h','--help'):
- print self.usage()
- sys.exit()
- if o == '--env':
- self._template.searchList().insert(0, os.environ)
- if o == '--pickle':
- if a == '-':
- unpickled = load(sys.stdin)
- self._template.searchList().insert(0, unpickled)
- else:
- f = open(a)
- unpickled = load(f)
- f.close()
- self._template.searchList().insert(0, unpickled)
-
- def usage(self):
- return """Cheetah %(Version)s template module command-line interface
-
-Usage
------
- %(scriptName)s [OPTION]
-
-Options
--------
- -h, --help Print this help information
-
- --env Use shell ENVIRONMENT variables to fill the
- $placeholders in the template.
-
- --pickle <file> Use a variables from a dictionary stored in Python
- pickle file to fill $placeholders in the template.
- If <file> is - stdin is used:
- '%(scriptName)s --pickle -'
-
-Description
------------
-
-This interface allows you to execute a Cheetah template from the command line
-and collect the output. It can prepend the shell ENVIRONMENT or a pickled
-Python dictionary to the template's $placeholder searchList, overriding the
-defaults for the $placeholders.
-
-""" % {'scriptName':self._scriptName,
- 'Version':Version,
- }
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/Templates/SkeletonPage.py b/cobbler/Cheetah/Templates/SkeletonPage.py
deleted file mode 100644
index 0049d17..0000000
--- a/cobbler/Cheetah/Templates/SkeletonPage.py
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/usr/bin/env python
-
-
-"""A Skeleton HTML page template, that provides basic structure and utility methods.
-"""
-
-
-##################################################
-## DEPENDENCIES
-import sys
-import os
-import os.path
-from os.path import getmtime, exists
-import time
-import types
-import __builtin__
-from Cheetah.Version import MinCompatibleVersion as RequiredCheetahVersion
-from Cheetah.Version import MinCompatibleVersionTuple as RequiredCheetahVersionTuple
-from Cheetah.Template import Template
-from Cheetah.DummyTransaction import DummyTransaction
-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.Templates._SkeletonPage import _SkeletonPage
-
-##################################################
-## MODULE CONSTANTS
-try:
- True, False
-except NameError:
- True, False = (1==1), (1==0)
-VFFSL=valueFromFrameOrSearchList
-VFSL=valueFromSearchList
-VFN=valueForName
-currentTime=time.time
-__CHEETAH_version__ = '2.0rc6'
-__CHEETAH_versionTuple__ = (2, 0, 0, 'candidate', 6)
-__CHEETAH_genTime__ = 1139107954.3640411
-__CHEETAH_genTimestamp__ = 'Sat Feb 4 18:52:34 2006'
-__CHEETAH_src__ = 'src/Templates/SkeletonPage.tmpl'
-__CHEETAH_srcLastModified__ = 'Mon Oct 7 11:37:30 2002'
-__CHEETAH_docstring__ = 'Autogenerated by CHEETAH: The Python-Powered Template Engine'
-
-if __CHEETAH_versionTuple__ < RequiredCheetahVersionTuple:
- raise AssertionError(
- 'This template was compiled with Cheetah version'
- ' %s. Templates compiled before version %s must be recompiled.'%(
- __CHEETAH_version__, RequiredCheetahVersion))
-
-##################################################
-## CLASSES
-
-class SkeletonPage(_SkeletonPage):
-
- ##################################################
- ## CHEETAH GENERATED METHODS
-
-
- def __init__(self, *args, **KWs):
-
- _SkeletonPage.__init__(self, *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)
-
-
- def writeHeadTag(self, **KWS):
-
-
-
- ## CHEETAH: generated from #block writeHeadTag at line 22, col 1.
- trans = KWS.get("trans")
- if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
- trans = self.transaction # is None unless self.awake() was called
- if not trans:
- trans = DummyTransaction()
- _dummyTrans = True
- else: _dummyTrans = False
- write = trans.response().write
- SL = self._CHEETAH__searchList
- _filter = self._CHEETAH__currentFilter
-
- ########################################
- ## START - generated method body
-
- write('<head>\n<title>')
- _v = VFFSL(SL,"title",True) # '$title' on line 24, col 8
- if _v is not None: write(_filter(_v, rawExpr='$title')) # from line 24, col 8.
- write('</title>\n')
- _v = VFFSL(SL,"metaTags",True) # '$metaTags' on line 25, col 1
- if _v is not None: write(_filter(_v, rawExpr='$metaTags')) # from line 25, col 1.
- write(' \n')
- _v = VFFSL(SL,"stylesheetTags",True) # '$stylesheetTags' on line 26, col 1
- if _v is not None: write(_filter(_v, rawExpr='$stylesheetTags')) # from line 26, col 1.
- write(' \n')
- _v = VFFSL(SL,"javascriptTags",True) # '$javascriptTags' on line 27, col 1
- if _v is not None: write(_filter(_v, rawExpr='$javascriptTags')) # from line 27, col 1.
- write('\n</head>\n')
-
- ########################################
- ## END - generated method body
-
- return _dummyTrans and trans.response().getvalue() or ""
-
-
- def writeBody(self, **KWS):
-
-
-
- ## CHEETAH: generated from #block writeBody at line 36, col 1.
- trans = KWS.get("trans")
- if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
- trans = self.transaction # is None unless self.awake() was called
- if not trans:
- trans = DummyTransaction()
- _dummyTrans = True
- else: _dummyTrans = False
- write = trans.response().write
- SL = self._CHEETAH__searchList
- _filter = self._CHEETAH__currentFilter
-
- ########################################
- ## START - generated method body
-
- write('This skeleton page has no flesh. Its body needs to be implemented.\n')
-
- ########################################
- ## END - generated method body
-
- return _dummyTrans and trans.response().getvalue() or ""
-
-
- def respond(self, trans=None):
-
-
-
- ## CHEETAH: main method generated for this template
- if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
- trans = self.transaction # is None unless self.awake() was called
- if not trans:
- trans = DummyTransaction()
- _dummyTrans = True
- else: _dummyTrans = False
- write = trans.response().write
- SL = self._CHEETAH__searchList
- _filter = self._CHEETAH__currentFilter
-
- ########################################
- ## START - generated method body
-
-
- ## START CACHE REGION: ID=header. line 6, col 1 in the source.
- _RECACHE_header = False
- _cacheRegion_header = self.getCacheRegion(regionID='header', cacheInfo={'type': 2, 'id': 'header'})
- if _cacheRegion_header.isNew():
- _RECACHE_header = True
- _cacheItem_header = _cacheRegion_header.getCacheItem('header')
- if _cacheItem_header.hasExpired():
- _RECACHE_header = True
- if (not _RECACHE_header) and _cacheItem_header.getRefreshTime():
- try:
- _output = _cacheItem_header.renderOutput()
- except KeyError:
- _RECACHE_header = True
- else:
- write(_output)
- del _output
- if _RECACHE_header or not _cacheItem_header.getRefreshTime():
- _orig_transheader = trans
- trans = _cacheCollector_header = DummyTransaction()
- write = _cacheCollector_header.response().write
- _v = VFFSL(SL,"docType",True) # '$docType' on line 7, col 1
- if _v is not None: write(_filter(_v, rawExpr='$docType')) # from line 7, col 1.
- write('\n')
- _v = VFFSL(SL,"htmlTag",True) # '$htmlTag' on line 8, col 1
- if _v is not None: write(_filter(_v, rawExpr='$htmlTag')) # from line 8, col 1.
- write('''
-<!-- This document was autogenerated by Cheetah(http://CheetahTemplate.org).
-Do not edit it directly!
-
-Copyright ''')
- _v = VFFSL(SL,"currentYr",True) # '$currentYr' on line 12, col 11
- if _v is not None: write(_filter(_v, rawExpr='$currentYr')) # from line 12, col 11.
- write(' - ')
- _v = VFFSL(SL,"siteCopyrightName",True) # '$siteCopyrightName' on line 12, col 24
- if _v is not None: write(_filter(_v, rawExpr='$siteCopyrightName')) # from line 12, col 24.
- write(' - All Rights Reserved.\nFeel free to copy any javascript or html you like on this site,\nprovided you remove all links and/or references to ')
- _v = VFFSL(SL,"siteDomainName",True) # '$siteDomainName' on line 14, col 52
- if _v is not None: write(_filter(_v, rawExpr='$siteDomainName')) # from line 14, col 52.
- write('''
-However, please do not copy any content or images without permission.
-
-''')
- _v = VFFSL(SL,"siteCredits",True) # '$siteCredits' on line 17, col 1
- if _v is not None: write(_filter(_v, rawExpr='$siteCredits')) # from line 17, col 1.
- write('''
-
--->
-
-
-''')
- self.writeHeadTag(trans=trans)
- write('\n')
- trans = _orig_transheader
- write = trans.response().write
- _cacheData = _cacheCollector_header.response().getvalue()
- _cacheItem_header.setData(_cacheData)
- write(_cacheData)
- del _cacheData
- del _cacheCollector_header
- del _orig_transheader
- ## END CACHE REGION: header
-
- write('\n')
- _v = VFFSL(SL,"bodyTag",True) # '$bodyTag' on line 34, col 1
- if _v is not None: write(_filter(_v, rawExpr='$bodyTag')) # from line 34, col 1.
- write('\n\n')
- self.writeBody(trans=trans)
- write('''
-</body>
-</html>
-
-
-
-''')
-
- ########################################
- ## END - generated method body
-
- return _dummyTrans and trans.response().getvalue() or ""
-
- ##################################################
- ## CHEETAH GENERATED ATTRIBUTES
-
-
- _CHEETAH__instanceInitialized = False
-
- _CHEETAH_version = __CHEETAH_version__
-
- _CHEETAH_versionTuple = __CHEETAH_versionTuple__
-
- _CHEETAH_genTime = __CHEETAH_genTime__
-
- _CHEETAH_genTimestamp = __CHEETAH_genTimestamp__
-
- _CHEETAH_src = __CHEETAH_src__
-
- _CHEETAH_srcLastModified = __CHEETAH_srcLastModified__
-
- _mainCheetahMethod_for_SkeletonPage= 'respond'
-
-## END CLASS DEFINITION
-
-if not hasattr(SkeletonPage, '_initCheetahAttributes'):
- templateAPIClass = getattr(SkeletonPage, '_CHEETAH_templateClass', Template)
- templateAPIClass._addCheetahPlumbingCodeToClass(SkeletonPage)
-
-
-# CHEETAH was developed by Tavis Rudd and Mike Orr
-# with code, advice and input from many other volunteers.
-# For more information visit http://www.CheetahTemplate.org/
-
-##################################################
-## if run from command line:
-if __name__ == '__main__':
- from Cheetah.TemplateCmdLineIface import CmdLineIface
- CmdLineIface(templateObj=SkeletonPage()).run()
-
-
diff --git a/cobbler/Cheetah/Templates/SkeletonPage.tmpl b/cobbler/Cheetah/Templates/SkeletonPage.tmpl
deleted file mode 100644
index 43c5ecd..0000000
--- a/cobbler/Cheetah/Templates/SkeletonPage.tmpl
+++ /dev/null
@@ -1,44 +0,0 @@
-##doc-module: A Skeleton HTML page template, that provides basic structure and utility methods.
-################################################################################
-#extends Cheetah.Templates._SkeletonPage
-#implements respond
-################################################################################
-#cache id='header'
-$docType
-$htmlTag
-<!-- This document was autogenerated by Cheetah(http://CheetahTemplate.org).
-Do not edit it directly!
-
-Copyright $currentYr - $siteCopyrightName - All Rights Reserved.
-Feel free to copy any javascript or html you like on this site,
-provided you remove all links and/or references to $siteDomainName
-However, please do not copy any content or images without permission.
-
-$siteCredits
-
--->
-
-
-#block writeHeadTag
-<head>
-<title>$title</title>
-$metaTags
-$stylesheetTags
-$javascriptTags
-</head>
-#end block writeHeadTag
-
-#end cache header
-#################
-
-$bodyTag
-
-#block writeBody
-This skeleton page has no flesh. Its body needs to be implemented.
-#end block writeBody
-
-</body>
-</html>
-
-
-
diff --git a/cobbler/Cheetah/Templates/_SkeletonPage.py b/cobbler/Cheetah/Templates/_SkeletonPage.py
deleted file mode 100644
index bf10e30..0000000
--- a/cobbler/Cheetah/Templates/_SkeletonPage.py
+++ /dev/null
@@ -1,216 +0,0 @@
-#!/usr/bin/env python
-# $Id: _SkeletonPage.py,v 1.13 2002/10/01 17:52:02 tavis_rudd Exp $
-"""A baseclass for the SkeletonPage template
-
-Meta-Data
-==========
-Author: Tavis Rudd <tavis@damnsimple.com>,
-Version: $Revision: 1.13 $
-Start Date: 2001/04/05
-Last Revision Date: $Date: 2002/10/01 17:52:02 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.13 $"[11:-2]
-
-##################################################
-## DEPENDENCIES ##
-
-import time, types, os, sys
-
-# intra-package imports ...
-from Cheetah.Template import Template
-
-
-##################################################
-## GLOBALS AND CONSTANTS ##
-
-True = (1==1)
-False = (0==1)
-
-##################################################
-## CLASSES ##
-
-class _SkeletonPage(Template):
- """A baseclass for the SkeletonPage template"""
-
- docType = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ' + \
- '"http://www.w3.org/TR/html4/loose.dtd">'
-
- # docType = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' + \
- #'"http://www.w3.org/TR/xhtml1l/DTD/transitional.dtd">'
-
- title = ''
- siteDomainName = 'www.example.com'
- siteCredits = 'Designed & Implemented by Tavis Rudd'
- siteCopyrightName = "Tavis Rudd"
- htmlTag = '<html>'
-
- def __init__(self, *args, **KWs):
- Template.__init__(self, *args, **KWs)
- self._metaTags = {'HTTP-EQUIV':{'keywords':'Cheetah',
- 'Content-Type':'text/html; charset=iso-8859-1',
- },
- 'NAME':{'generator':'Cheetah: The Python-Powered Template Engine'}
- }
- # metaTags = {'HTTP_EQUIV':{'test':1234}, 'NAME':{'test':1234,'test2':1234} }
- self._stylesheets = {}
- # stylesheets = {'.cssClassName':'stylesheetCode'}
- self._stylesheetsOrder = []
- # stylesheetsOrder = ['.cssClassName',]
- self._stylesheetLibs = {}
- # stylesheetLibs = {'libName':'libSrcPath'}
- self._javascriptLibs = {}
- self._javascriptTags = {}
- # self._javascriptLibs = {'libName':'libSrcPath'}
- self._bodyTagAttribs = {}
-
- def metaTags(self):
- """Return a formatted vesion of the self._metaTags dictionary, using the
- formatMetaTags function from Cheetah.Macros.HTML"""
-
- return self.formatMetaTags(self._metaTags)
-
- def stylesheetTags(self):
- """Return a formatted version of the self._stylesheetLibs and
- self._stylesheets dictionaries. The keys in self._stylesheets must
- be listed in the order that they should appear in the list
- self._stylesheetsOrder, to ensure that the style rules are defined in
- the correct order."""
-
- stylesheetTagsTxt = ''
- for title, src in self._stylesheetLibs.items():
- stylesheetTagsTxt += '<link rel="stylesheet" type="text/css" href="' + str(src) + '" />\n'
-
- if not self._stylesheetsOrder:
- return stylesheetTagsTxt
-
- stylesheetTagsTxt += '<style type="text/css"><!--\n'
- for identifier in self._stylesheetsOrder:
- if not self._stylesheets.has_key(identifier):
- warning = '# the identifier ' + identifier + \
- 'was in stylesheetsOrder, but not in stylesheets'
- print warning
- stylesheetTagsTxt += warning
- continue
-
- attribsDict = self._stylesheets[identifier]
- cssCode = ''
- attribCode = ''
- for k, v in attribsDict.items():
- attribCode += str(k) + ': ' + str(v) + '; '
- attribCode = attribCode[:-2] # get rid of the last semicolon
-
- cssCode = '\n' + identifier + ' {' + attribCode + '}'
- stylesheetTagsTxt += cssCode
-
- stylesheetTagsTxt += '\n//--></style>\n'
-
- return stylesheetTagsTxt
-
- def javascriptTags(self):
- """Return a formatted version of the javascriptTags and
- javascriptLibs dictionaries. Each value in javascriptTags
- should be a either a code string to include, or a list containing the
- JavaScript version number and the code string. The keys can be anything.
- The same applies for javascriptLibs, but the string should be the
- SRC filename rather than a code string."""
-
- javascriptTagsTxt = []
- for key, details in self._javascriptTags.items():
- if type(details) not in (types.ListType, types.TupleType):
- details = ['',details]
-
- javascriptTagsTxt += ['<script language="JavaScript', str(details[0]),
- '" type="text/javascript"><!--\n',
- str(details[0]), '\n//--></script>\n']
-
-
- for key, details in self._javascriptLibs.items():
- if type(details) not in (types.ListType, types.TupleType):
- details = ['',details]
-
- javascriptTagsTxt += ['<script language="JavaScript', str(details[0]),
- '" type="text/javascript" src="',
- str(details[1]), '" />\n']
- return ''.join(javascriptTagsTxt)
-
- def bodyTag(self):
- """Create a body tag from the entries in the dict bodyTagAttribs."""
- return self.formHTMLTag('body', self._bodyTagAttribs)
-
-
- def imgTag(self, src, alt='', width=None, height=None, border=0):
-
- """Dynamically generate an image tag. Cheetah will try to convert the
- src argument to a WebKit serverSidePath relative to the servlet's
- location. If width and height aren't specified they are calculated using
- PIL or ImageMagick if available."""
-
- src = self.normalizePath(src)
-
-
- if not width or not height:
- try: # see if the dimensions can be calc'd with PIL
- import Image
- im = Image.open(src)
- calcWidth, calcHeight = im.size
- del im
- if not width: width = calcWidth
- if not height: height = calcHeight
-
- except:
- try: # try imageMagick instead
- calcWidth, calcHeight = os.popen(
- 'identify -format "%w,%h" ' + src).read().split(',')
- if not width: width = calcWidth
- if not height: height = calcHeight
-
- except:
- pass
-
- if width and height:
- return ''.join(['<img src="', src, '" width="', str(width), '" height="', str(height),
- '" alt="', alt, '" border="', str(border), '" />'])
- elif width:
- return ''.join(['<img src="', src, '" width="', str(width),
- '" alt="', alt, '" border="', str(border), '" />'])
- elif height:
- return ''.join(['<img src="', src, '" height="', str(height),
- '" alt="', alt, '" border="', str(border), '" />'])
- else:
- return ''.join(['<img src="', src, '" alt="', alt, '" border="', str(border),'" />'])
-
-
- def currentYr(self):
- """Return a string representing the current yr."""
- return time.strftime("%Y",time.localtime(time.time()))
-
- def currentDate(self, formatString="%b %d, %Y"):
- """Return a string representing the current localtime."""
- return time.strftime(formatString,time.localtime(time.time()))
-
- def spacer(self, width=1,height=1):
- return '<img src="spacer.gif" width="%s" height="%s" alt="" />'% (str(width), str(height))
-
- def formHTMLTag(self, tagName, attributes={}):
- """returns a string containing an HTML <tag> """
- tagTxt = ['<', tagName.lower()]
- for name, val in attributes.items():
- tagTxt += [' ', name.lower(), '="', str(val),'"']
- tagTxt.append('>')
- return ''.join(tagTxt)
-
- def formatMetaTags(self, metaTags):
- """format a dict of metaTag definitions into an HTML version"""
- metaTagsTxt = []
- if metaTags.has_key('HTTP-EQUIV'):
- for http_equiv, contents in metaTags['HTTP-EQUIV'].items():
- metaTagsTxt += ['<meta http-equiv="', str(http_equiv), '" content="',
- str(contents), '" />\n']
-
- if metaTags.has_key('NAME'):
- for name, contents in metaTags['NAME'].items():
- metaTagsTxt += ['<meta name="', str(name), '" content="', str(contents),
- '" />\n']
- return ''.join(metaTagsTxt)
-
diff --git a/cobbler/Cheetah/Templates/__init__.py b/cobbler/Cheetah/Templates/__init__.py
deleted file mode 100644
index 4265cc3..0000000
--- a/cobbler/Cheetah/Templates/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#!/usr/bin/env python
diff --git a/cobbler/Cheetah/Tests/CheetahWrapper.py b/cobbler/Cheetah/Tests/CheetahWrapper.py
deleted file mode 100644
index 316c43b..0000000
--- a/cobbler/Cheetah/Tests/CheetahWrapper.py
+++ /dev/null
@@ -1,596 +0,0 @@
-#!/usr/bin/env python
-# $Id: CheetahWrapper.py,v 1.5 2006/01/07 07:18:44 tavis_rudd Exp $
-"""Tests for the 'cheetah' command.
-
-Besides unittest usage, recognizes the following command-line options:
- --list CheetahWrapper.py
- List all scenarios that are tested. The argument is the path
- of this script.
- --nodelete
- Don't delete scratch directory at end.
- --output
- Show the output of each subcommand. (Normally suppressed.)
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@mso.oz.net>,
-Version: $Revision: 1.5 $
-Start Date: 2001/10/01
-Last Revision Date: $Date: 2006/01/07 07:18:44 $
-"""
-__author__ = "Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.5 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import commands, os, shutil, sys, tempfile
-import unittest_local_copy as unittest
-
-import re # Used by listTests.
-from Cheetah.CheetahWrapper import CheetahWrapper # Used by NoBackup.
-from Cheetah.Utils.optik import OptionParser # Used by main.
-
-##################################################
-## CONSTANTS & GLOBALS ##
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-DELETE = True # True to clean up after ourselves, False for debugging.
-OUTPUT = False # Normally False, True for debugging.
-
-#DELETE = False # True to clean up after ourselves, False for debugging.
-#OUTPUT = True # Normally False, True for debugging.
-
-BACKUP_SUFFIX = CheetahWrapper.BACKUP_SUFFIX
-
-def warn(msg):
- sys.stderr.write(msg + '\n')
-
-##################################################
-## TEST BASE CLASSES
-
-class CFBase(unittest.TestCase):
- """Base class for "cheetah compile" and "cheetah fill" unit tests.
- """
- srcDir = '' # Nonblank to create source directory.
- subdirs = ('child', 'child/grandkid') # Delete in reverse order.
- srcFiles = ('a.tmpl', 'child/a.tmpl', 'child/grandkid/a.tmpl')
- expectError = False # Used by --list option.
-
- def inform(self, message):
- if self.verbose:
- print message
-
- def setUp(self):
- """Create the top-level directories, subdirectories and .tmpl
- files.
- """
- I = self.inform
- # Step 1: Create the scratch directory and chdir into it.
- self.scratchDir = scratchDir = tempfile.mktemp()
- os.mkdir(scratchDir)
- self.origCwd = os.getcwd()
- os.chdir(scratchDir)
- if self.srcDir:
- os.mkdir(self.srcDir)
- # Step 2: Create source subdirectories.
- for dir in self.subdirs:
- os.mkdir(dir)
- # Step 3: Create the .tmpl files, each in its proper directory.
- for fil in self.srcFiles:
- f = open(fil, 'w')
- f.write("Hello, world!\n")
- f.close()
-
-
- def tearDown(self):
- os.chdir(self.origCwd)
- if DELETE:
- shutil.rmtree(self.scratchDir, True) # Ignore errors.
- if os.path.exists(self.scratchDir):
- warn("Warning: unable to delete scratch directory %s")
- else:
- warn("Warning: not deleting scratch directory %s" % self.scratchDir)
-
-
- def _checkDestFileHelper(self, path, expected,
- allowSurroundingText, errmsg):
- """Low-level helper to check a destination file.
-
- in : path, string, the destination path.
- expected, string, the expected contents.
- allowSurroundingtext, bool, allow the result to contain
- additional text around the 'expected' substring?
- errmsg, string, the error message. It may contain the
- following "%"-operator keys: path, expected, result.
- out: None
- """
- path = os.path.abspath(path)
- exists = os.path.exists(path)
- msg = "destination file missing: %s" % path
- self.failUnless(exists, msg)
- f = open(path, 'r')
- result = f.read()
- f.close()
- if allowSurroundingText:
- success = result.find(expected) != -1
- else:
- success = result == expected
- msg = errmsg % locals()
- self.failUnless(success, msg)
-
-
- def checkCompile(self, path):
- # Raw string to prevent "\n" from being converted to a newline.
- #expected = R"write('Hello, world!\n')"
- expected = R"'Hello, world!\n')" # might output a u'' string
- errmsg = """\
-destination file %(path)s doesn't contain expected substring:
-%(expected)r"""
- self._checkDestFileHelper(path, expected, True, errmsg)
-
-
- def checkFill(self, path):
- expected = "Hello, world!\n"
- errmsg = """\
-destination file %(path)s contains wrong result.
-Expected %(expected)r
-Found %(result)r"""
- self._checkDestFileHelper(path, expected, False, errmsg)
-
-
- def checkSubdirPyInit(self, path):
- """Verify a destination subdirectory exists and contains an
- __init__.py file.
- """
- exists = os.path.exists(path)
- msg = "destination subdirectory %s misssing" % path
- self.failUnless(exists, msg)
- initPath = os.path.join(path, "__init__.py")
- exists = os.path.exists(initPath)
- msg = "destination init file missing: %s" % initPath
- self.failUnless(exists, msg)
-
-
- def checkNoBackup(self, path):
- """Verify 'path' does not exist. (To check --nobackup.)
- """
- exists = os.path.exists(path)
- msg = "backup file exists in spite of --nobackup: %s" % path
- self.failIf(exists, msg)
-
-
- def go(self, cmd, expectedStatus=0, expectedOutputSubstring=None):
- """Run a "cheetah compile" or "cheetah fill" subcommand.
-
- in : cmd, string, the command to run.
- expectedStatus, int, subcommand's expected output status.
- 0 if the subcommand is expected to succeed, 1-255 otherwise.
- expectedOutputSubstring, string, substring which much appear
- in the standard output or standard error. None to skip this
- test.
- out: None.
- """
- # Use commands.getstatusoutput instead of os.system so
- # that we can mimic ">/dev/null 2>/dev/null" even on
- # non-Unix platforms.
- exit, output = commands.getstatusoutput(cmd)
- status, signal = divmod(exit, 256)
- if OUTPUT:
- if output.endswith("\n"):
- output = output[:-1]
- print
- print "SUBCOMMAND:", cmd
- print output
- print
- msg = "subcommand killed by signal %d: %s" % (signal, cmd)
- self.failUnlessEqual(signal, 0, msg)
- msg = "subcommand exit status %d: %s" % (status, cmd)
- if status!=expectedStatus:
- print output
- self.failUnlessEqual(status, expectedStatus, msg)
- if expectedOutputSubstring is not None:
- msg = "substring %r not found in subcommand output: %s" % \
- (expectedOutputSubstring, cmd)
- substringTest = output.find(expectedOutputSubstring) != -1
- self.failUnless(substringTest, msg)
-
-
- def goExpectError(self, cmd):
- """Run a subcommand and expect it to fail.
-
- in : cmd, string, the command to run.
- out: None.
- """
- # Use commands.getstatusoutput instead of os.system so
- # that we can mimic ">/dev/null 2>/dev/null" even on
- # non-Unix platforms.
- exit, output = commands.getstatusoutput(cmd)
- status, signal = divmod(exit, 256)
- msg = "subcommand killed by signal %s: %s" % (signal, cmd)
- self.failUnlessEqual(signal, 0, msg) # Signal must be 0.
- msg = "subcommand exit status %s: %s" % (status, cmd)
- self.failIfEqual(status, 0, msg) # Status must *not* be 0.
- if OUTPUT:
- if output.endswith("\n"):
- output = output[:-1]
- print
- print "SUBCOMMAND:", cmd
- print output
- print
-
-
-class CFIdirBase(CFBase):
- """Subclass for tests with --idir.
- """
- srcDir = 'SRC'
- subdirs = ('SRC/child', 'SRC/child/grandkid') # Delete in reverse order.
- srcFiles = ('SRC/a.tmpl', 'SRC/child/a.tmpl', 'SRC/child/grandkid/a.tmpl')
-
-
-
-##################################################
-## TEST CASE CLASSES
-
-class OneFile(CFBase):
- def testCompile(self):
- self.go("cheetah compile a.tmpl")
- self.checkCompile("a.py")
-
- def testFill(self):
- self.go("cheetah fill a.tmpl")
- self.checkFill("a.html")
-
- def testText(self):
- self.go("cheetah fill --oext txt a.tmpl")
- self.checkFill("a.txt")
-
-
-class OneFileNoExtension(CFBase):
- def testCompile(self):
- self.go("cheetah compile a")
- self.checkCompile("a.py")
-
- def testFill(self):
- self.go("cheetah fill a")
- self.checkFill("a.html")
-
- def testText(self):
- self.go("cheetah fill --oext txt a")
- self.checkFill("a.txt")
-
-
-class SplatTmpl(CFBase):
- def testCompile(self):
- self.go("cheetah compile *.tmpl")
- self.checkCompile("a.py")
-
- def testFill(self):
- self.go("cheetah fill *.tmpl")
- self.checkFill("a.html")
-
- def testText(self):
- self.go("cheetah fill --oext txt *.tmpl")
- self.checkFill("a.txt")
-
-class ThreeFilesWithSubdirectories(CFBase):
- def testCompile(self):
- self.go("cheetah compile a.tmpl child/a.tmpl child/grandkid/a.tmpl")
- self.checkCompile("a.py")
- self.checkCompile("child/a.py")
- self.checkCompile("child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill a.tmpl child/a.tmpl child/grandkid/a.tmpl")
- self.checkFill("a.html")
- self.checkFill("child/a.html")
- self.checkFill("child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill --oext txt a.tmpl child/a.tmpl child/grandkid/a.tmpl")
- self.checkFill("a.txt")
- self.checkFill("child/a.txt")
- self.checkFill("child/grandkid/a.txt")
-
-
-class ThreeFilesWithSubdirectoriesNoExtension(CFBase):
- def testCompile(self):
- self.go("cheetah compile a child/a child/grandkid/a")
- self.checkCompile("a.py")
- self.checkCompile("child/a.py")
- self.checkCompile("child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill a child/a child/grandkid/a")
- self.checkFill("a.html")
- self.checkFill("child/a.html")
- self.checkFill("child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill --oext txt a child/a child/grandkid/a")
- self.checkFill("a.txt")
- self.checkFill("child/a.txt")
- self.checkFill("child/grandkid/a.txt")
-
-
-class SplatTmplWithSubdirectories(CFBase):
- def testCompile(self):
- self.go("cheetah compile *.tmpl child/*.tmpl child/grandkid/*.tmpl")
- self.checkCompile("a.py")
- self.checkCompile("child/a.py")
- self.checkCompile("child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill *.tmpl child/*.tmpl child/grandkid/*.tmpl")
- self.checkFill("a.html")
- self.checkFill("child/a.html")
- self.checkFill("child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill --oext txt *.tmpl child/*.tmpl child/grandkid/*.tmpl")
- self.checkFill("a.txt")
- self.checkFill("child/a.txt")
- self.checkFill("child/grandkid/a.txt")
-
-
-class OneFileWithOdir(CFBase):
- def testCompile(self):
- self.go("cheetah compile --odir DEST a.tmpl")
- self.checkSubdirPyInit("DEST")
- self.checkCompile("DEST/a.py")
-
- def testFill(self):
- self.go("cheetah fill --odir DEST a.tmpl")
- self.checkFill("DEST/a.html")
-
- def testText(self):
- self.go("cheetah fill --odir DEST --oext txt a.tmpl")
- self.checkFill("DEST/a.txt")
-
-
-class VarietyWithOdir(CFBase):
- def testCompile(self):
- self.go("cheetah compile --odir DEST a.tmpl child/a child/grandkid/*.tmpl")
- self.checkSubdirPyInit("DEST")
- self.checkSubdirPyInit("DEST/child")
- self.checkSubdirPyInit("DEST/child/grandkid")
- self.checkCompile("DEST/a.py")
- self.checkCompile("DEST/child/a.py")
- self.checkCompile("DEST/child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill --odir DEST a.tmpl child/a child/grandkid/*.tmpl")
- self.checkFill("DEST/a.html")
- self.checkFill("DEST/child/a.html")
- self.checkFill("DEST/child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill --odir DEST --oext txt a.tmpl child/a child/grandkid/*.tmpl")
- self.checkFill("DEST/a.txt")
- self.checkFill("DEST/child/a.txt")
- self.checkFill("DEST/child/grandkid/a.txt")
-
-
-class RecurseExplicit(CFBase):
- def testCompile(self):
- self.go("cheetah compile -R child")
- self.checkCompile("child/a.py")
- self.checkCompile("child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill -R child")
- self.checkFill("child/a.html")
- self.checkFill("child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill -R --oext txt child")
- self.checkFill("child/a.txt")
- self.checkFill("child/grandkid/a.txt")
-
-
-class RecurseImplicit(CFBase):
- def testCompile(self):
- self.go("cheetah compile -R")
- self.checkCompile("child/a.py")
- self.checkCompile("child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill -R")
- self.checkFill("a.html")
- self.checkFill("child/a.html")
- self.checkFill("child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill -R --oext txt")
- self.checkFill("a.txt")
- self.checkFill("child/a.txt")
- self.checkFill("child/grandkid/a.txt")
-
-
-class RecurseExplicitWIthOdir(CFBase):
- def testCompile(self):
- self.go("cheetah compile -R --odir DEST child")
- self.checkSubdirPyInit("DEST/child")
- self.checkSubdirPyInit("DEST/child/grandkid")
- self.checkCompile("DEST/child/a.py")
- self.checkCompile("DEST/child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill -R --odir DEST child")
- self.checkFill("DEST/child/a.html")
- self.checkFill("DEST/child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill -R --odir DEST --oext txt child")
- self.checkFill("DEST/child/a.txt")
- self.checkFill("DEST/child/grandkid/a.txt")
-
-
-class Flat(CFBase):
- def testCompile(self):
- self.go("cheetah compile --flat child/a.tmpl")
- self.checkCompile("a.py")
-
- def testFill(self):
- self.go("cheetah fill --flat child/a.tmpl")
- self.checkFill("a.html")
-
- def testText(self):
- self.go("cheetah fill --flat --oext txt child/a.tmpl")
- self.checkFill("a.txt")
-
-
-class FlatRecurseCollision(CFBase):
- expectError = True
-
- def testCompile(self):
- self.goExpectError("cheetah compile -R --flat")
-
- def testFill(self):
- self.goExpectError("cheetah fill -R --flat")
-
- def testText(self):
- self.goExpectError("cheetah fill -R --flat")
-
-
-class IdirRecurse(CFIdirBase):
- def testCompile(self):
- self.go("cheetah compile -R --idir SRC child")
- self.checkSubdirPyInit("child")
- self.checkSubdirPyInit("child/grandkid")
- self.checkCompile("child/a.py")
- self.checkCompile("child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill -R --idir SRC child")
- self.checkFill("child/a.html")
- self.checkFill("child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill -R --idir SRC --oext txt child")
- self.checkFill("child/a.txt")
- self.checkFill("child/grandkid/a.txt")
-
-
-class IdirOdirRecurse(CFIdirBase):
- def testCompile(self):
- self.go("cheetah compile -R --idir SRC --odir DEST child")
- self.checkSubdirPyInit("DEST/child")
- self.checkSubdirPyInit("DEST/child/grandkid")
- self.checkCompile("DEST/child/a.py")
- self.checkCompile("DEST/child/grandkid/a.py")
-
- def testFill(self):
- self.go("cheetah fill -R --idir SRC --odir DEST child")
- self.checkFill("DEST/child/a.html")
- self.checkFill("DEST/child/grandkid/a.html")
-
- def testText(self):
- self.go("cheetah fill -R --idir SRC --odir DEST --oext txt child")
- self.checkFill("DEST/child/a.txt")
- self.checkFill("DEST/child/grandkid/a.txt")
-
-
-class IdirFlatRecurseCollision(CFIdirBase):
- expectError = True
-
- def testCompile(self):
- self.goExpectError("cheetah compile -R --flat --idir SRC")
-
- def testFill(self):
- self.goExpectError("cheetah fill -R --flat --idir SRC")
-
- def testText(self):
- self.goExpectError("cheetah fill -R --flat --idir SRC --oext txt")
-
-
-class NoBackup(CFBase):
- """Run the command twice each time and verify a backup file is
- *not* created.
- """
- def testCompile(self):
- self.go("cheetah compile --nobackup a.tmpl")
- self.go("cheetah compile --nobackup a.tmpl")
- self.checkNoBackup("a.py" + BACKUP_SUFFIX)
-
- def testFill(self):
- self.go("cheetah fill --nobackup a.tmpl")
- self.go("cheetah fill --nobackup a.tmpl")
- self.checkNoBackup("a.html" + BACKUP_SUFFIX)
-
- def testText(self):
- self.go("cheetah fill --nobackup --oext txt a.tmpl")
- self.go("cheetah fill --nobackup --oext txt a.tmpl")
- self.checkNoBackup("a.txt" + BACKUP_SUFFIX)
-
-
-
-
-
-##################################################
-## LIST TESTS ##
-
-def listTests(cheetahWrapperFile):
- """cheetahWrapperFile, string, path of this script.
-
- XXX TODO: don't print test where expectError is true.
- """
- rx = re.compile( R'self\.go\("(.*?)"\)' )
- f = open(cheetahWrapperFile)
- while 1:
- lin = f.readline()
- if not lin:
- break
- m = rx.search(lin)
- if m:
- print m.group(1)
- f.close()
-
-##################################################
-## MAIN ROUTINE ##
-
-class MyOptionParser(OptionParser):
- """Disable the standard --help and --verbose options since
- --help is used for another purpose.
- """
- standard_option_list = []
-
-def main():
- global DELETE, OUTPUT
- parser = MyOptionParser()
- parser.add_option("--list", action="store", dest="listTests")
- parser.add_option("--nodelete", action="store_true")
- parser.add_option("--output", action="store_true")
- # The following options are passed to unittest.
- parser.add_option("-e", "--explain", action="store_true")
- parser.add_option("-h", "--help", action="store_true")
- parser.add_option("-v", "--verbose", action="store_true")
- parser.add_option("-q", "--quiet", action="store_true")
- opts, files = parser.parse_args()
- if opts.nodelete:
- DELETE = False
- if opts.output:
- OUTPUT = True
- if opts.listTests:
- listTests(opts.listTests)
- else:
- # Eliminate script-specific command-line arguments to prevent
- # errors in unittest.
- del sys.argv[1:]
- for opt in ("explain", "help", "verbose", "quiet"):
- if getattr(opts, opt):
- sys.argv.append("--" + opt)
- sys.argv.extend(files)
- unittest.main()
-
-##################################################
-## if run from the command line ##
-
-if __name__ == '__main__': main()
-
-# vim: sw=4 ts=4 expandtab
diff --git a/cobbler/Cheetah/Tests/FileRefresh.py b/cobbler/Cheetah/Tests/FileRefresh.py
deleted file mode 100644
index 4beb3e7..0000000
--- a/cobbler/Cheetah/Tests/FileRefresh.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python
-# $Id: FileRefresh.py,v 1.6 2002/10/01 17:52:03 tavis_rudd Exp $
-"""Tests to make sure that the file-update-monitoring code is working properly
-
-THIS TEST MODULE IS JUST A SHELL AT THE MOMENT. Feel like filling it in??
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>,
-Version: $Revision: 1.6 $
-Start Date: 2001/10/01
-Last Revision Date: $Date: 2002/10/01 17:52:03 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.6 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import sys
-import types
-import os
-import os.path
-
-
-import unittest_local_copy as unittest
-from Cheetah.Template import Template
-
-##################################################
-## CONSTANTS & GLOBALS ##
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-##################################################
-## TEST DATA FOR USE IN THE TEMPLATES ##
-
-##################################################
-## TEST BASE CLASSES
-
-class TemplateTest(unittest.TestCase):
- pass
-
-##################################################
-## TEST CASE CLASSES
-
-
-##################################################
-## if run from the command line ##
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/cobbler/Cheetah/Tests/NameMapper.py b/cobbler/Cheetah/Tests/NameMapper.py
deleted file mode 100644
index 2782463..0000000
--- a/cobbler/Cheetah/Tests/NameMapper.py
+++ /dev/null
@@ -1,539 +0,0 @@
-#!/usr/bin/env python
-# $Id: NameMapper.py,v 1.11 2006/01/15 20:45:22 tavis_rudd Exp $
-"""NameMapper Tests
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>,
-Version: $Revision: 1.11 $
-Start Date: 2001/10/01
-Last Revision Date: $Date: 2006/01/15 20:45:22 $
-"""
-from __future__ import generators
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.11 $"[11:-2]
-import sys
-import types
-import os
-import os.path
-
-import unittest_local_copy as unittest
-from Cheetah.NameMapper import NotFound, valueForKey, \
- valueForName, valueFromSearchList, valueFromFrame, valueFromFrameOrSearchList
-
-
-##################################################
-## TEST DATA FOR USE IN THE TEMPLATES ##
-
-class DummyClass:
- classVar1 = 123
-
- def __init__(self):
- self.instanceVar1 = 123
-
- def __str__(self):
- return 'object'
-
- def meth(self, arg="arff"):
- return str(arg)
-
- def meth1(self, arg="doo"):
- return arg
-
- def meth2(self, arg1="a1", arg2="a2"):
- raise ValueError
-
- def meth3(self):
- """Tests a bug that Jeff Johnson reported on Oct 1, 2001"""
-
- x = 'A string'
- try:
- for i in [1,2,3,4]:
- if x == 2:
- pass
-
- if x == 'xx':
- pass
- return x
- except:
- raise
-
-
-def dummyFunc(arg="Scooby"):
- return arg
-
-def funcThatRaises():
- raise ValueError
-
-
-testNamespace = {
- 'aStr':'blarg',
- 'anInt':1,
- 'aFloat':1.5,
- 'aDict': {'one':'item1',
- 'two':'item2',
- 'nestedDict':{'one':'nestedItem1',
- 'two':'nestedItem2',
- 'funcThatRaises':funcThatRaises,
- 'aClass': DummyClass,
- },
- 'nestedFunc':dummyFunc,
- },
- 'aClass': DummyClass,
- 'aFunc': dummyFunc,
- 'anObj': DummyClass(),
- 'aMeth': DummyClass().meth1,
- 'none' : None,
- 'emptyString':'',
- 'funcThatRaises':funcThatRaises,
- }
-
-autoCallResults = {'aFunc':'Scooby',
- 'aMeth':'doo',
- }
-
-results = testNamespace.copy()
-results.update({'anObj.meth1':'doo',
- 'aDict.one':'item1',
- 'aDict.nestedDict':testNamespace['aDict']['nestedDict'],
- 'aDict.nestedDict.one':'nestedItem1',
- 'aDict.nestedDict.aClass':DummyClass,
- 'aDict.nestedFunc':'Scooby',
- 'aClass.classVar1':123,
- 'anObj.instanceVar1':123,
- 'anObj.meth3':'A string',
- })
-
-for k in testNamespace.keys():
- # put them in the globals for the valueFromFrame tests
- exec '%s = testNamespace[k]'%k
-
-##################################################
-## TEST BASE CLASSES
-
-class NameMapperTest(unittest.TestCase):
- failureException = (NotFound,AssertionError)
- _testNamespace = testNamespace
- _results = results
-
- def namespace(self):
- return self._testNamespace
-
- def VFN(self, name, autocall=True):
- return valueForName(self.namespace(), name, autocall)
-
- def VFS(self, searchList, name, autocall=True):
- return valueFromSearchList(searchList, name, autocall)
-
-
- # alias to be overriden later
- get = VFN
-
- def check(self, name):
- got = self.get(name)
- if autoCallResults.has_key(name):
- expected = autoCallResults[name]
- else:
- expected = self._results[name]
- assert got == expected
-
-
-##################################################
-## TEST CASE CLASSES
-
-class VFN(NameMapperTest):
-
- def test1(self):
- """string in dict lookup"""
- self.check('aStr')
-
- def test2(self):
- """string in dict lookup in a loop"""
- for i in range(10):
- self.check('aStr')
-
- def test3(self):
- """int in dict lookup"""
- self.check('anInt')
-
- def test4(self):
- """int in dict lookup in a loop"""
- for i in range(10):
- self.check('anInt')
-
- def test5(self):
- """float in dict lookup"""
- self.check('aFloat')
-
- def test6(self):
- """float in dict lookup in a loop"""
- for i in range(10):
- self.check('aFloat')
-
- def test7(self):
- """class in dict lookup"""
- self.check('aClass')
-
- def test8(self):
- """class in dict lookup in a loop"""
- for i in range(10):
- self.check('aClass')
-
- def test9(self):
- """aFunc in dict lookup"""
- self.check('aFunc')
-
- def test10(self):
- """aFunc in dict lookup in a loop"""
- for i in range(10):
- self.check('aFunc')
-
- def test11(self):
- """aMeth in dict lookup"""
- self.check('aMeth')
-
- def test12(self):
- """aMeth in dict lookup in a loop"""
- for i in range(10):
- self.check('aMeth')
-
- def test13(self):
- """aMeth in dict lookup"""
- self.check('aMeth')
-
- def test14(self):
- """aMeth in dict lookup in a loop"""
- for i in range(10):
- self.check('aMeth')
-
- def test15(self):
- """anObj in dict lookup"""
- self.check('anObj')
-
- def test16(self):
- """anObj in dict lookup in a loop"""
- for i in range(10):
- self.check('anObj')
-
- def test17(self):
- """aDict in dict lookup"""
- self.check('aDict')
-
- def test18(self):
- """aDict in dict lookup in a loop"""
- for i in range(10):
- self.check('aDict')
-
- def test17(self):
- """aDict in dict lookup"""
- self.check('aDict')
-
- def test18(self):
- """aDict in dict lookup in a loop"""
- for i in range(10):
- self.check('aDict')
-
- def test19(self):
- """aClass.classVar1 in dict lookup"""
- self.check('aClass.classVar1')
-
- def test20(self):
- """aClass.classVar1 in dict lookup in a loop"""
- for i in range(10):
- self.check('aClass.classVar1')
-
-
- def test23(self):
- """anObj.instanceVar1 in dict lookup"""
- self.check('anObj.instanceVar1')
-
- def test24(self):
- """anObj.instanceVar1 in dict lookup in a loop"""
- for i in range(10):
- self.check('anObj.instanceVar1')
-
- ## tests 22, 25, and 26 removed when the underscored lookup was removed
-
- def test27(self):
- """anObj.meth1 in dict lookup"""
- self.check('anObj.meth1')
-
- def test28(self):
- """anObj.meth1 in dict lookup in a loop"""
- for i in range(10):
- self.check('anObj.meth1')
-
- def test29(self):
- """aDict.one in dict lookup"""
- self.check('aDict.one')
-
- def test30(self):
- """aDict.one in dict lookup in a loop"""
- for i in range(10):
- self.check('aDict.one')
-
- def test31(self):
- """aDict.nestedDict in dict lookup"""
- self.check('aDict.nestedDict')
-
- def test32(self):
- """aDict.nestedDict in dict lookup in a loop"""
- for i in range(10):
- self.check('aDict.nestedDict')
-
- def test33(self):
- """aDict.nestedDict.one in dict lookup"""
- self.check('aDict.nestedDict.one')
-
- def test34(self):
- """aDict.nestedDict.one in dict lookup in a loop"""
- for i in range(10):
- self.check('aDict.nestedDict.one')
-
- def test35(self):
- """aDict.nestedFunc in dict lookup"""
- self.check('aDict.nestedFunc')
-
- def test36(self):
- """aDict.nestedFunc in dict lookup in a loop"""
- for i in range(10):
- self.check('aDict.nestedFunc')
-
- def test37(self):
- """aDict.nestedFunc in dict lookup - without autocalling"""
- assert self.get('aDict.nestedFunc', False) == dummyFunc
-
- def test38(self):
- """aDict.nestedFunc in dict lookup in a loop - without autocalling"""
- for i in range(10):
- assert self.get('aDict.nestedFunc', False) == dummyFunc
-
- def test39(self):
- """aMeth in dict lookup - without autocalling"""
- assert self.get('aMeth', False) == self.namespace()['aMeth']
-
- def test40(self):
- """aMeth in dict lookup in a loop - without autocalling"""
- for i in range(10):
- assert self.get('aMeth', False) == self.namespace()['aMeth']
-
- def test41(self):
- """anObj.meth3 in dict lookup"""
- self.check('anObj.meth3')
-
- def test42(self):
- """aMeth in dict lookup in a loop"""
- for i in range(10):
- self.check('anObj.meth3')
-
- def test43(self):
- """NotFound test"""
-
- def test(self=self):
- self.get('anObj.methX')
- self.assertRaises(NotFound,test)
-
- def test44(self):
- """NotFound test in a loop"""
- def test(self=self):
- self.get('anObj.methX')
-
- for i in range(10):
- self.assertRaises(NotFound,test)
-
- def test45(self):
- """Other exception from meth test"""
-
- def test(self=self):
- self.get('anObj.meth2')
- self.assertRaises(ValueError, test)
-
- def test46(self):
- """Other exception from meth test in a loop"""
- def test(self=self):
- self.get('anObj.meth2')
-
- for i in range(10):
- self.assertRaises(ValueError,test)
-
- def test47(self):
- """None in dict lookup"""
- self.check('none')
-
- def test48(self):
- """None in dict lookup in a loop"""
- for i in range(10):
- self.check('none')
-
- def test49(self):
- """EmptyString in dict lookup"""
- self.check('emptyString')
-
- def test50(self):
- """EmptyString in dict lookup in a loop"""
- for i in range(10):
- self.check('emptyString')
-
- def test51(self):
- """Other exception from func test"""
-
- def test(self=self):
- self.get('funcThatRaises')
- self.assertRaises(ValueError, test)
-
- def test52(self):
- """Other exception from func test in a loop"""
- def test(self=self):
- self.get('funcThatRaises')
-
- for i in range(10):
- self.assertRaises(ValueError,test)
-
-
- def test53(self):
- """Other exception from func test"""
-
- def test(self=self):
- self.get('aDict.nestedDict.funcThatRaises')
- self.assertRaises(ValueError, test)
-
- def test54(self):
- """Other exception from func test in a loop"""
- def test(self=self):
- self.get('aDict.nestedDict.funcThatRaises')
-
- for i in range(10):
- self.assertRaises(ValueError,test)
-
- def test55(self):
- """aDict.nestedDict.aClass in dict lookup"""
- self.check('aDict.nestedDict.aClass')
-
- def test56(self):
- """aDict.nestedDict.aClass in dict lookup in a loop"""
- for i in range(10):
- self.check('aDict.nestedDict.aClass')
-
- def test57(self):
- """aDict.nestedDict.aClass in dict lookup - without autocalling"""
- assert self.get('aDict.nestedDict.aClass', False) == DummyClass
-
- def test58(self):
- """aDict.nestedDict.aClass in dict lookup in a loop - without autocalling"""
- for i in range(10):
- assert self.get('aDict.nestedDict.aClass', False) == DummyClass
-
- def test59(self):
- """Other exception from func test -- but without autocalling shouldn't raise"""
-
- self.get('aDict.nestedDict.funcThatRaises', False)
-
- def test60(self):
- """Other exception from func test in a loop -- but without autocalling shouldn't raise"""
-
- for i in range(10):
- self.get('aDict.nestedDict.funcThatRaises', False)
-
-class VFS(VFN):
- _searchListLength = 1
-
- def searchList(self):
- lng = self._searchListLength
- if lng == 1:
- return [self.namespace()]
- elif lng == 2:
- return [self.namespace(),{'dummy':1234}]
- elif lng == 3:
- # a tuple for kicks
- return ({'dummy':1234}, self.namespace(),{'dummy':1234})
- elif lng == 4:
- # a generator for more kicks
- return self.searchListGenerator()
-
- def searchListGenerator(self):
- class Test:
- pass
- for i in [Test(),{'dummy':1234}, self.namespace(),{'dummy':1234}]:
- yield i
-
- def get(self, name, autocall=True):
- return self.VFS(self.searchList(), name, autocall)
-
-class VFS_2namespaces(VFS):
- _searchListLength = 2
-
-class VFS_3namespaces(VFS):
- _searchListLength = 3
-
-class VFS_4namespaces(VFS):
- _searchListLength = 4
-
-class VFF(VFN):
- def get(self, name, autocall=True):
- ns = self._testNamespace
- aStr = ns['aStr']
- aFloat = ns['aFloat']
- none = 'some'
- return valueFromFrame(name, autocall)
-
- def setUp(self):
- """Mod some of the data
- """
- self._testNamespace = ns = self._testNamespace.copy()
- self._results = res = self._results.copy()
- ns['aStr'] = res['aStr'] = 'BLARG'
- ns['aFloat'] = res['aFloat'] = 0.1234
- res['none'] = 'some'
- res['True'] = True
- res['False'] = False
- res['None'] = None
- res['eval'] = eval
-
- def test_VFF_1(self):
- """Builtins"""
- self.check('True')
- self.check('None')
- self.check('False')
- assert self.get('eval', False)==eval
- assert self.get('range', False)==range
-
-class VFFSL(VFS):
- _searchListLength = 1
-
- def setUp(self):
- """Mod some of the data
- """
- self._testNamespace = ns = self._testNamespace.copy()
- self._results = res = self._results.copy()
- ns['aStr'] = res['aStr'] = 'BLARG'
- ns['aFloat'] = res['aFloat'] = 0.1234
- res['none'] = 'some'
-
- del ns['anInt'] # will be picked up by globals
-
- def VFFSL(self, searchList, name, autocall=True):
- anInt = 1
- none = 'some'
- return valueFromFrameOrSearchList(searchList, name, autocall)
-
- def get(self, name, autocall=True):
- return self.VFFSL(self.searchList(), name, autocall)
-
-class VFFSL_2(VFFSL):
- _searchListLength = 2
-
-class VFFSL_3(VFFSL):
- _searchListLength = 3
-
-class VFFSL_4(VFFSL):
- _searchListLength = 4
-
-if sys.platform.startswith('java'):
- del VFF, VFFSL, VFFSL_2, VFFSL_3, VFFSL_4
-
-
-##################################################
-## if run from the command line ##
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/cobbler/Cheetah/Tests/SyntaxAndOutput.py b/cobbler/Cheetah/Tests/SyntaxAndOutput.py
deleted file mode 100644
index 09abc4d..0000000
--- a/cobbler/Cheetah/Tests/SyntaxAndOutput.py
+++ /dev/null
@@ -1,3170 +0,0 @@
-#!/usr/bin/env python
-# $Id: SyntaxAndOutput.py,v 1.105 2006/06/21 23:48:19 tavis_rudd Exp $
-"""Syntax and Output tests.
-
-TODO
-- #finally
-- #filter
-- #errorCatcher
-- #echo
-- #silent
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.105 $
-Start Date: 2001/03/30
-Last Revision Date: $Date: 2006/06/21 23:48:19 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.105 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import sys
-import types
-import re
-from copy import deepcopy
-import os
-import os.path
-import new
-import warnings
-
-from Cheetah.NameMapper import NotFound
-from Cheetah.NameMapper import C_VERSION as NameMapper_C_VERSION
-from Cheetah.Template import Template
-from Cheetah.Parser import ParseError
-from Cheetah.Compiler import Compiler, DEFAULT_COMPILER_SETTINGS
-import unittest_local_copy as unittest
-
-class Unspecified: pass
-##################################################
-## CONSTANTS & GLOBALS ##
-
-majorVer, minorVer = sys.version_info[0], sys.version_info[1]
-versionTuple = (majorVer, minorVer)
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-##################################################
-## TEST DATA FOR USE IN THE TEMPLATES ##
-
-def testdecorator(func):
- return func
-
-class DummyClass:
- _called = False
- def __str__(self):
- return 'object'
-
- def meth(self, arg="arff"):
- return str(arg)
-
- def meth1(self, arg="doo"):
- return arg
-
- def meth2(self, arg1="a1", arg2="a2"):
- return str(arg1) + str(arg2)
-
- def methWithPercentSignDefaultArg(self, arg1="110%"):
- return str(arg1)
-
- def callIt(self, arg=1234):
- self._called = True
- self._callArg = arg
-
-
-def dummyFunc(arg="Scooby"):
- return arg
-
-defaultTestNameSpace = {
- 'aStr':'blarg',
- 'anInt':1,
- 'aFloat':1.5,
- 'aList': ['item0','item1','item2'],
- 'aDict': {'one':'item1',
- 'two':'item2',
- 'nestedDict':{1:'nestedItem1',
- 'two':'nestedItem2'
- },
- 'nestedFunc':dummyFunc,
- },
- 'aFunc': dummyFunc,
- 'anObj': DummyClass(),
- 'aMeth': DummyClass().meth1,
- 'aStrToBeIncluded': "$aStr $anInt",
- 'none' : None,
- 'emptyString':'',
- 'numOne':1,
- 'numTwo':2,
- 'zero':0,
- 'tenDigits': 1234567890,
- 'webSafeTest': 'abc <=> &',
- 'strip1': ' \t strippable whitespace \t\t \n',
- 'strip2': ' \t strippable whitespace \t\t ',
- 'strip3': ' \t strippable whitespace \t\t\n1 2 3\n',
-
- 'blockToBeParsed':"""$numOne $numTwo""",
- 'includeBlock2':"""$numOne $numTwo $aSetVar""",
-
- 'includeFileName':'parseTest.txt',
- 'listOfLambdas':[lambda x: x, lambda x: x, lambda x: x,],
- 'list': [
- {'index': 0, 'numOne': 1, 'numTwo': 2},
- {'index': 1, 'numOne': 1, 'numTwo': 2},
- ],
- 'nameList': [('john', 'doe'), ('jane', 'smith')],
- 'letterList': ['a', 'b', 'c'],
- '_': lambda x: 'Translated: ' + x,
- 'unicodeData':u'aoeu12345\u1234',
- }
-
-
-##################################################
-## TEST BASE CLASSES
-
-class OutputTest(unittest.TestCase):
- report = '''
-Template output mismatch:
-
- Input Template =
-%(template)s%(end)s
-
- Expected Output =
-%(expected)s%(end)s
-
- Actual Output =
-%(actual)s%(end)s'''
-
- convertEOLs = True
- _EOLreplacement = None
- _debugEOLReplacement = False
-
- DEBUGLEV = 0
- _searchList = [defaultTestNameSpace]
-
- _useNewStyleCompilation = True
- #_useNewStyleCompilation = False
-
- _extraCompileKwArgs = None
-
- def searchList(self):
- return self._searchList
-
- def verify(self, input, expectedOutput,
- inputEncoding=None,
- outputEncoding=None,
- convertEOLs=Unspecified):
- if self._EOLreplacement:
- if convertEOLs is Unspecified:
- convertEOLs = self.convertEOLs
- if convertEOLs:
- input = input.replace('\n', self._EOLreplacement)
- expectedOutput = expectedOutput.replace('\n', self._EOLreplacement)
-
- self._input = input
- if self._useNewStyleCompilation:
- extraKwArgs = self._extraCompileKwArgs or {}
-
- templateClass = Template.compile(
- source=input,
- compilerSettings=self._getCompilerSettings(),
- keepRefToGeneratedCode=True,
- **extraKwArgs
- )
- moduleCode = templateClass._CHEETAH_generatedModuleCode
- self.template = templateObj = templateClass(searchList=self.searchList())
- else:
- self.template = templateObj = Template(
- input,
- searchList=self.searchList(),
- compilerSettings=self._getCompilerSettings(),
- )
- moduleCode = templateObj._CHEETAH_generatedModuleCode
- if self.DEBUGLEV >= 1:
- print moduleCode
- try:
- try:
- output = templateObj.respond() # rather than __str__, because of unicode
- if outputEncoding:
- output = output.decode(outputEncoding)
- assert output==expectedOutput, self._outputMismatchReport(output, expectedOutput)
- except:
- #print >>sys.stderr, moduleCode
- raise
- finally:
- templateObj.shutdown()
-
- def _getCompilerSettings(self):
- return {}
-
- def _outputMismatchReport(self, output, expectedOutput):
- if self._debugEOLReplacement and self._EOLreplacement:
- EOLrepl = self._EOLreplacement
- marker = '*EOL*'
- return self.report % {'template': self._input.replace(EOLrepl,marker),
- 'expected': expectedOutput.replace(EOLrepl,marker),
- 'actual': output.replace(EOLrepl,marker),
- 'end': '(end)'}
- else:
- return self.report % {'template': self._input,
- 'expected': expectedOutput,
- 'actual': output,
- 'end': '(end)'}
-
- def genClassCode(self):
- if hasattr(self, 'template'):
- return self.template.generatedClassCode()
-
- def genModuleCode(self):
- if hasattr(self, 'template'):
- return self.template.generatedModuleCode()
-
-##################################################
-## TEST CASE CLASSES
-
-class EmptyTemplate(OutputTest):
- convertEOLs = False
- def test1(self):
- """an empty string for the template"""
-
- warnings.filterwarnings('error',
- 'You supplied an empty string for the source!',
- UserWarning)
- try:
- self.verify("", "")
- except UserWarning:
- pass
- else:
- self.fail("Should warn about empty source strings.")
-
- try:
- self.verify("#implements foo", "")
- except NotImplementedError:
- pass
- else:
- self.fail("This should barf about respond() not being implemented.")
-
- self.verify("#implements respond", "")
-
- self.verify("#implements respond(foo=1234)", "")
-
-
-class Backslashes(OutputTest):
- convertEOLs = False
-
- def setUp(self):
- fp = open('backslashes.txt','w')
- fp.write(r'\ #LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n')
- fp.flush()
- fp.close
-
- def tearDown(self):
- if os.path.exists('backslashes.txt'):
- os.remove('backslashes.txt')
-
- def test1(self):
- """ a single \\ using rawstrings"""
- self.verify(r"\ ",
- r"\ ")
-
- def test2(self):
- """ a single \\ using rawstrings and lots of lines"""
- self.verify(r"\ " + "\n\n\n\n\n\n\n\n\n",
- r"\ " + "\n\n\n\n\n\n\n\n\n")
-
- def test3(self):
- """ a single \\ without using rawstrings"""
- self.verify("\ \ ",
- "\ \ ")
-
- def test4(self):
- """ single line from an apache conf file"""
- self.verify(r'#LogFormat "%h %l %u %t \"%r\" %>s %b"',
- r'#LogFormat "%h %l %u %t \"%r\" %>s %b"')
-
- def test5(self):
- """ single line from an apache conf file with many NEWLINES
-
- The NEWLINES are used to make sure that MethodCompiler.commitStrConst()
- is handling long and short strings in the same fashion. It uses
- triple-quotes for strings with lots of \\n in them and repr(theStr) for
- shorter strings with only a few newlines."""
-
- self.verify(r'#LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n',
- r'#LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n')
-
- def test6(self):
- """ test backslash handling in an included file"""
- self.verify(r'#include "backslashes.txt"',
- r'\ #LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n')
-
- def test7(self):
- """ a single \\ without using rawstrings plus many NEWLINES"""
- self.verify("\ \ " + "\n\n\n\n\n\n\n\n\n",
- "\ \ " + "\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
- """
-
- self.verify(r"""#LogFormat '%h %l %u %t \"%r\" %>s %b'""" + '\n\n\n\n\n\n\n',
- r"""#LogFormat '%h %l %u %t \"%r\" %>s %b'""" + '\n\n\n\n\n\n\n')
-
-class NonTokens(OutputTest):
- def test1(self):
- """dollar signs not in Cheetah $vars"""
- self.verify("$ $$ $5 $. $ test",
- "$ $$ $5 $. $ test")
-
- def test2(self):
- """hash not in #directives"""
- self.verify("# \# #5 ",
- "# # #5 ")
-
- def test3(self):
- """escapted comments"""
- self.verify(" \##escaped comment ",
- " ##escaped comment ")
-
- def test4(self):
- """escapted multi-line comments"""
- self.verify(" \#*escaped comment \n*# ",
- " #*escaped comment \n*# ")
-
- def test5(self):
- """1 dollar sign"""
- self.verify("$",
- "$")
- def _X_test6(self):
- """1 dollar sign followed by hash"""
- self.verify("\n$#\n",
- "\n$#\n")
-
- def test6(self):
- """1 dollar sign followed by EOL Slurp Token"""
- if DEFAULT_COMPILER_SETTINGS['EOLSlurpToken']:
- self.verify("\n$%s\n"%DEFAULT_COMPILER_SETTINGS['EOLSlurpToken'],
- "\n$")
- else:
- self.verify("\n$#\n",
- "\n$#\n")
-
-class Comments_SingleLine(OutputTest):
- def test1(self):
- """## followed by WS"""
- self.verify("## ",
- "")
-
- def test2(self):
- """## followed by NEWLINE"""
- self.verify("##\n",
- "")
-
- def test3(self):
- """## followed by text then NEWLINE"""
- self.verify("## oeuao aoe uaoe \n",
- "")
- def test4(self):
- """## gobbles leading WS"""
- self.verify(" ## oeuao aoe uaoe \n",
- "")
-
- def test5(self):
- """## followed by text then NEWLINE, + leading WS"""
- self.verify(" ## oeuao aoe uaoe \n",
- "")
-
- def test6(self):
- """## followed by EOF"""
- self.verify("##",
- "")
-
- def test7(self):
- """## followed by EOF with leading WS"""
- self.verify(" ##",
- "")
-
- def test8(self):
- """## gobble line
- with text on previous and following lines"""
- self.verify("line1\n ## aoeu 1234 \nline2",
- "line1\nline2")
-
- def test9(self):
- """## don't gobble line
- with text on previous and following lines"""
- self.verify("line1\n 12 ## aoeu 1234 \nline2",
- "line1\n 12 \nline2")
-
- def test10(self):
- """## containing $placeholders
- """
- self.verify("##$a$b $c($d)",
- "")
-
- def test11(self):
- """## containing #for directive
- """
- self.verify("##for $i in range(15)",
- "")
-
-
-class Comments_MultiLine_NoGobble(OutputTest):
- """
- Multiline comments used to not gobble whitespace. They do now, but this can
- be turned off with a compilerSetting
- """
-
- def _getCompilerSettings(self):
- return {'gobbleWhitespaceAroundMultiLineComments':False}
-
- def test1(self):
- """#* *# followed by WS
- Shouldn't gobble WS
- """
- self.verify("#* blarg *# ",
- " ")
-
- def test2(self):
- """#* *# preceded and followed by WS
- Shouldn't gobble WS
- """
- self.verify(" #* blarg *# ",
- " ")
-
- def test3(self):
- """#* *# followed by WS, with NEWLINE
- Shouldn't gobble WS
- """
- self.verify("#* \nblarg\n *# ",
- " ")
-
- def test4(self):
- """#* *# preceded and followed by WS, with NEWLINE
- Shouldn't gobble WS
- """
- self.verify(" #* \nblarg\n *# ",
- " ")
-
-class Comments_MultiLine(OutputTest):
- """
- Note: Multiline comments don't gobble whitespace!
- """
-
- def test1(self):
- """#* *# followed by WS
- Should gobble WS
- """
- self.verify("#* blarg *# ",
- "")
-
- def test2(self):
- """#* *# preceded and followed by WS
- Should gobble WS
- """
- self.verify(" #* blarg *# ",
- "")
-
- def test3(self):
- """#* *# followed by WS, with NEWLINE
- Shouldn't gobble WS
- """
- self.verify("#* \nblarg\n *# ",
- "")
-
- def test4(self):
- """#* *# preceded and followed by WS, with NEWLINE
- Shouldn't gobble WS
- """
- self.verify(" #* \nblarg\n *# ",
- "")
-
- def test5(self):
- """#* *# containing nothing
- """
- self.verify("#**#",
- "")
-
- def test6(self):
- """#* *# containing only NEWLINES
- """
- self.verify(" #*\n\n\n\n\n\n\n\n*# ",
- "")
-
- def test7(self):
- """#* *# containing $placeholders
- """
- self.verify("#* $var $var(1234*$c) *#",
- "")
-
- def test8(self):
- """#* *# containing #for directive
- """
- self.verify("#* #for $i in range(15) *#",
- "")
-
- def test9(self):
- """ text around #* *# containing #for directive
- """
- self.verify("foo\nfoo bar #* #for $i in range(15) *# foo\n",
- "foo\nfoo bar foo\n")
-
- def test9(self):
- """ text around #* *# containing #for directive and trailing whitespace
- which should be gobbled
- """
- self.verify("foo\nfoo bar #* #for $i in range(15) *# \ntest",
- "foo\nfoo bar \ntest")
-
- def test10(self):
- """ text around #* *# containing #for directive and newlines: trailing whitespace
- which should be gobbled.
- """
- self.verify("foo\nfoo bar #* \n\n#for $i in range(15) \n\n*# \ntest",
- "foo\nfoo bar \ntest")
-
-class Placeholders(OutputTest):
- def test1(self):
- """1 placeholder"""
- self.verify("$aStr", "blarg")
-
- def test2(self):
- """2 placeholders"""
- self.verify("$aStr $anInt", "blarg 1")
-
- def test3(self):
- """2 placeholders, back-to-back"""
- self.verify("$aStr$anInt", "blarg1")
-
- def test4(self):
- """1 placeholder enclosed in ()"""
- self.verify("$(aStr)", "blarg")
-
- def test5(self):
- """1 placeholder enclosed in {}"""
- self.verify("${aStr}", "blarg")
-
- def test6(self):
- """1 placeholder enclosed in []"""
- self.verify("$[aStr]", "blarg")
-
- def test7(self):
- """1 placeholder enclosed in () + WS
-
- Test to make sure that $(<WS><identifier>.. matches
- """
- self.verify("$( aStr )", "blarg")
-
- def test8(self):
- """1 placeholder enclosed in {} + WS"""
- self.verify("${ aStr }", "blarg")
-
- def test9(self):
- """1 placeholder enclosed in [] + WS"""
- self.verify("$[ aStr ]", "blarg")
-
- def test10(self):
- """1 placeholder enclosed in () + WS + * cache
-
- Test to make sure that $*(<WS><identifier>.. matches
- """
- self.verify("$*( aStr )", "blarg")
-
- def test11(self):
- """1 placeholder enclosed in {} + WS + *cache"""
- self.verify("$*{ aStr }", "blarg")
-
- def test12(self):
- """1 placeholder enclosed in [] + WS + *cache"""
- self.verify("$*[ aStr ]", "blarg")
-
- def test13(self):
- """1 placeholder enclosed in {} + WS + *<int>*cache"""
- self.verify("$*5*{ aStr }", "blarg")
-
- def test14(self):
- """1 placeholder enclosed in [] + WS + *<int>*cache"""
- self.verify("$*5*[ aStr ]", "blarg")
-
- def test15(self):
- """1 placeholder enclosed in {} + WS + *<float>*cache"""
- self.verify("$*0.5d*{ aStr }", "blarg")
-
- def test16(self):
- """1 placeholder enclosed in [] + WS + *<float>*cache"""
- self.verify("$*.5*[ aStr ]", "blarg")
-
- def test17(self):
- """1 placeholder + *<int>*cache"""
- self.verify("$*5*aStr", "blarg")
-
- def test18(self):
- """1 placeholder *<float>*cache"""
- self.verify("$*0.5h*aStr", "blarg")
-
- def test19(self):
- """1 placeholder surrounded by single quotes and multiple newlines"""
- self.verify("""'\n\n\n\n'$aStr'\n\n\n\n'""",
- """'\n\n\n\n'blarg'\n\n\n\n'""")
-
- def test20(self):
- """silent mode $!placeholders """
- self.verify("$!aStr$!nonExistant$!*nonExistant$!{nonExistant}", "blarg")
-
- try:
- self.verify("$!aStr$nonExistant",
- "blarg")
- except NotFound:
- pass
- else:
- self.fail('should raise NotFound exception')
-
- def test21(self):
- """Make sure that $*caching is actually working"""
- namesStr = 'You Me Them Everyone'
- names = namesStr.split()
-
- tmpl = Template.compile('#for name in $names: $name ', baseclass=dict)
- assert str(tmpl({'names':names})).strip()==namesStr
-
- tmpl = tmpl.subclass('#for name in $names: $*name ')
- assert str(tmpl({'names':names}))=='You '*len(names)
-
- tmpl = tmpl.subclass('#for name in $names: $*1*name ')
- assert str(tmpl({'names':names}))=='You '*len(names)
-
- tmpl = tmpl.subclass('#for name in $names: $*1*(name) ')
- assert str(tmpl({'names':names}))=='You '*len(names)
-
- if versionTuple > (2,2):
- tmpl = tmpl.subclass('#for name in $names: $*1*(name) ')
- assert str(tmpl(names=names))=='You '*len(names)
-
-class Placeholders_Vals(OutputTest):
- convertEOLs = False
- def test1(self):
- """string"""
- self.verify("$aStr", "blarg")
-
- def test2(self):
- """string - with whitespace"""
- self.verify(" $aStr ", " blarg ")
-
- def test3(self):
- """empty string - with whitespace"""
- self.verify("$emptyString", "")
-
- def test4(self):
- """int"""
- self.verify("$anInt", "1")
-
- def test5(self):
- """float"""
- self.verify("$aFloat", "1.5")
-
- def test6(self):
- """list"""
- self.verify("$aList", "['item0', 'item1', 'item2']")
-
- def test7(self):
- """None
-
- The default output filter is ReplaceNone.
- """
- self.verify("$none", "")
-
- def test8(self):
- """True, False
- """
- self.verify("$True $False", "%s %s"%(repr(True), repr(False)))
-
- def test9(self):
- """$_
- """
- self.verify("$_('foo')", "Translated: foo")
-
-class PlaceholderStrings(OutputTest):
- def test1(self):
- """some c'text $placeholder text' strings"""
- self.verify("$str(c'$aStr')", "blarg")
-
- def test2(self):
- """some c'text $placeholder text' strings"""
- self.verify("$str(c'$aStr.upper')", "BLARG")
-
- def test3(self):
- """some c'text $placeholder text' strings"""
- self.verify("$str(c'$(aStr.upper.replace(c\"A$str()\",\"\"))')", "BLRG")
-
- def test4(self):
- """some c'text $placeholder text' strings"""
- self.verify("#echo $str(c'$(aStr.upper)')", "BLARG")
-
- def test5(self):
- """some c'text $placeholder text' strings"""
- self.verify("#if 1 then $str(c'$(aStr.upper)') else 0", "BLARG")
-
- def test6(self):
- """some c'text $placeholder text' strings"""
- self.verify("#if 1\n$str(c'$(aStr.upper)')#slurp\n#else\n0#end if", "BLARG")
-
- def test7(self):
- """some c'text $placeholder text' strings"""
- self.verify("#def foo(arg=c'$(\"BLARG\")')\n"
- "$arg#slurp\n"
- "#end def\n"
- "$foo()$foo(c'$anInt')#slurp",
-
- "BLARG1")
-
-
-
-class UnicodeStrings(OutputTest):
- def test1(self):
- """unicode data in placeholder
- """
- #self.verify(u"$unicodeData", defaultTestNameSpace['unicodeData'], outputEncoding='utf8')
- self.verify(u"$unicodeData", defaultTestNameSpace['unicodeData'])
-
- def test2(self):
- """unicode data in body
- """
- self.verify(u"aoeu12345\u1234", u"aoeu12345\u1234")
- #self.verify(u"#encoding utf8#aoeu12345\u1234", u"aoeu12345\u1234")
-
-class EncodingDirective(OutputTest):
- def test1(self):
- """basic #encoding """
- self.verify("#encoding utf-8\n1234",
- "1234")
-
- def test2(self):
- """basic #encoding """
- self.verify("#encoding ascii\n1234",
- "1234")
-
- def test3(self):
- """basic #encoding """
- self.verify("#encoding utf-8\n\xe1\x88\xb4",
- u'\u1234', outputEncoding='utf8')
-
- def test4(self):
- """basic #encoding """
- self.verify("#encoding ascii\n\xe1\x88\xb4",
- "\xe1\x88\xb4")
-
- def test5(self):
- """basic #encoding """
- self.verify("#encoding latin-1\nAndr\202",
- u'Andr\202', outputEncoding='latin-1')
-
-class Placeholders_Esc(OutputTest):
- convertEOLs = False
- def test1(self):
- """1 escaped placeholder"""
- self.verify("\$var",
- "$var")
-
- def test2(self):
- """2 escaped placeholders"""
- self.verify("\$var \$_",
- "$var $_")
-
- def test3(self):
- """2 escaped placeholders - back to back"""
- self.verify("\$var\$_",
- "$var$_")
-
- def test4(self):
- """2 escaped placeholders - nested"""
- self.verify("\$var(\$_)",
- "$var($_)")
-
- def test5(self):
- """2 escaped placeholders - nested and enclosed"""
- self.verify("\$(var(\$_)",
- "$(var($_)")
-
-
-class Placeholders_Calls(OutputTest):
- def test1(self):
- """func placeholder - no ()"""
- self.verify("$aFunc",
- "Scooby")
-
- def test2(self):
- """func placeholder - with ()"""
- self.verify("$aFunc()",
- "Scooby")
-
- def test3(self):
- r"""func placeholder - with (\n\n)"""
- self.verify("$aFunc(\n\n)",
- "Scooby", convertEOLs=False)
-
- def test4(self):
- r"""func placeholder - with (\n\n) and $() enclosure"""
- self.verify("$(aFunc(\n\n))",
- "Scooby", convertEOLs=False)
-
- def test5(self):
- r"""func placeholder - with (\n\n) and ${} enclosure"""
- self.verify("${aFunc(\n\n)}",
- "Scooby", convertEOLs=False)
-
- def test6(self):
- """func placeholder - with (int)"""
- self.verify("$aFunc(1234)",
- "1234")
-
- def test7(self):
- r"""func placeholder - with (\nint\n)"""
- self.verify("$aFunc(\n1234\n)",
- "1234", convertEOLs=False)
- def test8(self):
- """func placeholder - with (string)"""
- self.verify("$aFunc('aoeu')",
- "aoeu")
-
- def test9(self):
- """func placeholder - with ('''string''')"""
- self.verify("$aFunc('''aoeu''')",
- "aoeu")
- def test10(self):
- r"""func placeholder - with ('''\nstring\n''')"""
- self.verify("$aFunc('''\naoeu\n''')",
- "\naoeu\n")
-
- def test11(self):
- r"""func placeholder - with ('''\nstring'\n''')"""
- self.verify("$aFunc('''\naoeu'\n''')",
- "\naoeu'\n")
-
- def test12(self):
- r'''func placeholder - with ("""\nstring\n""")'''
- self.verify('$aFunc("""\naoeu\n""")',
- "\naoeu\n")
-
- def test13(self):
- """func placeholder - with (string*int)"""
- self.verify("$aFunc('aoeu'*2)",
- "aoeuaoeu")
-
- def test14(self):
- """func placeholder - with (int*int)"""
- self.verify("$aFunc(2*2)",
- "4")
-
- def test15(self):
- """func placeholder - with (int*float)"""
- self.verify("$aFunc(2*2.0)",
- "4.0")
-
- def test16(self):
- r"""func placeholder - with (int\n*\nfloat)"""
- self.verify("$aFunc(2\n*\n2.0)",
- "4.0", convertEOLs=False)
-
- def test17(self):
- """func placeholder - with ($arg=float)"""
- self.verify("$aFunc($arg=4.0)",
- "4.0")
-
- def test18(self):
- """func placeholder - with (arg=float)"""
- self.verify("$aFunc(arg=4.0)",
- "4.0")
-
- def test19(self):
- """deeply nested argstring, no enclosure"""
- self.verify("$aFunc($arg=$aMeth($arg=$aFunc(1)))",
- "1")
-
- def test20(self):
- """deeply nested argstring, no enclosure + with WS"""
- self.verify("$aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) )",
- "1")
- def test21(self):
- """deeply nested argstring, () enclosure + with WS"""
- self.verify("$(aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) ) )",
- "1")
-
- def test22(self):
- """deeply nested argstring, {} enclosure + with WS"""
- self.verify("${aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) ) }",
- "1")
-
- def test23(self):
- """deeply nested argstring, [] enclosure + with WS"""
- self.verify("$[aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) ) ]",
- "1")
-
- def test24(self):
- """deeply nested argstring, () enclosure + *cache"""
- self.verify("$*(aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) ) )",
- "1")
- def test25(self):
- """deeply nested argstring, () enclosure + *15*cache"""
- self.verify("$*15*(aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) ) )",
- "1")
-
- def test26(self):
- """a function call with the Python None kw."""
- self.verify("$aFunc(None)",
- "")
-
-class NameMapper(OutputTest):
- def test1(self):
- """autocalling"""
- self.verify("$aFunc! $aFunc().",
- "Scooby! Scooby.")
-
- def test2(self):
- """nested autocalling"""
- self.verify("$aFunc($aFunc).",
- "Scooby.")
-
- def test3(self):
- """list subscription"""
- self.verify("$aList[0]",
- "item0")
-
- def test4(self):
- """list slicing"""
- self.verify("$aList[:2]",
- "['item0', 'item1']")
-
- def test5(self):
- """list slicing and subcription combined"""
- self.verify("$aList[:2][0]",
- "item0")
-
- def test6(self):
- """dictionary access - NameMapper style"""
- self.verify("$aDict.one",
- "item1")
-
- def test7(self):
- """dictionary access - Python style"""
- self.verify("$aDict['one']",
- "item1")
-
- def test8(self):
- """dictionary access combined with autocalled string method"""
- self.verify("$aDict.one.upper",
- "ITEM1")
-
- def test9(self):
- """dictionary access combined with string method"""
- self.verify("$aDict.one.upper()",
- "ITEM1")
-
- def test10(self):
- """nested dictionary access - NameMapper style"""
- self.verify("$aDict.nestedDict.two",
- "nestedItem2")
-
- def test11(self):
- """nested dictionary access - Python style"""
- self.verify("$aDict['nestedDict']['two']",
- "nestedItem2")
-
- def test12(self):
- """nested dictionary access - alternating style"""
- self.verify("$aDict['nestedDict'].two",
- "nestedItem2")
-
- def test13(self):
- """nested dictionary access using method - alternating style"""
- self.verify("$aDict.get('nestedDict').two",
- "nestedItem2")
-
- def test14(self):
- """nested dictionary access - NameMapper style - followed by method"""
- self.verify("$aDict.nestedDict.two.upper",
- "NESTEDITEM2")
-
- def test15(self):
- """nested dictionary access - alternating style - followed by method"""
- self.verify("$aDict['nestedDict'].two.upper",
- "NESTEDITEM2")
-
- def test16(self):
- """nested dictionary access - NameMapper style - followed by method, then slice"""
- self.verify("$aDict.nestedDict.two.upper[:4]",
- "NEST")
-
- def test17(self):
- """nested dictionary access - Python style using a soft-coded key"""
- self.verify("$aDict[$anObj.meth('nestedDict')].two",
- "nestedItem2")
-
- def test18(self):
- """object method access"""
- self.verify("$anObj.meth1",
- "doo")
-
- def test19(self):
- """object method access, followed by complex slice"""
- self.verify("$anObj.meth1[0: ((4/4*2)*2)/$anObj.meth1(2) ]",
- "do")
-
- def test20(self):
- """object method access, followed by a very complex slice
- If it can pass this one, it's safe to say it works!!"""
- self.verify("$( anObj.meth1[0:\n (\n(4/4*2)*2)/$anObj.meth1(2)\n ] )",
- "do")
-
- def test21(self):
- """object method access with % in the default arg for the meth.
-
- This tests a bug that Jeff Johnson found and submitted a patch to SF
- for."""
-
- self.verify("$anObj.methWithPercentSignDefaultArg",
- "110%")
-
-
-#class NameMapperDict(OutputTest):
-#
-# _searchList = [{"update": "Yabba dabba doo!"}]
-#
-# def test1(self):
-# if NameMapper_C_VERSION:
-# return # This feature is not in the C version yet.
-# self.verify("$update", "Yabba dabba doo!")
-#
-
-class CacheDirective(OutputTest):
-
- def test1(self):
- r"""simple #cache """
- self.verify("#cache:$anInt",
- "1")
-
- def test2(self):
- r"""simple #cache + WS"""
- self.verify(" #cache \n$anInt#end cache",
- "1")
-
- def test3(self):
- r"""simple #cache ... #end cache"""
- self.verify("""#cache id='cache1', timer=150m
-$anInt
-#end cache
-$aStr""",
- "1\nblarg")
-
- def test4(self):
- r"""2 #cache ... #end cache blocks"""
- self.verify("""#slurp
-#def foo
-#cache ID='cache1', timer=150m
-$anInt
-#end cache
-#cache id='cache2', timer=15s
- #for $i in range(5)
-$i#slurp
- #end for
-#end cache
-$aStr#slurp
-#end def
-$foo$foo$foo$foo$foo""",
- "1\n01234blarg"*5)
-
-
- def test5(self):
- r"""nested #cache blocks"""
- self.verify("""#slurp
-#def foo
-#cache ID='cache1', timer=150m
-$anInt
-#cache id='cache2', timer=15s
- #for $i in range(5)
-$i#slurp
- #end for
-$*(6)#slurp
-#end cache
-#end cache
-$aStr#slurp
-#end def
-$foo$foo$foo$foo$foo""",
- "1\n012346blarg"*5)
-
-
-class CallDirective(OutputTest):
-
- def test1(self):
- r"""simple #call """
- self.verify("#call int\n$anInt#end call",
- "1")
- # single line version
- self.verify("#call int: $anInt",
- "1")
- self.verify("#call int: 10\n$aStr",
- "10\nblarg")
-
- def test2(self):
- r"""simple #call + WS"""
- self.verify("#call int\n$anInt #end call",
- "1")
-
- def test3(self):
- r"""a longer #call"""
- self.verify('''\
-#def meth(arg)
-$arg.upper()#slurp
-#end def
-#call $meth
-$(1234+1) foo#slurp
-#end call''',
- "1235 FOO")
-
- def test4(self):
- r"""#call with keyword #args"""
- self.verify('''\
-#def meth(arg1, arg2)
-$arg1.upper() - $arg2.lower()#slurp
-#end def
-#call self.meth
-#arg arg1
-$(1234+1) foo#slurp
-#arg arg2
-UPPER#slurp
-#end call''',
- "1235 FOO - upper")
-
- def test5(self):
- r"""#call with single-line keyword #args """
- self.verify('''\
-#def meth(arg1, arg2)
-$arg1.upper() - $arg2.lower()#slurp
-#end def
-#call self.meth
-#arg arg1:$(1234+1) foo#slurp
-#arg arg2:UPPER#slurp
-#end call''',
- "1235 FOO - upper")
-
- def test6(self):
- """#call with python kwargs and cheetah output for the 1s positional
- arg"""
-
- self.verify('''\
-#def meth(arg1, arg2)
-$arg1.upper() - $arg2.lower()#slurp
-#end def
-#call self.meth arg2="UPPER"
-$(1234+1) foo#slurp
-#end call''',
- "1235 FOO - upper")
-
- def test7(self):
- """#call with python kwargs and #args"""
- self.verify('''\
-#def meth(arg1, arg2, arg3)
-$arg1.upper() - $arg2.lower() - $arg3#slurp
-#end def
-#call self.meth arg2="UPPER", arg3=999
-#arg arg1:$(1234+1) foo#slurp
-#end call''',
- "1235 FOO - upper - 999")
-
- def test8(self):
- """#call with python kwargs and #args, and using a function to get the
- function that will be called"""
- self.verify('''\
-#def meth(arg1, arg2, arg3)
-$arg1.upper() - $arg2.lower() - $arg3#slurp
-#end def
-#call getattr(self, "meth") arg2="UPPER", arg3=999
-#arg arg1:$(1234+1) foo#slurp
-#end call''',
- "1235 FOO - upper - 999")
-
- def test9(self):
- """nested #call directives"""
- self.verify('''\
-#def meth(arg1)
-$arg1#slurp
-#end def
-#def meth2(x,y)
-$x$y#slurp
-#end def
-##
-#call self.meth
-1#slurp
-#call self.meth
-2#slurp
-#call self.meth
-3#slurp
-#end call 3
-#set two = 2
-#call self.meth2 y=c"$(10/$two)"
-#arg x
-4#slurp
-#end call 4
-#end call 2
-#end call 1''',
- "12345")
-
-
-
-class I18nDirective(OutputTest):
- def test1(self):
- r"""simple #call """
- self.verify("#i18n \n$anInt#end i18n",
- "1")
-
- # single line version
- self.verify("#i18n: $anInt",
- "1")
- self.verify("#i18n: 10\n$aStr",
- "10\nblarg")
-
-
-class CaptureDirective(OutputTest):
- def test1(self):
- r"""simple #capture"""
- self.verify('''\
-#capture cap1
-$(1234+1) foo#slurp
-#end capture
-$cap1#slurp
-''',
- "1235 foo")
-
-
- def test2(self):
- r"""slightly more complex #capture"""
- self.verify('''\
-#def meth(arg)
-$arg.upper()#slurp
-#end def
-#capture cap1
-$(1234+1) $anInt $meth("foo")#slurp
-#end capture
-$cap1#slurp
-''',
- "1235 1 FOO")
-
-
-class SlurpDirective(OutputTest):
- def test1(self):
- r"""#slurp with 1 \n """
- self.verify("#slurp\n",
- "")
-
- def test2(self):
- r"""#slurp with 1 \n, leading whitespace
- Should gobble"""
- self.verify(" #slurp\n",
- "")
-
- def test3(self):
- r"""#slurp with 1 \n, leading content
- Shouldn't gobble"""
- self.verify(" 1234 #slurp\n",
- " 1234 ")
-
- def test4(self):
- r"""#slurp with WS then \n, leading content
- Shouldn't gobble"""
- self.verify(" 1234 #slurp \n",
- " 1234 ")
-
- def test5(self):
- r"""#slurp with garbage chars then \n, leading content
- Should eat the garbage"""
- self.verify(" 1234 #slurp garbage \n",
- " 1234 ")
-
-
-
-class EOLSlurpToken(OutputTest):
- _EOLSlurpToken = DEFAULT_COMPILER_SETTINGS['EOLSlurpToken']
- def test1(self):
- r"""#slurp with 1 \n """
- self.verify("%s\n"%self._EOLSlurpToken,
- "")
-
- def test2(self):
- r"""#slurp with 1 \n, leading whitespace
- Should gobble"""
- self.verify(" %s\n"%self._EOLSlurpToken,
- "")
- def test3(self):
- r"""#slurp with 1 \n, leading content
- Shouldn't gobble"""
- self.verify(" 1234 %s\n"%self._EOLSlurpToken,
- " 1234 ")
-
- def test4(self):
- r"""#slurp with WS then \n, leading content
- Shouldn't gobble"""
- self.verify(" 1234 %s \n"%self._EOLSlurpToken,
- " 1234 ")
-
- def test5(self):
- r"""#slurp with garbage chars then \n, leading content
- Should NOT eat the garbage"""
- self.verify(" 1234 %s garbage \n"%self._EOLSlurpToken,
- " 1234 %s garbage \n"%self._EOLSlurpToken)
-
-if not DEFAULT_COMPILER_SETTINGS['EOLSlurpToken']:
- del EOLSlurpToken
-
-class RawDirective(OutputTest):
- def test1(self):
- """#raw till EOF"""
- self.verify("#raw\n$aFunc().\n\n",
- "$aFunc().\n\n")
-
- def test2(self):
- """#raw till #end raw"""
- self.verify("#raw\n$aFunc().\n#end raw\n$anInt",
- "$aFunc().\n1")
-
- def test3(self):
- """#raw till #end raw gobble WS"""
- self.verify(" #raw \n$aFunc().\n #end raw \n$anInt",
- "$aFunc().\n1")
-
- def test4(self):
- """#raw till #end raw using explicit directive closure
- Shouldn't gobble"""
- self.verify(" #raw #\n$aFunc().\n #end raw #\n$anInt",
- " \n$aFunc().\n\n1")
-
- def test5(self):
- """single-line short form #raw: """
- self.verify("#raw: $aFunc().\n\n",
- "$aFunc().\n\n")
-
- self.verify("#raw: $aFunc().\n$anInt",
- "$aFunc().\n1")
-
-class BreakpointDirective(OutputTest):
- def test1(self):
- """#breakpoint part way through source code"""
- self.verify("$aFunc(2).\n#breakpoint\n$anInt",
- "2.\n")
-
- def test2(self):
- """#breakpoint at BOF"""
- self.verify("#breakpoint\n$anInt",
- "")
-
- def test3(self):
- """#breakpoint at EOF"""
- self.verify("$anInt\n#breakpoint",
- "1\n")
-
-
-class StopDirective(OutputTest):
- def test1(self):
- """#stop part way through source code"""
- self.verify("$aFunc(2).\n#stop\n$anInt",
- "2.\n")
-
- def test2(self):
- """#stop at BOF"""
- self.verify("#stop\n$anInt",
- "")
-
- def test3(self):
- """#stop at EOF"""
- self.verify("$anInt\n#stop",
- "1\n")
-
- def test4(self):
- """#stop in pos test block"""
- self.verify("""$anInt
-#if 1
-inside the if block
-#stop
-#end if
-blarg""",
- "1\ninside the if block\n")
-
- def test5(self):
- """#stop in neg test block"""
- self.verify("""$anInt
-#if 0
-inside the if block
-#stop
-#end if
-blarg""",
- "1\nblarg")
-
-
-class ReturnDirective(OutputTest):
-
- def test1(self):
- """#return'ing an int """
- self.verify("""1
-$str($test-6)
-3
-#def test
-#if 1
-#return (3 *2) \
- + 2
-#else
-aoeuoaeu
-#end if
-#end def
-""",
- "1\n2\n3\n")
-
- def test2(self):
- """#return'ing an string """
- self.verify("""1
-$str($test[1])
-3
-#def test
-#if 1
-#return '123'
-#else
-aoeuoaeu
-#end if
-#end def
-""",
- "1\n2\n3\n")
-
- def test3(self):
- """#return'ing an string AND streaming other output via the transaction"""
- self.verify("""1
-$str($test(trans=trans)[1])
-3
-#def test
-1.5
-#if 1
-#return '123'
-#else
-aoeuoaeu
-#end if
-#end def
-""",
- "1\n1.5\n2\n3\n")
-
-
-class YieldDirective(OutputTest):
- convertEOLs = False
- def test1(self):
- """simple #yield """
-
- src1 = """#for i in range(10)\n#yield i\n#end for"""
- src2 = """#for i in range(10)\n$i#slurp\n#yield\n#end for"""
- src3 = ("#def iterator\n"
- "#for i in range(10)\n#yield i\n#end for\n"
- "#end def\n"
- "#for i in $iterator\n$i#end for"
- )
-
-
- for src in (src1,src2,src3):
- klass = Template.compile(src, keepRefToGeneratedCode=True)
- #print klass._CHEETAH_generatedModuleCode
- iter = klass().respond()
- output = [str(i) for i in iter]
- assert ''.join(output)=='0123456789'
- #print ''.join(output)
-
- # @@TR: need to expand this to cover error conditions etc.
-
-if versionTuple < (2,3):
- del YieldDirective
-
-class ForDirective(OutputTest):
-
- def test1(self):
- """#for loop with one local var"""
- self.verify("#for $i in range(5)\n$i\n#end for",
- "0\n1\n2\n3\n4\n")
-
- self.verify("#for $i in range(5):\n$i\n#end for",
- "0\n1\n2\n3\n4\n")
-
- self.verify("#for $i in range(5): ##comment\n$i\n#end for",
- "0\n1\n2\n3\n4\n")
-
- self.verify("#for $i in range(5) ##comment\n$i\n#end for",
- "0\n1\n2\n3\n4\n")
-
-
- def test2(self):
- """#for loop with WS in loop"""
- self.verify("#for $i in range(5)\n$i \n#end for",
- "0 \n1 \n2 \n3 \n4 \n")
-
- def test3(self):
- """#for loop gobble WS"""
- self.verify(" #for $i in range(5) \n$i \n #end for ",
- "0 \n1 \n2 \n3 \n4 \n")
-
- def test4(self):
- """#for loop over list"""
- self.verify("#for $i, $j in [(0,1),(2,3)]\n$i,$j\n#end for",
- "0,1\n2,3\n")
-
- def test5(self):
- """#for loop over list, with #slurp"""
- self.verify("#for $i, $j in [(0,1),(2,3)]\n$i,$j#slurp\n#end for",
- "0,12,3")
-
- def test6(self):
- """#for loop with explicit closures"""
- self.verify("#for $i in range(5)#$i#end for#",
- "01234")
-
- def test7(self):
- """#for loop with explicit closures and WS"""
- self.verify(" #for $i in range(5)#$i#end for# ",
- " 01234 ")
-
- def test8(self):
- """#for loop using another $var"""
- self.verify(" #for $i in range($aFunc(5))#$i#end for# ",
- " 01234 ")
-
- def test9(self):
- """test methods in for loops"""
- self.verify("#for $func in $listOfLambdas\n$func($anInt)\n#end for",
- "1\n1\n1\n")
-
-
- def test10(self):
- """#for loop over list, using methods of the items"""
- self.verify("#for i, j in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
- "AA,BB\nCC,DD\n")
- self.verify("#for $i, $j in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
- "AA,BB\nCC,DD\n")
-
- def test11(self):
- """#for loop over list, using ($i,$j) style target list"""
- self.verify("#for (i, j) in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
- "AA,BB\nCC,DD\n")
- self.verify("#for ($i, $j) in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
- "AA,BB\nCC,DD\n")
-
- def test12(self):
- """#for loop over list, using i, (j,k) style target list"""
- self.verify("#for i, (j, k) in enumerate([('aa','bb'),('cc','dd')])\n$j.upper,$k.upper\n#end for",
- "AA,BB\nCC,DD\n")
- self.verify("#for $i, ($j, $k) in enumerate([('aa','bb'),('cc','dd')])\n$j.upper,$k.upper\n#end for",
- "AA,BB\nCC,DD\n")
-
- def test13(self):
- """single line #for"""
- self.verify("#for $i in range($aFunc(5)): $i",
- "01234")
-
- def test14(self):
- """single line #for with 1 extra leading space"""
- self.verify("#for $i in range($aFunc(5)): $i",
- " 0 1 2 3 4")
-
- def test15(self):
- """2 times single line #for"""
- self.verify("#for $i in range($aFunc(5)): $i#slurp\n"*2,
- "01234"*2)
-
- def test16(self):
- """false single line #for """
- self.verify("#for $i in range(5): \n$i\n#end for",
- "0\n1\n2\n3\n4\n")
-
-if versionTuple < (2,3):
- del ForDirective.test12
-
-class RepeatDirective(OutputTest):
-
- def test1(self):
- """basic #repeat"""
- self.verify("#repeat 3\n1\n#end repeat",
- "1\n1\n1\n")
- self.verify("#repeat 3: \n1\n#end repeat",
- "1\n1\n1\n")
-
- self.verify("#repeat 3 ##comment\n1\n#end repeat",
- "1\n1\n1\n")
-
- self.verify("#repeat 3: ##comment\n1\n#end repeat",
- "1\n1\n1\n")
-
- def test2(self):
- """#repeat with numeric expression"""
- self.verify("#repeat 3*3/3\n1\n#end repeat",
- "1\n1\n1\n")
-
- def test3(self):
- """#repeat with placeholder"""
- self.verify("#repeat $numTwo\n1\n#end repeat",
- "1\n1\n")
-
- def test4(self):
- """#repeat with placeholder * num"""
- self.verify("#repeat $numTwo*1\n1\n#end repeat",
- "1\n1\n")
-
- def test5(self):
- """#repeat with placeholder and WS"""
- self.verify(" #repeat $numTwo \n1\n #end repeat ",
- "1\n1\n")
-
- def test6(self):
- """single-line #repeat"""
- self.verify("#repeat $numTwo: 1",
- "11")
- self.verify("#repeat $numTwo: 1\n"*2,
- "1\n1\n"*2)
-
- #false single-line
- self.verify("#repeat 3: \n1\n#end repeat",
- "1\n1\n1\n")
-
-
-class AttrDirective(OutputTest):
-
- def test1(self):
- """#attr with int"""
- self.verify("#attr $test = 1234\n$test",
- "1234")
-
- def test2(self):
- """#attr with string"""
- self.verify("#attr $test = 'blarg'\n$test",
- "blarg")
-
- def test3(self):
- """#attr with expression"""
- self.verify("#attr $test = 'blarg'.upper()*2\n$test",
- "BLARGBLARG")
-
- def test4(self):
- """#attr with string + WS
- Should gobble"""
- self.verify(" #attr $test = 'blarg' \n$test",
- "blarg")
-
- def test5(self):
- """#attr with string + WS + leading text
- Shouldn't gobble"""
- self.verify(" -- #attr $test = 'blarg' \n$test",
- " -- \nblarg")
-
-
-class DefDirective(OutputTest):
-
- def test1(self):
- """#def without argstring"""
- self.verify("#def testMeth\n1234\n#end def\n$testMeth",
- "1234\n")
-
- self.verify("#def testMeth ## comment\n1234\n#end def\n$testMeth",
- "1234\n")
-
- self.verify("#def testMeth: ## comment\n1234\n#end def\n$testMeth",
- "1234\n")
-
- def test2(self):
- """#def without argstring, gobble WS"""
- self.verify(" #def testMeth \n1234\n #end def \n$testMeth",
- "1234\n")
-
- def test3(self):
- """#def with argstring, gobble WS"""
- self.verify(" #def testMeth($a=999) \n1234-$a\n #end def\n$testMeth",
- "1234-999\n")
-
- def test4(self):
- """#def with argstring, gobble WS, string used in call"""
- self.verify(" #def testMeth($a=999) \n1234-$a\n #end def\n$testMeth('ABC')",
- "1234-ABC\n")
-
- def test5(self):
- """#def with argstring, gobble WS, list used in call"""
- self.verify(" #def testMeth($a=999) \n1234-$a\n #end def\n$testMeth([1,2,3])",
- "1234-[1, 2, 3]\n")
-
- def test6(self):
- """#def with 2 args, gobble WS, list used in call"""
- self.verify(" #def testMeth($a, $b='default') \n1234-$a$b\n #end def\n$testMeth([1,2,3])",
- "1234-[1, 2, 3]default\n")
-
- def test7(self):
- """#def with *args, gobble WS"""
- self.verify(" #def testMeth($*args) \n1234-$args\n #end def\n$testMeth",
- "1234-()\n")
-
- def test8(self):
- """#def with **KWs, gobble WS"""
- self.verify(" #def testMeth($**KWs) \n1234-$KWs\n #end def\n$testMeth",
- "1234-{}\n")
-
- def test9(self):
- """#def with *args + **KWs, gobble WS"""
- self.verify(" #def testMeth($*args, $**KWs) \n1234-$args-$KWs\n #end def\n$testMeth",
- "1234-()-{}\n")
-
- def test10(self):
- """#def with *args + **KWs, gobble WS"""
- self.verify(
- " #def testMeth($*args, $**KWs) \n1234-$args-$KWs.a\n #end def\n$testMeth(1,2, a=1)",
- "1234-(1, 2)-1\n")
-
-
- def test11(self):
- """single line #def with extra WS"""
- self.verify(
- "#def testMeth: aoeuaoeu\n- $testMeth -",
- "- aoeuaoeu -")
-
- def test12(self):
- """single line #def with extra WS and nested $placeholders"""
- self.verify(
- "#def testMeth: $anInt $aFunc(1234)\n- $testMeth -",
- "- 1 1234 -")
-
- def test13(self):
- """single line #def escaped $placeholders"""
- self.verify(
- "#def testMeth: \$aFunc(\$anInt)\n- $testMeth -",
- "- $aFunc($anInt) -")
-
- def test14(self):
- """single line #def 1 escaped $placeholders"""
- self.verify(
- "#def testMeth: \$aFunc($anInt)\n- $testMeth -",
- "- $aFunc(1) -")
-
- def test15(self):
- """single line #def 1 escaped $placeholders + more WS"""
- self.verify(
- "#def testMeth : \$aFunc($anInt)\n- $testMeth -",
- "- $aFunc(1) -")
-
- def test16(self):
- """multiline #def with $ on methodName"""
- self.verify("#def $testMeth\n1234\n#end def\n$testMeth",
- "1234\n")
-
- def test17(self):
- """single line #def with $ on methodName"""
- self.verify("#def $testMeth:1234\n$testMeth",
- "1234")
-
- def test18(self):
- """single line #def with an argument"""
- self.verify("#def $testMeth($arg=1234):$arg\n$testMeth",
- "1234")
-
-
-class DecoratorDirective(OutputTest):
- def test1(self):
- """single line #def with decorator"""
- self.verify("#from Cheetah.Tests.SyntaxAndOutput import testdecorator\n"
- +"#@testdecorator"
- +"\n#def $testMeth():1234\n$testMeth",
-
- "1234")
-
- self.verify("#from Cheetah.Tests.SyntaxAndOutput import testdecorator\n"
- +"#@testdecorator"
- +"\n#block $testMeth():1234",
-
- "1234")
-
- try:
- self.verify(
- "#from Cheetah.Tests.SyntaxAndOutput import testdecorator\n"
- +"#@testdecorator\n sdf"
- +"\n#def $testMeth():1234\n$testMeth",
-
- "1234")
- except ParseError:
- pass
- else:
- self.fail('should raise a ParseError')
-
-if versionTuple < (2,4):
- del DecoratorDirective
-
-class BlockDirective(OutputTest):
-
- def test1(self):
- """#block without argstring"""
- self.verify("#block testBlock\n1234\n#end block",
- "1234\n")
-
- self.verify("#block testBlock ##comment\n1234\n#end block",
- "1234\n")
-
- def test2(self):
- """#block without argstring, gobble WS"""
- self.verify(" #block testBlock \n1234\n #end block ",
- "1234\n")
-
- def test3(self):
- """#block with argstring, gobble WS
-
- Because blocks can be reused in multiple parts of the template arguments
- (!!with defaults!!) can be given."""
-
- self.verify(" #block testBlock($a=999) \n1234-$a\n #end block ",
- "1234-999\n")
-
- def test4(self):
- """#block with 2 args, gobble WS"""
- self.verify(" #block testBlock($a=999, $b=444) \n1234-$a$b\n #end block ",
- "1234-999444\n")
-
-
- def test5(self):
- """#block with 2 nested blocks
-
- Blocks can be nested to any depth and the name of the block is optional
- for the #end block part: #end block OR #end block [name] """
-
- self.verify("""#block testBlock
-this is a test block
-#block outerNest
-outer
-#block innerNest
-inner
-#end block innerNest
-#end block outerNest
----
-#end block testBlock
-""",
- "this is a test block\nouter\ninner\n---\n")
-
-
- def test6(self):
- """single line #block """
- self.verify(
- "#block testMeth: This is my block",
- "This is my block")
-
- def test7(self):
- """single line #block with WS"""
- self.verify(
- "#block testMeth: This is my block",
- "This is my block")
-
- def test8(self):
- """single line #block 1 escaped $placeholders"""
- self.verify(
- "#block testMeth: \$aFunc($anInt)",
- "$aFunc(1)")
-
- def test9(self):
- """single line #block 1 escaped $placeholders + WS"""
- self.verify(
- "#block testMeth: \$aFunc( $anInt )",
- "$aFunc( 1 )")
-
- def test10(self):
- """single line #block 1 escaped $placeholders + more WS"""
- self.verify(
- "#block testMeth : \$aFunc( $anInt )",
- "$aFunc( 1 )")
-
- def test11(self):
- """multiline #block $ on argstring"""
- self.verify("#block $testBlock\n1234\n#end block",
- "1234\n")
-
- def test12(self):
- """single line #block with $ on methodName """
- self.verify(
- "#block $testMeth: This is my block",
- "This is my block")
-
- def test13(self):
- """single line #block with an arg """
- self.verify(
- "#block $testMeth($arg='This is my block'): $arg",
- "This is my block")
-
- def test14(self):
- """single line #block with None for content"""
- self.verify(
- """#block $testMeth: $None\ntest $testMeth-""",
- "test -")
-
- def test15(self):
- """single line #block with nothing for content"""
- self.verify(
- """#block $testMeth: \nfoo\n#end block\ntest $testMeth-""",
- "foo\ntest foo\n-")
-
-class IncludeDirective(OutputTest):
-
- def setUp(self):
- fp = open('parseTest.txt','w')
- fp.write("$numOne $numTwo")
- fp.flush()
- fp.close
-
- def tearDown(self):
- if os.path.exists('parseTest.txt'):
- os.remove('parseTest.txt')
-
- def test1(self):
- """#include raw of source $emptyString"""
- self.verify("#include raw source=$emptyString",
- "")
-
- def test2(self):
- """#include raw of source $blockToBeParsed"""
- self.verify("#include raw source=$blockToBeParsed",
- "$numOne $numTwo")
-
- def test3(self):
- """#include raw of 'parseTest.txt'"""
- self.verify("#include raw 'parseTest.txt'",
- "$numOne $numTwo")
-
- def test4(self):
- """#include raw of $includeFileName"""
- self.verify("#include raw $includeFileName",
- "$numOne $numTwo")
-
- def test5(self):
- """#include raw of $includeFileName, with WS"""
- self.verify(" #include raw $includeFileName ",
- "$numOne $numTwo")
-
- def test6(self):
- """#include raw of source= , with WS"""
- self.verify(" #include raw source='This is my $Source '*2 ",
- "This is my $Source This is my $Source ")
-
- def test7(self):
- """#include of $blockToBeParsed"""
- self.verify("#include source=$blockToBeParsed",
- "1 2")
-
- def test8(self):
- """#include of $blockToBeParsed, with WS"""
- self.verify(" #include source=$blockToBeParsed ",
- "1 2")
-
- def test9(self):
- """#include of 'parseTest.txt', with WS"""
- self.verify(" #include source=$blockToBeParsed ",
- "1 2")
-
- def test10(self):
- """#include of "parseTest.txt", with WS"""
- self.verify(" #include source=$blockToBeParsed ",
- "1 2")
-
- def test11(self):
- """#include of 'parseTest.txt', with WS and surrounding text"""
- self.verify("aoeu\n #include source=$blockToBeParsed \naoeu",
- "aoeu\n1 2aoeu")
-
- def test12(self):
- """#include of 'parseTest.txt', with WS and explicit closure"""
- self.verify(" #include source=$blockToBeParsed# ",
- " 1 2 ")
-
-
-class SilentDirective(OutputTest):
-
- def test1(self):
- """simple #silent"""
- self.verify("#silent $aFunc",
- "")
-
- def test2(self):
- """simple #silent"""
- self.verify("#silent $anObj.callIt\n$anObj.callArg",
- "1234")
-
- self.verify("#silent $anObj.callIt ##comment\n$anObj.callArg",
- "1234")
-
- def test3(self):
- """simple #silent"""
- self.verify("#silent $anObj.callIt(99)\n$anObj.callArg",
- "99")
-
-class SetDirective(OutputTest):
-
- def test1(self):
- """simple #set"""
- self.verify("#set $testVar = 'blarg'\n$testVar",
- "blarg")
- self.verify("#set testVar = 'blarg'\n$testVar",
- "blarg")
-
-
- self.verify("#set testVar = 'blarg'##comment\n$testVar",
- "blarg")
-
- def test2(self):
- """simple #set with no WS between operands"""
- self.verify("#set $testVar='blarg'",
- "")
- def test3(self):
- """#set + use of var"""
- self.verify("#set $testVar = 'blarg'\n$testVar",
- "blarg")
-
- def test4(self):
- """#set + use in an #include"""
- self.verify("#set global $aSetVar = 1234\n#include source=$includeBlock2",
- "1 2 1234")
-
- def test5(self):
- """#set with a dictionary"""
- self.verify( """#set $testDict = {'one':'one1','two':'two2','three':'three3'}
-$testDict.one
-$testDict.two""",
- "one1\ntwo2")
-
- def test6(self):
- """#set with string, then used in #if block"""
-
- self.verify("""#set $test='a string'\n#if $test#blarg#end if""",
- "blarg")
-
- def test7(self):
- """simple #set, gobble WS"""
- self.verify(" #set $testVar = 'blarg' ",
- "")
-
- def test8(self):
- """simple #set, don't gobble WS"""
- self.verify(" #set $testVar = 'blarg'#---",
- " ---")
-
- def test9(self):
- """simple #set with a list"""
- self.verify(" #set $testVar = [1, 2, 3] \n$testVar",
- "[1, 2, 3]")
-
- def test10(self):
- """simple #set global with a list"""
- self.verify(" #set global $testVar = [1, 2, 3] \n$testVar",
- "[1, 2, 3]")
-
- def test11(self):
- """simple #set global with a list and *cache
-
- Caching only works with global #set vars. Local vars are not accesible
- to the cache namespace.
- """
-
- self.verify(" #set global $testVar = [1, 2, 3] \n$*testVar",
- "[1, 2, 3]")
-
- def test12(self):
- """simple #set global with a list and *<int>*cache"""
- self.verify(" #set global $testVar = [1, 2, 3] \n$*5*testVar",
- "[1, 2, 3]")
-
- def test13(self):
- """simple #set with a list and *<float>*cache"""
- self.verify(" #set global $testVar = [1, 2, 3] \n$*.5*testVar",
- "[1, 2, 3]")
-
- def test14(self):
- """simple #set without NameMapper on"""
- self.verify("""#compiler useNameMapper = 0\n#set $testVar = 1 \n$testVar""",
- "1")
-
- def test15(self):
- """simple #set without $"""
- self.verify("""#set testVar = 1 \n$testVar""",
- "1")
-
- def test16(self):
- """simple #set global without $"""
- self.verify("""#set global testVar = 1 \n$testVar""",
- "1")
-
- def test17(self):
- """simple #set module without $"""
- self.verify("""#set module __foo__ = 'bar'\n$__foo__""",
- "bar")
-
- def test18(self):
- """#set with i,j=list style assignment"""
- self.verify("""#set i,j = [1,2]\n$i$j""",
- "12")
- self.verify("""#set $i,$j = [1,2]\n$i$j""",
- "12")
-
- def test19(self):
- """#set with (i,j)=list style assignment"""
- self.verify("""#set (i,j) = [1,2]\n$i$j""",
- "12")
- self.verify("""#set ($i,$j) = [1,2]\n$i$j""",
- "12")
-
- def test20(self):
- """#set with i, (j,k)=list style assignment"""
- self.verify("""#set i, (j,k) = [1,(2,3)]\n$i$j$k""",
- "123")
- self.verify("""#set $i, ($j,$k) = [1,(2,3)]\n$i$j$k""",
- "123")
-
-
-class IfDirective(OutputTest):
-
- def test1(self):
- """simple #if block"""
- self.verify("#if 1\n$aStr\n#end if\n",
- "blarg\n")
-
- self.verify("#if 1:\n$aStr\n#end if\n",
- "blarg\n")
-
- self.verify("#if 1: \n$aStr\n#end if\n",
- "blarg\n")
-
- self.verify("#if 1: ##comment \n$aStr\n#end if\n",
- "blarg\n")
-
- self.verify("#if 1 ##comment \n$aStr\n#end if\n",
- "blarg\n")
-
- self.verify("#if 1##for i in range(10)#$i#end for##end if",
- '0123456789')
-
- self.verify("#if 1: #for i in range(10)#$i#end for",
- '0123456789')
-
- self.verify("#if 1: #for i in range(10):$i",
- '0123456789')
-
- def test2(self):
- """simple #if block, with WS"""
- self.verify(" #if 1\n$aStr\n #end if \n",
- "blarg\n")
- def test3(self):
- """simple #if block, with WS and explicit closures"""
- self.verify(" #if 1#\n$aStr\n #end if #--\n",
- " \nblarg\n --\n")
-
- def test4(self):
- """#if block using $numOne"""
- self.verify("#if $numOne\n$aStr\n#end if\n",
- "blarg\n")
-
- def test5(self):
- """#if block using $zero"""
- self.verify("#if $zero\n$aStr\n#end if\n",
- "")
- def test6(self):
- """#if block using $emptyString"""
- self.verify("#if $emptyString\n$aStr\n#end if\n",
- "")
- def test7(self):
- """#if ... #else ... block using a $emptyString"""
- self.verify("#if $emptyString\n$anInt\n#else\n$anInt - $anInt\n#end if",
- "1 - 1\n")
-
- def test8(self):
- """#if ... #elif ... #else ... block using a $emptyString"""
- self.verify("#if $emptyString\n$c\n#elif $numOne\n$numOne\n#else\n$c - $c\n#end if",
- "1\n")
-
- def test9(self):
- """#if 'not' test, with #slurp"""
- self.verify("#if not $emptyString\n$aStr#slurp\n#end if\n",
- "blarg")
-
- def test10(self):
- """#if block using $*emptyString
-
- This should barf
- """
- try:
- self.verify("#if $*emptyString\n$aStr\n#end if\n",
- "")
- except ParseError:
- pass
- else:
- self.fail('This should barf')
-
- def test11(self):
- """#if block using invalid top-level $(placeholder) syntax - should barf"""
-
- for badSyntax in ("#if $*5*emptyString\n$aStr\n#end if\n",
- "#if ${emptyString}\n$aStr\n#end if\n",
- "#if $(emptyString)\n$aStr\n#end if\n",
- "#if $[emptyString]\n$aStr\n#end if\n",
- "#if $!emptyString\n$aStr\n#end if\n",
- ):
- try:
- self.verify(badSyntax, "")
- except ParseError:
- pass
- else:
- self.fail('This should barf')
-
- def test12(self):
- """#if ... #else if ... #else ... block using a $emptyString
- Same as test 8 but using else if instead of elif"""
- self.verify("#if $emptyString\n$c\n#else if $numOne\n$numOne\n#else\n$c - $c\n#end if",
- "1\n")
-
-
- def test13(self):
- """#if# ... #else # ... block using a $emptyString with """
- self.verify("#if $emptyString# $anInt#else#$anInt - $anInt#end if",
- "1 - 1")
-
- def test14(self):
- """single-line #if: simple"""
- self.verify("#if $emptyString then 'true' else 'false'",
- "false")
-
- def test15(self):
- """single-line #if: more complex"""
- self.verify("#if $anInt then 'true' else 'false'",
- "true")
-
- def test16(self):
- """single-line #if: with the words 'else' and 'then' in the output """
- self.verify("#if ($anInt and not $emptyString==''' else ''') then $str('then') else 'else'",
- "then")
-
- def test17(self):
- """single-line #if: """
- self.verify("#if 1: foo\n#if 0: bar\n#if 1: foo",
- "foo\nfoo")
-
-
- self.verify("#if 1: foo\n#if 0: bar\n#if 1: foo",
- "foo\nfoo")
-
- def test18(self):
- """single-line #if: \n#else: """
- self.verify("#if 1: foo\n#elif 0: bar",
- "foo\n")
-
- self.verify("#if 1: foo\n#elif 0: bar\n#else: blarg\n",
- "foo\n")
-
- self.verify("#if 0: foo\n#elif 0: bar\n#else: blarg\n",
- "blarg\n")
-
-class UnlessDirective(OutputTest):
-
- def test1(self):
- """#unless 1"""
- self.verify("#unless 1\n 1234 \n#end unless",
- "")
-
- self.verify("#unless 1:\n 1234 \n#end unless",
- "")
-
- self.verify("#unless 1: ##comment\n 1234 \n#end unless",
- "")
-
- self.verify("#unless 1 ##comment\n 1234 \n#end unless",
- "")
-
-
- def test2(self):
- """#unless 0"""
- self.verify("#unless 0\n 1234 \n#end unless",
- " 1234 \n")
-
- def test3(self):
- """#unless $none"""
- self.verify("#unless $none\n 1234 \n#end unless",
- " 1234 \n")
-
- def test4(self):
- """#unless $numTwo"""
- self.verify("#unless $numTwo\n 1234 \n#end unless",
- "")
-
- def test5(self):
- """#unless $numTwo with WS"""
- self.verify(" #unless $numTwo \n 1234 \n #end unless ",
- "")
-
- def test6(self):
- """single-line #unless"""
- self.verify("#unless 1: 1234", "")
- self.verify("#unless 0: 1234", "1234")
- self.verify("#unless 0: 1234\n"*2, "1234\n"*2)
-
-class PSP(OutputTest):
-
- def test1(self):
- """simple <%= [int] %>"""
- self.verify("<%= 1234 %>", "1234")
-
- def test2(self):
- """simple <%= [string] %>"""
- self.verify("<%= 'blarg' %>", "blarg")
-
- def test3(self):
- """simple <%= None %>"""
- self.verify("<%= None %>", "")
- def test4(self):
- """simple <%= [string] %> + $anInt"""
- self.verify("<%= 'blarg' %>$anInt", "blarg1")
-
- def test5(self):
- """simple <%= [EXPR] %> + $anInt"""
- self.verify("<%= ('blarg'*2).upper() %>$anInt", "BLARGBLARG1")
-
- def test6(self):
- """for loop in <%%>"""
- self.verify("<% for i in range(5):%>1<%end%>", "11111")
-
- def test7(self):
- """for loop in <%%> and using <%=i%>"""
- self.verify("<% for i in range(5):%><%=i%><%end%>", "01234")
-
- def test8(self):
- """for loop in <% $%> and using <%=i%>"""
- self.verify("""<% for i in range(5):
- i=i*2$%><%=i%><%end%>""", "02468")
-
- def test9(self):
- """for loop in <% $%> and using <%=i%> plus extra text"""
- self.verify("""<% for i in range(5):
- i=i*2$%><%=i%>-<%end%>""", "0-2-4-6-8-")
-
-
-class WhileDirective(OutputTest):
- def test1(self):
- """simple #while with a counter"""
- self.verify("#set $i = 0\n#while $i < 5\n$i#slurp\n#set $i += 1\n#end while",
- "01234")
-
-class ContinueDirective(OutputTest):
- def test1(self):
- """#continue with a #while"""
- self.verify("""#set $i = 0
-#while $i < 5
-#if $i == 3
- #set $i += 1
- #continue
-#end if
-$i#slurp
-#set $i += 1
-#end while""",
- "0124")
-
- def test2(self):
- """#continue with a #for"""
- self.verify("""#for $i in range(5)
-#if $i == 3
- #continue
-#end if
-$i#slurp
-#end for""",
- "0124")
-
-class BreakDirective(OutputTest):
- def test1(self):
- """#break with a #while"""
- self.verify("""#set $i = 0
-#while $i < 5
-#if $i == 3
- #break
-#end if
-$i#slurp
-#set $i += 1
-#end while""",
- "012")
-
- def test2(self):
- """#break with a #for"""
- self.verify("""#for $i in range(5)
-#if $i == 3
- #break
-#end if
-$i#slurp
-#end for""",
- "012")
-
-
-class TryDirective(OutputTest):
-
- def test1(self):
- """simple #try
- """
- self.verify("#try\n1234\n#except\nblarg\n#end try",
- "1234\n")
-
- def test2(self):
- """#try / #except with #raise
- """
- self.verify("#try\n#raise ValueError\n#except\nblarg\n#end try",
- "blarg\n")
-
- def test3(self):
- """#try / #except with #raise + WS
-
- Should gobble
- """
- self.verify(" #try \n #raise ValueError \n #except \nblarg\n #end try",
- "blarg\n")
-
-
- def test4(self):
- """#try / #except with #raise + WS and leading text
-
- Shouldn't gobble
- """
- self.verify("--#try \n #raise ValueError \n #except \nblarg\n #end try#--",
- "--\nblarg\n --")
-
- def test5(self):
- """nested #try / #except with #raise
- """
- self.verify(
-"""#try
- #raise ValueError
-#except
- #try
- #raise ValueError
- #except
-blarg
- #end try
-#end try""",
- "blarg\n")
-
-class PassDirective(OutputTest):
- def test1(self):
- """#pass in a #try / #except block
- """
- self.verify("#try\n#raise ValueError\n#except\n#pass\n#end try",
- "")
-
- def test2(self):
- """#pass in a #try / #except block + WS
- """
- self.verify(" #try \n #raise ValueError \n #except \n #pass \n #end try",
- "")
-
-
-class AssertDirective(OutputTest):
- def test1(self):
- """simple #assert
- """
- self.verify("#set $x = 1234\n#assert $x == 1234",
- "")
-
- def test2(self):
- """simple #assert that fails
- """
- def test(self=self):
- self.verify("#set $x = 1234\n#assert $x == 999",
- ""),
- self.failUnlessRaises(AssertionError, test)
-
- def test3(self):
- """simple #assert with WS
- """
- self.verify("#set $x = 1234\n #assert $x == 1234 ",
- "")
-
-
-class RaiseDirective(OutputTest):
- def test1(self):
- """simple #raise ValueError
-
- Should raise ValueError
- """
- def test(self=self):
- self.verify("#raise ValueError",
- ""),
- self.failUnlessRaises(ValueError, test)
-
- def test2(self):
- """#raise ValueError in #if block
-
- Should raise ValueError
- """
- def test(self=self):
- self.verify("#if 1\n#raise ValueError\n#end if\n",
- "")
- self.failUnlessRaises(ValueError, test)
-
-
- def test3(self):
- """#raise ValueError in #if block
-
- Shouldn't raise ValueError
- """
- self.verify("#if 0\n#raise ValueError\n#else\nblarg#end if\n",
- "blarg\n")
-
-
-
-class ImportDirective(OutputTest):
- def test1(self):
- """#import math
- """
- self.verify("#import math",
- "")
-
- def test2(self):
- """#import math + WS
-
- Should gobble
- """
- self.verify(" #import math ",
- "")
-
- def test3(self):
- """#import math + WS + leading text
-
- Shouldn't gobble
- """
- self.verify(" -- #import math ",
- " -- ")
-
- def test4(self):
- """#from math import syn
- """
- self.verify("#from math import cos",
- "")
-
- def test5(self):
- """#from math import cos + WS
- Should gobble
- """
- self.verify(" #from math import cos ",
- "")
-
- def test6(self):
- """#from math import cos + WS + leading text
- Shouldn't gobble
- """
- self.verify(" -- #from math import cos ",
- " -- ")
-
- def test7(self):
- """#from math import cos -- use it
- """
- self.verify("#from math import cos\n$cos(0)",
- "1.0")
-
- def test8(self):
- """#from math import cos,tan,sin -- and use them
- """
- self.verify("#from math import cos, tan, sin\n$cos(0)-$tan(0)-$sin(0)",
- "1.0-0.0-0.0")
-
- def test9(self):
- """#import os.path -- use it
- """
-
- self.verify("#import os.path\n$os.path.exists('.')",
- repr(True))
-
- def test10(self):
- """#import os.path -- use it with NameMapper turned off
- """
- self.verify("""##
-#compiler-settings
-useNameMapper=False
-#end compiler-settings
-#import os.path
-$os.path.exists('.')""",
- repr(True))
-
- def test11(self):
- """#from math import *
- """
-
- self.verify("#from math import *\n$pow(1,2) $log10(10)",
- "1.0 1.0")
-
-class CompilerDirective(OutputTest):
- def test1(self):
- """overriding the commentStartToken
- """
- self.verify("""$anInt##comment
-#compiler commentStartToken = '//'
-$anInt//comment
-""",
- "1\n1\n")
-
- def test2(self):
- """overriding and resetting the commentStartToken
- """
- self.verify("""$anInt##comment
-#compiler commentStartToken = '//'
-$anInt//comment
-#compiler reset
-$anInt//comment
-""",
- "1\n1\n1//comment\n")
-
-
-class CompilerSettingsDirective(OutputTest):
-
- def test1(self):
- """overriding the cheetahVarStartToken
- """
- self.verify("""$anInt
-#compiler-settings
-cheetahVarStartToken = @
-#end compiler-settings
-@anInt
-#compiler-settings reset
-$anInt
-""",
- "1\n1\n1\n")
-
- def test2(self):
- """overriding the directiveStartToken
- """
- self.verify("""#set $x = 1234
-$x
-#compiler-settings
-directiveStartToken = @
-#end compiler-settings
-@set $x = 1234
-$x
-""",
- "1234\n1234\n")
-
- def test3(self):
- """overriding the commentStartToken
- """
- self.verify("""$anInt##comment
-#compiler-settings
-commentStartToken = //
-#end compiler-settings
-$anInt//comment
-""",
- "1\n1\n")
-
-if sys.platform.startswith('java'):
- del CompilerDirective
- del CompilerSettingsDirective
-
-class ExtendsDirective(OutputTest):
-
- def test1(self):
- """#extends Cheetah.Templates._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
-#extends _SkeletonPage
-#implements respond(foo=1234)
-$spacer()$foo
-""",
- '<img src="spacer.gif" width="1" height="1" alt="" />1234\n')
-
- def test2(self):
- """#extends Cheetah.Templates.SkeletonPage without #import"""
- self.verify("""#extends Cheetah.Templates.SkeletonPage
-#implements respond
-$spacer()
-""",
- '<img src="spacer.gif" width="1" height="1" alt="" />\n')
-
- def test3(self):
- """#extends Cheetah.Templates.SkeletonPage.SkeletonPage without #import"""
- self.verify("""#extends Cheetah.Templates.SkeletonPage.SkeletonPage
-#implements respond
-$spacer()
-""",
- '<img src="spacer.gif" width="1" height="1" alt="" />\n')
-
- def test4(self):
- """#extends with globals and searchList test"""
- self.verify("""#extends Cheetah.Templates.SkeletonPage
-#set global g="Hello"
-#implements respond
-$g $numOne
-""",
- 'Hello 1\n')
-
-class ImportantExampleCases(OutputTest):
- def test1(self):
- """how to make a comma-delimited list"""
- self.verify("""#set $sep = ''
-#for $letter in $letterList
-$sep$letter#slurp
-#set $sep = ', '
-#end for
-""",
- "a, b, c")
-
-class FilterDirective(OutputTest):
- convertEOLs=False
-
- def _getCompilerSettings(self):
- return {'useFilterArgsInPlaceholders':True}
-
- def test1(self):
- """#filter ReplaceNone
- """
- self.verify("#filter ReplaceNone\n$none#end filter",
- "")
-
- self.verify("#filter ReplaceNone: $none",
- "")
-
- def test2(self):
- """#filter ReplaceNone with WS
- """
- self.verify("#filter ReplaceNone \n$none#end filter",
- "")
-
- def test3(self):
- """#filter MaxLen -- maxlen of 5"""
-
- self.verify("#filter MaxLen \n${tenDigits, $maxlen=5}#end filter",
- "12345")
-
- def test4(self):
- """#filter MaxLen -- no maxlen
- """
- self.verify("#filter MaxLen \n${tenDigits}#end filter",
- "1234567890")
-
- def test5(self):
- """#filter WebSafe -- basic usage
- """
- self.verify("#filter WebSafe \n$webSafeTest#end filter",
- "abc &lt;=&gt; &amp;")
-
- def test6(self):
- """#filter WebSafe -- also space
- """
- self.verify("#filter WebSafe \n${webSafeTest, $also=' '}#end filter",
- "abc&nbsp;&lt;=&gt;&nbsp;&amp;")
-
- def test7(self):
- """#filter WebSafe -- also space, without $ on the args
- """
- self.verify("#filter WebSafe \n${webSafeTest, also=' '}#end filter",
- "abc&nbsp;&lt;=&gt;&nbsp;&amp;")
-
- def test8(self):
- """#filter Strip -- trailing newline
- """
- self.verify("#filter Strip\n$strip1#end filter",
- "strippable whitespace\n")
-
- def test9(self):
- """#filter Strip -- no trailing newine
- """
- self.verify("#filter Strip\n$strip2#end filter",
- "strippable whitespace")
-
- def test10(self):
- """#filter Strip -- multi-line
- """
- self.verify("#filter Strip\n$strip3#end filter",
- "strippable whitespace\n1 2 3\n")
-
- def test11(self):
- """#filter StripSqueeze -- canonicalize all whitespace to ' '
- """
- self.verify("#filter StripSqueeze\n$strip3#end filter",
- "strippable whitespace 1 2 3")
-
-
-class EchoDirective(OutputTest):
- def test1(self):
- """#echo 1234
- """
- self.verify("#echo 1234",
- "1234")
-
-class SilentDirective(OutputTest):
- def test1(self):
- """#silent 1234
- """
- self.verify("#silent 1234",
- "")
-
-class ErrorCatcherDirective(OutputTest):
- pass
-
-
-class VarExists(OutputTest): # Template.varExists()
-
- def test1(self):
- """$varExists('$anInt')
- """
- self.verify("$varExists('$anInt')",
- repr(True))
-
- def test2(self):
- """$varExists('anInt')
- """
- self.verify("$varExists('anInt')",
- repr(True))
-
- def test3(self):
- """$varExists('$anInt')
- """
- self.verify("$varExists('$bogus')",
- repr(False))
-
- def test4(self):
- """$varExists('$anInt') combined with #if false
- """
- self.verify("#if $varExists('$bogus')\n1234\n#else\n999\n#end if",
- "999\n")
-
- def test5(self):
- """$varExists('$anInt') combined with #if true
- """
- self.verify("#if $varExists('$anInt')\n1234\n#else\n999#end if",
- "1234\n")
-
-class GetVar(OutputTest): # Template.getVar()
- def test1(self):
- """$getVar('$anInt')
- """
- self.verify("$getVar('$anInt')",
- "1")
-
- def test2(self):
- """$getVar('anInt')
- """
- self.verify("$getVar('anInt')",
- "1")
-
- def test3(self):
- """$self.getVar('anInt')
- """
- self.verify("$self.getVar('anInt')",
- "1")
-
- def test4(self):
- """$getVar('bogus', 1234)
- """
- self.verify("$getVar('bogus', 1234)",
- "1234")
-
- def test5(self):
- """$getVar('$bogus', 1234)
- """
- self.verify("$getVar('$bogus', 1234)",
- "1234")
-
-
-class MiscComplexSyntax(OutputTest):
- def test1(self):
- """Complex use of {},[] and () in a #set expression
- ----
- #set $c = {'A':0}[{}.get('a', {'a' : 'A'}['a'])]
- $c
- """
- self.verify("#set $c = {'A':0}[{}.get('a', {'a' : 'A'}['a'])]\n$c",
- "0")
-
-
-class CGI(OutputTest):
- """CGI scripts with(out) the CGI environment and with(out) GET variables.
- """
- convertEOLs=False
-
- def _beginCGI(self):
- os.environ['REQUEST_METHOD'] = "GET"
- def _endCGI(self):
- try:
- del os.environ['REQUEST_METHOD']
- except KeyError:
- pass
- _guaranteeNoCGI = _endCGI
-
-
- def test1(self):
- """A regular template."""
- self._guaranteeNoCGI()
- source = "#extends Cheetah.Tools.CGITemplate\n" + \
- "#implements respond\n" + \
- "$cgiHeaders#slurp\n" + \
- "Hello, world!"
- self.verify(source, "Hello, world!")
-
-
- def test2(self):
- """A CGI script."""
- self._beginCGI()
- source = "#extends Cheetah.Tools.CGITemplate\n" + \
- "#implements respond\n" + \
- "$cgiHeaders#slurp\n" + \
- "Hello, world!"
- self.verify(source, "Content-type: text/html\n\nHello, world!")
- self._endCGI()
-
-
- def test3(self):
- """A (pseudo) Webware servlet.
-
- This uses the Python syntax escape to set
- self._CHEETAH__isControlledByWebKit.
- We could instead do '#silent self._CHEETAH__isControlledByWebKit = True',
- taking advantage of the fact that it will compile unchanged as long
- as there's no '$' in the statement. (It won't compile with an '$'
- because that would convert to a function call, and you can't assign
- to a function call.) Because this isn't really being called from
- Webware, we'd better not use any Webware services! Likewise, we'd
- better not call $cgiImport() because it would be misled.
- """
- self._beginCGI()
- source = "#extends Cheetah.Tools.CGITemplate\n" + \
- "#implements respond\n" + \
- "<% self._CHEETAH__isControlledByWebKit = True %>#slurp\n" + \
- "$cgiHeaders#slurp\n" + \
- "Hello, world!"
- self.verify(source, "Hello, world!")
- self._endCGI()
-
-
- def test4(self):
- """A CGI script with a GET variable."""
- self._beginCGI()
- os.environ['QUERY_STRING'] = "cgiWhat=world"
- source = "#extends Cheetah.Tools.CGITemplate\n" + \
- "#implements respond\n" + \
- "$cgiHeaders#slurp\n" + \
- "#silent $webInput(['cgiWhat'])##slurp\n" + \
- "Hello, $cgiWhat!"
- self.verify(source,
- "Content-type: text/html\n\nHello, world!")
- del os.environ['QUERY_STRING']
- self._endCGI()
-
-
-
-class WhitespaceAfterDirectiveTokens(OutputTest):
- def _getCompilerSettings(self):
- return {'allowWhitespaceAfterDirectiveStartToken':True}
-
- def test1(self):
- self.verify("# for i in range(10): $i",
- "0123456789")
- self.verify("# for i in range(10)\n$i# end for",
- "0123456789")
- self.verify("# for i in range(10)#$i#end for",
- "0123456789")
-
-
-
-class DefmacroDirective(OutputTest):
- def _getCompilerSettings(self):
- def aMacro(src):
- return '$aStr'
-
- return {'macroDirectives':{'aMacro':aMacro
- }}
-
- def test1(self):
- self.verify("""\
-#defmacro inc: #set @src +=1
-#set i = 1
-#inc: $i
-$i""",
- "2")
-
-
-
- self.verify("""\
-#defmacro test
-#for i in range(10): @src
-#end defmacro
-#test: $i-foo#slurp
-#for i in range(3): $i""",
- "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo012")
-
- self.verify("""\
-#defmacro test
-#for i in range(10): @src
-#end defmacro
-#test: $i-foo
-#for i in range(3): $i""",
- "0-foo\n1-foo\n2-foo\n3-foo\n4-foo\n5-foo\n6-foo\n7-foo\n8-foo\n9-foo\n012")
-
-
- self.verify("""\
-#defmacro test: #for i in range(10): @src
-#test: $i-foo#slurp
--#for i in range(3): $i""",
- "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
-
- self.verify("""\
-#defmacro test##for i in range(10): @src#end defmacro##slurp
-#test: $i-foo#slurp
--#for i in range(3): $i""",
- "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
-
- self.verify("""\
-#defmacro testFoo: nothing
-#defmacro test(foo=1234): #for i in range(10): @src
-#test foo=234: $i-foo#slurp
--#for i in range(3): $i""",
- "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
-
- self.verify("""\
-#defmacro testFoo: nothing
-#defmacro test(foo=1234): #for i in range(10): @src@foo
-#test foo='-foo'#$i#end test#-#for i in range(3): $i""",
- "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
-
- self.verify("""\
-#defmacro testFoo: nothing
-#defmacro test(foo=1234): #for i in range(10): @src.strip()@foo
-#test foo='-foo': $i
--#for i in range(3): $i""",
- "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
-
- def test2(self):
- self.verify("#aMacro: foo",
- "blarg")
- self.verify("#defmacro nested: @macros.aMacro(@src)\n#nested: foo",
- "blarg")
-
-
-class Indenter(OutputTest):
- convertEOLs=False
-
- source = """
-public class X
-{
- #for $method in $methods
- $getMethod($method)
-
- #end for
-}
-//end of class
-
-#def getMethod($method)
- #indent ++
- public $getType($method) ${method.Name}($getParams($method.Params));
- #indent --
-#end def
-
-#def getParams($params)
- #indent off
-
- #for $counter in $range($len($params))
- #if $counter == len($params) - 1
- $params[$counter]#slurp
- #else:
- $params[$counter],
- #end if
- #end for
- #indent on
-#end def
-
-#def getType($method)
- #indent push
- #indent=0
- #if $method.Type == "VT_VOID"
- void#slurp
- #elif $method.Type == "VT_INT"
- int#slurp
- #elif $method.Type == "VT_VARIANT"
- Object#slurp
- #end if
- #indent pop
-#end def
-"""
-
- control = """
-public class X
-{
- public void Foo(
- _input,
- _output);
-
-
- public int Bar(
- _str1,
- str2,
- _str3);
-
-
- public Object Add(
- value1,
- value);
-
-
-}
-//end of class
-
-
-
-"""
- def _getCompilerSettings(self):
- return {'useFilterArgsInPlaceholders':True}
-
- def searchList(self): # Inside Indenter class.
- class Method:
- def __init__(self, _name, _type, *_params):
- self.Name = _name
- self.Type = _type
- self.Params = _params
- methods = [Method("Foo", "VT_VOID", "_input", "_output"),
- Method("Bar", "VT_INT", "_str1", "str2", "_str3"),
- Method("Add", "VT_VARIANT", "value1", "value")]
- return [{"methods": methods}]
-
- def test1(self): # Inside Indenter class.
- self.verify(self.source, self.control)
-
-
-##################################################
-## CREATE CONVERTED EOL VERSIONS OF THE TEST CASES
-
-if OutputTest._useNewStyleCompilation and versionTuple >= (2,3):
- extraCompileKwArgsForDiffBaseclass = {'baseclass':dict}
-else:
- extraCompileKwArgsForDiffBaseclass = {'baseclass':object}
-
-
-for klass in [var for var in globals().values()
- if type(var) == types.ClassType and issubclass(var, unittest.TestCase)]:
- name = klass.__name__
- if hasattr(klass,'convertEOLs') and klass.convertEOLs:
- win32Src = r"class %(name)s_Win32EOL(%(name)s): _EOLreplacement = '\r\n'"%locals()
- macSrc = r"class %(name)s_MacEOL(%(name)s): _EOLreplacement = '\r'"%locals()
- #print win32Src
- #print macSrc
- exec win32Src+'\n'
- exec macSrc+'\n'
-
- if versionTuple >= (2,3):
- src = r"class %(name)s_DiffBaseClass(%(name)s): "%locals()
- src += " _extraCompileKwArgs = extraCompileKwArgsForDiffBaseclass"
- exec src+'\n'
-
- del name
- del klass
-
-##################################################
-## if run from the command line ##
-
-if __name__ == '__main__':
- unittest.main()
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/Tests/Template.py b/cobbler/Cheetah/Tests/Template.py
deleted file mode 100644
index b97cf5d..0000000
--- a/cobbler/Cheetah/Tests/Template.py
+++ /dev/null
@@ -1,312 +0,0 @@
-#!/usr/bin/env python
-# $Id: Template.py,v 1.16 2006/02/03 21:05:50 tavis_rudd Exp $
-"""Tests of the Template class API
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>,
-Version: $Revision: 1.16 $
-Start Date: 2001/10/01
-Last Revision Date: $Date: 2006/02/03 21:05:50 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.16 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import sys
-import types
-import os
-import os.path
-import tempfile
-import shutil
-import unittest_local_copy as unittest
-from Cheetah.Template import Template
-
-##################################################
-## CONSTANTS & GLOBALS ##
-
-majorVer, minorVer = sys.version_info[0], sys.version_info[1]
-versionTuple = (majorVer, minorVer)
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-##################################################
-## TEST DATA FOR USE IN THE TEMPLATES ##
-
-##################################################
-## TEST BASE CLASSES
-
-class TemplateTest(unittest.TestCase):
- pass
-
-##################################################
-## TEST CASE CLASSES
-
-class ClassMethods_compile(TemplateTest):
- """I am using the same Cheetah source for each test to root out clashes
- caused by the compile caching in Template.compile().
- """
-
- def test_basicUsage(self):
- klass = Template.compile(source='$foo')
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
-
- def test_baseclassArg(self):
- klass = Template.compile(source='$foo', baseclass=dict)
- t = klass({'foo':1234})
- assert str(t)=='1234'
-
- klass2 = Template.compile(source='$foo', baseclass=klass)
- t = klass2({'foo':1234})
- assert str(t)=='1234'
-
- klass3 = Template.compile(source='#implements dummy\n$bar', baseclass=klass2)
- t = klass3({'foo':1234})
- assert str(t)=='1234'
-
- klass4 = Template.compile(source='$foo', baseclass='dict')
- t = klass4({'foo':1234})
- assert str(t)=='1234'
-
- def test_moduleFileCaching(self):
- if versionTuple < (2,3):
- return
- tmpDir = tempfile.mkdtemp()
- try:
- #print tmpDir
- assert os.path.exists(tmpDir)
- klass = Template.compile(source='$foo',
- cacheModuleFilesForTracebacks=True,
- cacheDirForModuleFiles=tmpDir)
- mod = sys.modules[klass.__module__]
- #print mod.__file__
- assert os.path.exists(mod.__file__)
- assert os.path.dirname(mod.__file__)==tmpDir
- finally:
- shutil.rmtree(tmpDir, True)
-
- def test_classNameArg(self):
- klass = Template.compile(source='$foo', className='foo123')
- assert klass.__name__=='foo123'
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
-
- def test_moduleNameArg(self):
- klass = Template.compile(source='$foo', moduleName='foo99')
- mod = sys.modules['foo99']
- assert klass.__name__=='foo99'
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
-
-
- klass = Template.compile(source='$foo',
- moduleName='foo1',
- className='foo2')
- mod = sys.modules['foo1']
- assert klass.__name__=='foo2'
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
-
-
- def test_mainMethodNameArg(self):
- klass = Template.compile(source='$foo',
- className='foo123',
- mainMethodName='testMeth')
- assert klass.__name__=='foo123'
- t = klass(namespaces={'foo':1234})
- #print t.generatedClassCode()
- assert str(t)=='1234'
- assert t.testMeth()=='1234'
-
- klass = Template.compile(source='$foo',
- moduleName='fooXXX',
- className='foo123',
- mainMethodName='testMeth',
- baseclass=dict)
- assert klass.__name__=='foo123'
- t = klass({'foo':1234})
- #print t.generatedClassCode()
- assert str(t)=='1234'
- assert t.testMeth()=='1234'
-
-
-
- def test_moduleGlobalsArg(self):
- klass = Template.compile(source='$foo',
- moduleGlobals={'foo':1234})
- t = klass()
- assert str(t)=='1234'
-
- klass2 = Template.compile(source='$foo', baseclass='Test1',
- moduleGlobals={'Test1':dict})
- t = klass2({'foo':1234})
- assert str(t)=='1234'
-
- klass3 = Template.compile(source='$foo', baseclass='Test1',
- moduleGlobals={'Test1':dict, 'foo':1234})
- t = klass3()
- assert str(t)=='1234'
-
-
- def test_keepRefToGeneratedCodeArg(self):
- klass = Template.compile(source='$foo',
- className='unique58',
- cacheCompilationResults=False,
- keepRefToGeneratedCode=False)
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
- assert not t.generatedModuleCode()
-
-
- klass2 = Template.compile(source='$foo',
- className='unique58',
- keepRefToGeneratedCode=True)
- t = klass2(namespaces={'foo':1234})
- assert str(t)=='1234'
- assert t.generatedModuleCode()
-
- klass3 = Template.compile(source='$foo',
- className='unique58',
- keepRefToGeneratedCode=False)
- t = klass3(namespaces={'foo':1234})
- assert str(t)=='1234'
- # still there as this class came from the cache
- assert t.generatedModuleCode()
-
-
- def test_compilationCache(self):
- klass = Template.compile(source='$foo',
- className='unique111',
- cacheCompilationResults=False)
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
- assert not klass._CHEETAH_isInCompilationCache
-
-
- # this time it will place it in the cache
- klass = Template.compile(source='$foo',
- className='unique111',
- cacheCompilationResults=True)
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
- assert klass._CHEETAH_isInCompilationCache
-
- # by default it will be in the cache
- klass = Template.compile(source='$foo',
- className='unique999099')
- t = klass(namespaces={'foo':1234})
- assert str(t)=='1234'
- assert klass._CHEETAH_isInCompilationCache
-
-
-class ClassMethods_subclass(TemplateTest):
-
- def test_basicUsage(self):
- klass = Template.compile(source='$foo', baseclass=dict)
- t = klass({'foo':1234})
- assert str(t)=='1234'
-
- klass2 = klass.subclass(source='$foo')
- t = klass2({'foo':1234})
- assert str(t)=='1234'
-
- klass3 = klass2.subclass(source='#implements dummy\n$bar')
- t = klass3({'foo':1234})
- assert str(t)=='1234'
-
-
-class Preprocessors(TemplateTest):
-
- def test_basicUsage1(self):
- src='''\
- %set foo = @a
- $(@foo*10)
- @a'''
- src = '\n'.join([ln.strip() for ln in src.splitlines()])
- preprocessors = {'tokens':'@ %',
- 'namespaces':{'a':99}
- }
- klass = Template.compile(src, preprocessors=preprocessors)
- assert str(klass())=='990\n99'
-
- def test_normalizePreprocessorArgVariants(self):
- src='%set foo = 12\n%%comment\n$(@foo*10)'
-
- class Settings1: tokens = '@ %'
- Settings1 = Settings1()
-
- from Cheetah.Template import TemplatePreprocessor
- settings = Template._normalizePreprocessorSettings(Settings1)
- preprocObj = TemplatePreprocessor(settings)
-
- def preprocFunc(source, file):
- return '$(12*10)', None
-
- class TemplateSubclass(Template):
- pass
-
- compilerSettings = {'cheetahVarStartToken':'@',
- 'directiveStartToken':'%',
- 'commentStartToken':'%%',
- }
-
- for arg in ['@ %',
- {'tokens':'@ %'},
- {'compilerSettings':compilerSettings},
- {'compilerSettings':compilerSettings,
- 'templateInitArgs':{}},
- {'tokens':'@ %',
- 'templateAPIClass':TemplateSubclass},
- Settings1,
- preprocObj,
- preprocFunc,
- ]:
-
- klass = Template.compile(src, preprocessors=arg)
- assert str(klass())=='120'
-
-
- def test_complexUsage(self):
- src='''\
- %set foo = @a
- %def func1: #def func(arg): $arg("***")
- %% comment
- $(@foo*10)
- @func1
- $func(lambda x:c"--$x--@a")'''
- src = '\n'.join([ln.strip() for ln in src.splitlines()])
-
-
- for arg in [{'tokens':'@ %', 'namespaces':{'a':99} },
- {'tokens':'@ %', 'namespaces':{'a':99} },
- ]:
- klass = Template.compile(src, preprocessors=arg)
- t = klass()
- assert str(t)=='990\n--***--99'
-
-
-
- def test_i18n(self):
- src='''\
- %i18n: This is a $string that needs translation
- %i18n id="foo", domain="root": This is a $string that needs translation
- '''
- src = '\n'.join([ln.strip() for ln in src.splitlines()])
- klass = Template.compile(src, preprocessors='@ %', baseclass=dict)
- t = klass({'string':'bit of text'})
- #print str(t), repr(str(t))
- assert str(t)==('This is a bit of text that needs translation\n'*2)[:-1]
-
-
-##################################################
-## if run from the command line ##
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/cobbler/Cheetah/Tests/Test.py b/cobbler/Cheetah/Tests/Test.py
deleted file mode 100644
index 9e46a5d..0000000
--- a/cobbler/Cheetah/Tests/Test.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python
-# $Id: Test.py,v 1.44 2006/01/15 20:45:10 tavis_rudd Exp $
-"""Core module of Cheetah's Unit-testing framework
-
-TODO
-================================================================================
-# combo tests
-# negative test cases for expected exceptions
-# black-box vs clear-box testing
-# do some tests that run the Template for long enough to check that the refresh code works
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>,
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.44 $
-Start Date: 2001/03/30
-Last Revision Date: $Date: 2006/01/15 20:45:10 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.44 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import sys
-import unittest_local_copy as unittest
-
-##################################################
-## CONSTANTS & GLOBALS
-
-try:
- True, False
-except NameError:
- True, False = (1==1),(1==0)
-
-##################################################
-## TESTS
-
-import SyntaxAndOutput
-import NameMapper
-import Template
-import FileRefresh
-import CheetahWrapper
-
-SyntaxSuite = unittest.findTestCases(SyntaxAndOutput)
-NameMapperSuite = unittest.findTestCases(NameMapper)
-TemplateSuite = unittest.findTestCases(Template)
-FileRefreshSuite = unittest.findTestCases(FileRefresh)
-if not sys.platform.startswith('java'):
- CheetahWrapperSuite = unittest.findTestCases(CheetahWrapper)
-
-from SyntaxAndOutput import *
-from NameMapper import *
-from Template import *
-from FileRefresh import *
-
-if not sys.platform.startswith('java'):
- from CheetahWrapper import *
-
-##################################################
-## if run from the command line
-
-if __name__ == '__main__':
- unittest.main()
-
-
-
diff --git a/cobbler/Cheetah/Tests/__init__.py b/cobbler/Cheetah/Tests/__init__.py
deleted file mode 100644
index 792d600..0000000
--- a/cobbler/Cheetah/Tests/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/cobbler/Cheetah/Tests/unittest_local_copy.py b/cobbler/Cheetah/Tests/unittest_local_copy.py
deleted file mode 100644
index 54061ae..0000000
--- a/cobbler/Cheetah/Tests/unittest_local_copy.py
+++ /dev/null
@@ -1,977 +0,0 @@
-#!/usr/bin/env python
-""" This is a hacked version of PyUnit that extends its reporting capabilities
-with optional meta data on the test cases. It also makes it possible to
-separate the standard and error output streams in TextTestRunner.
-
-It's a hack rather than a set of subclasses because a) Steve had used double
-underscore private attributes for some things I needed access to, and b) the
-changes affected so many classes that it was easier just to hack it.
-
-The changes are in the following places:
-TestCase:
- - minor refactoring of __init__ and __call__ internals
- - added some attributes and methods for storing and retrieving meta data
-
-_TextTestResult
- - refactored the stream handling
- - incorporated all the output code from TextTestRunner
- - made the output of FAIL and ERROR information more flexible and
- incorporated the new meta data from TestCase
- - added a flag called 'explain' to __init__ that controls whether the new '
- explanation' meta data from TestCase is printed along with tracebacks
-
-TextTestRunner
- - delegated all output to _TextTestResult
- - added 'err' and 'explain' to the __init__ signature to match the changes
- in _TextTestResult
-
-TestProgram
- - added -e and --explain as flags on the command line
-
--- Tavis Rudd <tavis@redonions.net> (Sept 28th, 2001)
-
-- _TestTextResult.printErrorList(): print blank line after each traceback
-
--- Mike Orr <mso@oz.net> (Nov 11, 2002)
-
-TestCase methods copied from unittest in Python 2.3:
- - .assertAlmostEqual(first, second, places=7, msg=None): to N decimal places.
- - .failIfAlmostEqual(first, second, places=7, msg=None)
-
--- Mike Orr (Jan 5, 2004)
-
-
-Below is the original docstring for unittest.
----------------------------------------------------------------------------
-Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
-Smalltalk testing framework.
-
-This module contains the core framework classes that form the basis of
-specific test cases and suites (TestCase, TestSuite etc.), and also a
-text-based utility class for running the tests and reporting the results
-(TextTestRunner).
-
-Simple usage:
-
- import unittest
-
- class IntegerArithmenticTestCase(unittest.TestCase):
- def testAdd(self): ## test method names begin 'test*'
- self.assertEquals((1 + 2), 3)
- self.assertEquals(0 + 1, 1)
- def testMultiply(self);
- self.assertEquals((0 * 10), 0)
- self.assertEquals((5 * 8), 40)
-
- if __name__ == '__main__':
- unittest.main()
-
-Further information is available in the bundled documentation, and from
-
- http://pyunit.sourceforge.net/
-
-Copyright (c) 1999, 2000, 2001 Steve Purcell
-This module is free software, and you may redistribute it and/or modify
-it under the same terms as Python itself, so long as this copyright message
-and disclaimer are retained in their original form.
-
-IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
-SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
-THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
-AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-"""
-
-__author__ = "Steve Purcell"
-__email__ = "stephen_purcell at yahoo dot com"
-__revision__ = "$Revision: 1.11 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import os
-import re
-import string
-import sys
-import time
-import traceback
-import types
-import pprint
-
-##################################################
-## CONSTANTS & GLOBALS
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-##############################################################################
-# Test framework core
-##############################################################################
-
-
-class TestResult:
- """Holder for test result information.
-
- Test results are automatically managed by the TestCase and TestSuite
- classes, and do not need to be explicitly manipulated by writers of tests.
-
- Each instance holds the total number of tests run, and collections of
- failures and errors that occurred among those test runs. The collections
- contain tuples of (testcase, exceptioninfo), where exceptioninfo is a
- tuple of values as returned by sys.exc_info().
- """
- def __init__(self):
- self.failures = []
- self.errors = []
- self.testsRun = 0
- self.shouldStop = 0
-
- def startTest(self, test):
- "Called when the given test is about to be run"
- self.testsRun = self.testsRun + 1
-
- def stopTest(self, test):
- "Called when the given test has been run"
- pass
-
- def addError(self, test, err):
- "Called when an error has occurred"
- self.errors.append((test, err))
-
- def addFailure(self, test, err):
- "Called when a failure has occurred"
- self.failures.append((test, err))
-
- def addSuccess(self, test):
- "Called when a test has completed successfully"
- pass
-
- def wasSuccessful(self):
- "Tells whether or not this result was a success"
- return len(self.failures) == len(self.errors) == 0
-
- def stop(self):
- "Indicates that the tests should be aborted"
- self.shouldStop = 1
-
- def __repr__(self):
- return "<%s run=%i errors=%i failures=%i>" % \
- (self.__class__, self.testsRun, len(self.errors),
- len(self.failures))
-
-class TestCase:
- """A class whose instances are single test cases.
-
- By default, the test code itself should be placed in a method named
- 'runTest'.
-
- If the fixture may be used for many test cases, create as
- many test methods as are needed. When instantiating such a TestCase
- subclass, specify in the constructor arguments the name of the test method
- that the instance is to execute.
-
- Test authors should subclass TestCase for their own tests. Construction
- and deconstruction of the test's environment ('fixture') can be
- implemented by overriding the 'setUp' and 'tearDown' methods respectively.
-
- If it is necessary to override the __init__ method, the base class
- __init__ method must always be called. It is important that subclasses
- should not change the signature of their __init__ method, since instances
- of the classes are instantiated automatically by parts of the framework
- in order to be run.
- """
-
- # This attribute determines which exception will be raised when
- # the instance's assertion methods fail; test methods raising this
- # exception will be deemed to have 'failed' rather than 'errored'
-
- failureException = AssertionError
-
- # the name of the fixture. Used for displaying meta data about the test
- name = None
-
- def __init__(self, methodName='runTest'):
- """Create an instance of the class that will use the named test
- method when executed. Raises a ValueError if the instance does
- not have a method with the specified name.
- """
- self._testMethodName = methodName
- self._setupTestMethod()
- self._setupMetaData()
-
- def _setupTestMethod(self):
- try:
- self._testMethod = getattr(self, self._testMethodName)
- except AttributeError:
- raise ValueError, "no such test method in %s: %s" % \
- (self.__class__, self._testMethodName)
-
- ## meta data methods
-
- def _setupMetaData(self):
- """Setup the default meta data for the test case:
-
- - id: self.__class__.__name__ + testMethodName OR self.name + testMethodName
- - description: 1st line of Class docstring + 1st line of method docstring
- - explanation: rest of Class docstring + rest of method docstring
-
- """
-
-
- testDoc = self._testMethod.__doc__ or '\n'
- testDocLines = testDoc.splitlines()
-
- testDescription = testDocLines[0].strip()
- if len(testDocLines) > 1:
- testExplanation = '\n'.join(
- [ln.strip() for ln in testDocLines[1:]]
- ).strip()
- else:
- testExplanation = ''
-
- fixtureDoc = self.__doc__ or '\n'
- fixtureDocLines = fixtureDoc.splitlines()
- fixtureDescription = fixtureDocLines[0].strip()
- if len(fixtureDocLines) > 1:
- fixtureExplanation = '\n'.join(
- [ln.strip() for ln in fixtureDocLines[1:]]
- ).strip()
- else:
- fixtureExplanation = ''
-
- if not self.name:
- self.name = self.__class__
- self._id = "%s.%s" % (self.name, self._testMethodName)
-
- if not fixtureDescription:
- self._description = testDescription
- else:
- self._description = fixtureDescription + ', ' + testDescription
-
- if not fixtureExplanation:
- self._explanation = testExplanation
- else:
- self._explanation = ['Fixture Explanation:',
- '--------------------',
- fixtureExplanation,
- '',
- 'Test Explanation:',
- '-----------------',
- testExplanation
- ]
- self._explanation = '\n'.join(self._explanation)
-
- def id(self):
- return self._id
-
- def setId(self, id):
- self._id = id
-
- def describe(self):
- """Returns a one-line description of the test, or None if no
- description has been provided.
-
- The default implementation of this method returns the first line of
- the specified test method's docstring.
- """
- return self._description
-
- shortDescription = describe
-
- def setDescription(self, descr):
- self._description = descr
-
- def explain(self):
- return self._explanation
-
- def setExplanation(self, expln):
- self._explanation = expln
-
- ## core methods
-
- def setUp(self):
- "Hook method for setting up the test fixture before exercising it."
- pass
-
- def run(self, result=None):
- return self(result)
-
- def tearDown(self):
- "Hook method for deconstructing the test fixture after testing it."
- pass
-
- def debug(self):
- """Run the test without collecting errors in a TestResult"""
- self.setUp()
- self._testMethod()
- self.tearDown()
-
- ## internal methods
-
- def defaultTestResult(self):
- return TestResult()
-
- def __call__(self, result=None):
- if result is None:
- result = self.defaultTestResult()
-
- result.startTest(self)
- try:
- try:
- self.setUp()
- except:
- result.addError(self, self.__exc_info())
- return
-
- ok = 0
- try:
- self._testMethod()
- ok = 1
- except self.failureException, e:
- result.addFailure(self, self.__exc_info())
- except:
- result.addError(self, self.__exc_info())
- try:
- self.tearDown()
- except:
- result.addError(self, self.__exc_info())
- ok = 0
- if ok:
- result.addSuccess(self)
- finally:
- result.stopTest(self)
-
- return result
-
- def countTestCases(self):
- return 1
-
- def __str__(self):
- return "%s (%s)" % (self._testMethodName, self.__class__)
-
- def __repr__(self):
- return "<%s testMethod=%s>" % \
- (self.__class__, self._testMethodName)
-
- def __exc_info(self):
- """Return a version of sys.exc_info() with the traceback frame
- minimised; usually the top level of the traceback frame is not
- needed.
- """
- exctype, excvalue, tb = sys.exc_info()
- if sys.platform[:4] == 'java': ## tracebacks look different in Jython
- return (exctype, excvalue, tb)
- newtb = tb.tb_next
- if newtb is None:
- return (exctype, excvalue, tb)
- return (exctype, excvalue, newtb)
-
- ## methods for use by the test cases
-
- def fail(self, msg=None):
- """Fail immediately, with the given message."""
- raise self.failureException, msg
-
- def failIf(self, expr, msg=None):
- "Fail the test if the expression is true."
- if expr: raise self.failureException, msg
-
- def failUnless(self, expr, msg=None):
- """Fail the test unless the expression is true."""
- if not expr: raise self.failureException, msg
-
- def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
- """Fail unless an exception of class excClass is thrown
- by callableObj when invoked with arguments args and keyword
- arguments kwargs. If a different type of exception is
- thrown, it will not be caught, and the test case will be
- deemed to have suffered an error, exactly as for an
- unexpected exception.
- """
- try:
- apply(callableObj, args, kwargs)
- except excClass:
- return
- else:
- if hasattr(excClass,'__name__'): excName = excClass.__name__
- else: excName = str(excClass)
- raise self.failureException, excName
-
- def failUnlessEqual(self, first, second, msg=None):
- """Fail if the two objects are unequal as determined by the '!='
- operator.
- """
- if first != second:
- raise self.failureException, (msg or '%s != %s' % (first, second))
-
- def failIfEqual(self, first, second, msg=None):
- """Fail if the two objects are equal as determined by the '=='
- operator.
- """
- if first == second:
- raise self.failureException, (msg or '%s == %s' % (first, second))
-
- def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
- """Fail if the two objects are unequal as determined by their
- difference rounded to the given number of decimal places
- (default 7) and comparing to zero.
-
- Note that decimal places (from zero) is usually not the same
- as significant digits (measured from the most signficant digit).
- """
- if round(second-first, places) != 0:
- raise self.failureException, \
- (msg or '%s != %s within %s places' % (`first`, `second`, `places` ))
-
- def failIfAlmostEqual(self, first, second, places=7, msg=None):
- """Fail if the two objects are equal as determined by their
- difference rounded to the given number of decimal places
- (default 7) and comparing to zero.
-
- Note that decimal places (from zero) is usually not the same
- as significant digits (measured from the most signficant digit).
- """
- if round(second-first, places) == 0:
- raise self.failureException, \
- (msg or '%s == %s within %s places' % (`first`, `second`, `places`))
-
- ## aliases
-
- assertEqual = assertEquals = failUnlessEqual
-
- assertNotEqual = assertNotEquals = failIfEqual
-
- assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
-
- assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
-
- assertRaises = failUnlessRaises
-
- assert_ = failUnless
-
-
-class FunctionTestCase(TestCase):
- """A test case that wraps a test function.
-
- This is useful for slipping pre-existing test functions into the
- PyUnit framework. Optionally, set-up and tidy-up functions can be
- supplied. As with TestCase, the tidy-up ('tearDown') function will
- always be called if the set-up ('setUp') function ran successfully.
- """
-
- def __init__(self, testFunc, setUp=None, tearDown=None,
- description=None):
- TestCase.__init__(self)
- self.__setUpFunc = setUp
- self.__tearDownFunc = tearDown
- self.__testFunc = testFunc
- self.__description = description
-
- def setUp(self):
- if self.__setUpFunc is not None:
- self.__setUpFunc()
-
- def tearDown(self):
- if self.__tearDownFunc is not None:
- self.__tearDownFunc()
-
- def runTest(self):
- self.__testFunc()
-
- def id(self):
- return self.__testFunc.__name__
-
- def __str__(self):
- return "%s (%s)" % (self.__class__, self.__testFunc.__name__)
-
- def __repr__(self):
- return "<%s testFunc=%s>" % (self.__class__, self.__testFunc)
-
-
- def describe(self):
- if self.__description is not None: return self.__description
- doc = self.__testFunc.__doc__
- return doc and string.strip(string.split(doc, "\n")[0]) or None
-
- ## aliases
- shortDescription = describe
-
-class TestSuite:
- """A test suite is a composite test consisting of a number of TestCases.
-
- For use, create an instance of TestSuite, then add test case instances.
- When all tests have been added, the suite can be passed to a test
- runner, such as TextTestRunner. It will run the individual test cases
- in the order in which they were added, aggregating the results. When
- subclassing, do not forget to call the base class constructor.
- """
- def __init__(self, tests=(), suiteName=None):
- self._tests = []
- self._testMap = {}
- self.suiteName = suiteName
- self.addTests(tests)
-
- def __repr__(self):
- return "<%s tests=%s>" % (self.__class__, pprint.pformat(self._tests))
-
- __str__ = __repr__
-
- def countTestCases(self):
- cases = 0
- for test in self._tests:
- cases = cases + test.countTestCases()
- return cases
-
- def addTest(self, test):
- self._tests.append(test)
- if isinstance(test, TestSuite) and test.suiteName:
- name = test.suiteName
- elif isinstance(test, TestCase):
- #print test, test._testMethodName
- name = test._testMethodName
- else:
- name = test.__class__.__name__
- self._testMap[name] = test
-
- def addTests(self, tests):
- for test in tests:
- self.addTest(test)
-
- def getTestForName(self, name):
- return self._testMap[name]
-
- def run(self, result):
- return self(result)
-
- def __call__(self, result):
- for test in self._tests:
- if result.shouldStop:
- break
- test(result)
- return result
-
- def debug(self):
- """Run the tests without collecting errors in a TestResult"""
- for test in self._tests: test.debug()
-
-
-##############################################################################
-# Text UI
-##############################################################################
-
-class StreamWrapper:
- def __init__(self, out=sys.stdout, err=sys.stderr):
- self._streamOut = out
- self._streamErr = err
-
- def write(self, txt):
- self._streamOut.write(txt)
- self._streamOut.flush()
-
- def writeln(self, *lines):
- for line in lines:
- self.write(line + '\n')
- if not lines:
- self.write('\n')
-
- def writeErr(self, txt):
- self._streamErr.write(txt)
-
- def writelnErr(self, *lines):
- for line in lines:
- self.writeErr(line + '\n')
- if not lines:
- self.writeErr('\n')
-
-
-class _TextTestResult(TestResult, StreamWrapper):
- _separatorWidth = 70
- _sep1 = '='
- _sep2 = '-'
- _errorSep1 = '*'
- _errorSep2 = '-'
- _errorSep3 = ''
-
- def __init__(self,
- stream=sys.stdout,
- errStream=sys.stderr,
- verbosity=1,
- explain=False):
-
- TestResult.__init__(self)
- StreamWrapper.__init__(self, out=stream, err=errStream)
-
- self._verbosity = verbosity
- self._showAll = verbosity > 1
- self._dots = (verbosity == 1)
- self._explain = explain
-
- ## startup and shutdown methods
-
- def beginTests(self):
- self._startTime = time.time()
-
- def endTests(self):
- self._stopTime = time.time()
- self._timeTaken = float(self._stopTime - self._startTime)
-
- def stop(self):
- self.shouldStop = 1
-
- ## methods called for each test
-
- def startTest(self, test):
- TestResult.startTest(self, test)
- if self._showAll:
- self.write("%s (%s)" %( test.id(), test.describe() ) )
- self.write(" ... ")
-
- def addSuccess(self, test):
- TestResult.addSuccess(self, test)
- if self._showAll:
- self.writeln("ok")
- elif self._dots:
- self.write('.')
-
- def addError(self, test, err):
- TestResult.addError(self, test, err)
- if self._showAll:
- self.writeln("ERROR")
- elif self._dots:
- self.write('E')
- if err[0] is KeyboardInterrupt:
- self.stop()
-
- def addFailure(self, test, err):
- TestResult.addFailure(self, test, err)
- if self._showAll:
- self.writeln("FAIL")
- elif self._dots:
- self.write('F')
-
- ## display methods
-
- def summarize(self):
- self.printErrors()
- self.writeSep2()
- run = self.testsRun
- self.writeln("Ran %d test%s in %.3fs" %
- (run, run == 1 and "" or "s", self._timeTaken))
- self.writeln()
- if not self.wasSuccessful():
- self.writeErr("FAILED (")
- failed, errored = map(len, (self.failures, self.errors))
- if failed:
- self.writeErr("failures=%d" % failed)
- if errored:
- if failed: self.writeErr(", ")
- self.writeErr("errors=%d" % errored)
- self.writelnErr(")")
- else:
- self.writelnErr("OK")
-
- def writeSep1(self):
- self.writeln(self._sep1 * self._separatorWidth)
-
- def writeSep2(self):
- self.writeln(self._sep2 * self._separatorWidth)
-
- def writeErrSep1(self):
- self.writeln(self._errorSep1 * self._separatorWidth)
-
- def writeErrSep2(self):
- self.writeln(self._errorSep2 * self._separatorWidth)
-
- def printErrors(self):
- if self._dots or self._showAll:
- self.writeln()
- self.printErrorList('ERROR', self.errors)
- self.printErrorList('FAIL', self.failures)
-
- def printErrorList(self, flavour, errors):
- for test, err in errors:
- self.writeErrSep1()
- self.writelnErr("%s %s (%s)" % (flavour, test.id(), test.describe() ))
- if self._explain:
- expln = test.explain()
- if expln:
- self.writeErrSep2()
- self.writeErr( expln )
- self.writelnErr()
-
- self.writeErrSep2()
- for line in apply(traceback.format_exception, err):
- for l in line.split("\n")[:-1]:
- self.writelnErr(l)
- self.writelnErr("")
-
-class TextTestRunner:
- def __init__(self,
- stream=sys.stdout,
- errStream=sys.stderr,
- verbosity=1,
- explain=False):
-
- self._out = stream
- self._err = errStream
- self._verbosity = verbosity
- self._explain = explain
-
- ## main methods
-
- def run(self, test):
- result = self._makeResult()
- result.beginTests()
- test( result )
- result.endTests()
- result.summarize()
-
- return result
-
- ## internal methods
-
- def _makeResult(self):
- return _TextTestResult(stream=self._out,
- errStream=self._err,
- verbosity=self._verbosity,
- explain=self._explain,
- )
-
-##############################################################################
-# Locating and loading tests
-##############################################################################
-
-class TestLoader:
- """This class is responsible for loading tests according to various
- criteria and returning them wrapped in a Test
- """
- testMethodPrefix = 'test'
- sortTestMethodsUsing = cmp
- suiteClass = TestSuite
-
- def loadTestsFromTestCase(self, testCaseClass):
- """Return a suite of all tests cases contained in testCaseClass"""
- return self.suiteClass(tests=map(testCaseClass,
- self.getTestCaseNames(testCaseClass)),
- suiteName=testCaseClass.__name__)
-
- def loadTestsFromModule(self, module):
- """Return a suite of all tests cases contained in the given module"""
- tests = []
- for name in dir(module):
- obj = getattr(module, name)
- if type(obj) == types.ClassType and issubclass(obj, TestCase):
- tests.append(self.loadTestsFromTestCase(obj))
- return self.suiteClass(tests)
-
- def loadTestsFromName(self, name, module=None):
- """Return a suite of all tests cases given a string specifier.
-
- The name may resolve either to a module, a test case class, a
- test method within a test case class, or a callable object which
- returns a TestCase or TestSuite instance.
-
- The method optionally resolves the names relative to a given module.
- """
- parts = string.split(name, '.')
- if module is None:
- if not parts:
- raise ValueError, "incomplete test name: %s" % name
- else:
- parts_copy = parts[:]
- while parts_copy:
- try:
- module = __import__(string.join(parts_copy,'.'))
- break
- except ImportError:
- del parts_copy[-1]
- if not parts_copy: raise
- parts = parts[1:]
- obj = module
- for part in parts:
- if isinstance(obj, TestSuite):
- obj = obj.getTestForName(part)
- else:
- obj = getattr(obj, part)
-
- if type(obj) == types.ModuleType:
- return self.loadTestsFromModule(obj)
- elif type(obj) == types.ClassType and issubclass(obj, TestCase):
- return self.loadTestsFromTestCase(obj)
- elif type(obj) == types.UnboundMethodType:
- return obj.im_class(obj.__name__)
- elif isinstance(obj, TestSuite):
- return obj
- elif isinstance(obj, TestCase):
- return obj
- elif callable(obj):
- test = obj()
- if not isinstance(test, TestCase) and \
- not isinstance(test, TestSuite):
- raise ValueError, \
- "calling %s returned %s, not a test" %(obj,test)
- return test
- else:
- raise ValueError, "don't know how to make test from: %s" % obj
-
- def loadTestsFromNames(self, names, module=None):
- """Return a suite of all tests cases found using the given sequence
- of string specifiers. See 'loadTestsFromName()'.
- """
- suites = []
- for name in names:
- suites.append(self.loadTestsFromName(name, module))
- return self.suiteClass(suites)
-
- def getTestCaseNames(self, testCaseClass):
- """Return a sorted sequence of method names found within testCaseClass.
- """
- testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p,
- dir(testCaseClass))
- for baseclass in testCaseClass.__bases__:
- for testFnName in self.getTestCaseNames(baseclass):
- if testFnName not in testFnNames: # handle overridden methods
- testFnNames.append(testFnName)
- if self.sortTestMethodsUsing:
- testFnNames.sort(self.sortTestMethodsUsing)
- return testFnNames
-
-
-
-defaultTestLoader = TestLoader()
-
-
-##############################################################################
-# Patches for old functions: these functions should be considered obsolete
-##############################################################################
-
-def _makeLoader(prefix, sortUsing, suiteClass=None):
- loader = TestLoader()
- loader.sortTestMethodsUsing = sortUsing
- loader.testMethodPrefix = prefix
- if suiteClass: loader.suiteClass = suiteClass
- return loader
-
-def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
- return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
-
-def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
- return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
-
-def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
- return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
-
-##############################################################################
-# Facilities for running tests from the command line
-##############################################################################
-
-class TestProgram:
- """A command-line program that runs a set of tests; this is primarily
- for making test modules conveniently executable.
- """
- USAGE = """\
-Usage: %(progName)s [options] [test] [...]
-
-Options:
- -h, --help Show this message
- -v, --verbose Verbose output
- -q, --quiet Minimal output
- -e, --expain Output extra test details if there is a failure or error
-
-Examples:
- %(progName)s - run default set of tests
- %(progName)s MyTestSuite - run suite 'MyTestSuite'
- %(progName)s MyTestSuite.MyTestCase - run suite 'MyTestSuite'
- %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
- %(progName)s MyTestCase - run all 'test*' test methods
- in MyTestCase
-"""
- def __init__(self, module='__main__', defaultTest=None,
- argv=None, testRunner=None, testLoader=defaultTestLoader,
- testSuite=None):
- if type(module) == type(''):
- self.module = __import__(module)
- for part in string.split(module,'.')[1:]:
- self.module = getattr(self.module, part)
- else:
- self.module = module
- if argv is None:
- argv = sys.argv
- self.test = testSuite
- self.verbosity = 1
- self.explain = 0
- self.defaultTest = defaultTest
- self.testRunner = testRunner
- self.testLoader = testLoader
- self.progName = os.path.basename(argv[0])
- self.parseArgs(argv)
- self.runTests()
-
- def usageExit(self, msg=None):
- if msg: print msg
- print self.USAGE % self.__dict__
- sys.exit(2)
-
- def parseArgs(self, argv):
- import getopt
- try:
- options, args = getopt.getopt(argv[1:], 'hHvqer',
- ['help','verbose','quiet','explain', 'raise'])
- for opt, value in options:
- if opt in ('-h','-H','--help'):
- self.usageExit()
- if opt in ('-q','--quiet'):
- self.verbosity = 0
- if opt in ('-v','--verbose'):
- self.verbosity = 2
- if opt in ('-e','--explain'):
- self.explain = True
- if len(args) == 0 and self.defaultTest is None and self.test is None:
- self.test = self.testLoader.loadTestsFromModule(self.module)
- return
- if len(args) > 0:
- self.testNames = args
- else:
- self.testNames = (self.defaultTest,)
- self.createTests()
- except getopt.error, msg:
- self.usageExit(msg)
-
- def createTests(self):
- if self.test == None:
- self.test = self.testLoader.loadTestsFromNames(self.testNames,
- self.module)
-
- def runTests(self):
- if self.testRunner is None:
- self.testRunner = TextTestRunner(verbosity=self.verbosity,
- explain=self.explain)
- result = self.testRunner.run(self.test)
- self._cleanupAfterRunningTests()
- sys.exit(not result.wasSuccessful())
-
- def _cleanupAfterRunningTests(self):
- """A hook method that is called immediately prior to calling
- sys.exit(not result.wasSuccessful()) in self.runTests().
- """
- pass
-
-main = TestProgram
-
-
-##############################################################################
-# Executing this module from the command line
-##############################################################################
-
-if __name__ == "__main__":
- main(module=None)
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/Tools/CGITemplate.py b/cobbler/Cheetah/Tools/CGITemplate.py
deleted file mode 100644
index b72e62b..0000000
--- a/cobbler/Cheetah/Tools/CGITemplate.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python
-# $Id: CGITemplate.py,v 1.6 2006/01/29 02:09:59 tavis_rudd Exp $
-"""A subclass of Cheetah.Template for use in CGI scripts.
-
-Usage in a template:
- #extends Cheetah.Tools.CGITemplate
- #implements respond
- $cgiHeaders#slurp
-
-Usage in a template inheriting a Python class:
-1. The template
- #extends MyPythonClass
- #implements respond
- $cgiHeaders#slurp
-
-2. The Python class
- from Cheetah.Tools import CGITemplate
- class MyPythonClass(CGITemplate):
- def cgiHeadersHook(self):
- return "Content-Type: text/html; charset=koi8-r\n\n"
-
-To read GET/POST variables, use the .webInput method defined in
-Cheetah.Utils.WebInputMixin (available in all templates without importing
-anything), use Python's 'cgi' module, or make your own arrangements.
-
-This class inherits from Cheetah.Template to make it usable in Cheetah's
-single-inheritance model.
-
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@mso.oz.net>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.6 $
-Start Date: 2001/10/03
-Last Revision Date: $Date: 2006/01/29 02:09:59 $
-"""
-__author__ = "Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.6 $"[11:-2]
-
-import os
-from Cheetah.Template import Template
-
-class CGITemplate(Template):
- """Methods useful in CGI scripts.
-
- Any class that inherits this mixin must also inherit Cheetah.Servlet.
- """
-
-
- def cgiHeaders(self):
- """Outputs the CGI headers if this is a CGI script.
-
- Usage: $cgiHeaders#slurp
- Override .cgiHeadersHook() if you want to customize the headers.
- """
- if self.isCgi():
- return self.cgiHeadersHook()
-
-
-
- def cgiHeadersHook(self):
- """Override if you want to customize the CGI headers.
- """
- return "Content-type: text/html\n\n"
-
-
- def isCgi(self):
- """Is this a CGI script?
- """
- env = os.environ.has_key('REQUEST_METHOD')
- wk = self._CHEETAH__isControlledByWebKit
- return env and not wk
-
-
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/Tools/MondoReport.py b/cobbler/Cheetah/Tools/MondoReport.py
deleted file mode 100644
index f73e7fc..0000000
--- a/cobbler/Cheetah/Tools/MondoReport.py
+++ /dev/null
@@ -1,464 +0,0 @@
-#!/usr/bin/env python
-"""
-@@TR: This code is pretty much unsupported.
-
-MondoReport.py -- Batching module for Python and Cheetah.
-
-Version 2001-Nov-18. Doesn't do much practical yet, but the companion
-testMondoReport.py passes all its tests.
--Mike Orr (Iron)
-
-TODO: BatchRecord.prev/next/prev_batches/next_batches/query, prev.query,
-next.query.
-
-How about Report: .page(), .all(), .summary()? Or PageBreaker.
-"""
-import operator, types
-try:
- from Cheetah.NameMapper import valueForKey as lookup_func
-except ImportError:
- def lookup_func(obj, name):
- if hasattr(obj, name):
- return getattr(obj, name)
- else:
- return obj[name] # Raises KeyError.
-
-########## CONSTANTS ##############################
-
-True, False = (1==1), (1==0)
-numericTypes = types.IntType, types.LongType, types.FloatType
-
-########## PUBLIC GENERIC FUNCTIONS ##############################
-
-class NegativeError(ValueError):
- pass
-
-def isNumeric(v):
- return type(v) in numericTypes
-
-def isNonNegative(v):
- ret = isNumeric(v)
- if ret and v < 0:
- raise NegativeError(v)
-
-def isNotNone(v):
- return v is not None
-
-def Roman(n):
- n = int(n) # Raises TypeError.
- if n < 1:
- raise ValueError("roman numeral for zero or negative undefined: " + n)
- roman = ''
- while n >= 1000:
- n = n - 1000
- roman = roman + 'M'
- while n >= 500:
- n = n - 500
- roman = roman + 'D'
- while n >= 100:
- n = n - 100
- roman = roman + 'C'
- while n >= 50:
- n = n - 50
- roman = roman + 'L'
- while n >= 10:
- n = n - 10
- roman = roman + 'X'
- while n >= 5:
- n = n - 5
- roman = roman + 'V'
- while n < 5 and n >= 1:
- n = n - 1
- roman = roman + 'I'
- roman = roman.replace('DCCCC', 'CM')
- roman = roman.replace('CCCC', 'CD')
- roman = roman.replace('LXXXX', 'XC')
- roman = roman.replace('XXXX', 'XL')
- roman = roman.replace('VIIII', 'IX')
- roman = roman.replace('IIII', 'IV')
- return roman
-
-
-def sum(lis):
- return reduce(operator.add, lis, 0)
-
-def mean(lis):
- """Always returns a floating-point number.
- """
- lis_len = len(lis)
- if lis_len == 0:
- return 0.00 # Avoid ZeroDivisionError (not raised for floats anyway)
- total = float( sum(lis) )
- return total / lis_len
-
-def median(lis):
- lis = lis[:]
- lis.sort()
- return lis[int(len(lis)/2)]
-
-
-def variance(lis):
- raise NotImplementedError()
-
-def variance_n(lis):
- raise NotImplementedError()
-
-def standardDeviation(lis):
- raise NotImplementedError()
-
-def standardDeviation_n(lis):
- raise NotImplementedError()
-
-
-
-class IndexFormats:
- """Eight ways to display a subscript index.
- ("Fifty ways to leave your lover....")
- """
- def __init__(self, index, item=None):
- self._index = index
- self._number = index + 1
- self._item = item
-
- def index(self):
- return self._index
-
- __call__ = index
-
- def number(self):
- return self._number
-
- def even(self):
- return self._number % 2 == 0
-
- def odd(self):
- return not self.even()
-
- def even_i(self):
- return self._index % 2 == 0
-
- def odd_i(self):
- return not self.even_i()
-
- def letter(self):
- return self.Letter().lower()
-
- def Letter(self):
- n = ord('A') + self._index
- return chr(n)
-
- def roman(self):
- return self.Roman().lower()
-
- def Roman(self):
- return Roman(self._number)
-
- def item(self):
- return self._item
-
-
-
-########## PRIVATE CLASSES ##############################
-
-class ValuesGetterMixin:
- def __init__(self, origList):
- self._origList = origList
-
- def _getValues(self, field=None, criteria=None):
- if field:
- ret = [lookup_func(elm, field) for elm in self._origList]
- else:
- ret = self._origList
- if criteria:
- ret = filter(criteria, ret)
- return ret
-
-
-class RecordStats(IndexFormats, ValuesGetterMixin):
- """The statistics that depend on the current record.
- """
- def __init__(self, origList, index):
- record = origList[index] # Raises IndexError.
- IndexFormats.__init__(self, index, record)
- ValuesGetterMixin.__init__(self, origList)
-
- def length(self):
- return len(self._origList)
-
- def first(self):
- return self._index == 0
-
- def last(self):
- return self._index >= len(self._origList) - 1
-
- def _firstOrLastValue(self, field, currentIndex, otherIndex):
- currentValue = self._origList[currentIndex] # Raises IndexError.
- try:
- otherValue = self._origList[otherIndex]
- except IndexError:
- return True
- if field:
- currentValue = lookup_func(currentValue, field)
- otherValue = lookup_func(otherValue, field)
- return currentValue != otherValue
-
- def firstValue(self, field=None):
- return self._firstOrLastValue(field, self._index, self._index - 1)
-
- def lastValue(self, field=None):
- return self._firstOrLastValue(field, self._index, self._index + 1)
-
- # firstPage and lastPage not implemented. Needed?
-
- def percentOfTotal(self, field=None, suffix='%', default='N/A', decimals=2):
- rec = self._origList[self._index]
- if field:
- val = lookup_func(rec, field)
- else:
- val = rec
- try:
- lis = self._getValues(field, isNumeric)
- except NegativeError:
- return default
- total = sum(lis)
- if total == 0.00: # Avoid ZeroDivisionError.
- return default
- val = float(val)
- try:
- percent = (val / total) * 100
- except ZeroDivisionError:
- return default
- if decimals == 0:
- percent = int(percent)
- else:
- percent = round(percent, decimals)
- if suffix:
- return str(percent) + suffix # String.
- else:
- return percent # Numeric.
-
- def __call__(self): # Overrides IndexFormats.__call__
- """This instance is not callable, so we override the super method.
- """
- raise NotImplementedError()
-
- def prev(self):
- if self._index == 0:
- return None
- else:
- length = self.length()
- start = self._index - length
- return PrevNextPage(self._origList, length, start)
-
- def next(self):
- if self._index + self.length() == self.length():
- return None
- else:
- length = self.length()
- start = self._index + length
- return PrevNextPage(self._origList, length, start)
-
- def prevPages(self):
- raise NotImplementedError()
-
- def nextPages(self):
- raise NotImplementedError()
-
- prev_batches = prevPages
- next_batches = nextPages
-
- def summary(self):
- raise NotImplementedError()
-
-
-
- def _prevNextHelper(self, start,end,size,orphan,sequence):
- """Copied from Zope's DT_InSV.py's "opt" function.
- """
- if size < 1:
- if start > 0 and end > 0 and end >= start:
- size=end+1-start
- else: size=7
-
- if start > 0:
-
- try: sequence[start-1]
- except: start=len(sequence)
- # if start > l: start=l
-
- if end > 0:
- if end < start: end=start
- else:
- end=start+size-1
- try: sequence[end+orphan-1]
- except: end=len(sequence)
- # if l - end < orphan: end=l
- elif end > 0:
- try: sequence[end-1]
- except: end=len(sequence)
- # if end > l: end=l
- start=end+1-size
- if start - 1 < orphan: start=1
- else:
- start=1
- end=start+size-1
- try: sequence[end+orphan-1]
- except: end=len(sequence)
- # if l - end < orphan: end=l
- return start,end,size
-
-
-
-class Summary(ValuesGetterMixin):
- """The summary statistics, that don't depend on the current record.
- """
- def __init__(self, origList):
- ValuesGetterMixin.__init__(self, origList)
-
- def sum(self, field=None):
- lis = self._getValues(field, isNumeric)
- return sum(lis)
-
- total = sum
-
- def count(self, field=None):
- lis = self._getValues(field, isNotNone)
- return len(lis)
-
- def min(self, field=None):
- lis = self._getValues(field, isNotNone)
- return min(lis) # Python builtin function min.
-
- def max(self, field=None):
- lis = self._getValues(field, isNotNone)
- return max(lis) # Python builtin function max.
-
- def mean(self, field=None):
- """Always returns a floating point number.
- """
- lis = self._getValues(field, isNumeric)
- return mean(lis)
-
- average = mean
-
- def median(self, field=None):
- lis = self._getValues(field, isNumeric)
- return median(lis)
-
- def variance(self, field=None):
- raiseNotImplementedError()
-
- def variance_n(self, field=None):
- raiseNotImplementedError()
-
- def standardDeviation(self, field=None):
- raiseNotImplementedError()
-
- def standardDeviation_n(self, field=None):
- raiseNotImplementedError()
-
-
-class PrevNextPage:
- def __init__(self, origList, size, start):
- end = start + size
- self.start = IndexFormats(start, origList[start])
- self.end = IndexFormats(end, origList[end])
- self.length = size
-
-
-########## MAIN PUBLIC CLASS ##############################
-class MondoReport:
- _RecordStatsClass = RecordStats
- _SummaryClass = Summary
-
- def __init__(self, origlist):
- self._origList = origlist
-
- def page(self, size, start, overlap=0, orphan=0):
- """Returns list of ($r, $a, $b)
- """
- if overlap != 0:
- raise NotImplementedError("non-zero overlap")
- if orphan != 0:
- raise NotImplementedError("non-zero orphan")
- origList = self._origList
- origList_len = len(origList)
- start = max(0, start)
- end = min( start + size, len(self._origList) )
- mySlice = origList[start:end]
- ret = []
- for rel in range(size):
- abs_ = start + rel
- r = mySlice[rel]
- a = self._RecordStatsClass(origList, abs_)
- b = self._RecordStatsClass(mySlice, rel)
- tup = r, a, b
- ret.append(tup)
- return ret
-
-
- batch = page
-
- def all(self):
- origList_len = len(self._origList)
- return self.page(origList_len, 0, 0, 0)
-
-
- def summary(self):
- return self._SummaryClass(self._origList)
-
-"""
-**********************************
- Return a pageful of records from a sequence, with statistics.
-
- in : origlist, list or tuple. The entire set of records. This is
- usually a list of objects or a list of dictionaries.
- page, int >= 0. Which page to display.
- size, int >= 1. How many records per page.
- widow, int >=0. Not implemented.
- orphan, int >=0. Not implemented.
- base, int >=0. Number of first page (usually 0 or 1).
-
- out: list of (o, b) pairs. The records for the current page. 'o' is
- the original element from 'origlist' unchanged. 'b' is a Batch
- object containing meta-info about 'o'.
- exc: IndexError if 'page' or 'size' is < 1. If 'origlist' is empty or
- 'page' is too high, it returns an empty list rather than raising
- an error.
-
- origlist_len = len(origlist)
- start = (page + base) * size
- end = min(start + size, origlist_len)
- ret = []
- # widow, orphan calculation: adjust 'start' and 'end' up and down,
- # Set 'widow', 'orphan', 'first_nonwidow', 'first_nonorphan' attributes.
- for i in range(start, end):
- o = origlist[i]
- b = Batch(origlist, size, i)
- tup = o, b
- ret.append(tup)
- return ret
-
- def prev(self):
- # return a PrevNextPage or None
-
- def next(self):
- # return a PrevNextPage or None
-
- def prev_batches(self):
- # return a list of SimpleBatch for the previous batches
-
- def next_batches(self):
- # return a list of SimpleBatch for the next batches
-
-########## PUBLIC MIXIN CLASS FOR CHEETAH TEMPLATES ##############
-class MondoReportMixin:
- def batch(self, origList, size=None, start=0, overlap=0, orphan=0):
- bat = MondoReport(origList)
- return bat.batch(size, start, overlap, orphan)
- def batchstats(self, origList):
- bat = MondoReport(origList)
- return bat.stats()
-"""
-
-# vim: shiftwidth=4 tabstop=4 expandtab textwidth=79
diff --git a/cobbler/Cheetah/Tools/MondoReportDoc.txt b/cobbler/Cheetah/Tools/MondoReportDoc.txt
deleted file mode 100644
index 29a026d..0000000
--- a/cobbler/Cheetah/Tools/MondoReportDoc.txt
+++ /dev/null
@@ -1,391 +0,0 @@
-MondoReport Documentation
-Version 0.01 alpha 24-Nov-2001. iron@mso.oz.net or mso@oz.net.
-Copyright (c) 2001 Mike Orr. License: same as Python or Cheetah.
-
-* * * * *
-STATUS: previous/next batches and query string are not implemented yet.
-Sorting not designed yet. Considering "click on this column header to sort by
-this field" and multiple ascending/descending sort fields for a future version.
-
-Tested with Python 2.2b1. May work with Python 2.1 or 2.0.
-
-* * * * *
-OVERVIEW
-
-MondoReport -- provide information about a list that is useful in generating
-any kind of report. The module consists of one main public class, and some
-generic functions you may find useful in other programs. This file contains an
-overview, syntax reference and examples. The module is designed both for
-standalone use and for integration with the Cheetah template system
-(http://www.cheetahtemplate.org/), so the examples are in both Python and
-Cheetah. The main uses of MondoReport are:
-
-(A) to iterate through a list. In this sense MR is a for-loop enhancer,
-providing information that would be verbose to calculate otherwise.
-
-(B) to separate a list into equal-size "pages" (or "batches"--the two terms are
-interchangeable) and only display the current page, plus limited information
-about the previous and next pages.
-
-(C) to extract summary statistics about a certain column ("field") in the list.
-
-* * * * *
-MAIN PUBLIC CLASS
-
-To create a MondoReport instance, supply a list to operate on.
-
- mr = MondoReport(origList)
-
-The list may be a list of anything, but if you use the 'field' argument in any
-of the methods below, the elements must be instances or dictionaries.
-
-MondoReport assumes it's operating on an unchanging list. Do not modify the
-list or any of its elements until you are completely finished with the
-ModoReport object and its sub-objects. Otherwise, you may get an exception or
-incorrect results.
-
-MondoReport instances have three methods:
-
- .page(size, start, overlap=0, orphan=0
- sort=None, reverse=False) => list of (r, a, b).
-
-'size' is an integer >= 1. 'start', 'overlap' and 'orphan' are integers >= 0.
-The list returned contains one triple for each record in the current page. 'r'
-is the original record. 'a' is a BatchRecord instance for the current record
-in relation to all records in the origList. 'b' is a BatchRecord instance for
-the current record in relation to all the records in that batch/page. (There
-is a .batch method that's identical to .page.)
-
-The other options aren't implemented yet, but 'overlap' duplicates this many
-records on adjacent batches. 'orphan' moves this many records or fewer, if
-they are on a page alone, onto the neighboring page. 'sort' (string) specifies
-a field to sort the records by. It may be suffixed by ":desc" to sort in
-descending order. 'reverse' (boolean) reverses the sort order. If both
-":desc" and 'reverse' are specified, they will cancel each other out. This
-sorting/reversal happens on a copy of the origList, and all objects returned
-by this method use the sorted list, except when resorting the next time.
-To do more complicated sorting, such as a hierarchy of columns, do it to the
-original list before creating the ModoReport object.
-
- .all(sort=None, reverse=False) => list of (r, a).
-
-Same, but the current page spans the entire origList.
-
- .summary() => Summary instance.
-
-Summary statistics for the entire origList.
-
-In Python, use .page or .all in a for loop:
-
- from Cheetah.Tools.MondoReport import MondoReport
- mr = MondoReport(myList)
- for r, a, b in mr.page(20, 40):
- # Do something with r, a and b. The current page is the third page,
- # with twenty records corresponding to origList[40:60].
- if not myList:
- # Warn the user there are no records in the list.
-
-It works the same way in Cheetah, just convert to Cheetah syntax. This example
-assumes the template doubles as a Webware servlet, so we use the servlet's
-'$request' method to look up the CGI parameter 'start'. The default value is 0
-for the first page.
-
- #from Cheetah.Tools.MondoReport import MondoReport
- #set $mr = $MondoReport($bigList)
- #set $start = $request.field("start", 0)
- #for $o, $a, $b in $mr.page(20, $start)
- ... do something with $o, $a and $b ...
- #end for
- #unless $bigList
- This is displayed if the original list has no elements.
- It's equivalent to the "else" part Zope DTML's <dtml-in>.
- #end unless
-
-* * * * *
-USING 'r' RECORDS
-
-Use 'r' just as you would the original element. For instance:
-
- print r.attribute # If r is an instance.
- print r['key'] # If r is a dictionary.
- print r # If r is numeric or a string.
-
-In Cheetah, you can take advantage of Universal Dotted Notation and autocalling:
-
- $r.name ## 'name' may be an attribute or key of 'r'. If 'r' and/or
- ## 'name' is a function or method, it will be called without
- ## arguments.
- $r.attribute
- $r['key']
- $r
- $r().attribute()['key']()
-
-If origList is a list of name/value pairs (2-tuples or 2-lists), you may
-prefer to do this:
-
- for (key, value), a, b in mr.page(20, 40):
- print key, "=>", value
-
- #for ($key, $value), $a, $b in $mr.page(20, $start)
- $key =&gt; $value
- #end for
-
-* * * * *
-STATISTICS METHODS AND FIELD VALUES
-
-Certain methods below have an optional argument 'field'. If specified,
-MondoReport will look up that field in each affected record and use its value
-in the calculation. MondoReport uses Cheetah's NameMapper if available,
-otherwise it uses a minimal NameMapper substitute that looks for an attribute
-or dictionary key called "field". You'll get an exception if any record is a
-type without attributes or keys, or if one or more records is missing that
-attribute/key.
-
-If 'field' is None, MondoReport will use the entire record in its
-calculation. This makes sense mainly if the records are a numeric type.
-
-All statistics methods filter out None values from their calculations, and
-reduce the number of records accordingly. Most filter out non-numeric fields
-(or records). Some raise NegativeError if a numeric field (or record) is
-negative.
-
-
-* * * * *
-BatchRecord METHODS
-
-The 'a' and 'b' objects of MondoReport.page() and MondoReport.all() provide
-these methods.
-
- .index()
-
-The current subscript. For 'a', this is the true subscript into origList.
-For 'b', this is relative to the current page, so the first record will be 0.
-Hint: In Cheetah, use autocalling to skip the parentheses: '$b.index'.
-
- .number()
-
-The record's position starting from 1. This is always '.index() + 1'.
-
- .Letter()
-
-The letter ("A", "B", "C") corresponding to .number(). Undefined if .number()
-> 26. The current implementation just adds the offset to 'a' and returns
-whatever character it happens to be.
-
-To make a less dumb implementation (e.g., "Z, AA, BB" or "Z, A1, B1"):
-1) Subclass BatchRecord and override the .Letter method.
-2) Subclass MondoReport and set the class variable .BatchRecordClass to your
-new improved class.
-
- .letter()
-
-Same but lower case.
-
- .Roman()
-
-The Roman numeral corresponding to .number().
-
- .roman()
-
-Same but lower case.
-
- .even()
-
-True if .number() is even.
-
- .odd()
-
-True if .number() is odd.
-
- .even_i()
-
-True if .index() is even.
-
- .odd_i()
-
-True if .index() is odd.
-
- .length()
-
-For 'a', number of records in origList. For 'b', number of records on this
-page.
-
- .item()
-
-The record itself. You don't need this in the normal case since it's the same
-as 'r', but it's useful for previous/next batches.
-
- .size()
-
-The 'size' argument used when this BatchRecord was created.
-'a.size() == b.size()'.
-
- .first()
-
-True if this is the first record.
-
- .last()
-
-True if this is the last record.
-
- .firstValue(field=None)
-
-True if there is no previous record, or if the previous field/record has a
-different value. Used for to print section headers. For instance, if you
-are printing addresses by country, this will be true at the first occurrance
-of each country. Or for indexes, you can have a non-printing field showing
-which letter of the alphablet this entry starts with, and then print a "B"
-header before printing the first record starting with "B".
-
- .lastValue(field=None)
-
-True if this is the last record containing the current value in the
-field/record.
-
- .percentOfTotal(field=None, suffix="%", default="N/A", decimals=2)
-
-Returns the percent that the current field/record is of all fields/records.
-If 'suffix' is None, returns a number; otherwise it returns a string with
-'suffix' suffixed. If the current value is non-numeric, returns 'default'
-instead (without 'suffix'). 'decimals' tells the number of decimal places to
-return; if 0, there will be no decimal point.
-
- .prev()
-
-Returns a PrevNextBatch instance for the previous page. If there is no
-previous page, returns None. [Not implemented yet.]
-
- .next()
-
-Returns a PrevNextBatch instance for the next page. If there is no next page,
-returns None. [Not implemented yet.]
-
- .prevPages()
-
-Returns a list of PrevNextPage instances for every previous page, or [] if no
-previous pages. [Not implemented yet.]
-
- .nextPages()
-
-Returns a list of PrevNextPage instances for every next page, or [] if no next
-pages. [Not implemented yet.]
-
- .query(start=None, label=None, attribName="start", attribs=[])
-
-[Not implemented yet.]
-
-With no arguments, returns the HTML query string with start value removed (so
-you can append a new start value in your hyperlink). The query string is taken
-from the 'QUERY_STRING' environmental variable, or "" if missing. (This is
-Webware compatible.)
-
-With 'start' (an integer >= 0), returns the query string with an updated start
-value, normally for the next or previous batch.
-
-With 'label' (a string), returns a complete HTML hyperlink:
-'<A HREF="?new_query_string">label</A>'. You'll get a TypeError if you specify
-'label' but not 'start'.
-
-With 'attribName' (a string), uses this attribute name rather than "start".
-Useful if you have another CGI parameter "start" that's used for something
-else.
-
-With 'attribs' (a dictionary), adds these attributes to the hyperlink.
-For instance, 'attribs={"target": "_blank"}'. Ignored unless 'label' is
-specified too.
-
-This method assumes the start parameter is a GET variable, not a POST variable.
-
- .summary()
-
-Returns a Summary instance. 'a.summary()' refers to all records in the
-origList, so it's the same as MondoReport.summary(). 'b.summary()' refers only
-to the records on the current page. [Not implemented yet.]
-
-* * * * *
-PrevNextPage INSTANCES
-
-[Not implemented yet.]
-
-PrevNextPage instances have the following methods:
-
- .start()
-
-The index (true index of origList) that that page starts at. You may also use
-'.start().index()', '.start().number()', etc. Also
-'.start().item(field=None)'. (Oh, so *that*'s what .item is for!)
-
- .end()
-
-The index (true index of origList) that that page ends at. You may also use
-'.end().index()', '.end().number()', etc. Also
-'.end().item(field=None)'.
-
- .length()
-
-Number of records on that page.
-
- .query(label=None, attribName="start", attribs={}, before="", after="")
-
-[Not implemented yet.]
-
-Similar to 'a.query()' and 'b.query()', but automatically calculates the start
-value for the appropriate page.
-
-For fancy HTML formatting, 'before' is prepended to the returned text and
-'after' is appended. (There was an argument 'else_' for if there is no such
-batch, but it was removed because you can't even get to this method at all in
-that case.)
-
-* * * * * *
-SUMMARY STATISTICS
-
-These methods are supported by the Summary instances returned by
-MondoReport.Summary():
-
- .sum(field=None)
-
-Sum of all numeric values in a field, or sum of all records.
-
- .total(field=None)
-
-Same.
-
- .count(field=None)
-
-Number of fields/records with non-None values.
-
- .min(field=None)
-
-Minimum value in that field/record. Ignores None values.
-
- .max(field=None)
-
-Maximum value in that field/record. Ignores None values.
-
- .mean(field=None)
-
-The mean (=average) of all numeric values in that field/record.
-
- .average(field=None)
-
-Same.
-
- .median(field=None)
-
-The median of all numeric values in that field/record. This is done by sorting
-the values and taking the middle value.
-
- .variance(field=None), .variance_n(field=None)
- .standardDeviation(field=None), .standardDeviation_n(field=None)
-
-[Not implemented yet.]
-
-
-* * * * *
-To run the regression tests (requires unittest.py, which is standard with
-Python 2.2), run MondoReportTest.py from the command line. The regression test
-double as usage examples.
-
-
-# vim: shiftwidth=4 tabstop=4 expandtab textwidth=79
diff --git a/cobbler/Cheetah/Tools/RecursiveNull.py b/cobbler/Cheetah/Tools/RecursiveNull.py
deleted file mode 100644
index 4897d80..0000000
--- a/cobbler/Cheetah/Tools/RecursiveNull.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-"""Nothing, but in a friendly way. Good for filling in for objects you want to
-hide. If $form.f1 is a RecursiveNull object, then
-$form.f1.anything["you"].might("use") will resolve to the empty string.
-
-This module was contributed by Ian Bicking.
-"""
-
-class RecursiveNull:
- __doc__ = __doc__ # Use the module's docstring for the class's docstring.
- def __getattr__(self, attr):
- return self
- def __getitem__(self, item):
- return self
- def __call__(self, *vars, **kw):
- return self
- def __str__(self):
- return ''
- def __repr__(self):
- return ''
- def __nonzero__(self):
- return 0
-
diff --git a/cobbler/Cheetah/Tools/SiteHierarchy.py b/cobbler/Cheetah/Tools/SiteHierarchy.py
deleted file mode 100644
index d4a92e1..0000000
--- a/cobbler/Cheetah/Tools/SiteHierarchy.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/env python
-# $Id: SiteHierarchy.py,v 1.1 2001/10/11 03:25:54 tavis_rudd Exp $
-"""Create menus and crumbs from a site hierarchy.
-
-You define the site hierarchy as lists/tuples. Each location in the hierarchy
-is a (url, description) tuple. Each list has the base URL/text in the 0
-position, and all the children coming after it. Any child can be a list,
-representing further depth to the hierarchy. See the end of the file for an
-example hierarchy.
-
-Use Hierarchy(contents, currentURL), where contents is this hierarchy, and
-currentURL is the position you are currently in. The menubar and crumbs methods
-give you the HTML output.
-
-There are methods you can override to customize the HTML output.
-
-Meta-Data
-================================================================================
-Author: Ian Bicking <ianb@colorstudy.com>
-Version: $Revision: 1.1 $
-Start Date: 2001/07/23
-Last Revision Date: $Date: 2001/10/11 03:25:54 $
-"""
-__author__ = "Ian Bicking <ianb@colorstudy.com>"
-__version__ = "$Revision: 1.1 $"[11:-2]
-
-##################################################
-## DEPENDENCIES
-import string
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
-
-##################################################
-## GLOBALS & CONSTANTS
-
-True, False = (1==1), (0==1)
-
-##################################################
-## CLASSES
-
-class Hierarchy:
- def __init__(self, hierarchy, currentURL, prefix='', menuCSSClass=None,
- crumbCSSClass=None):
- """
- hierarchy is described above, currentURL should be somewhere in
- the hierarchy. prefix will be added before all of the URLs (to
- help mitigate the problems with absolute URLs), and if given,
- cssClass will be used for both links *and* nonlinks.
- """
-
- self._contents = hierarchy
- self._currentURL = currentURL
- if menuCSSClass:
- self._menuCSSClass = ' class="%s"' % menuCSSClass
- else:
- self._menuCSSClass = ''
- if crumbCSSClass:
- self._crumbCSSClass = ' class="%s"' % crumbCSSClass
- else:
- self._crumbCSSClass = ''
- self._prefix=prefix
-
-
- ## Main output methods
-
- def menuList(self, menuCSSClass=None):
- """An indented menu list"""
- if menuCSSClass:
- self._menuCSSClass = ' class="%s"' % menuCSSClass
-
- stream = StringIO()
- for item in self._contents[1:]:
- self._menubarRecurse(item, 0, stream)
- return stream.getvalue()
-
- def crumbs(self, crumbCSSClass=None):
- """The home>where>you>are crumbs"""
- if crumbCSSClass:
- self._crumbCSSClass = ' class="%s"' % crumbCSSClass
-
- path = []
- pos = self._contents
- while 1:
- ## This is not the fastest algorithm, I'm afraid.
- ## But it probably won't be for a huge hierarchy anyway.
- foundAny = False
- path.append(pos[0])
- for item in pos[1:]:
- if self._inContents(item):
- if type(item) is type(()):
- path.append(item)
- break
- else:
- pos = item
- foundAny = True
- break
- if not foundAny:
- break
- if len(path) == 1:
- return self.emptyCrumb()
- return string.join(map(lambda x, self=self: self.crumbLink(x[0], x[1]),
- path), self.crumbSeperator()) + \
- self.crumbTerminator()
-
- ## Methods to control the Aesthetics
- # - override these methods for your own look
-
- def menuLink(self, url, text, indent):
- if url == self._currentURL or self._prefix + url == self._currentURL:
- return '%s<B%s>%s</B> <BR>\n' % ('&nbsp;'*2*indent,
- self._menuCSSClass, text)
- else:
- return '%s<A HREF="%s%s"%s>%s</A> <BR>\n' % \
- ('&nbsp;'*2*indent, self._prefix, url,
- self._menuCSSClass, text)
-
- def crumbLink(self, url, text):
- if url == self._currentURL or self._prefix + url == self._currentURL:
- return '<B%s>%s</B>' % (text, self._crumbCSSClass)
- else:
- return '<A HREF="%s%s"%s>%s</A>' % \
- (self._prefix, url, self._crumbCSSClass, text)
-
- def crumbSeperator(self):
- return '&nbsp;&gt;&nbsp;'
-
- def crumbTerminator(self):
- return ''
-
- def emptyCrumb(self):
- """When you are at the homepage"""
- return ''
-
- ## internal methods
-
- def _menubarRecurse(self, contents, indent, stream):
- if type(contents) is type(()):
- url, text = contents
- rest = []
- else:
- url, text = contents[0]
- rest = contents[1:]
- stream.write(self.menuLink(url, text, indent))
- if self._inContents(contents):
- for item in rest:
- self._menubarRecurse(item, indent+1, stream)
-
- def _inContents(self, contents):
- if type(contents) is type(()):
- return self._currentURL == contents[0]
- for item in contents:
- if self._inContents(item):
- return True
- return False
-
-##################################################
-## from the command line
-
-if __name__ == '__main__':
- hierarchy = [('/', 'home'),
- ('/about', 'About Us'),
- [('/services', 'Services'),
- [('/services/products', 'Products'),
- ('/services/products/widget', 'The Widget'),
- ('/services/products/wedge', 'The Wedge'),
- ('/services/products/thimble', 'The Thimble'),
- ],
- ('/services/prices', 'Prices'),
- ],
- ('/contact', 'Contact Us'),
- ]
-
- for url in ['/', '/services', '/services/products/widget', '/contact']:
- print '<p>', '='*50
- print '<br> %s: <br>\n' % url
- n = Hierarchy(hierarchy, url, menuCSSClass='menu', crumbCSSClass='crumb',
- prefix='/here')
- print n.menuList()
- print '<p>', '-'*50
- print n.crumbs()
diff --git a/cobbler/Cheetah/Tools/__init__.py b/cobbler/Cheetah/Tools/__init__.py
deleted file mode 100644
index 506503b..0000000
--- a/cobbler/Cheetah/Tools/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-"""This package contains classes, functions, objects and packages contributed
- by Cheetah users. They are not used by Cheetah itself. There is no
- guarantee that this directory will be included in Cheetah releases, that
- these objects will remain here forever, or that they will remain
- backward-compatible.
-"""
-
-# vim: shiftwidth=5 tabstop=5 expandtab
diff --git a/cobbler/Cheetah/Unspecified.py b/cobbler/Cheetah/Unspecified.py
deleted file mode 100644
index 89c5176..0000000
--- a/cobbler/Cheetah/Unspecified.py
+++ /dev/null
@@ -1,9 +0,0 @@
-try:
- from ds.sys.Unspecified import Unspecified
-except ImportError:
- class _Unspecified:
- def __repr__(self):
- return 'Unspecified'
- def __str__(self):
- return 'Unspecified'
- Unspecified = _Unspecified()
diff --git a/cobbler/Cheetah/Utils/Indenter.py b/cobbler/Cheetah/Utils/Indenter.py
deleted file mode 100644
index abdb0dd..0000000
--- a/cobbler/Cheetah/Utils/Indenter.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/env python
-# $Id: Indenter.py,v 1.7 2006/01/08 01:09:30 tavis_rudd Exp $
-"""Indentation maker.
-@@TR: this code is unsupported and largely undocumented ...
-
-This version is based directly on code by Robert Kuzelj
-<robert_kuzelj@yahoo.com> and uses his directive syntax. Some classes and
-attributes have been renamed. Indentation is output via
-$self._CHEETAH__indenter.indent() to prevent '_indenter' being looked up on the
-searchList and another one being found. The directive syntax will
-soon be changed somewhat.
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@mso.oz.net>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.7 $
-Start Date: 2001/11/07
-Last Revision Date: $Date: 2006/01/08 01:09:30 $
-"""
-__author__ = "Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.7 $"[11:-2]
-
-import re
-import sys
-
-def indentize(source):
- return IndentProcessor().process(source)
-
-class IndentProcessor:
- """Preprocess #indent tags."""
- LINE_SEP = '\n'
- ARGS = "args"
- INDENT_DIR = re.compile(r'[ \t]*#indent[ \t]*(?P<args>.*)')
- DIRECTIVE = re.compile(r"[ \t]*#")
- WS = "ws"
- WHITESPACES = re.compile(r"(?P<ws>[ \t]*)")
-
- INC = "++"
- DEC = "--"
-
- SET = "="
- CHAR = "char"
-
- ON = "on"
- OFF = "off"
-
- PUSH = "push"
- POP = "pop"
-
- def process(self, _txt):
- result = []
-
- for line in _txt.splitlines():
- match = self.INDENT_DIR.match(line)
- if match:
- #is indention directive
- args = match.group(self.ARGS).strip()
- if args == self.ON:
- line = "#silent $self._CHEETAH__indenter.on()"
- elif args == self.OFF:
- line = "#silent $self._CHEETAH__indenter.off()"
- elif args == self.INC:
- line = "#silent $self._CHEETAH__indenter.inc()"
- elif args == self.DEC:
- line = "#silent $self._CHEETAH__indenter.dec()"
- elif args.startswith(self.SET):
- level = int(args[1:])
- line = "#silent $self._CHEETAH__indenter.setLevel(%(level)d)" % {"level":level}
- elif args.startswith('chars'):
- self.indentChars = eval(args.split('=')[1])
- line = "#silent $self._CHEETAH__indenter.setChars(%(level)d)" % {"level":level}
- elif args.startswith(self.PUSH):
- line = "#silent $self._CHEETAH__indenter.push()"
- elif args.startswith(self.POP):
- line = "#silent $self._CHEETAH__indenter.pop()"
- else:
- match = self.DIRECTIVE.match(line)
- if not match:
- #is not another directive
- match = self.WHITESPACES.match(line)
- if match:
- size = len(match.group("ws").expandtabs(4))
- line = ("${self._CHEETAH__indenter.indent(%(size)d)}" % {"size":size}) + line.lstrip()
- else:
- line = "${self._CHEETAH__indenter.indent(0)}" + line
- result.append(line)
-
- return self.LINE_SEP.join(result)
-
-class Indenter:
- """A class that keeps track of the current indentation level.
- .indent() returns the appropriate amount of indentation.
- """
- def __init__(self):
- self.On = 1
- self.Level = 0
- self.Chars = " "*4
- self.LevelStack = []
- def on(self):
- self.On = 1
- def off(self):
- self.On = 0
- def inc(self):
- self.Level += 1
- def dec(self):
- """decrement can only be applied to values greater zero
- values below zero don't make any sense at all!"""
- if self.Level > 0:
- self.Level -= 1
- def push(self):
- self.LevelStack.append(self.Level)
- def pop(self):
- """the levestack can not become -1. any attempt to do so
- sets the level to 0!"""
- if len(self.LevelStack) > 0:
- self.Level = self.LevelStack.pop()
- else:
- self.Level = 0
- def setLevel(self, _level):
- """the leve can't be less than zero. any attempt to do so
- sets the level automatically to zero!"""
- if _level < 0:
- self.Level = 0
- else:
- self.Level = _level
- def setChar(self, _chars):
- self.Chars = _chars
- def indent(self, _default=0):
- if self.On:
- return self.Chars * self.Level
- else:
- return " " * _default
-
diff --git a/cobbler/Cheetah/Utils/Misc.py b/cobbler/Cheetah/Utils/Misc.py
deleted file mode 100644
index aa5cc6d..0000000
--- a/cobbler/Cheetah/Utils/Misc.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# $Id: Misc.py,v 1.8 2005/11/02 22:26:08 tavis_rudd Exp $
-"""Miscellaneous functions/objects used by Cheetah but also useful standalone.
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@mso.oz.net>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.8 $
-Start Date: 2001/11/07
-Last Revision Date: $Date: 2005/11/02 22:26:08 $
-"""
-__author__ = "Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.8 $"[11:-2]
-
-import os # Used in mkdirsWithPyInitFile.
-import types # Used in useOrRaise.
-import sys # Used in die.
-
-##################################################
-## MISCELLANEOUS FUNCTIONS
-
-def die(reason):
- sys.stderr.write(reason + '\n')
- sys.exit(1)
-
-def useOrRaise(thing, errmsg=''):
- """Raise 'thing' if it's a subclass of Exception. Otherwise return it.
-
- Called by: Cheetah.Servlet.cgiImport()
- """
- if type(thing) == types.ClassType and issubclass(thing, Exception):
- raise thing(errmsg)
- return thing
-
-
-def checkKeywords(dic, legalKeywords, what='argument'):
- """Verify no illegal keyword arguments were passed to a function.
-
- in : dic, dictionary (**kw in the calling routine).
- legalKeywords, list of strings, the keywords that are allowed.
- what, string, suffix for error message (see function source).
- out: None.
- exc: TypeError if 'dic' contains a key not in 'legalKeywords'.
- called by: Cheetah.Template.__init__()
- """
- # XXX legalKeywords could be a set when sets get added to Python.
- for k in dic.keys(): # Can be dic.iterkeys() if Python >= 2.2.
- if k not in legalKeywords:
- raise TypeError("'%s' is not a valid %s" % (k, what))
-
-
-def removeFromList(list_, *elements):
- """Save as list_.remove(each element) but don't raise an error if
- element is missing. Modifies 'list_' in place! Returns None.
- """
- for elm in elements:
- try:
- list_.remove(elm)
- except ValueError:
- pass
-
-
-def mkdirsWithPyInitFiles(path):
- """Same as os.makedirs (mkdir 'path' and all missing parent directories)
- but also puts a Python '__init__.py' file in every directory it
- creates. Does nothing (without creating an '__init__.py' file) if the
- directory already exists.
- """
- dir, fil = os.path.split(path)
- if dir and not os.path.exists(dir):
- mkdirsWithPyInitFiles(dir)
- if not os.path.exists(path):
- os.mkdir(path)
- init = os.path.join(path, "__init__.py")
- f = open(init, 'w') # Open and close to produce empty file.
- f.close()
-
-
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/Utils/VerifyType.py b/cobbler/Cheetah/Utils/VerifyType.py
deleted file mode 100644
index 6c52e09..0000000
--- a/cobbler/Cheetah/Utils/VerifyType.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# $Id: VerifyType.py,v 1.4 2005/11/02 22:26:08 tavis_rudd Exp $
-"""Functions to verify an argument's type
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@mso.oz.net>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.4 $
-Start Date: 2001/11/07
-Last Revision Date: $Date: 2005/11/02 22:26:08 $
-"""
-__author__ = "Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.4 $"[11:-2]
-
-##################################################
-## DEPENDENCIES
-
-import types # Used in VerifyTypeClass.
-
-##################################################
-## PRIVATE FUNCTIONS
-
-def _errmsg(argname, ltd, errmsgExtra=''):
- """Construct an error message.
-
- argname, string, the argument name.
- ltd, string, description of the legal types.
- errmsgExtra, string, text to append to error mssage.
- Returns: string, the error message.
- """
- if errmsgExtra:
- errmsgExtra = '\n' + errmsgExtra
- return "arg '%s' must be %s%s" % (argname, ltd, errmsgExtra)
-
-
-##################################################
-## TYPE VERIFICATION FUNCTIONS
-
-def VerifyType(arg, argname, legalTypes, ltd, errmsgExtra=''):
- """Verify the type of an argument.
-
- arg, any, the argument.
- argname, string, name of the argument.
- legalTypes, list of type objects, the allowed types.
- ltd, string, description of legal types (for error message).
- errmsgExtra, string, text to append to error message.
- Returns: None.
- Exceptions: TypeError if 'arg' is the wrong type.
- """
- if type(arg) not in legalTypes:
- m = _errmsg(argname, ltd, errmsgExtra)
- raise TypeError(m)
-
-
-def VerifyTypeClass(arg, argname, legalTypes, ltd, klass, errmsgExtra=''):
- """Same, but if it's a class, verify it's a subclass of the right class.
-
- arg, any, the argument.
- argname, string, name of the argument.
- legalTypes, list of type objects, the allowed types.
- ltd, string, description of legal types (for error message).
- klass, class, the parent class.
- errmsgExtra, string, text to append to the error message.
- Returns: None.
- Exceptions: TypeError if 'arg' is the wrong type.
- """
- VerifyType(arg, argname, legalTypes, ltd, errmsgExtra)
- # If no exception, the arg is a legal type.
- if type(arg) == types.ClassType and not issubclass(arg, klass):
- # Must test for "is class type" to avoid TypeError from issubclass().
- m = _errmsg(argname, ltd, errmsgExtra)
- raise TypeError(m)
-
-# @@MO: Commented until we determine whether it's useful.
-#def VerifyClass(arg, argname, klass, ltd):
-# """Same, but allow *only* a subclass of the right class.
-# """
-# VerifyTypeClass(arg, argname, [types.ClassType], ltd, klass)
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cobbler/Cheetah/Utils/WebInputMixin.py b/cobbler/Cheetah/Utils/WebInputMixin.py
deleted file mode 100644
index 930c13e..0000000
--- a/cobbler/Cheetah/Utils/WebInputMixin.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python
-# $Id: WebInputMixin.py,v 1.10 2006/01/06 21:56:54 tavis_rudd Exp $
-"""Provides helpers for Template.webInput(), a method for importing web
-transaction variables in bulk. See the docstring of webInput for full details.
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@mso.oz.net>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.10 $
-Start Date: 2002/03/17
-Last Revision Date: $Date: 2006/01/06 21:56:54 $
-"""
-__author__ = "Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.10 $"[11:-2]
-
-from Cheetah.Utils.Misc import useOrRaise
-
-class NonNumericInputError(ValueError): pass
-
-##################################################
-## PRIVATE FUNCTIONS AND CLASSES
-
-class _Converter:
- """A container object for info about type converters.
- .name, string, name of this converter (for error messages).
- .func, function, factory function.
- .default, value to use or raise if the real value is missing.
- .error, value to use or raise if .func() raises an exception.
- """
- def __init__(self, name, func, default, error):
- self.name = name
- self.func = func
- self.default = default
- self.error = error
-
-
-def _lookup(name, func, multi, converters):
- """Look up a Webware field/cookie/value/session value. Return
- '(realName, value)' where 'realName' is like 'name' but with any
- conversion suffix strips off. Applies numeric conversion and
- single vs multi values according to the comments in the source.
- """
- # Step 1 -- split off the conversion suffix from 'name'; e.g. "height:int".
- # If there's no colon, the suffix is "". 'longName' is the name with the
- # suffix, 'shortName' is without.
- # XXX This implementation assumes "height:" means "height".
- colon = name.find(':')
- if colon != -1:
- longName = name
- shortName, ext = name[:colon], name[colon+1:]
- else:
- longName = shortName = name
- ext = ''
-
- # Step 2 -- look up the values by calling 'func'.
- if longName != shortName:
- values = func(longName, None) or func(shortName, None)
- else:
- values = func(shortName, None)
- # 'values' is a list of strings, a string or None.
-
- # Step 3 -- Coerce 'values' to a list of zero, one or more strings.
- if values is None:
- values = []
- elif isinstance(values, str):
- values = [values]
-
- # Step 4 -- Find a _Converter object or raise TypeError.
- try:
- converter = converters[ext]
- except KeyError:
- fmt = "'%s' is not a valid converter name in '%s'"
- tup = (ext, longName)
- raise TypeError(fmt % tup)
-
- # Step 5 -- if there's a converter func, run it on each element.
- # If the converter raises an exception, use or raise 'converter.error'.
- if converter.func is not None:
- tmp = values[:]
- values = []
- for elm in tmp:
- try:
- elm = converter.func(elm)
- except (TypeError, ValueError):
- tup = converter.name, elm
- errmsg = "%s '%s' contains invalid characters" % tup
- elm = useOrRaise(converter.error, errmsg)
- values.append(elm)
- # 'values' is now a list of strings, ints or floats.
-
- # Step 6 -- If we're supposed to return a multi value, return the list
- # as is. If we're supposed to return a single value and the list is
- # empty, return or raise 'converter.default'. Otherwise, return the
- # first element in the list and ignore any additional values.
- if multi:
- return shortName, values
- if len(values) == 0:
- return shortName, useOrRaise(converter.default)
- return shortName, values[0]
-
-# vim: sw=4 ts=4 expandtab
diff --git a/cobbler/Cheetah/Utils/__init__.py b/cobbler/Cheetah/Utils/__init__.py
deleted file mode 100644
index 792d600..0000000
--- a/cobbler/Cheetah/Utils/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/cobbler/Cheetah/Utils/htmlDecode.py b/cobbler/Cheetah/Utils/htmlDecode.py
deleted file mode 100644
index 2832a74..0000000
--- a/cobbler/Cheetah/Utils/htmlDecode.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""This is a copy of the htmlDecode function in Webware.
-
-@@TR: It implemented more efficiently.
-
-"""
-
-from Cheetah.Utils.htmlEncode import htmlCodesReversed
-
-def htmlDecode(s, codes=htmlCodesReversed):
- """ Returns the ASCII decoded version of the given HTML string. This does
- NOT remove normal HTML tags like <p>. It is the inverse of htmlEncode()."""
- for code in codes:
- s = s.replace(code[1], code[0])
- return s
diff --git a/cobbler/Cheetah/Utils/htmlEncode.py b/cobbler/Cheetah/Utils/htmlEncode.py
deleted file mode 100644
index f76c77e..0000000
--- a/cobbler/Cheetah/Utils/htmlEncode.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""This is a copy of the htmlEncode function in Webware.
-
-
-@@TR: It implemented more efficiently.
-
-"""
-htmlCodes = [
- ['&', '&amp;'],
- ['<', '&lt;'],
- ['>', '&gt;'],
- ['"', '&quot;'],
-]
-htmlCodesReversed = htmlCodes[:]
-htmlCodesReversed.reverse()
-
-def htmlEncode(s, codes=htmlCodes):
- """ Returns the HTML encoded version of the given string. This is useful to
- display a plain ASCII text string on a web page."""
- for code in codes:
- s = s.replace(code[0], code[1])
- return s
diff --git a/cobbler/Cheetah/Utils/memcache.py b/cobbler/Cheetah/Utils/memcache.py
deleted file mode 100644
index 03ba032..0000000
--- a/cobbler/Cheetah/Utils/memcache.py
+++ /dev/null
@@ -1,625 +0,0 @@
-#!/usr/bin/env python
-
-"""
-client module for memcached (memory cache daemon)
-
-Overview
-========
-
-See U{the MemCached homepage<http://www.danga.com/memcached>} for more about memcached.
-
-Usage summary
-=============
-
-This should give you a feel for how this module operates::
-
- import memcache
- mc = memcache.Client(['127.0.0.1:11211'], debug=0)
-
- mc.set("some_key", "Some value")
- value = mc.get("some_key")
-
- mc.set("another_key", 3)
- mc.delete("another_key")
-
- mc.set("key", "1") # note that the key used for incr/decr must be a string.
- mc.incr("key")
- mc.decr("key")
-
-The standard way to use memcache with a database is like this::
-
- key = derive_key(obj)
- obj = mc.get(key)
- if not obj:
- obj = backend_api.get(...)
- mc.set(key, obj)
-
- # we now have obj, and future passes through this code
- # will use the object from the cache.
-
-Detailed Documentation
-======================
-
-More detailed documentation is available in the L{Client} class.
-"""
-
-import sys
-import socket
-import time
-import types
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
-
-__author__ = "Evan Martin <martine@danga.com>"
-__version__ = "1.2_tummy5"
-__copyright__ = "Copyright (C) 2003 Danga Interactive"
-__license__ = "Python"
-
-class _Error(Exception):
- pass
-
-class Client:
- """
- Object representing a pool of memcache servers.
-
- See L{memcache} for an overview.
-
- In all cases where a key is used, the key can be either:
- 1. A simple hashable type (string, integer, etc.).
- 2. A tuple of C{(hashvalue, key)}. This is useful if you want to avoid
- making this module calculate a hash value. You may prefer, for
- example, to keep all of a given user's objects on the same memcache
- server, so you could use the user's unique id as the hash value.
-
- @group Setup: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog
- @group Insertion: set, add, replace
- @group Retrieval: get, get_multi
- @group Integers: incr, decr
- @group Removal: delete
- @sort: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog,\
- set, add, replace, get, get_multi, incr, decr, delete
- """
-
- _usePickle = False
- _FLAG_PICKLE = 1<<0
- _FLAG_INTEGER = 1<<1
- _FLAG_LONG = 1<<2
-
- _SERVER_RETRIES = 10 # how many times to try finding a free server.
-
- def __init__(self, servers, debug=0):
- """
- Create a new Client object with the given list of servers.
-
- @param servers: C{servers} is passed to L{set_servers}.
- @param debug: whether to display error messages when a server can't be
- contacted.
- """
- self.set_servers(servers)
- self.debug = debug
- self.stats = {}
-
- def set_servers(self, servers):
- """
- Set the pool of servers used by this client.
-
- @param servers: an array of servers.
- Servers can be passed in two forms:
- 1. Strings of the form C{"host:port"}, which implies a default weight of 1.
- 2. Tuples of the form C{("host:port", weight)}, where C{weight} is
- an integer weight value.
- """
- self.servers = [_Host(s, self.debuglog) for s in servers]
- self._init_buckets()
-
- def get_stats(self):
- '''Get statistics from each of the servers.
-
- @return: A list of tuples ( server_identifier, stats_dictionary ).
- The dictionary contains a number of name/value pairs specifying
- the name of the status field and the string value associated with
- it. The values are not converted from strings.
- '''
- data = []
- for s in self.servers:
- if not s.connect(): continue
- name = '%s:%s (%s)' % ( s.ip, s.port, s.weight )
- s.send_cmd('stats')
- serverData = {}
- data.append(( name, serverData ))
- readline = s.readline
- while 1:
- line = readline()
- if not line or line.strip() == 'END': break
- stats = line.split(' ', 2)
- serverData[stats[1]] = stats[2]
-
- return(data)
-
- def flush_all(self):
- 'Expire all data currently in the memcache servers.'
- for s in self.servers:
- if not s.connect(): continue
- s.send_cmd('flush_all')
- s.expect("OK")
-
- def debuglog(self, str):
- if self.debug:
- sys.stderr.write("MemCached: %s\n" % str)
-
- def _statlog(self, func):
- if not self.stats.has_key(func):
- self.stats[func] = 1
- else:
- self.stats[func] += 1
-
- def forget_dead_hosts(self):
- """
- Reset every host in the pool to an "alive" state.
- """
- for s in self.servers:
- s.dead_until = 0
-
- def _init_buckets(self):
- self.buckets = []
- for server in self.servers:
- for i in range(server.weight):
- self.buckets.append(server)
-
- def _get_server(self, key):
- if type(key) == types.TupleType:
- serverhash = key[0]
- key = key[1]
- else:
- serverhash = hash(key)
-
- for i in range(Client._SERVER_RETRIES):
- server = self.buckets[serverhash % len(self.buckets)]
- if server.connect():
- #print "(using server %s)" % server,
- return server, key
- serverhash = hash(str(serverhash) + str(i))
- return None, None
-
- def disconnect_all(self):
- for s in self.servers:
- s.close_socket()
-
- def delete(self, key, time=0):
- '''Deletes a key from the memcache.
-
- @return: Nonzero on success.
- @rtype: int
- '''
- server, key = self._get_server(key)
- if not server:
- return 0
- self._statlog('delete')
- if time != None:
- cmd = "delete %s %d" % (key, time)
- else:
- cmd = "delete %s" % key
-
- try:
- server.send_cmd(cmd)
- server.expect("DELETED")
- except socket.error, msg:
- server.mark_dead(msg[1])
- return 0
- return 1
-
- def incr(self, key, delta=1):
- """
- Sends a command to the server to atomically increment the value for C{key} by
- C{delta}, or by 1 if C{delta} is unspecified. Returns None if C{key} doesn't
- exist on server, otherwise it returns the new value after incrementing.
-
- Note that the value for C{key} must already exist in the memcache, and it
- must be the string representation of an integer.
-
- >>> mc.set("counter", "20") # returns 1, indicating success
- 1
- >>> mc.incr("counter")
- 21
- >>> mc.incr("counter")
- 22
-
- Overflow on server is not checked. Be aware of values approaching
- 2**32. See L{decr}.
-
- @param delta: Integer amount to increment by (should be zero or greater).
- @return: New value after incrementing.
- @rtype: int
- """
- return self._incrdecr("incr", key, delta)
-
- def decr(self, key, delta=1):
- """
- Like L{incr}, but decrements. Unlike L{incr}, underflow is checked and
- new values are capped at 0. If server value is 1, a decrement of 2
- returns 0, not -1.
-
- @param delta: Integer amount to decrement by (should be zero or greater).
- @return: New value after decrementing.
- @rtype: int
- """
- return self._incrdecr("decr", key, delta)
-
- def _incrdecr(self, cmd, key, delta):
- server, key = self._get_server(key)
- if not server:
- return 0
- self._statlog(cmd)
- cmd = "%s %s %d" % (cmd, key, delta)
- try:
- server.send_cmd(cmd)
- line = server.readline()
- return int(line)
- except socket.error, msg:
- server.mark_dead(msg[1])
- return None
-
- def add(self, key, val, time=0):
- '''
- Add new key with value.
-
- Like L{set}, but only stores in memcache if the key doesn\'t already exist.
-
- @return: Nonzero on success.
- @rtype: int
- '''
- return self._set("add", key, val, time)
- def replace(self, key, val, time=0):
- '''Replace existing key with value.
-
- Like L{set}, but only stores in memcache if the key already exists.
- The opposite of L{add}.
-
- @return: Nonzero on success.
- @rtype: int
- '''
- return self._set("replace", key, val, time)
- def set(self, key, val, time=0):
- '''Unconditionally sets a key to a given value in the memcache.
-
- The C{key} can optionally be an tuple, with the first element being the
- hash value, if you want to avoid making this module calculate a hash value.
- You may prefer, for example, to keep all of a given user's objects on the
- same memcache server, so you could use the user's unique id as the hash
- value.
-
- @return: Nonzero on success.
- @rtype: int
- '''
- return self._set("set", key, val, time)
-
- def _set(self, cmd, key, val, time):
- server, key = self._get_server(key)
- if not server:
- return 0
-
- self._statlog(cmd)
-
- flags = 0
- if isinstance(val, types.StringTypes):
- pass
- elif isinstance(val, int):
- flags |= Client._FLAG_INTEGER
- val = "%d" % val
- elif isinstance(val, long):
- flags |= Client._FLAG_LONG
- val = "%d" % val
- elif self._usePickle:
- flags |= Client._FLAG_PICKLE
- val = pickle.dumps(val, 2)
- else:
- pass
-
- fullcmd = "%s %s %d %d %d\r\n%s" % (cmd, key, flags, time, len(val), val)
- try:
- server.send_cmd(fullcmd)
- server.expect("STORED")
- except socket.error, msg:
- server.mark_dead(msg[1])
- return 0
- return 1
-
- def get(self, key):
- '''Retrieves a key from the memcache.
-
- @return: The value or None.
- '''
- server, key = self._get_server(key)
- if not server:
- return None
-
- self._statlog('get')
-
- try:
- server.send_cmd("get %s" % key)
- rkey, flags, rlen, = self._expectvalue(server)
- if not rkey:
- return None
- value = self._recv_value(server, flags, rlen)
- server.expect("END")
- except (_Error, socket.error), msg:
- if type(msg) is types.TupleType:
- msg = msg[1]
- server.mark_dead(msg)
- return None
- return value
-
- def get_multi(self, keys):
- '''
- Retrieves multiple keys from the memcache doing just one query.
-
- >>> success = mc.set("foo", "bar")
- >>> success = mc.set("baz", 42)
- >>> mc.get_multi(["foo", "baz", "foobar"]) == {"foo": "bar", "baz": 42}
- 1
-
- This method is recommended over regular L{get} as it lowers the number of
- total packets flying around your network, reducing total latency, since
- your app doesn\'t have to wait for each round-trip of L{get} before sending
- the next one.
-
- @param keys: An array of keys.
- @return: A dictionary of key/value pairs that were available.
-
- '''
-
- self._statlog('get_multi')
-
- server_keys = {}
-
- # build up a list for each server of all the keys we want.
- for key in keys:
- server, key = self._get_server(key)
- if not server:
- continue
- if not server_keys.has_key(server):
- server_keys[server] = []
- server_keys[server].append(key)
-
- # send out all requests on each server before reading anything
- dead_servers = []
- for server in server_keys.keys():
- try:
- server.send_cmd("get %s" % " ".join(server_keys[server]))
- except socket.error, msg:
- server.mark_dead(msg[1])
- dead_servers.append(server)
-
- # if any servers died on the way, don't expect them to respond.
- for server in dead_servers:
- del server_keys[server]
-
- retvals = {}
- for server in server_keys.keys():
- try:
- line = server.readline()
- while line and line != 'END':
- rkey, flags, rlen = self._expectvalue(server, line)
- # Bo Yang reports that this can sometimes be None
- if rkey is not None:
- val = self._recv_value(server, flags, rlen)
- retvals[rkey] = val
- line = server.readline()
- except (_Error, socket.error), msg:
- server.mark_dead(msg)
- return retvals
-
- def _expectvalue(self, server, line=None):
- if not line:
- line = server.readline()
-
- if line[:5] == 'VALUE':
- resp, rkey, flags, len = line.split()
- flags = int(flags)
- rlen = int(len)
- return (rkey, flags, rlen)
- else:
- return (None, None, None)
-
- def _recv_value(self, server, flags, rlen):
- rlen += 2 # include \r\n
- buf = server.recv(rlen)
- if len(buf) != rlen:
- raise _Error("received %d bytes when expecting %d" % (len(buf), rlen))
-
- if len(buf) == rlen:
- buf = buf[:-2] # strip \r\n
-
- if flags == 0:
- val = buf
- elif flags & Client._FLAG_INTEGER:
- val = int(buf)
- elif flags & Client._FLAG_LONG:
- val = long(buf)
- elif self._usePickle and flags & Client._FLAG_PICKLE:
- try:
- val = pickle.loads(buf)
- except:
- self.debuglog('Pickle error...\n')
- val = None
- else:
- self.debuglog("unknown flags on get: %x\n" % flags)
-
- return val
-
-class _Host:
- _DEAD_RETRY = 30 # number of seconds before retrying a dead server.
-
- def __init__(self, host, debugfunc=None):
- if isinstance(host, types.TupleType):
- host = host[0]
- self.weight = host[1]
- else:
- self.weight = 1
-
- if host.find(":") > 0:
- self.ip, self.port = host.split(":")
- self.port = int(self.port)
- else:
- self.ip, self.port = host, 11211
-
- if not debugfunc:
- debugfunc = lambda x: x
- self.debuglog = debugfunc
-
- self.deaduntil = 0
- self.socket = None
-
- def _check_dead(self):
- if self.deaduntil and self.deaduntil > time.time():
- return 1
- self.deaduntil = 0
- return 0
-
- def connect(self):
- if self._get_socket():
- return 1
- return 0
-
- def mark_dead(self, reason):
- self.debuglog("MemCache: %s: %s. Marking dead." % (self, reason))
- self.deaduntil = time.time() + _Host._DEAD_RETRY
- self.close_socket()
-
- def _get_socket(self):
- if self._check_dead():
- return None
- if self.socket:
- return self.socket
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # Python 2.3-ism: s.settimeout(1)
- try:
- s.connect((self.ip, self.port))
- except socket.error, msg:
- self.mark_dead("connect: %s" % msg[1])
- return None
- self.socket = s
- return s
-
- def close_socket(self):
- if self.socket:
- self.socket.close()
- self.socket = None
-
- def send_cmd(self, cmd):
- if len(cmd) > 100:
- self.socket.sendall(cmd)
- self.socket.sendall('\r\n')
- else:
- self.socket.sendall(cmd + '\r\n')
-
- def readline(self):
- buffers = ''
- recv = self.socket.recv
- while 1:
- data = recv(1)
- if not data:
- self.mark_dead('Connection closed while reading from %s'
- % repr(self))
- break
- if data == '\n' and buffers and buffers[-1] == '\r':
- return(buffers[:-1])
- buffers = buffers + data
- return(buffers)
-
- def expect(self, text):
- line = self.readline()
- if line != text:
- self.debuglog("while expecting '%s', got unexpected response '%s'" % (text, line))
- return line
-
- def recv(self, rlen):
- buf = ''
- recv = self.socket.recv
- while len(buf) < rlen:
- buf = buf + recv(rlen - len(buf))
- return buf
-
- def __str__(self):
- d = ''
- if self.deaduntil:
- d = " (dead until %d)" % self.deaduntil
- return "%s:%d%s" % (self.ip, self.port, d)
-
-def _doctest():
- import doctest, memcache
- servers = ["127.0.0.1:11211"]
- mc = Client(servers, debug=1)
- globs = {"mc": mc}
- return doctest.testmod(memcache, globs=globs)
-
-if __name__ == "__main__":
- print "Testing docstrings..."
- _doctest()
- print "Running tests:"
- print
- #servers = ["127.0.0.1:11211", "127.0.0.1:11212"]
- servers = ["127.0.0.1:11211"]
- mc = Client(servers, debug=1)
-
- def to_s(val):
- if not isinstance(val, types.StringTypes):
- return "%s (%s)" % (val, type(val))
- return "%s" % val
- def test_setget(key, val):
- print "Testing set/get {'%s': %s} ..." % (to_s(key), to_s(val)),
- mc.set(key, val)
- newval = mc.get(key)
- if newval == val:
- print "OK"
- return 1
- else:
- print "FAIL"
- return 0
-
- class FooStruct:
- def __init__(self):
- self.bar = "baz"
- def __str__(self):
- return "A FooStruct"
- def __eq__(self, other):
- if isinstance(other, FooStruct):
- return self.bar == other.bar
- return 0
-
- test_setget("a_string", "some random string")
- test_setget("an_integer", 42)
- if test_setget("long", long(1<<30)):
- print "Testing delete ...",
- if mc.delete("long"):
- print "OK"
- else:
- print "FAIL"
- print "Testing get_multi ...",
- print mc.get_multi(["a_string", "an_integer"])
-
- print "Testing get(unknown value) ...",
- print to_s(mc.get("unknown_value"))
-
- f = FooStruct()
- test_setget("foostruct", f)
-
- print "Testing incr ...",
- x = mc.incr("an_integer", 1)
- if x == 43:
- print "OK"
- else:
- print "FAIL"
-
- print "Testing decr ...",
- x = mc.decr("an_integer", 1)
- if x == 42:
- print "OK"
- else:
- print "FAIL"
-
-
-
-# vim: ts=4 sw=4 et :
diff --git a/cobbler/Cheetah/Utils/optik/__init__.py b/cobbler/Cheetah/Utils/optik/__init__.py
deleted file mode 100644
index 75a30ba..0000000
--- a/cobbler/Cheetah/Utils/optik/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""optik
-
-A powerful, extensible, and easy-to-use command-line parser for Python.
-
-By Greg Ward <gward@python.net>
-
-See http://optik.sourceforge.net/
-
-Cheetah modifications: added "Cheetah.Utils.optik." prefix to
- all intra-Optik imports.
-"""
-
-# Copyright (c) 2001 Gregory P. Ward. All rights reserved.
-# See the README.txt distributed with Optik for licensing terms.
-
-__revision__ = "$Id: __init__.py,v 1.2 2002/09/12 06:56:51 hierro Exp $"
-
-__version__ = "1.3"
-
-
-# Re-import these for convenience
-from Cheetah.Utils.optik.option import Option
-from Cheetah.Utils.optik.option_parser import \
- OptionParser, SUPPRESS_HELP, SUPPRESS_USAGE, STD_HELP_OPTION
-from Cheetah.Utils.optik.errors import OptionValueError
-
-
-# Some day, there might be many Option classes. As of Optik 1.3, the
-# preferred way to instantiate Options is indirectly, via make_option(),
-# which will become a factory function when there are many Option
-# classes.
-make_option = Option
diff --git a/cobbler/Cheetah/Utils/optik/errors.py b/cobbler/Cheetah/Utils/optik/errors.py
deleted file mode 100644
index 2ed75e6..0000000
--- a/cobbler/Cheetah/Utils/optik/errors.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""optik.errors
-
-Exception classes used by Optik.
-"""
-
-__revision__ = "$Id: errors.py,v 1.1 2002/08/24 17:10:06 hierro Exp $"
-
-# Copyright (c) 2001 Gregory P. Ward. All rights reserved.
-# See the README.txt distributed with Optik for licensing terms.
-
-# created 2001/10/17 GPW (from optik.py)
-
-
-class OptikError (Exception):
- def __init__ (self, msg):
- self.msg = msg
-
- def __str__ (self):
- return self.msg
-
-
-class OptionError (OptikError):
- """
- Raised if an Option instance is created with invalid or
- inconsistent arguments.
- """
-
- def __init__ (self, msg, option):
- self.msg = msg
- self.option_id = str(option)
-
- def __str__ (self):
- if self.option_id:
- return "option %s: %s" % (self.option_id, self.msg)
- else:
- return self.msg
-
-class OptionConflictError (OptionError):
- """
- Raised if conflicting options are added to an OptionParser.
- """
-
-class OptionValueError (OptikError):
- """
- Raised if an invalid option value is encountered on the command
- line.
- """
-
-class BadOptionError (OptikError):
- """
- Raised if an invalid or ambiguous option is seen on the command-line.
- """
diff --git a/cobbler/Cheetah/Utils/optik/option.py b/cobbler/Cheetah/Utils/optik/option.py
deleted file mode 100644
index ac85c3d..0000000
--- a/cobbler/Cheetah/Utils/optik/option.py
+++ /dev/null
@@ -1,354 +0,0 @@
-"""optik.option
-
-Defines the Option class and some standard value-checking functions.
-
-Cheetah modifications: added "Cheetah.Utils.optik." prefix to
- all intra-Optik imports.
-"""
-
-__revision__ = "$Id: option.py,v 1.2 2002/09/12 06:56:51 hierro Exp $"
-
-# Copyright (c) 2001 Gregory P. Ward. All rights reserved.
-# See the README.txt distributed with Optik for licensing terms.
-
-# created 2001/10/17, GPW (from optik.py)
-
-import sys
-from types import TupleType, DictType
-from Cheetah.Utils.optik.errors import OptionError, OptionValueError
-
-_builtin_cvt = { "int" : (int, "integer"),
- "long" : (long, "long integer"),
- "float" : (float, "floating-point"),
- "complex" : (complex, "complex") }
-
-def check_builtin (option, opt, value):
- (cvt, what) = _builtin_cvt[option.type]
- try:
- return cvt(value)
- except ValueError:
- raise OptionValueError(
- #"%s: invalid %s argument %r" % (opt, what, value))
- "option %s: invalid %s value: %r" % (opt, what, value))
-
-# Not supplying a default is different from a default of None,
-# so we need an explicit "not supplied" value.
-NO_DEFAULT = "NO"+"DEFAULT"
-
-
-class Option:
- """
- Instance attributes:
- _short_opts : [string]
- _long_opts : [string]
-
- action : string
- type : string
- dest : string
- default : any
- nargs : int
- const : any
- callback : function
- callback_args : (any*)
- callback_kwargs : { string : any }
- help : string
- metavar : string
- """
-
- # The list of instance attributes that may be set through
- # keyword args to the constructor.
- ATTRS = ['action',
- 'type',
- 'dest',
- 'default',
- 'nargs',
- 'const',
- 'callback',
- 'callback_args',
- 'callback_kwargs',
- 'help',
- 'metavar']
-
- # The set of actions allowed by option parsers. Explicitly listed
- # here so the constructor can validate its arguments.
- ACTIONS = ("store",
- "store_const",
- "store_true",
- "store_false",
- "append",
- "count",
- "callback",
- "help",
- "version")
-
- # The set of actions that involve storing a value somewhere;
- # also listed just for constructor argument validation. (If
- # the action is one of these, there must be a destination.)
- STORE_ACTIONS = ("store",
- "store_const",
- "store_true",
- "store_false",
- "append",
- "count")
-
- # The set of actions for which it makes sense to supply a value
- # type, ie. where we expect an argument to this option.
- TYPED_ACTIONS = ("store",
- "append",
- "callback")
-
- # The set of known types for option parsers. Again, listed here for
- # constructor argument validation.
- TYPES = ("string", "int", "long", "float", "complex")
-
- # Dictionary of argument checking functions, which convert and
- # validate option arguments according to the option type.
- #
- # Signature of checking functions is:
- # check(option : Option, opt : string, value : string) -> any
- # where
- # option is the Option instance calling the checker
- # opt is the actual option seen on the command-line
- # (eg. "-a", "--file")
- # value is the option argument seen on the command-line
- #
- # The return value should be in the appropriate Python type
- # for option.type -- eg. an integer if option.type == "int".
- #
- # If no checker is defined for a type, arguments will be
- # unchecked and remain strings.
- TYPE_CHECKER = { "int" : check_builtin,
- "long" : check_builtin,
- "float" : check_builtin,
- "complex" : check_builtin,
- }
-
-
- # CHECK_METHODS is a list of unbound method objects; they are called
- # by the constructor, in order, after all attributes are
- # initialized. The list is created and filled in later, after all
- # the methods are actually defined. (I just put it here because I
- # like to define and document all class attributes in the same
- # place.) Subclasses that add another _check_*() method should
- # define their own CHECK_METHODS list that adds their check method
- # to those from this class.
- CHECK_METHODS = None
-
-
- # -- Constructor/initialization methods ----------------------------
-
- def __init__ (self, *opts, **attrs):
- # Set _short_opts, _long_opts attrs from 'opts' tuple
- opts = self._check_opt_strings(opts)
- self._set_opt_strings(opts)
-
- # Set all other attrs (action, type, etc.) from 'attrs' dict
- self._set_attrs(attrs)
-
- # Check all the attributes we just set. There are lots of
- # complicated interdependencies, but luckily they can be farmed
- # out to the _check_*() methods listed in CHECK_METHODS -- which
- # could be handy for subclasses! The one thing these all share
- # is that they raise OptionError if they discover a problem.
- for checker in self.CHECK_METHODS:
- checker(self)
-
- def _check_opt_strings (self, opts):
- # Filter out None because early versions of Optik had exactly
- # one short option and one long option, either of which
- # could be None.
- opts = filter(None, opts)
- if not opts:
- raise OptionError("at least one option string must be supplied",
- self)
- return opts
-
- def _set_opt_strings (self, opts):
- self._short_opts = []
- self._long_opts = []
- for opt in opts:
- if len(opt) < 2:
- raise OptionError(
- "invalid option string %r: "
- "must be at least two characters long" % opt, self)
- elif len(opt) == 2:
- if not (opt[0] == "-" and opt[1] != "-"):
- raise OptionError(
- "invalid short option string %r: "
- "must be of the form -x, (x any non-dash char)" % opt,
- self)
- self._short_opts.append(opt)
- else:
- if not (opt[0:2] == "--" and opt[2] != "-"):
- raise OptionError(
- "invalid long option string %r: "
- "must start with --, followed by non-dash" % opt,
- self)
- self._long_opts.append(opt)
-
- def _set_attrs (self, attrs):
- for attr in self.ATTRS:
- if attrs.has_key(attr):
- setattr(self, attr, attrs[attr])
- del attrs[attr]
- else:
- if attr == 'default':
- setattr(self, attr, NO_DEFAULT)
- else:
- setattr(self, attr, None)
- if attrs:
- raise OptionError(
- "invalid keyword arguments: %s" % ", ".join(attrs.keys()),
- self)
-
-
- # -- Constructor validation methods --------------------------------
-
- def _check_action (self):
- if self.action is None:
- self.action = "store"
- elif self.action not in self.ACTIONS:
- raise OptionError("invalid action: %r" % self.action, self)
-
- def _check_type (self):
- if self.type is None:
- # XXX should factor out another class attr here: list of
- # actions that *require* a type
- if self.action in ("store", "append"):
- # No type given? "string" is the most sensible default.
- self.type = "string"
- else:
- if self.type not in self.TYPES:
- raise OptionError("invalid option type: %r" % self.type, self)
- if self.action not in self.TYPED_ACTIONS:
- raise OptionError(
- "must not supply a type for action %r" % self.action, self)
-
- def _check_dest (self):
- if self.action in self.STORE_ACTIONS and self.dest is None:
- # No destination given, and we need one for this action.
- # Glean a destination from the first long option string,
- # or from the first short option string if no long options.
- if self._long_opts:
- # eg. "--foo-bar" -> "foo_bar"
- self.dest = self._long_opts[0][2:].replace('-', '_')
- else:
- self.dest = self._short_opts[0][1]
-
- def _check_const (self):
- if self.action != "store_const" and self.const is not None:
- raise OptionError(
- "'const' must not be supplied for action %r" % self.action,
- self)
-
- def _check_nargs (self):
- if self.action in self.TYPED_ACTIONS:
- if self.nargs is None:
- self.nargs = 1
- elif self.nargs is not None:
- raise OptionError(
- "'nargs' must not be supplied for action %r" % self.action,
- self)
-
- def _check_callback (self):
- if self.action == "callback":
- if not callable(self.callback):
- raise OptionError(
- "callback not callable: %r" % self.callback, self)
- if (self.callback_args is not None and
- type(self.callback_args) is not TupleType):
- raise OptionError(
- "callback_args, if supplied, must be a tuple: not %r"
- % self.callback_args, self)
- if (self.callback_kwargs is not None and
- type(self.callback_kwargs) is not DictType):
- raise OptionError(
- "callback_kwargs, if supplied, must be a dict: not %r"
- % self.callback_kwargs, self)
- else:
- if self.callback is not None:
- raise OptionError(
- "callback supplied (%r) for non-callback option"
- % self.callback, self)
- if self.callback_args is not None:
- raise OptionError(
- "callback_args supplied for non-callback option", self)
- if self.callback_kwargs is not None:
- raise OptionError(
- "callback_kwargs supplied for non-callback option", self)
-
-
- CHECK_METHODS = [_check_action,
- _check_type,
- _check_dest,
- _check_const,
- _check_nargs,
- _check_callback]
-
-
- # -- Miscellaneous methods -----------------------------------------
-
- def __str__ (self):
- if self._short_opts or self._long_opts:
- return "/".join(self._short_opts + self._long_opts)
- else:
- raise RuntimeError, "short_opts and long_opts both empty!"
-
- def takes_value (self):
- return self.type is not None
-
-
- # -- Processing methods --------------------------------------------
-
- def check_value (self, opt, value):
- checker = self.TYPE_CHECKER.get(self.type)
- if checker is None:
- return value
- else:
- return checker(self, opt, value)
-
- def process (self, opt, value, values, parser):
-
- # First, convert the value(s) to the right type. Howl if any
- # value(s) are bogus.
- if value is not None:
- if self.nargs == 1:
- value = self.check_value(opt, value)
- else:
- value = tuple([self.check_value(opt, v) for v in value])
-
- # And then take whatever action is expected of us.
- # This is a separate method to make life easier for
- # subclasses to add new actions.
- return self.take_action(
- self.action, self.dest, opt, value, values, parser)
-
- def take_action (self, action, dest, opt, value, values, parser):
- if action == "store":
- setattr(values, dest, value)
- elif action == "store_const":
- setattr(values, dest, self.const)
- elif action == "store_true":
- setattr(values, dest, 1)
- elif action == "store_false":
- setattr(values, dest, 0)
- elif action == "append":
- values.ensure_value(dest, []).append(value)
- elif action == "count":
- setattr(values, dest, values.ensure_value(dest, 0) + 1)
- elif action == "callback":
- args = self.callback_args or ()
- kwargs = self.callback_kwargs or {}
- self.callback(self, opt, value, parser, *args, **kwargs)
- elif action == "help":
- parser.print_help()
- sys.exit(0)
- elif action == "version":
- parser.print_version()
- sys.exit(0)
- else:
- raise RuntimeError, "unknown action %r" % self.action
-
- return 1
-
-# class Option
diff --git a/cobbler/Cheetah/Utils/optik/option_parser.py b/cobbler/Cheetah/Utils/optik/option_parser.py
deleted file mode 100644
index 1b4e632..0000000
--- a/cobbler/Cheetah/Utils/optik/option_parser.py
+++ /dev/null
@@ -1,667 +0,0 @@
-"""optik.option_parser
-
-Provides the OptionParser and Values classes.
-
-Cheetah modifications: added "Cheetah.Utils.optik." prefix to
- all intra-Optik imports.
-"""
-
-__revision__ = "$Id: option_parser.py,v 1.2 2002/09/12 06:56:51 hierro Exp $"
-
-# Copyright (c) 2001 Gregory P. Ward. All rights reserved.
-# See the README.txt distributed with Optik for licensing terms.
-
-# created 2001/10/17, GPW (from optik.py)
-
-import sys, os
-import types
-from Cheetah.Utils.optik.option import Option, NO_DEFAULT
-from Cheetah.Utils.optik.errors import OptionConflictError, OptionValueError, BadOptionError
-
-def get_prog_name ():
- return os.path.basename(sys.argv[0])
-
-
-SUPPRESS_HELP = "SUPPRESS"+"HELP"
-SUPPRESS_USAGE = "SUPPRESS"+"USAGE"
-
-STD_HELP_OPTION = Option("-h", "--help",
- action="help",
- help="show this help message and exit")
-STD_VERSION_OPTION = Option("--version",
- action="version",
- help="show program's version number and exit")
-
-
-class Values:
-
- def __init__ (self, defaults=None):
- if defaults:
- for (attr, val) in defaults.items():
- setattr(self, attr, val)
-
-
- def _update_careful (self, dict):
- """
- Update the option values from an arbitrary dictionary, but only
- use keys from dict that already have a corresponding attribute
- in self. Any keys in dict without a corresponding attribute
- are silently ignored.
- """
- for attr in dir(self):
- if dict.has_key(attr):
- dval = dict[attr]
- if dval is not None:
- setattr(self, attr, dval)
-
- def _update_loose (self, dict):
- """
- Update the option values from an arbitrary dictionary,
- using all keys from the dictionary regardless of whether
- they have a corresponding attribute in self or not.
- """
- self.__dict__.update(dict)
-
- def _update (self, dict, mode):
- if mode == "careful":
- self._update_careful(dict)
- elif mode == "loose":
- self._update_loose(dict)
- else:
- raise ValueError, "invalid update mode: %r" % mode
-
- def read_module (self, modname, mode="careful"):
- __import__(modname)
- mod = sys.modules[modname]
- self._update(vars(mod), mode)
-
- def read_file (self, filename, mode="careful"):
- vars = {}
- execfile(filename, vars)
- self._update(vars, mode)
-
- def ensure_value (self, attr, value):
- if not hasattr(self, attr) or getattr(self, attr) is None:
- setattr(self, attr, value)
- return getattr(self, attr)
-
-
-class OptionParser:
- """
- Class attributes:
- standard_option_list : [Option]
- list of standard options that will be accepted by all instances
- of this parser class (intended to be overridden by subclasses).
-
- Instance attributes:
- usage : string
- a usage string for your program. Before it is displayed
- to the user, "%prog" will be expanded to the name of
- your program (os.path.basename(sys.argv[0])).
- option_list : [Option]
- the list of all options accepted on the command-line of
- this program
- _short_opt : { string : Option }
- dictionary mapping short option strings, eg. "-f" or "-X",
- to the Option instances that implement them. If an Option
- has multiple short option strings, it will appears in this
- dictionary multiple times.
- _long_opt : { string : Option }
- dictionary mapping long option strings, eg. "--file" or
- "--exclude", to the Option instances that implement them.
- Again, a given Option can occur multiple times in this
- dictionary.
- _long_opts : [string]
- list of long option strings recognized by this option
- parser. Should be equal to _long_opt.values().
- defaults : { string : any }
- dictionary mapping option destination names to default
- values for each destination.
-
- allow_interspersed_args : boolean = true
- if true, positional arguments may be interspersed with options.
- Assuming -a and -b each take a single argument, the command-line
- -ablah foo bar -bboo baz
- will be interpreted the same as
- -ablah -bboo -- foo bar baz
- If this flag were false, that command line would be interpreted as
- -ablah -- foo bar -bboo baz
- -- ie. we stop processing options as soon as we see the first
- non-option argument. (This is the tradition followed by
- Python's getopt module, Perl's Getopt::Std, and other argument-
- parsing libraries, but it is generally annoying to users.)
-
- rargs : [string]
- the argument list currently being parsed. Only set when
- parse_args() is active, and continually trimmed down as
- we consume arguments. Mainly there for the benefit of
- callback options.
- largs : [string]
- the list of leftover arguments that we have skipped while
- parsing options. If allow_interspersed_args is false, this
- list is always empty.
- values : Values
- the set of option values currently being accumulated. Only
- set when parse_args() is active. Also mainly for callbacks.
-
- Because of the 'rargs', 'largs', and 'values' attributes,
- OptionParser is not thread-safe. If, for some perverse reason, you
- need to parse command-line arguments simultaneously in different
- threads, use different OptionParser instances.
-
- """
-
- standard_option_list = [STD_HELP_OPTION]
-
-
- def __init__ (self,
- usage=None,
- option_list=None,
- option_class=Option,
- version=None,
- conflict_handler="error"):
- self.set_usage(usage)
- self.option_class = option_class
- self.version = version
- self.set_conflict_handler(conflict_handler)
- self.allow_interspersed_args = 1
-
- # Create the various lists and dicts that constitute the
- # "option list". See class docstring for details about
- # each attribute.
- self._create_option_list()
-
- # Populate the option list; initial sources are the
- # standard_option_list class attribute, the 'option_list'
- # argument, and the STD_VERSION_OPTION global (if 'version'
- # supplied).
- self._populate_option_list(option_list)
-
- self._init_parsing_state()
-
- # -- Private methods -----------------------------------------------
- # (used by the constructor)
-
- def _create_option_list (self):
- self.option_list = []
- self._short_opt = {} # single letter -> Option instance
- self._long_opt = {} # long option -> Option instance
- self._long_opts = [] # list of long options
- self.defaults = {} # maps option dest -> default value
-
- def _populate_option_list (self, option_list):
- if self.standard_option_list:
- self.add_options(self.standard_option_list)
- if self.version:
- self.add_option(STD_VERSION_OPTION)
- if option_list:
- self.add_options(option_list)
-
- def _init_parsing_state (self):
- # These are set in parse_args() for the convenience of callbacks.
- self.rargs = None
- self.largs = None
- self.values = None
-
-
- # -- Simple modifier methods ---------------------------------------
-
- def set_usage (self, usage):
- if usage is None:
- self.usage = "usage: %prog [options]"
- elif usage is SUPPRESS_USAGE:
- self.usage = None
- else:
- self.usage = usage
-
- def enable_interspersed_args (self):
- self.allow_interspersed_args = 1
-
- def disable_interspersed_args (self):
- self.allow_interspersed_args = 0
-
- def set_conflict_handler (self, handler):
- if handler not in ("ignore", "error", "resolve"):
- raise ValueError, "invalid conflict_resolution value %r" % handler
- self.conflict_handler = handler
-
- def set_default (self, dest, value):
- self.defaults[dest] = value
-
- def set_defaults (self, **kwargs):
- self.defaults.update(kwargs)
-
-
- # -- Option-adding methods -----------------------------------------
-
- def _check_conflict (self, option):
- conflict_opts = []
- for opt in option._short_opts:
- if self._short_opt.has_key(opt):
- conflict_opts.append((opt, self._short_opt[opt]))
- for opt in option._long_opts:
- if self._long_opt.has_key(opt):
- conflict_opts.append((opt, self._long_opt[opt]))
-
- if conflict_opts:
- handler = self.conflict_handler
- if handler == "ignore": # behaviour for Optik 1.0, 1.1
- pass
- elif handler == "error": # new in 1.2
- raise OptionConflictError(
- "conflicting option string(s): %s"
- % ", ".join([co[0] for co in conflict_opts]),
- option)
- elif handler == "resolve": # new in 1.2
- for (opt, c_option) in conflict_opts:
- if opt.startswith("--"):
- c_option._long_opts.remove(opt)
- del self._long_opt[opt]
- else:
- c_option._short_opts.remove(opt)
- del self._short_opt[opt]
- if not (c_option._short_opts or c_option._long_opts):
- self.option_list.remove(c_option)
-
-
- def add_option (self, *args, **kwargs):
- """add_option(Option)
- add_option(opt_str, ..., kwarg=val, ...)
- """
- if type(args[0]) is types.StringType:
- option = self.option_class(*args, **kwargs)
- elif len(args) == 1 and not kwargs:
- option = args[0]
- if not isinstance(option, Option):
- raise TypeError, "not an Option instance: %r" % option
- else:
- raise TypeError, "invalid arguments"
-
- self._check_conflict(option)
-
- self.option_list.append(option)
- for opt in option._short_opts:
- self._short_opt[opt] = option
- for opt in option._long_opts:
- self._long_opt[opt] = option
- self._long_opts.append(opt)
-
- if option.dest is not None: # option has a dest, we need a default
- if option.default is not NO_DEFAULT:
- self.defaults[option.dest] = option.default
- elif not self.defaults.has_key(option.dest):
- self.defaults[option.dest] = None
-
- def add_options (self, option_list):
- for option in option_list:
- self.add_option(option)
-
-
- # -- Option query/removal methods ----------------------------------
-
- def get_option (self, opt_str):
- return (self._short_opt.get(opt_str) or
- self._long_opt.get(opt_str))
-
- def has_option (self, opt_str):
- return (self._short_opt.has_key(opt_str) or
- self._long_opt.has_key(opt_str))
-
-
- def remove_option (self, opt_str):
- option = self._short_opt.get(opt_str)
- if option is None:
- option = self._long_opt.get(opt_str)
- if option is None:
- raise ValueError("no such option %r" % opt_str)
-
- for opt in option._short_opts:
- del self._short_opt[opt]
- for opt in option._long_opts:
- del self._long_opt[opt]
- self._long_opts.remove(opt)
- self.option_list.remove(option)
-
-
- # -- Option-parsing methods ----------------------------------------
-
- def _get_args (self, args):
- if args is None:
- return sys.argv[1:]
- else:
- return args[:] # don't modify caller's list
-
- def parse_args (self, args=None, values=None):
- """
- parse_args(args : [string] = sys.argv[1:],
- values : Values = None)
- -> (values : Values, args : [string])
-
- Parse the command-line options found in 'args' (default:
- sys.argv[1:]). Any errors result in a call to 'error()', which
- by default prints the usage message to stderr and calls
- sys.exit() with an error message. On success returns a pair
- (values, args) where 'values' is an Values instance (with all
- your option values) and 'args' is the list of arguments left
- over after parsing options.
- """
- rargs = self._get_args(args)
- if values is None:
- values = Values(self.defaults)
-
- # Store the halves of the argument list as attributes for the
- # convenience of callbacks:
- # rargs
- # the rest of the command-line (the "r" stands for
- # "remaining" or "right-hand")
- # largs
- # the leftover arguments -- ie. what's left after removing
- # options and their arguments (the "l" stands for "leftover"
- # or "left-hand")
-
- # Say this is the original argument list:
- # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)]
- # ^
- # (we are about to process arg(i)).
- #
- # Then rargs is [arg(i), ..., arg(N-1)]
- # and largs is a *subset* of [arg0, ..., arg(i-1)]
- # (any options and their arguments will have been removed
- # from largs).
- #
- # _process_arg() will always consume 1 or more arguments.
- # If it consumes 1 (eg. arg is an option that takes no arguments),
- # then after _process_arg() is done the situation is:
- # largs = subset of [arg0, ..., arg(i)]
- # rargs = [arg(i+1), ..., arg(N-1)]
- #
- # If allow_interspersed_args is false, largs will always be
- # *empty* -- still a subset of [arg0, ..., arg(i-1)], but
- # not a very interesting subset!
-
- self.rargs = rargs
- self.largs = largs = []
- self.values = values
-
- stop = 0
- while rargs and not stop:
- try:
- stop = self._process_arg(largs, rargs, values)
- except (BadOptionError, OptionValueError), err:
- self.error(err.msg)
-
- args = largs + rargs
- return self.check_values(values, args)
-
- def check_values (self, values, args):
- """
- check_values(values : Values, args : [string])
- -> (values : Values, args : [string])
-
- Check that the supplied option values and leftover arguments are
- valid. Returns the option values and leftover arguments
- (possibly adjusted, possibly completely new -- whatever you
- like). Default implementation just returns the passed-in
- values; subclasses may override as desired.
- """
- return (values, args)
-
- def _process_arg (self, largs, rargs, values):
- """_process_args(largs : [string],
- rargs : [string],
- values : Values)
- -> stop : boolean
-
- Process a single command-line argument, consuming zero or more
- arguments. The next argument to process is rargs[0], which will
- almost certainly be consumed from rargs. (It might wind up in
- largs, or it might affect a value in values, or -- if a callback
- is involved -- almost anything might happen. It will not be
- consumed if it is a non-option argument and
- allow_interspersed_args is false.) More arguments from rargs
- may also be consumed, depending on circumstances.
-
- Returns true if option processing should stop after this
- argument is processed.
- """
-
- # We handle bare "--" explicitly, and bare "-" is handled by the
- # standard arg handler since the short arg case ensures that the len
- # of the opt string is greater than 1.
-
- arg = rargs[0]
- if arg == "--":
- del rargs[0]
- return 1
- elif arg[0:2] == "--":
- # process a single long option (possibly with value(s))
- self._process_long_opt(rargs, values)
- elif arg[:1] == "-" and len(arg) > 1:
- # process a cluster of short options (possibly with
- # value(s) for the last one only)
- self._process_short_opts(rargs, values)
- else:
- if self.allow_interspersed_args:
- largs.append(arg)
- del rargs[0]
- else:
- return 1 # stop now, leave this arg in rargs
-
- return 0 # keep processing args
-
- def _match_long_opt (self, opt):
- """_match_long_opt(opt : string) -> string
-
- Determine which long option string 'opt' matches, ie. which one
- it is an unambiguous abbrevation for. Raises BadOptionError if
- 'opt' doesn't unambiguously match any long option string.
- """
- return _match_abbrev(opt, self._long_opts)
-
- def _process_long_opt (self, rargs, values):
- arg = rargs.pop(0)
-
- # Value explicitly attached to arg? Pretend it's the next
- # argument.
- if "=" in arg:
- (opt, next_arg) = arg.split("=", 1)
- rargs.insert(0, next_arg)
- had_explicit_value = 1
- else:
- opt = arg
- had_explicit_value = 0
-
- opt = self._match_long_opt(opt)
- option = self._long_opt[opt]
- if option.takes_value():
- nargs = option.nargs
- if len(rargs) < nargs:
- if nargs == 1:
- self.error("%s option requires a value" % opt)
- else:
- self.error("%s option requires %d values"
- % (opt, nargs))
- elif nargs == 1:
- value = rargs.pop(0)
- else:
- value = tuple(rargs[0:nargs])
- del rargs[0:nargs]
-
- elif had_explicit_value:
- self.error("%s option does not take a value" % opt)
-
- else:
- value = None
-
- option.process(opt, value, values, self)
-
- def _process_short_opts (self, rargs, values):
- arg = rargs.pop(0)
- stop = 0
- i = 1
- for ch in arg[1:]:
- opt = "-" + ch
- option = self._short_opt.get(opt)
- i += 1 # we have consumed a character
-
- if not option:
- self.error("no such option: %s" % opt)
- if option.takes_value():
- # Any characters left in arg? Pretend they're the
- # next arg, and stop consuming characters of arg.
- if i < len(arg):
- rargs.insert(0, arg[i:])
- stop = 1
-
- nargs = option.nargs
- if len(rargs) < nargs:
- if nargs == 1:
- self.error("%s option requires a value" % opt)
- else:
- self.error("%s option requires %s values"
- % (opt, nargs))
- elif nargs == 1:
- value = rargs.pop(0)
- else:
- value = tuple(rargs[0:nargs])
- del rargs[0:nargs]
-
- else: # option doesn't take a value
- value = None
-
- option.process(opt, value, values, self)
-
- if stop:
- break
-
-
- # -- Output/error methods ------------------------------------------
-
- def error (self, msg):
- self.print_usage(sys.stderr)
- sys.exit("%s: error: %s" % (get_prog_name(), msg))
-
- def print_usage (self, file=None):
- if self.usage:
- usage = self.usage.replace("%prog", get_prog_name())
- print >>file, usage
- print >>file
-
- def print_version (self, file=None):
- if self.version:
- version = self.version.replace("%prog", get_prog_name())
- print >>file, version
-
- def print_help (self, file=None):
- from distutils.fancy_getopt import wrap_text
-
- if file is None:
- file = sys.stdout
-
- self.print_usage(file)
-
- # The help for each option consists of two parts:
- # * the opt strings and metavars
- # eg. ("-x", or "-fFILENAME, --file=FILENAME")
- # * the user-supplied help string
- # eg. ("turn on expert mode", "read data from FILENAME")
- #
- # If possible, we write both of these on the same line:
- # -x turn on expert mode
- #
- # But if the opt string list is too long, we put the help
- # string on a second line, indented to the same column it would
- # start in if it fit on the first line.
- # -fFILENAME, --file=FILENAME
- # read data from FILENAME
-
- print >>file, "options:"
- width = 78 # assume 80 cols for now
-
- option_help = [] # list of (string, string) tuples
- lengths = []
-
- for option in self.option_list:
- takes_value = option.takes_value()
- if takes_value:
- metavar = option.metavar or option.dest.upper()
-
- opts = [] # list of "-a" or "--foo=FILE" strings
- if option.help is SUPPRESS_HELP:
- continue
-
- if takes_value:
- for sopt in option._short_opts:
- opts.append(sopt + metavar)
- for lopt in option._long_opts:
- opts.append(lopt + "=" + metavar)
- else:
- for opt in option._short_opts + option._long_opts:
- opts.append(opt)
-
- opts = ", ".join(opts)
- option_help.append((opts, option.help))
- lengths.append(len(opts))
-
- max_opts = min(max(lengths), 20)
-
- for (opts, help) in option_help:
- # how much to indent lines 2 .. N of help text
- indent_rest = 2 + max_opts + 2
- help_width = width - indent_rest
-
- if len(opts) > max_opts:
- opts = " " + opts + "\n"
- indent_first = indent_rest
-
- else: # start help on same line as opts
- opts = " %-*s " % (max_opts, opts)
- indent_first = 0
-
- file.write(opts)
-
- if help:
- help_lines = wrap_text(help, help_width)
- print >>file, "%*s%s" % (indent_first, "", help_lines[0])
- for line in help_lines[1:]:
- print >>file, "%*s%s" % (indent_rest, "", line)
- elif opts[-1] != "\n":
- file.write("\n")
-
-# class OptionParser
-
-
-def _match_abbrev (s, words):
- """_match_abbrev(s : string, words : [string]) -> string
-
- Returns the string in 'words' for which 's' is an unambiguous
- abbreviation. If 's' is found to be ambiguous or doesn't match any
- of 'words', raises BadOptionError.
- """
- match = None
- for word in words:
- # If s isn't even a prefix for this word, don't waste any
- # more time on it: skip to the next word and try again.
- if not word.startswith(s):
- continue
-
- # Exact match? Great, return now.
- if s == word:
- return word
-
- # Now comes the tricky business of disambiguation. At this
- # point, we know s is a proper prefix of word, eg. s='--foo' and
- # word=='--foobar'. If we have already seen another word where
- # this was the case, eg. '--foobaz', fail: s is ambiguous.
- # Otherwise record this match and keep looping; we will return
- # if we see an exact match, or when we fall out of the loop and
- # it turns out that the current word is the match.
- if match:
- raise BadOptionError("ambiguous option: %s (%s, %s, ...?)"
- % (s, match, word))
- match = word
-
- if match:
- return match
- else:
- raise BadOptionError("no such option: %s" % s)
diff --git a/cobbler/Cheetah/Version.py b/cobbler/Cheetah/Version.py
deleted file mode 100644
index 32af08a..0000000
--- a/cobbler/Cheetah/Version.py
+++ /dev/null
@@ -1,58 +0,0 @@
-Version = '2.0rc7'
-VersionTuple = (2,0,0,'candidate',7)
-
-MinCompatibleVersion = '2.0rc6'
-MinCompatibleVersionTuple = (2,0,0,'candidate',6)
-
-####
-def convertVersionStringToTuple(s):
- versionNum = [0,0,0]
- releaseType = 'final'
- releaseTypeSubNum = 0
- if s.find('a')!=-1:
- num, releaseTypeSubNum = s.split('a')
- releaseType = 'alpha'
- elif s.find('b')!=-1:
- num, releaseTypeSubNum = s.split('b')
- releaseType = 'beta'
- elif s.find('rc')!=-1:
- num, releaseTypeSubNum = s.split('rc')
- releaseType = 'candidate'
- else:
- num = s
- num = num.split('.')
- for i in range(len(num)):
- versionNum[i] = int(num[i])
- if len(versionNum)<3:
- versionNum += [0]
- releaseTypeSubNum = int(releaseTypeSubNum)
-
- return tuple(versionNum+[releaseType,releaseTypeSubNum])
-
-
-if __name__ == '__main__':
- c = convertVersionStringToTuple
- print c('2.0a1')
- print c('2.0b1')
- print c('2.0rc1')
- print c('2.0')
- print c('2.0.2')
-
-
- assert c('0.9.19b1') < c('0.9.19')
- assert c('0.9b1') < c('0.9.19')
-
- assert c('2.0a2') > c('2.0a1')
- assert c('2.0b1') > c('2.0a2')
- assert c('2.0b2') > c('2.0b1')
- assert c('2.0b2') == c('2.0b2')
-
- assert c('2.0rc1') > c('2.0b1')
- assert c('2.0rc2') > c('2.0rc1')
- assert c('2.0rc2') > c('2.0b1')
-
- assert c('2.0') > c('2.0a1')
- assert c('2.0') > c('2.0b1')
- assert c('2.0') > c('2.0rc1')
- assert c('2.0.1') > c('2.0')
- assert c('2.0rc1') > c('2.0b1')
diff --git a/cobbler/Cheetah/__init__.py b/cobbler/Cheetah/__init__.py
deleted file mode 100644
index 08c240e..0000000
--- a/cobbler/Cheetah/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python
-# $Id: __init__.py,v 1.10 2006/01/14 04:44:07 tavis_rudd Exp $
-
-"""Cheetah is an open source template engine and code generation tool.
-
-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.
-
-Homepage
-================================================================================
-http://www.CheetahTemplate.org/
-
-Documentation
-================================================================================
-For a high-level introduction to Cheetah please refer to the User's Guide
-at http://cheetahtemplate.org/learn.html
-
-Mailing list
-================================================================================
-cheetahtemplate-discuss@lists.sourceforge.net
-Subscribe at http://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.10 $"[11:-2]
-
-from Version import Version
diff --git a/cobbler/Cheetah/_namemapper.so b/cobbler/Cheetah/_namemapper.so
deleted file mode 100755
index 8f56724..0000000
--- a/cobbler/Cheetah/_namemapper.so
+++ /dev/null
Binary files differ
diff --git a/cobbler/Cheetah/convertTmplPathToModuleName.py b/cobbler/Cheetah/convertTmplPathToModuleName.py
deleted file mode 100644
index 4f9d8ea..0000000
--- a/cobbler/Cheetah/convertTmplPathToModuleName.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import os.path
-import string
-
-l = ['_'] * 256
-for c in string.digits + string.letters:
- l[ord(c)] = c
-_pathNameTransChars = string.join(l, '')
-del l, c
-
-def convertTmplPathToModuleName(tmplPath,
- _pathNameTransChars=_pathNameTransChars,
- splitdrive=os.path.splitdrive,
- translate=string.translate,
- ):
- return translate(splitdrive(tmplPath)[1], _pathNameTransChars)