User Guide
This user guide documents several use cases of the letitshine command line utitility. All the examples run here can be found in the examples directory. For you convenience, the create_examples.sh contains the command line arguments used to produce the Shiny apps included in the apps directory.
Command line options
Command line options can be accessed
$ letitshine --help
usage: letitshine_make_app [-h] [-i FUNCTION_TO_INTERACTIVE]
[-type TYPE_OF_OUTPUT] [-create]
This program generates an app.py file to interact with a python code
options:
-h, --help show this help message and exit
-i FUNCTION_TO_INTERACTIVE, --function_to_interactive FUNCTION_TO_INTERACTIVE
Name of the function and module:
name_of_module.funcion_in_module
-type TYPE_OF_OUTPUT, --type_of_output TYPE_OF_OUTPUT
Type of Output ('txt', 'tex', 'plot', 'data_frame','doc').
If there is more than one output separe them with a
comma.
-create, --create_app
Create an app file with app_[NAMEOFFUNCTION].py
Use it at your own risk
The invokation of letitshine requires an input string (-i) which is a module in Python followed by a function to make interactive, name_of_module.funcion_in_module. While input types are inferred from the function definition (see the examples below), the types (and number) of output values need to be explicitely given.
Output types and Shiny outputs
The current accepted output types are a subset of Shiny outputs and are given in the following table
| Keyword | Type of Output | Shiny output |
|---|---|---|
txt |
Text strings | output_text |
tex |
Latex Formatted Text strings | output_text with Katex |
plot |
Pyplot Plot | output_plot |
data_frame |
Pandas DataFrame | output_data_frame |
doc |
Function Documentation | output_text |
Notes:
- The doc output type produces a well-formated documentation of the function using the docstring_to_markdown module if it is installed. Otherwise only the parser utility from the standard docstring_parser module is used. See the package documentation for accepted docstring formats.
In the current version of letitshine, each output is placed in a card with a header, which allows for further rearrangement using Shiny components. We stress that usually the generated Shiny app is a starting point for more tailored apps. In the examples section, you can see examples of use of different combinations.
Input Types and Shiny Inputs
The main point of letitshine is that it quickly allows to prototype a Python function in a module into a Shiny app based on the default types. Instead of defining the correspondence between the input parameters of the Python function and Shiny inputs for each app, we use only information obtained from the function itself. The idea is that by documenting and using types for the variables in the function you get the desirend Shiny input. For some types there are several natural options, and they are commented in the code so that it is easy to use this code as a draft for further costumisation.
Letitshine
spend as little as you can in letitshine while improving the base function encouraging standard coding practices.
The type of Shiny input is inferred from the type annotation of the variable name_of_variable:type_of_variable(see the examples for more ideas and the official documentation for the standard typing module) and its default value. The parameter description is taken from docstrings if any. The core of this input UI generation is done in ui_from_function. For instance, the following example shows the preference of type annotation and default values
>>> from letitshine import ui_from_function
>>> simply_twice=lambda x: 2*x # Function with no annotations or docs
>>> print(ui_from_function(simply_twice))
ui.input_text("x", "x?", "Input Text"),
>>> def twice(x:int=0): # We will use a conflicting type definition
... r"""
... Multiply an integer by two.
...
... :param x: Input Number
... :type str: x
...
... :return: Twice x.
... :rtype: float
... """
... return 2*x
...
>>> print(ui_from_function(twice))
#ui.input_slider("x", "Input Number:", value=0,min=MIN,max=MAX,step=1), #Replace MIN and MAX
ui.input_numeric("x", "Input Number:", 0),
The following table gives the default values:
| Python Type | Default? | Shiny input | Shiny output UI |
|---|---|---|---|
str |
Yes | Text Input | ui.input_text |
str |
Only if default string contains "\n" or it is long. | Text Input | ui.input_text |
int |
Yes | Numeric Input | ui.input_numeric |
int |
No (commented) | Slider | ui.input_slider |
float |
Yes | Numeric Input | ui.input_numeric |
float |
Yes | Numeric Input | ui.input_numeric |
bool |
Yes | Switch | ui.input_switch |
typing.TextIO |
TODO | File Upload | ui.input_file |
typing.BinaryIO |
TODO | File Upload | ui.input_file |
Deploying Shinylive apps
Warning
As with any Shiny Live app, appending /edit to the URL of the shiny app, opens a Shiny editor where you can find the code of the original function and the app as well. Do not store any important information in Shiny live apps, for instance, it is not suitable for online exams.
Safety considerations
Always important to sanitize expressions which are parsed from strings. One of the goals of this project was to generete calculators of symbolic mathematical expressions using Sympy, so it is natural to accept strings and later parse them in Sympy as sympy objects.
Conclusions
Not for exams, as the code can easily be seen and interacted with. No secrets or passwords either, for the same reason.