Updated section on templating.
1 parent 02cefd1 commit 85d864b507684c8f5e3b83eff6ecff003b6dedb7
@tundra tundra authored on 20 Jan 2005
Showing 1 changed file
View
208
tconfpy.3
\fCtconfpy\fP can parse configurations both in files as well as in-memory
lists. Whenever you see the term "file", think "a file or a set of
configuration statements stored in a list".
 
.B ANOTHER NOTE:
Throughout this document we refer to "symbols" and "variables"
interchangeably. Strictly speaking, this is not really right. A
"symbol" is an entry in a symbol table representing the state of some
"variable" that is visible to a person writing a configuration. But
it's safe to assume you're smart enough to understand this subtlety
and know what is meant by context ;)
 
.B JUST ONE LAST NOTE:
If you run \fCtconfpy\fP directly, it will dump version and copyright
information, as well as the value of the current predefined
System Variables:
 
.ft C \" Courier
.nf
class SymbolTable(object):
def __init__(self):
 
# These items are populated when the parser returns
 
self.Symbols = {}
self.DebugMsgs = []
self.ErrMsgs = []
self.WarnMsgs = []
self.LiteralLines = []
self.TotalLines = 0
self.Visited = []
 
# These items are for internal parser use only
# Never write an application to depend on their content
 
self.Templates = Template()
self.ALLOWNEWVAR = True
self.TEMPONLY = False
self.LITERALVARS = False
if you wish to provide an initial symbol table. In this case,
only \fCSymbols\fP need be populated.
 
When the parse is complete, an object of this same type is returned.
\fCSymbols\fP, \fCDebugMsgs\fP, \fCErrMsgs\fP, \fCWarnMsgs\fP, and
\fCLiteralLines\fP will be populated with the parse results as
appropriate.
\fCSymbols\fP, \fCDebugMsgs\fP, \fCErrMsgs\fP, \fCWarnMsgs\fP,
\fCLiteralLines\fP, \fCTotalLines\fP, and \fCVisited\fP will be
populated with the parse results as appropriate. The remaining
elements of the object are meaningless when the parser returns, and
applications should never make use of them.
 
 
.TP
.B The Variable Descriptor Object
list in sequential order, treating each entry as a configuration line.
This allows you to use \fCtconfpy\fP for parsing either configuration files or
in-memory configurations. If you pass anything other than a string
or list here, \fCtconfpy\fP will produce an error.
 
If you do pass the API an in-memory list, \fCtconfpy\fP treats each
entry as a line in a configuration "file". However, this means that
each element of the list must be a
.B string.
The parser checks this first and only processes entries in the list
that are strings. Entries of any other type produce an error and are
ignored.
 
 
.TP
.B CallingProgram (Default: \fC\fCtconfpy\fP + Version Number\fP)
this:
 
.ft C \" Courier
.nf
from tconfpy import *
# Create an empty symbol table
MySymTable = SymbolTable()
 
# Repeat this process for all variables, then call the parser
 
retval = ParseConfig("MyConfigFile", InitialSymTable=MySymTable)
 
.fi
.ft \" revert
 
 
 
.ft C \" Courier
.nf
retval = ParseConfig("myconfigfile", AllowNewVars=False)
.fi
.ft \" revert
 
This means that the configuration file can "reference"
any predefined variables, and even change their values
(if they are Writeable), but it cannot create
w.fi
.ft \" revert
 
This means that the configuration file can "reference" any predefined
variables, and even change their values (if they are Writeable), but
it cannot create
.B new
variables.
 
This feature is primarily intended for use when you pass an initial
example:
 
.ft C \" Courier
.nf
 
inter1 = Really, really, really, really, long argument #1
inter2 = Really, really, really, really, long argument #2
 
realvar = command [inter1] [inter2]
.B exact same thing
as a predefined variable you might pass in the initial symbol
table. In other words, it is a Python dictionary entry where the
key is the variable name and the entry is in \fCVarDescriptor\fP
format.
 
The only difference is that a templated variable does not come into
existence in the main symbol table until a variable by that
format. The big difference here is that normal variables are stored
in the symbol table in a \fCSymbolTable\fP container object. But
templated variables are stored in a \fCTemplate\fP container object.
(See
.B Core Objects
above for the details.)
 
Templated variables are thus defined (by the calling program) just
like you would any other variable - but stored in a different place:
 
