diff --git a/tconfpy.3 b/tconfpy.3 index 91f70f6..4bd8640 100644 --- a/tconfpy.3 +++ b/tconfpy.3 @@ -26,6 +26,15 @@ 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: @@ -120,6 +129,9 @@ .nf class SymbolTable(object): def __init__(self): + + # These items are populated when the parser returns + self.Symbols = {} self.DebugMsgs = [] self.ErrMsgs = [] @@ -127,6 +139,10 @@ 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 @@ -143,9 +159,11 @@ 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 @@ -235,6 +253,14 @@ 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) @@ -415,7 +441,6 @@ .ft C \" Courier .nf - from tconfpy import * # Create an empty symbol table @@ -433,7 +458,6 @@ # Repeat this process for all variables, then call the parser retval = ParseConfig("MyConfigFile", InitialSymTable=MySymTable) - .fi .ft \" revert @@ -825,12 +849,12 @@ .ft C \" Courier .nf retval = ParseConfig("myconfigfile", AllowNewVars=False) -.fi +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 +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. @@ -866,7 +890,6 @@ .ft C \" Courier .nf - inter1 = Really, really, really, really, long argument #1 inter2 = Really, really, really, really, long argument #2 @@ -1024,10 +1047,48 @@ 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. +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.) -The only difference is that a templated variable does not come into -existence in the main symbol table until a variable by that +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. @@ -1076,7 +1137,9 @@ 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.) @@ -1101,6 +1164,57 @@ 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. @@ -1281,7 +1395,7 @@ 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). @@ -1296,7 +1410,12 @@ .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 @@ -3248,4 +3367,4 @@ .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 $