==================== ``grail.rtv`` module ==================== .. include:: ..\version.h .. include:: ..\Library_Reference\lib-reference.h .. contents:: Table of Contents :backlinks: top ----------- Description ----------- Run time variable module. These variables are commonly associated with the MineSightŪ Grail widgets (GWidgets), and allow you to, 1. Associate a variable that updates as at the same time a user updates a widget. 2. Work within the MineSightŪ-Compass context. ----------- RTV Classes ----------- The various type of basic RTV classes defined in this module all inherit from the base RTV class. The basic hierarchy is as follows, - :c:`RTV` - :c:`FloatRTV` - :c:`IntegerRTV` - :c:`StringRTV` class :dc:`RTV([name, value, validity]` Base class for all :c:`RTV` classes. As the base class, all setting, getting and validation is done here. If you wish to construct your own customized RTV object, you will need to override the _fromstringimpl() and _tostringimpot(). You can listen to the variable changing by using the :d:`const.sigON_CHANGE` message (see grail.const_). .. Note:: This object was built up over a series of iterations. Looking at in hindsight, it seems the usererrormessage() method resembles the human appendix. .. Methods to override: :f:`_fromstringimpl` Takes a string value and calls :f:`set` with a converted value. Should raise a :e:`RTVValueError` if the conversion fails. :f:`_tostringimpl` Takes the result of :f:`get` and converts it to a string. Builds the :c:`RTV` object. Since this is the base class, the value and validity do not have reasonable default values. However the name, must have a value. Arguments: :a:`value` Value for the RTV object. :a:`validity` : :c:`Validity` class What is "valid" for this object. :a:`name` : string Name for this object, must be unique. :df:`fromstring(string_)` Converts the string into the internal value. Conversion routine is defined by the :f:`_fromstringimpl()` method. Arguments: :a:`string_` : string A string value that can be converted to the internal value. Raises: :e:`RTVError` If the :a:`string_` is not a string. :e:`RTVValueError` If the conversion can not work or the value is invalid. .. Note:: That in multi-run setup mode (for MineSightŪ-Compass), everything is acceptable. :df:`get()` Returns the internal value. :df:`isvalid(value)` Determines if a value is valid or not. This is based on the validity object. :df:`name()` Returns the name of the variable. :df:`set(value)` Set the internal value to the input value. This method will raise a :e:`RTVValueError` if the value does not satisfy :f:`isvalid`. :df:`setvalidity(validityobj)` Indicate what validity object you would like to use internally. :df:`tostring()` Converts the internal value to a string. :df:`usererrormessage()` Returns the error message for invalid data (or None if no validity). class :dc:`FloatRTV([name, value, validity])` Represents a Float run-time-variable. The internal value is of type float. This class inherits from :c:`RTV`. Arguments: :a:`name` : string A unique name for this variable, name must be unique to a python session. :a:`value` : float A starting floating point value (default is 0.0). :a:`validity` : :c:`Validity` A :c:`Validity` object that can be used to state that a given value is valid. class :dc:`IntegerRTV([name, value, validity])` Represents an Integer run-time-variable. The internal value is of type integer. This class inherits from :c:`RTV`. Arguments: :a:`name` : string A unique name for this variable, name must be unique to a python session. :a:`value` : integer A starting integer value (default is 0). :a:`validity` : :c:`Validity` A :c:`Validity` object that can be used to state that a given value is valid (default is :c:`IntegerValidity`). class :dc:`StringRTV([name, value, validity])` Represents a String run-time-variable. The internal value is of type string. This class inherits from :c:`RTV`. Arguments: :a:`name` : string A unique name for this variable, name must be unique to a python session. :a:`value` : string A starting string value (default is ""). :a:`validity` : :c:`Validity` A :c:`Validity` object that can be used to state that a given value is valid (default is :c:`StringValidity`). Signals ------- You can listen to the variable changing by using the :d:`const.sigON_CHANGE` message (see grail.const_). .. python:: from grail import rtv from grail import objsignal from grail import const def on_var_change(var): print "new value is ", var.get() my_var = rtv.IntegerRTV(name="my_var") objsignal.listen(my_var, const.sigON_CHANGE, None, on_var_change) this will execute the function :f:`on_var_change`, with the new variable. .. _grail.const: lib-grail-const.html On Demand RTV Class ------------------- So what are these :c:`OnDemandRTV` objects? Well, in the early days we need a way to dynamically build :c:`RTV` objects on the fly, as well as, use :c:`RTV` objects that already exist. So for example, lets say on one execution of a procedure the user only needed 2 variables in a list, but on another execution they needed 8, and then again, they went back to 3. Basically, we never knew how many RTV's the user would need, so we can never pre-generate the number. So our first step would be to make "enough" of them that we do not have any problems. To do that we would pre-generate a list like this, .. Python:: NUM_LABELS = 20 itemlist = [rtv.StringRTV(name="item(%d)" % (i)) for i in range(NUM_LABELS)] # later we'd access it like... itemlist[10].set("one more wafer") Alas, what if during the scripts execution we wanted to access the 50th item in that list. Well, we'd either have to make sure :a:`NUM_LABELS` was set to 50 prior to creating that list, or re-create that list and hope to re-use existing variables, or take a deep breath and start using the :c:`OnDemandRTV` objects. That was a bit of the background, now on to how to use this beast. So, the basic premise is that we will define how to generate a name for a RTV when one is created (and or an existing one is retrieved), and we will also define how to go about creating these variables when we need one on the fly. So revisiting our example using the item list. This time we won't pre-define a maximum value, and instead we will use the :c:`OnDemandRTV` construct, .. Python:: itemlist = rtv.OnDemandRTV(rtvclass=rtv.StringRTV, configname="itemvar(%d)") # ... later ... # creates a StringRTV called "item(50)" and # sets its value to "one more wafer" itemlist(50).set("one more wafer") So you can see you never have to pre-generate a variable. The :c:`OnDemandRTV` basically takes any request and searches for the variable with an existing name :a:`itemvar(50)` or creates a new variable with the name :a:`itemvar(50)`. The :a:`configname` keyword indicates how the name is generated when you make the call :a:`itemlist(50)`. Notice that the configuration works the same as, .. Python:: print "itemvar(%d)" % (value) where in our example, the :a:`itemvar(%d)` was the configname. As a slightly more complex version consider, .. Python:: from grail import rtv matrix = rtv.OnDemandRTV(rtvclass=rtv.FloatRTV, configname="matrix(%d, %d)") for i in range(3): for j in range(3): matrixelement = matrix(i, j) In this above example you would have a set of variables generated for each :a:`i` and :a:`j` used in the for loop. In the end a call such as, .. Python:: matrix(2, 2).set(1.) Would retrieve already existing variable :a:`matrix(2, 2)` and set the value to :a:`1`. However the call, .. Python:: matrix(100, 100).set(10.) Would create a new variable :a:`matrix(100,100)` and set that value to :a:`10`. class :dc:`OnDemandRTV([, rtvclass=None, configname=None, *args, **kws])` Allows you to dynamically create variables on the fly. Arguments: :a:`rtvclass` : :c:`RTV` The class of variable you want to be dynamically creating, for example a :c:`StringRTV`. :a:`configname` : string The name that you wish to generate dynamically, see above. :a:`args` : variable argument list. Arguments you wish to apply to the rtvclass initialization. :a:`kws` : variable keyword dictionary. Keywords you wish to apply to the rtvclass initialization, for example, :a:`value=10` for all new :c:`IntegerRTV` objects. ---------------- Validity Classes ---------------- The Validity classes are specialized based on the type of validation you wish to perform. All validity classes inherit from the base :c:`Validity` class, and have the following hierarchy, * :c:`Validity` * :c:`IntegerValidity` * :c:`RangedIntegerValidity` * :c:`NaturalNumberValidity` * :c:`FloatValidity` * :c:`RangedFloatValidity` * :c:`StringValidity` * :c:`AlphaNumericStringValidity` * :c:`AlphaStringValidity` * :c:`DigitStringValidity` * :c:`LengthStringValidity` class :dc:`Validity([errmsg])` Base class for all Validity objects. Validity objects are used to configure :c:`RTV` objects to process invalid and valid values. The :c:`StringRTV`, :c:`FloatRTV`, and :c:`IntegerRTV` all come with obvious default validity objects. If you wish to customize your own validity object you can do so by overriding the :f:`valid()` method. As a contrived example, consider a Validity object that only only accepts strings starting with the letter "f". We will inherit from the StringValidity since that gives us one part of our validation -- that it is a string, and we will put together the test in the :f:`valid()` routine. The python code for this would look like this, .. Python:: from grail import rtv class FStringValidity(rtv.StringValidity): def __init__(self): rtv.StringValidity.__init__(self) def valid(self, value): return rtv.StringValidity.valid(self, value) and\ value[0] == 'f' Arguments: :a:`errmsg` : string A human readable error message to use when a validity test fails. Leave this as None to let MSGRAIL figure one out itself. :df:`errormessage()` Returns the error message stored on this :c:`Validity` object. :df:`valid(value)` **Override** This method to define what valid is for your :c:`Validity` object. Note that all the Validity objects in the rtv module have their :f:`valid()` methods overridden. class :dc:`IntegerValidity([errmsg])` Defines a validity that checks for integers. Any value is valid if it satisfies the equality, :df:`valid(value)` Returns true if the value is an integer. class :dc:`RangedIntegerValidity([min, max, errmsg])` Defines a validity that checks for integers between [min, max]. Any value is valid if it is an integer *and* it lies between the minimum and maximum values. The min/max use the following [min,max] range notation. There is no error checking to ensure that the min and max are integers, and min is less than max. Arguments: :a:`min` : integer Minimum (inclusive) value of the integer. :a:`max` : integer Maximum (inclusive) value of the integer. :df:`valid(value)` Returns true if the value is an integer betwee [min, max]. class :dc:`NaturalNumberValidity([errmsg])` Defines a validity that checks for Natural Numbers. A natural number is any Integer that is greater than, but not equal to 0. As defined by grail.utils.isnatural() (see grail.utils_). :df:`valid(value)` Returns true if the value is an integer greater than zero. class :dc:`FloatValidity([errmsg])` Defines a validity that checks for Floating Point numbers. If the value tested against was an integer, it will fail. Add '.0' to the integer to ensure that it passes. :df:`valid(value)` Returns true if the value is equal to types.FloatType. class :dc:`RangedFloatValidity([min, max, errmsg])` Defines a Validity that checks for floats within a set range. Valid values are floating point numbers and lie in the range [min, max]. The minimum and maximum are inclusive to within :d:`grail.const.FLOATING_POINT_TOLERANCE`. The inclusivity is defined by the grail.utils.isclose() predicate (see grail.utils_). There is no error checking to ensure min and max are floating point numbers, and that min < max. Arguments: :a:`min` : float Minimum (inclusive) valid value. :a:`max` : float Maximum (inclusive) valid value. :df:`valid(value)` Returns a true if the value is a float between [min, max]. class :dc:`StringValidity([errmsg])` Defines a Validity object for strings. Any value which is a string will be Valid. :df:`valid(value)` Verifies the value is a valid string. class :dc:`AlphaNumericStringValidity([errmsg])` Defines a Validity object for Alpha-Numeric Strings. Any string with either numbers or alphabetic characters (English) will be valid. These would satisfy the string.isalnum() predicate. :df:`valid(value)` Returns 1 for AlphaNumeric strings. class :dc:`AlphaStringValidity([errmsg])` Defines a Validity indicating that alpha character strings are valid. A alpha character is any character that satisfies :f:`string.isalpha()` [#python-lib-string]_. :df:`valid(value)` Returns true for alpha strings. class :dc:`DigitStringValidity([errmsg])` Defines a Validity indicating that digit only strings are valid. A digit is defined by any value in "1234567890". :df:`valid(value)` Returns true if the string is populated by digits only. class :dc:`LengthStringValidity([min, max, errmsg])` Defines a validity that checks for a strings length. A string that satisfies this has a len(value) that lies in the defined range: [min, max]. Arguments: :a:`min` : integer Minimum length (up to an including) for a string. Negative values are nonsense, but will be equivalent to 0. :a:`max` : integer Maximum length (up to an including) for the string. :df:`valid(value)` Returns true for strings with a length [min, max]. ---------- Exceptions ---------- The following exceptions may be generated from this module or any classes defined within this module. exception :de:`RTVError` Base error for all errors generated by this module. exception :de:`RTVValueError` Error indicates that a value was invalid or uncovertable. :df:`usermessage()` Returns a human readable message, or a default error message. --------- Functions --------- :df:`deletertv(name)` Removes a reference to a :c:`RTV` object with the given name. Since there is an internal map that keeps track of all the :c:`RTV` objects that exist in the 'grail world', there is a chance that an rtv variable will exist for ever (the internal map holding the 1 last reference to the variable). This function provides a means to remove that rtv. This function will raise a :e:`RTVError` if the name is not found in the internal mapping. Arguments: :a:`name` : string Name of the rtv that you wish to remove :df:`getrtv(name)` Returns a :c:`RTV` object based on the name. :df:`getvariablemap()` Returns a dictionary of all the :c:`RTV` objects stored in the system. The returned dictionary is a *copy* of the internal one and is formatted as, .. Python:: {name0:str_value0, ..., nameN:str_valueN} As you can see every variable's string representation (as supplied by the :f:`RTV.tostring()` method), is brought into the dictionary. This dictionary can be used by :f:`setvariablemap()`. .. Note:: That any :c:`RTV` with a name prefixed with "__" is for internal use, and will not be returned by this function. :df:`getvariablenames()` Returns all the run time variable names that are currently alive. :df:`isrtvname(name)` Checks to to see if a name is in the system's internal RTV map. :df:`resetglobals()` Cleans out the internal RTV map. Useful for multiple runs within the same execution environment. If you do not understand what that last sentence means, do not call this function. :df:`setvariablemap(vardict)` Sets the internal system variable map. Variable map (vardict) passed in should be of the form, .. Python:: {name0:str_value1, name1:str_value1, ..., nameN:str_valueN} Where a variable must be instantiated AND the str_value must be convertable for that variable. This is a very tricky function to play with. .. Warning:: Use this function "sparingly" and "judiciously". :df:`tracevars(yesno[, stream, filter='*'])` Indicates if you want to do a trace dump of variable changes. Just prior to an :a:`onChange()` signal, a message will be dumped to the desired stream. Examples: 1. Using the trace to see all variables starting with "clown" .. Python:: import rtv # other code... rtv.tracevars(1, filter="clown*") 2. Turning of the tracer, .. Python:: import rtv # other code... rtv.tracevar(0) Arguments: :a:`yesno` : integer (bool) Set to 0 to disable tracing, 1 to enable tracing. :a:`stream` : :c:`file` object The output stream you want the messages to be written to. The default is :d:`sys.stdin` [#python-lib-sys]_. :a:`filter` : string A basic filter, using wildcard notation, that allows you filter what variables you want to see modified. :df:`writertvs(stream)` Writes out all system RTV's to the given stream. Arguments: :a:`stream` : :c:`file` object A variable that has a :f:`write()` method. As examples, you could use sys.stdout or a file that you have configured for writing text. ---------- References ---------- .. [#python-lib-sys] "sys -- System-specific parameters and functions" *Python Library Reference*. 30 May 2003. 1 June 2004. .. [#python-lib-string] "string -- Common string operations" *Python Library Reference*. 30 May 2003. 1 June 2004. .. _grail.utils: lib-grail-utils.html