| |
---|
| | |
---|
| | .TP |
---|
| | .B LiteralVars (Default: \fCFalse\fP) |
---|
| | |
---|
| | If set to \fCTrue\fP this option enables variable substitutions within |
---|
| | If set to \fCTrue\fP, this option enables variable substitutions within |
---|
| | \fC.literal\fP blocks of a configuration file. See the section in the |
---|
| | language reference below on \fC.literal\fP usage for details. |
---|
| | |
---|
| | |
---|
| | .TP |
---|
| | .B ReturnPredefs (Default: \fCTrue\fP) |
---|
| | \fCtconfpy\fC "prefefines" some variables internally. By default, |
---|
| | \fCtconfpy\fP "prefefines" some variables internally. By default, |
---|
| | these are returned in the symbol table along with the variables |
---|
| | actually defined in the configuration file. If you want a |
---|
| | "pure" symbol table - that is, a table with |
---|
| | .B only |
---|
| |
---|
| | be referenced in a string substitution or conditional test, |
---|
| | but cannot be changed. |
---|
| | |
---|
| | .IP \(bu 4 |
---|
| | You may want to place limits on what values can be assigned to |
---|
| | a particular variable. When a variable is newly defined in a |
---|
| | a configuration file, it just defaults to being a string |
---|
| | variable without any limits on its length or content. But |
---|
| | variables that are created by a program have access to the |
---|
| | variable's "descriptor". By setting various attribues |
---|
| | of the variable descriptor you can control variable type, |
---|
| | content, and range of values. In other words, you can have |
---|
| | \*(TC "validate" what values the user assigns to particular |
---|
| | variables. This substantially simplifies your application because |
---|
| | no invalid variable value will ever be returned from the parser. |
---|
| | You may want to place limits on what values can be assigned to a |
---|
| | particular variable. When a variable is newly defined in a a |
---|
| | configuration file, it just defaults to being a string variable |
---|
| | without any limits on its length or content (unless you are using |
---|
| | Variable Templates). But variables that are created by a program have |
---|
| | access to the variable's "descriptor". By setting various attribues |
---|
| | of the variable descriptor you can control variable type, content, and |
---|
| | range of values. In other words, you can have \*(TC "validate" what |
---|
| | values the user assigns to particular variables. This substantially |
---|
| | simplifies your application because no invalid variable value will |
---|
| | ever be returned from the parser. |
---|
| | |
---|
| | |
---|
| | .SS How To Create An Initial Symbol Table |
---|
| | |
---|
| |
---|
| | and \fCrealvar\fP are predefined in the initial symbol |
---|
| | table passed to the parser. |
---|
| | |
---|
| | |
---|
| | .SS Using Variable Templates - The \fCTemplates\fP And \fCTemplatesOnly\fP API Options |
---|
| | .SS Using Variable Templates |
---|
| | |
---|
| | By default, any time a new variable is encountered in a configuration |
---|
| | file, it is created as a string type with no restrictions on its |
---|
| | content or length. As described above, you can predefine the variable |
---|
| | in the initial symbol table you pass to the parser. This allows you |
---|
| | to define that variable's type and to optionally place various |
---|
| | restrictions on the values it may take. In other words, you can "declare" |
---|
| | the variable ahead of time and \*(TC will do so-called "type |
---|
| | and value enforcement". |
---|
| | |
---|
| | "Variable Templates" are a related kind of idea, with a bit of |
---|
| | a twist. They give you a way to "declare" variable type |
---|
| | and content restrictions for selected |
---|
| | .B new variables |
---|
| | discovered in the configuration file. In other words, |
---|
| | by using Variable Templates, you can make sure that |
---|
| | a new variable also has restrictions placed on its type |
---|
| | and/or values. |
---|
| | |
---|
| | The obvious question here is, "Why not just do this |
---|
| | by predefining every variable of interest in the |
---|
| | initial symbol table passed to the parser?" There |
---|
| | are several answers to this: |
---|
| | |
---|
| | .IP \(bu 4 |
---|
| | The \*(TC configuration language has very powerful "existential" |
---|
| | conditional tests. These test to see if a variable "exists". |
---|
| | If you predefine every variable you will ever need, then |
---|
| | the kinds of existential tests you can do will be |
---|
| | somewhat limited (since every variable |
---|
| | .B does |
---|
| | already exist). |
---|
| | |
---|
| | With Variable Templates, you can define the type and value |
---|
| | constraints of a variable which will be applied, |
---|
| | .B but only if you actually bring that variable into existence. |
---|
| | This allows constructs like this to work: |
---|
| | |
---|
| | .ft C \" Courier |
---|
| | .nf |
---|
| | .if [.PLATFORM] == posix |
---|
| | posix = True |
---|
| | .endif |
---|
| | |
---|
| | .if [.PLATFORM] == nt |
---|
| | nt = True |
---|
| | .endif |
---|
| | |
---|
| | .ifall posix |
---|
| | ... |
---|
| | .endif |
---|
| | |
---|
| | .ifall nt |
---|
| | ... |
---|
| | .endif |
---|
| | |
---|
| | .ifnone posix nt |
---|
| | ... |
---|
| | .endif |
---|
| | |
---|
| | .fi |
---|
| | .ft \" revert |
---|
| | |
---|
| | In this example, notice that the variables \fCposix\fP and \fCnt\fP |
---|
| | may- or may not be actually created, depending on the value of |
---|
| | \fC.PLATFORM\fP. The logic later in the example depends upon this. |
---|
| | If you were to predefine these two variables (to specify type |
---|
| | and/or value restrictions), this type of logical flow would not |
---|
| | be possible. |
---|
| | |
---|
| | By providing Variable Templates for \fCposix\fP and \fCnt\fP, |
---|
| | you can define their type (likely Boolean in this case) |
---|
| | ahead of time |
---|
| | .B and this will be applied if the variable does come into existence. |
---|
| | |
---|
| | |
---|
| | .IP \(bu 4 |
---|
| | The other reason for Variable Templates is more subtle, but |
---|
| | gives \*(TC tremendous versatility beyond just processing |
---|
| | configuration files. Variable Templates give you a way to use |
---|
| | \*(TC to build data validation tools. |
---|
| | |
---|
| | Suppose you have a list of employee records exported in this |
---|
| | general format (easy to do with most databases): |
---|
| | |
---|
| | .ft C \" Courier |
---|
| | .nf |
---|
| | [Employee#] |
---|
| | LastName = ... |
---|
| | FirstName = ... |
---|
| | Address = ... |
---|
| | City = ... |
---|
| | |
---|
| | ... and so on |
---|
| | |
---|
| | .fi |
---|
| | .ft \" revert |
---|
| | |
---|
| | |
---|
| | By using the empoyee's ID as a lexical namespace, we end up creating |
---|
| | new variables for each employee. Say the employee number is |
---|
| | \fC1234\fP. Then we would get, \fC1234.LastName\fP, |
---|
| | \fC1234.FirstName\fP, and so on. |
---|
| | |
---|
| | Now, here's the subtle part. Notice that the type and content |
---|
| | restrictions of these variables is likely to be the |
---|
| | .B same |
---|
| | for each different employee. |
---|
| | |
---|
| | By defining Variable Templates for each of the variables we |
---|
| | intend to use over and over again in different namespace |
---|
| | contexts, we can |
---|
| | .B validate |
---|
| | each of them to make sure their content, type, length, and so forth |
---|
| | are correct. This makes it possible to use \*(TC as the underpinnings |
---|
| | of a "data validation" or "cleansing" program. |
---|
| | |
---|
| | .IP \(bu 4 |
---|
| | Another way to look at this is that Variable Templates give you |
---|
| | a way to define type/value restrictions on an entire "class" |
---|
| | of variables. Instead of having to explictly predefine |
---|
| | variables for every employee in our example above, you |
---|
| | just define templates for the variable set that is common to |
---|
| | all employees. This is |
---|
| | .B way |
---|
| | simpler than predefining every possible variable combination |
---|
| | ahead of time. |
---|
| | |
---|
| | |
---|
| | .SS The \fCTemplates\fP And \fCTemplatesOnly\fP API Options |
---|
| | |
---|
| | Variable Templates are supported with two API options: |
---|
| | \fCTemplates\fP And \fCTemplatesOnly\fP. \fCTemplates\fP |
---|
| | is used to pass a symbol table (separate from the main symbol |
---|
| | table) containing the Variable Templates. By default, this |
---|
| | option is set to \fC{}\fP which means no templates are |
---|
| | defined. |
---|
| | |
---|
| | So what exactly is a "Variable Template"? It is the |
---|
| | .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 |
---|
| | .B name |
---|
| | is encountered in the configuration file. Then the variable is |
---|
| | created using the template as its entry in the main symbol table. |
---|
| | |
---|
| | For example: |
---|
| | |
---|
| | .ft C \" Courier |
---|
| | .nf |
---|
| | [1234] |
---|
| | LastName = Jones |
---|
| | FirstName = William |
---|
| | Address = 123 Main Street |
---|
| | City = Anywhere |
---|
| | State = WI |
---|
| | ZIP = 00000-0000 |
---|
| | |
---|
| | [1235] |
---|
| | LastName = Jones |
---|
| | FirstName = Susan |
---|
| | Address = 123 Main Street |
---|
| | City = Anywhere |
---|
| | State = WI |
---|
| | ZIP = 00000-0000 |
---|
| | |
---|
| | .fi |
---|
| | .ft \" revert |
---|
| | |
---|
| | |
---|
| | Suppose you define variable templates for \fCLastName\fP, |
---|
| | \fCFirstName\fP, \fCAddress\fP, and so on. That is, you |
---|
| | define variables by these names, and define whatever type |
---|
| | and content restrictions you want in each of their |
---|
| | \fCVarDescriptor\fPs. You then pass these to the parser |
---|
| | via the \fCTemplates=\fP option. |
---|
| | |
---|
| | As \*(TC parses the file and encounters the new variables |
---|
| | \fC1234.LastName\fP ... \fC1235.ZIP\fP, it uses the following |
---|
| | "rules" when creating new variables: |
---|
| | |
---|
| | .IP \(bu 4 |
---|
| | See if there is a template variable whose name is the same as |
---|
| | the "base" name of the new variable. (The "base" name is just |
---|
| | the variable name without the prepended namespace.) |
---|
| | |
---|
| | 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. |
---|
| | (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 |
---|
| | error and do |
---|
| | .B not |
---|
| | create the variable in the symbol table. |
---|
| | |
---|
| | .IP \(bu 4 |
---|
| | If there is no template with a matching name, then just |
---|
| | create a new variable as usual - string type with no |
---|
| | restrictions, |
---|
| | .B unless |
---|
| | \fCTemplatesOnly\fP is set to \fCTrue\fP. Setting this |
---|
| | option to \fCTrue\fP tells the program that you want to |
---|
| | allow the creation of |
---|
| | .B only |
---|
| | those variables for which templates are defined. This is |
---|
| | a way to restrict just what new variables can be created |
---|
| | in any namespace. \fCTemplatesOnly\fP defaults to \fCFalse\fP |
---|
| | which means you can create new variables even when no template |
---|
| | for them exists. |
---|
| | |
---|
| | .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 |
---|
| | entire class of variables without having to explicitly name |
---|
| | each such variable ahead of time. Finally, Variable Templates |
---|
| | are an interesting way to use \*(TC as the basis for data |
---|
| | validation programs. |
---|
| | |
---|
| | |
---|
| | |
---|
| | .SS The \fCLiteralVars\fP API Option |
---|
| | |
---|
| |
---|
| | .B only |
---|
| | the variables actually encountered in the configuration file itself, |
---|
| | set \fCReturnPredefs=False\fP in the \fCParseConfig()\fP API call. |
---|
| | This will cause \fCtconfpy\fP to strip out all the predefined |
---|
| | variables before returning the final symbol table. Note that this |
---|
| | option also removes the \fCNAMESPACE\fP variable since it is understood |
---|
| | to also be outside the configuration file (even though you may have |
---|
| | passed an initial version of \fCNAMESPACE\fP to the parser). |
---|
| | variables before returning the final symbol table. |
---|
| | |
---|
| | Note that this option also removes the \fCNAMESPACE\fP variable since |
---|
| | it is understood to also be outside the configuration file (even |
---|
| | though you may have passed an initial version of \fCNAMESPACE\fP to |
---|
| | the parser). |
---|
| | |
---|
| | Note also that this option applies only to the variables predefined |
---|
| | by |
---|
| | .B \fCtconfpy\fP |
---|
| | itself. Any variables |
---|
| | .B you |
---|
| | predefine when passing an initial symbol table will be returned as usual, |
---|
| | regardless of the state of this option. |
---|
| | |
---|
| | |
---|
| | .SS The \fCDebug\fP API Option |
---|
| | |
---|
| |
---|
| | |