List generation can be faster and easier through automation, which essentially prevents the user from being prompted with another question. Many prompts may be easy to answer, but others require information that isn’t readily available. For example, if a prompt asks about the weather forecast, the user will need to go search for it.
Many automation options are possible, given the power of the Python language and its vast library. As with normal lists, Python scripts can be added to a user’s home folder and linked-to. When a list is generated, any script(s) it links to will be run by the built-in python 3.12 interpreter.
The scripts user account contains many useful scripts which are shared with group all. These not only provide useful & common functionality for any list, but are also examples of how to write a script that works with clir. These included scripts are discussed in more detail below.
For security reasons, users currently need approval to run their own python scripts. However, a protected python environment is currently under development, which will prevent any malicious or problematic code from running. This will allow users to develop python scripts that will serve their unique needs. If you are unable to wait for the upcoming protected environment, then you can submit a request for the script to be added to your user account, along with necessary packages to be installed and URLs to access. Once the script has been inspected and approved, it will be added to your account.
A script returns only a single value, which can be any one of the variable types that clir uses (question, select, number, text). A script can accept any number of arguments, each of which can be a variable or a constant value. If using an existing clir variable, then the name is provided in the same way as in a list. If a constant value is provided, then it is listed as with any normal python call (integer, float, boolean, string in double-quotes, list, array, dictionary, etc.).
A comment header at the top of the script is not required, but strongly recommended. A user is of course able to see the contents of their own script, but other users (with whom it has been shared) are only able to see the comment header. They are unable to see or change any of the python code. The comment header gives other users a description of what the script does, what values it requires, and what it returns.
In the Editor page, your own scripts appear in the List Browser pane at the left side, alongside normal lists. In the List Explorer view, python files (with .py extension) are marked with the blue & yellow python icon. Lists and python scripts that are shared with you by others are visible.
As stated in the intro above, the primary purpose of having a python script is to provide automation that spares the user from being prompted. However, it is always a possible for the python script to fail (syntax error, network error, takes too long, bad data provided, etc). Normally the python functionality is invisible to the user, but if anything goes wrong with the script, the user will be prompted to provide the information instead.
The syntax of a python script call is based on the same user prompt syntax discussed here, but with the additional syntax embedded:
( = script.py(arguments…) )
The top line and the bottom case have the same syntax as a prompt. The first case in parentheses is the call to the script. The return value is the type specified in the prompt header.
Example:
? (number -30:130) temperature_high
(
= scripts:weather/temperature/high/days.py("Chicago, IL", 3, 2)
) [
What's the highest possible temperature at destination?
]
The example above contains a call to a the script days.py , which is shared by user scripts, and is located in the folder path weather/temperature/high/. The path to the script is specified in the same way as with a link to a list, with folder path and then the script name, which must end in .py. If this is a link to a script shared with us, then the username precedes the path with username:, just like with normal lists which are shared. Opening & closing parentheses must be present after the python script name, and they may contain any number (including zero) of arguments passed to the script. Arguments are separated by a comma. Each argument can be either a constant value (any value type supported by a python function) or a clir variable. In the above example, if the python script failed for any reason during list generation, then the user would see the prompt text at the bottom of the case.
The following scripts are currently shared with group all, which means anyone can link to them. They can be found in the “sharers” section of the List Browser on the left side of the Editor page.
This script returns a number for the current day of the week. It is 1-based (Monday = 1, Sunday = 7). The only argument passed to it is an integer for the time zone of interest (e.g. GMT = 0, U.S. Eastern Standard Time = 5).
Returns the integer day of the year in the calendar, from 1 to 365 (or 366 for a leap year). The single argument passed to it is the time zone offset integer.
Below are a series of scripts, each providing a single value regarding the weather forecast at a particular location.
The following weather measurements are provided:
| humidity | High humidity level (% 0 - 100 number) | |
| Low humidity level (% 0 - 100 number) | ||
| precip_possible | Is any rain or snow possible? (true/false) | |
| rain | possible | Is there a chance of rain? (true/false) |
| level | Max rain level possible (number) 1=none, 2=light, 3=medium, 4=heavy |
|
| description | A text description of the conditions (e.g. “heavy rain” or “no rain”) | |
| snow | possible | Is there a chance of snow? (true/false) |
| level | Max snow level possible (number) 1=none, 2=light, 3=medium, 4=heavy |
|
| description | A text description of the conditions (e.g. “heavy snow” or “no snow”) | |
| temperature | high | High forecast temperature (degree F number) |
| low | Low forecast temperature (degree F number) | |
| uvindex | High forecast UV index (1 - 11 number) | |
| wind | speed | Highest wind speed (mph 0 – 100 number) |
| windy | Will there be wind speeds higher than 20 mph? (true/false) | |
Every weather script has the location as its 1st argument. This is a text value that contains either a readable description (e.g. Chicago, IL), or the latitude/longitude of the location (e.g. 41.88, -87.63 or 41.88 N, 87.63 W). This description is always the first argument of any weather script call.
For each one of these categories, there are 3 types of queries based on the time interval:
| 1day.py | Returns the corresponding weather measurement for a single day. This requires an offset number (0 – 7) from the current day (0 = today) as the 2nd argument. |
| days.py | Returns the maximum, or worst-case value within a range of days. If the measurement is for a high temperature, UV index, or wind speed, then it returns the highest value possible within the day range. For a measurement like “is rain possible” or “will it be windy”, it will return True if there is a possibility on any of the days in the range. This requires an offset number (0 – 7) from the current day for when the range of days starts (0 = today) as the 2nd argument, and the number of days of that range (0 – 7) as the 3rd argument. |
| weekend.py | Returns the maximum, or worst-case value that should occur in the upcoming weekend. This is determined by the current day of the week when this script is called. The behavior is like that described for days.py above. If this script is called on a Saturday or a Sunday, then the current conditions at the time are given. This script only uses the 1st location argument. |
The examples/travel/prep/weather list gives a basic example of how this weather script can be used to show a summary of the forecast in an info prompt.
This script accepts text with the measure of an ingredient (e.g. "2 tablespoons flour") and scales it by another value, converting between imperial units of measure. This is useful for scaling a recipe to make more (or fewer) servings. For example, if the scale value was 8, then the above result would be “1 cup flour”, and a scale of “1/3” would give “2 teaspons flour”.