diff --git a/tconfpy.3 b/tconfpy.3 index b282fcd..247c6b3 100644 --- a/tconfpy.3 +++ b/tconfpy.3 @@ -154,10 +154,12 @@ the calling program. .SS API Overview +The \*(TC API consists of a single call. Only the configuration file +to be processed is a required parameter, all the others are optional +and default as described below: .nf - -.B ParseConfig(cfgfile, InitialSymTbl={}, AllowNewVars=True, Debug=False, LiteralVars=False) +.B retval = ParseConfig(cfgfile, InitialSymTbl={}, AllowNewVars=True, AllowNewNamespaces=True, Debug=False, LiteralVars=False) where: @@ -173,6 +175,10 @@ Allow the user to create new variables in the configuration file. Defaults to True. +.B AllowNewNamespaces + Allow new namespaces to be created in the configuration file. + Defaults to True. + .B Debug Defaults to False. If set to True, \*(TC will provide detailed debugging information about each line processed when it returns. @@ -183,6 +189,200 @@ See the section in the language reference below on \'.literal\' usage for details. +.B retval + An object of type \'tconfpy.RetObj\' used to return parsing + results. + + +.SS Passing An Initial Symbol Table + +The simplest way to parse a configuration file is just to call +the parser with the name of that file: + + +.nf +retval = ParseConfig("myconfigfile") +.fi + +Assuming your configuration file is valid, \'ParseConfig()\' will +return a symbol table populated with all the variables defined in the +file and their associated values. This symbol table will have +.B only +the symbols defined in that file (plus a few built-in and pre-defined +symbols needed internally by \*(TC). + +However, the API provides a way for you to pass a "primed" symbol +table to the parser that contains pre-defined symbols/values of +your own choosing. Why on earth would you want to do this? There +are a number of reasons: + +.nf +1) You may wish to write a configuration file which somehow depends + on a pre-defined variable which only the calling program can know: + + .if [APPVERSION] == 1.0 + # Set configuration for older application releases + .else + # Set configuration for newer releases + .endif + + In this example, only the calling application can know its own + version, so it sets the variable APPVERSION in a symbol table + which is passed to \'ParseConfig()\'. + +2) You may wish to "protect" certain variable names be creating + them ahead of time and marking them as "Read Only". This is + useful when you want a variable to be available for use + within a configuration file, but you do not want users to + be able to change its value. In this case, the variable can + be referenced in a string substitution or conditional test, + but cannot be changed. + +3) You may want to place limits on what values can be assigned to + a particular variable. By default, all variables newly defined + within a configuration file are defined to be strings of any + length, with no restrictions on their content. By pre-defining a + variable, you can specify its type (integer, string, boolean, or + complex), a list of possible legal values, a range of legal values, + min/max string length, or a set of regular expressions for string + variables - one of which must match. 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. + +.fi + + + +class VarDescriptor(object): + + # Default variable type is a writeable string with no constraints + def __init__(self): + self.Value = "" + self.Writeable = True + self.Type = TYPE_STRING + self.Default = "" + self.LegalVals = [] + self.Min = None + self.Max = None + +# End of class 'VarDescriptor' + + + +When you pass an initial symbol table to the parser, \*(TC does +some basic validation that the table contents properly conform +to the \'VarDescriptor\' format and generates error messages if +it finds problems. However, the program does +.B not +check your specifications to see if they make sense. For instance +if you define an integer with a minimum value of 100 and a maximum +value of 50, \*(TC cheerfully accepts these limits even they they +are impossible. You'll just be unable to do anything with that +variable - any attempt to change its value will cause an error +to be recorded. Similarly, if you put a value in \'LegalVals\' that +is outside the range of \'Min\' to \'Max\', \*(TC will accept +it quietly. + +.SS The \'AllowNewVars\' Option + +By default, \*(TC lets the user define any new variables they +wish in a configuration file, merely by placing a line in the +file in this form: + +.nf + Varname = Value +.fi + +However, you can disable this capability by calling the parser like +this: + +.nf + retval = ParseConfig("myconfigfile", AllowNewVars=False) +.fi + +This means that the configuration file can "reference" +any pre-defined variables, and even change their values +(if they are not Read-Only), but it cannot create +.B new +variables. + +This feature is primarily intended for use when you pass an initial +symbol table to the parser and you do not want any other variables +defined by the user. Why? There are several possible uses for +this option: + +.nf + +1) You know every configuration variable name the calling program + will use ahead of time. Disabling new variable names keeps + the configuration file from getting cluttered with variables + that the calling program will ignore anyway, thereby + keeping the file more readable. + +2) You want to insulate your user from silent errors caused + by misspellings. Say your program looks for a configuration + variable called \'MyEmail\' but the user enters something + like \'myemail = foo@bar.com\'. \'MyEmail\' and \'myemail\' + are entirely different variables and only the former is + recognized by your calling program. By turning off new + variable creation, the user's inadvertent misspelling of + the desired variable name will be flagged as an error. + +.fi + +Note, however, that there is one big drawback to disabling +new variable creation. \*(TC processes the configuration +file on a line-by-line basis. No line "continuation" is +supported. For really long variable names and ease of +maintenance, it is sometimes helpful to create "intermediate" +variables what hold temporary values used to construct +a variable actually needed by the calling program. For example: + +.nf + +inter1 = Really, really, really, really, long argument #1 +inter2 = Really, really, really, really, long argument #2 + +realvar = command [inter1] [inter2] +.fi + +If you disable new variable creation you can't do this +anymore unless all the variables \'inter1\', \'inter2\', +and \'realvar\' are predefined in the initial symbol +table passed to the parser. + + +.SS The \'AllowNewNamespaces\' Option + +By default, \*(TC supports the use of an arbitrary number of +lexical namespaces. They can be predefined in an initial +symbol table passed to the parser and/or created in the configuration +file as desired. (The details are described in a later section +of this document.) + +There may be times, however, when you do not want users creating new +namespaces on their own. The reasons are much the same as for +preventing the creation of new variables in the option above: +Maintaining simplicity and clarity in the configuration file and +preventing "silent" errors due to misspellings. + +In this case, call the API with \'AllowNewNamespaces=False\' and the +creation of new namespaces in the configuration file will be disabled. +Any attempt to create a new namespaces via either the +\'[new-ns-name]\' or \'NAMESPACE=new-ns-name\' methods will cause a +parse error to be generated. + +It is important to realize that this option only disables the +creation of +.B new +namespaces. As discussed in the later section on namespace +processing, it is possible to pass an initial symbol table to the +parser which has one or more pre-defined namespaces in it. Each of +these pre-defined namespaces is available for use throughout the +configuration file even if \'AllowNewNamespaces\' is set to False. + + .SS The \'Debug\' Option \*(TC has a fairly rich set of debugging features built into its @@ -256,110 +456,6 @@ -.SS Passing An Initial Symbol Table - -The simplest way to parse a configuration file is just to call -the parser with the name of that file: - - -.nf -retval = ParseConfig("myconfigfile") -.fi - -Assuming your configuration file is valid, \'ParseConfig()\' will -return a symbol table populated with all the variables defined in the -file and their associated values. This symbol table will have -.B only -the symbols defined in that file (plus a few built-in and pre-defined -symbols needed internally by \*(TC). - -However, the API provides a way for you to pass a "primed" symbol -table to the parser that contains pre-defined symbols/values of -your own choosing. Why on earth would you want to do this? There -are a number of reasons: - -.nf -1) You may wish to write a configuration file which somehow depends - on a pre-defined variable which only the calling program can know: - - .if [APPVERSION] == 1.0 - # Set configuration for older application releases - .else - # Set configuration for newer releases - .endif - - In this example, only the calling application can know its own - version, so it sets the variable APPVERSION in a symbol table - which is passed to \'ParseConfig()\'. - -2) You may wish to "protect" certain variable names be creating - them ahead of time and marking them as "Read Only". This is - useful when you want a variable to be available for use - within a configuration file, but you do not want users to - be able to change its value. In this case, the variable can - be referenced in a string substitution or conditional test, - but cannot be changed. - -3) You may want to place limits on what values can be assigned to - a particular variable. By default, all variables newly defined - within a configuration file are defined to be strings of any - length, with no restrictions on their content. By pre-defining a - variable, you can specify its type (integer, string, boolean, or - complex), a list of possible legal values, a range of legal values, - min/max string length, or a set of regular expressions for string - variables - one of which must match. 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. - -.fi - - - - -When you pass an initial symbol table to the parser, \*(TC does -some basic validation that the table contents properly conform -to the \'VarDescriptor\' format and generates error messages if -it finds problems. However, the program does -.B not -check your specifications to see if they make sense. For instance -if you define an integer with a minimum value of 100 and a maximum -value of 50, \*(TC cheerfully accepts these limits even they they -are impossible. You'll just be unable to do anything with that -variable - any attempt to change its value will cause an error -to be recorded. Similarly, if you put a value in \'LegalVals\' that -is outside the range of \'Min\' to \'Max\', \*(TC will accept -it quietly. - -.SS The \'AllowNewVars\' Option - -By default, \*(TC lets the user define any new variables they -wish in a configuration file, merely by placing a line in the -file in this form: - -.nf - Varname = Value -.fi - -However, you can disable this capability by calling the parser like -this: - -.nf - retval = ParseConfig("myconfigfile", AllowNewVars=False) -.fi - -This means that the configuration file can "reference" -any pre-defined variables, and even change their values -(if they are not Read-Only), but it cannot create -.B new -variables. This is primarily intended for use when you -pass an initial symbol table to the parser and you do not want -any other variables defined by the user. Why? To prevent them -from making spelling errors. For example, you can define the -variable name "MyEmail" and they will get an error if they -accidentally try to do something like "myemail = x@y.com". - - .SS How \*(TC Processes Errors As a general matter, when \*(TC encounters an error in the