.ft C \" Courier
.nf
from tconfpy import *
# Create an empty template table
MyTemplates = Template()
# Create descriptor for new variable
MyTemplateVarDes = VarDescriptor()
# Code to fiddle with descriptor contents goes here
MyTemplateVarDes.Type = TYPE_INT
 
... and so forth
 
# Now load the variable into the symbol table
MyTemplates.Symbols["MyTemplateName"] = MyTemplateVarDes
 
# Now pass the Templates to the parser
retval = ParseConfig("myfile", Templates=MyTemplates)
.fi
.ft \" revert
 
.B NOTE:
You may optionally pass either an initial symbol table or a template
table or both to the parser when you call it. That is, the initial
set of symbols is disjoint from any templates you've defined.
 
Semantically, the only difference between "regular" and templated
variables, is that a templated variable does not come into existence
(i.e. Become an entry) in the main symbol table until a variable by
that
.B name
is encountered in the configuration file. Then the variable is
created using the template as its entry in the main symbol table.
 
If there is a template with a matching name, see if the value the
user wants to assign to that variable passes all the type/validation
rules. If so, load the variable into the symbol table and set its
value as requested,
.B using the \fCVarDescriptor\fP object from the template.
.B using the
\fCVarDescriptor\fP
.B object from the template.
(This ensures that future attempts to change the variable's value will
also be type/validation checked.)
 
If the assignment fails the validation tests, issue an appropriate
which means you can create new variables even when no template
for them exists.
 
.P
A few subtleties of templating variables are worth noting here:
 
.IP \(bu 4
The same template is used over and over again to create a
new variable of the same name
.B in different namespaces.
For example, suppose you've defined a template with the name,
\fCAccountNumber\fP:
 
.ft C \" Courier
.nf
[ComputerSupplier]
AccountNumber = 1234-5
 
[Lawyer]
AccountNumber = 3456-3
.fi
.ft \" revert
 
This would create two separate variables in the symbol table, based
on the same template: \fCComputerSupplier.AccountNumber\fP and
\fCLawyer.AccountNumber\fP.
 
This works because \fCtconfpy\fP checks the so-called "canonical" name
of a variable when it is being created (the part of the name without
the namespace information) to see if a template exists for it. For
this reason,
.B a template name must never contain a namespace.
If you attempt to create templates with names like \fCFoo.Templatename\fP,
the parser will reject it and produce an error.
 
 
.IP \(bu 4
Notice that for variables actually in the symbol table,
\fCVarDescriptor.Value\fP holds the current value for the variable.
However, this field is meaningless in a template. The template is
only used when creating a new variable
.B to be added the normal symbol table.
The value field of the template's variable descriptor is never
used for anything - it is never read nor is it ever set.
 
.IP \(bu 4
By definition, a templated variable does not actually exist (in the
symbol table) until you assign it some value in the configuration
file. This means that even if you mark the variable as Read Only
in its template, you are able to set it one time - to actually
create it. Thereafter, the variable exists in the symbol table
with it's \fCWriteable\fP attribute set to \fCFalse\fP and future
changes to the variable are prevented
 
.P
In summary, Variable Templates give you a way to place
restrictions on variable type and content
.B in the event that the variable actually comes into existence.
They also give you a way to define such restrictions for an
.B retval.DebugMsgs
 
A Python list containing detailed debug information for each line
parsed as well as some brief summary information about the parse.
\fCretval.Debug\fP defaults to an empty list and is only populated if you
\fCretval.DebugMsgs\fP defaults to an empty list and is only populated if you
set \fCDebug=True\fP in the API call that initiated the parse (as in the
example above).
 
 
.TP
.B retval.WarnMsgs
A Python list containing warning messages. These describe minor
problems not fatal to the parse process, but that you really ought to
clean up in the configuration file.
clean up in the configuration file. It is possible to create a configuration
that produces no errors but does produce warnings, for example. It is
almost always the case that this configuration is not being handled
the way you intended. As a general matter of good practice, apply
"belt and suspenders" rules in your applications, and demand that
a configration be free of both errors and warnings before proceding.
 
 
.TP
.B retval.LiteralLines
.fi
.ft \" revert
 
.SH DOCUMENT REVISION INFORMATION
$Id: tconfpy.3,v 1.156 2005/01/20 00:07:38 tundra Exp $
$Id: tconfpy.3,v 1.157 2005/01/20 08:18:32 tundra Exp $