Skip to main content

ALToolbox.misc

Any​

Dict​

List​

Optional​

TypedDict​

Union​

b64encode​

Decimal​

functions​

action_button_html​

Address​

as_datetime​

DADateTime​

DAEmpty​

DALazyTemplate​

defined​

showifdef​

space_to_underscore​

today​

user_has_privilege​

validation_error​

value​

word​

format_date​

re​

__all__​

shortenMe Objects​

class shortenMe()

Create a temporary redirect URL, exposed as shortenedURL.

Example​

Create a temporary redirect to the current interview. Use the object’s shortenedURL attribute as the link; the redirect expires after seven days.

Input (interview YAML)

code: |
short_link = shortenMe(interview_url()).shortenedURL

__init__​

def __init__(originalURL)

thousands​

def thousands(num: Union[float, str, Decimal], show_decimals=False) -> str

Return a whole number formatted with thousands separator.

Optionally, format with 2 decimal points (for a PDF form with the currency symbol already present in the form). If show_decimals is False, will call int(num), truncating the decimals instead of rounding to the closest int.

Arguments​

  • num Union[float, str, Decimal] - The numeric value to format.
  • show_decimals bool, optional - Whether to display 2 decimal places. Defaults to False.

Returns​

The formatted number string with thousands separators, optionally with 2 decimal places.

Example​

With users[0].monthly_income = 1234.56, format a PDF field that already has a printed currency symbol:

Input (Mako)

${ thousands(users[0].monthly_income, show_decimals=True) }

Input (Jinja2)

{{ thousands(users[0].monthly_income, show_decimals=True) }}

Output

1,234.56

tel​

def tel(phone_number) -> str

Format a phone number so you can click on it to open in your phone dialer.

Creates an HTML anchor tag with tel: protocol that allows users to click and dial the number on mobile devices or applications that support tel links.

Arguments​

  • phone_number - The phone number to format. Can be string or numeric type.

Returns​

  • str - HTML anchor tag with tel: link containing the phone number.

Example​

With users[0].phone_number = "202-555-0123", the output is HTML for a clickable phone link in question text:

Input (Mako)

${ tel(users[0].phone_number) }

Output

<a href="tel:202-555-0123">202-555-0123</a>

fa_icon​

def fa_icon(icon: str,
color: Optional[str] = "primary",
color_css: Optional[str] = None,
size: Optional[str] = "sm",
fa_class: str = "fa-solid",
aria_hidden: bool = True) -> str

Display a fontawesome icon inline.

Docassemble allows you to display an icon from fontawesome, but it does not provide control over the size or color of the icon. This function gives you more control over the icon that is inserted.

Arguments​

  • icon - a string representing a fontawesome icon. The icon needs to be in the free library.
  • color - can be any Bootstrap color variable. For example: primary, secondary, warning
  • color_css - allows you to use a CSS code to represent the color, e.g., blue, or rgb(255, 255, 255) for white
  • size - used to control the fontawesome size (without the fa- prefix). Valid values include 2xs, xs, the default of sm, md, lg, xl, 2x1, and the python None, which defaults to md.
  • fa_class - let's you specify the fontawesome class, needed for any icon that isn't the default class of fa-solid, like fa-brands, or fa-regular and fa-light.
  • aria_hidden - if True, adds aria-hidden="true" to the icon, which is the default

Returns​

HTML for a font-awesome icon of the specified size and color.

Display an information icon in question text:

Input (Mako)

${ fa_icon("circle-info", color="primary", size="lg") }

Example​

Display an information icon in question text:

Input (Mako)

${ fa_icon("circle-info", color="primary", size="lg") }

space​

def space(var_name: str, prefix=" ", suffix="") -> str

If the value as a string is defined, return it prefixed/suffixed.

Defaults to prefix of a space. Helps build a sentence with less cruft. Equivalent to SPACE function in HotDocs. Only returns the formatted value if the variable name is valid and the variable is defined and has a value.

Arguments​

  • var_name str - The name of the variable to check and format.
  • prefix str, optional - String to prepend to the value. Defaults to " ".
  • suffix str, optional - String to append to the value. Defaults to "".

Returns​

The variable value with prefix and suffix if variable is defined and has a value, otherwise an empty string.

Example​

With users[0].name.middle = "Morgan", include the leading space only when a middle name is defined and nonempty:

Input (Mako)

${ "Alex" + space("users[0].name.middle") + " Rivera" }

Input (Jinja2)

{{ "Alex" + space("users[0].name.middle") + " Rivera" }}

Output

Alex Morgan Rivera

yes_no_unknown​

def yes_no_unknown(var_name: str,
condition: Optional[bool],
unknown="Unknown",
placeholder=0) -> Any

Return 'unknown' if the value is None rather than False.

Helper for PDF filling with yesnomaybe fields. Distinguishes between False (explicitly no) and None (unknown/not answered).

Arguments​

  • var_name str - The name of the variable to return if condition is True.
  • condition Optional[bool] - The condition to evaluate. True returns the variable value, False returns placeholder, None returns unknown.
  • unknown str, optional - Value to return when condition is None. Defaults to "Unknown".
  • placeholder - Value to return when condition is False. Defaults to 0.

Returns​

The value of var_name if condition is True, the unknown string if condition is None, or the placeholder value if condition is False.

Example​

With users[0].has_income = None, show the unknown label instead of the amount or a zero:

Input (Mako)

${ yes_no_unknown("users[0].monthly_income", users[0].has_income) }

Input (Jinja2)

{{ yes_no_unknown("users[0].monthly_income", users[0].has_income) }}

Output

Unknown

number_to_letter​

def number_to_letter(n: Optional[int]) -> str

Returns a capital letter representing ordinal position.

E.g., 1=A, 2=B, etc. Appends letters once you reach 26 in a way compatible with Excel/Google Sheets column naming conventions. 27=AA, 28=AB...

Arguments​

  • n Optional[int] - The number to convert to letters. If None, treated as 0.

Returns​

  • str - The letter representation of the number using Excel-style column naming.

Example​

Turn a one-based exhibit number into a label:

Input (Mako)

${ number_to_letter(27) }

Input (Jinja2)

{{ number_to_letter(27) }}

Output

AA

collapse_template​

def collapse_template(template: DALazyTemplate,
classname: str | None = None,
closed_icon: str = "caret-right",
open_icon: str = "caret-down",
collapsed: bool = True) -> str

Insert HTML for a Bootstrap "collapse" div.

Creates a collapsible section with a clickable header that shows/hides content. Optionally, you can specify custom icons to override the defaults.

The default icons are "right caret" which displays when the text is collapsed (closed_icon) and "down caret" which displays when the text is open (open_icon).

Arguments​

  • template DALazyTemplate - The docassemble template to render in the collapsible section.
  • classname str | None, optional - CSS class name for styling the content container. Defaults to None (uses "bg-light").
  • closed_icon str, optional - FontAwesome icon name for collapsed state. Defaults to "caret-right".
  • open_icon str, optional - FontAwesome icon name for expanded state. Defaults to "caret-down".
  • collapsed bool, optional - Whether the section should start collapsed. Defaults to True.

Returns​

Complete HTML string for the Bootstrap collapse component, or empty string if template has no content.

In an interview:

Input (interview YAML)

include:
- docassemble.ALToolbox:collapse_template.yml
question: |
Your address
subquestion: |
${ collapse_template(help_text) }
fields:
- Street: users[0].address.address

Example​

In an interview:

Input (interview YAML)

include:
- docassemble.ALToolbox:collapse_template.yml
question: |
Your address
subquestion: |
${ collapse_template(help_text) }
fields:
- Street: users[0].address.address

tabbed_templates_html​

def tabbed_templates_html(tab_group_name: str, *pargs) -> str

Create Bootstrap v 4.5 tabs with template subjects as tab labels.

Provided a list of templates, creates a tabbed interface where each template's subject becomes the tab label and the content becomes the tab panel content.

Arguments​

  • tab_group_name str - The base name for the tab group, used to generate unique IDs for the tabs.
  • *pargs - Variable number of template objects that have subject and content_as_html methods.

Returns​

Complete HTML string containing Bootstrap tabs navigation and content panels.

In an interview:

Input (interview YAML)

include:
- docassemble.ALToolbox:display_template.yml
template: next_steps
subject: |
Next steps
content: |
Review your answers before downloading.
template: help_text
subject: |
What should I enter?
content: |
Enter your current mailing address.
question: |
Your address
subquestion: |
${ tabbed_templates_html("help_tabs", help_text, next_steps) }
fields:
- Street: users[0].address.address

review_widget​

def review_widget(
*,
up_action: str,
down_action: str,
review_action: Optional[str] = None,
thumbs_display: str = "Did we help you?",
review_display:
str = "Thank you for your feedback. Let us know what we could do better",
submit_review_button: str = "Add your review",
post_review_display: str = "Thank you for your review!") -> str

A widget that allows people to give a quick review (thumbs up and down, with an optional text component) in the middle of an interview without triggering a page reload.

If review_action is provided, once you press either of the thumbs, a text input screen with a submit button appears, and once the text review is submitted (or after the thumbs, if no review_action was provided), a final "thank you" message is displayed.

Arguments​

  • up_action - the variable name of an event to be executed on the server if the thumbs up is pressed
  • down_action - the variable name of an event to be executed on the server if the thumbs down is pressed
  • review_action - the variable name of an event to be execute on the server when someone submits their text review
  • thumbs_display - text displayed to user describing the thumbs
  • review_display - text displayed to user describing the text input
  • submit_review_button - text on the button to submit their text review
  • post_review_display - text displayed to user after review is submitted

Returns​

the HTML string of the widget

In an interview:

Input (interview YAML)

include:
- docassemble.ALToolbox:review_widget.yml
event: feedback_helpful
code: |
feedback_was_helpful = True
background_response()
question: |
Review your information
subquestion: |
${ review_widget(up_action="feedback_helpful", down_action="feedback_unhelpful") }
event: feedback_unhelpful
code: |
feedback_was_helpful = False
background_response()

sum_if_defined​

def sum_if_defined(*pargs) -> Union[int, float, Decimal]

Add up the value of variables that are not in a list.

Lets you sum the values of multiple variables, but only includes variables that are defined. Undefined variables are skipped rather than causing errors.

Arguments​

  • *pargs - Variable number of variable names (strings) to sum up.

Returns​

The sum of all defined variable values. Variables that are not defined are treated as 0 (skipped).

Example​

With users[0].monthly_income = 1200, users[0].other_income = 300, the sum is 1500. Undefined variables are skipped:

Input (Mako)

${ sum_if_defined("users[0].monthly_income", "users[0].other_income") }

Input (Jinja2)

{{ sum_if_defined("users[0].monthly_income", "users[0].other_income") }}

Output

1500

add_records​

def add_records(obj, labels) -> Any

List demo interviews in the current package to be run from the landing page.

Populates a DAList object with records containing interview information including name, description, and reference for creating a demo landing page.

Arguments​

  • obj - A DAList object to populate with interview records.
  • labels dict - Dictionary where keys are interview names and values are tuples/lists containing [description, reference].

Returns​

The populated obj (DAList) with interview records added.

Example​

With interview_list declared as a DAList, populate a demo landing page:

Input (interview YAML)

code: |
add_records(interview_list, {
"intake": ["Start an intake", "intake.yml"],
"feedback": ["Give feedback", "feedback.yml"],
})

output_checkbox​

def output_checkbox(value_to_check: bool,
checked_value: str = "[X]",
unchecked_value: str = "[ ]") -> str

Generate a conditional checkbox for docx templates.

Returns different values based on whether a boolean condition is true or false, useful for creating checkboxes in document templates.

Arguments​

  • value_to_check bool - The boolean value to evaluate.
  • checked_value str, optional - Value to return when condition is True. Defaults to "[X]". Can be any string or even a DAFile or DAStaticFile with the image of a checkbox.
  • unchecked_value str, optional - Value to return when condition is False. Defaults to "[ ]". Opposite meaning of checked_value.

Returns​

The checked_value if value_to_check is True, otherwise unchecked_value.

Example​

With users[0].has_income = True, mark a checkbox in a form:

Input (Mako)

${ output_checkbox(users[0].has_income) }

Input (Jinja2)

{{ output_checkbox(users[0].has_income) }}

Output

[X]

nice_county_name​

def nice_county_name(address: Address) -> str

Clean up county name by removing " County" suffix if present.

If the county name contains the word "County", which Google Address Autocomplete does by default, remove it to get a cleaner display name.

Arguments​

  • address Address - A docassemble Address object that may have a county attribute.

Returns​

The county name with " County" suffix removed, or empty string if the address has no county attribute.

Example​

With users[0].address.county = "Suffolk County":

Input (Mako)

${ nice_county_name(users[0].address) }

Input (Jinja2)

{{ nice_county_name(users[0].address) }}

Output

Suffolk

ButtonDict Objects​

class ButtonDict(TypedDict)

name: str​

image: str​

url: str​

privilege: NotRequired[Union[str, List[str]]]​

button_array​

def button_array(buttons: List[ButtonDict],
custom_container_class="",
custom_link_class="") -> str

Create a grid of da-buttons from a dictionary of links and icons

This uses the same CSS classes to mimic the look and feel of Docassemble's buttons field type, but doesn't have the limits of that particular input method. This is meant to appear on any page of an interview in the subquestion area.

Optionally, you can limit access to paricular buttons by specifying a privilege or a list of privileges.

Arguments​

  • buttons List[ButtonDict] - A list of ButtonDicts (or plain dictionaries) with the following keys:
    • name: the text to display on the button
    • image: the name of a fontawesome icon to display on the button
    • url: the name of the page to link to
    • privilege: optional, the name of a Docassemble privilege that the user must have to see the button. Can be a list or a single string.
  • custom_container_class str, optional - Additional CSS classes to add to the container div. Defaults to "".
  • custom_link_class str, optional - Additional CSS classes to add to each link. Defaults to "".

Returns​

  • str - HTML for a grid of buttons that mimics Docassemble's button field type.

Example​

With a review_answers event defined in your interview:

Input (interview YAML)

question: |
What would you like to do?
subquestion: |
${ button_array([{"name": "Review answers", "image": "pen-to-square", "url": url_action("review_answers")}]) }

none_to_empty​

def none_to_empty(val: Any) -> Any

If the value is None or "None", return a DAEmpty value. Otherwise return the value.

This is useful for filling in a template and to prevent the word None from appearing in the output. For example, when handling a radio button that is not required and left unanswered.

A DAEmpty value appears as an empty string in the output. You can also safely transform it or use any method on it without raising an error.

Arguments​

  • val - the value to check

Returns​

a DAEmpty if the value is None, otherwise the value

Example​

With users[0].name.middle = None, the brackets show where the empty value appears; the word "None" is omitted:

Input (Mako)

${ "Middle name: [" + str(none_to_empty(users[0].name.middle)) + "]" }

Input (Jinja2)

{{ "Middle name: [" ~ none_to_empty(users[0].name.middle) ~ "]" }}

Output

Middle name: []

option_or_other​

def option_or_other(variable_name: str,
other_variable_name: Optional[str] = None) -> str

If the variable is set to 'Other', return the value of the 'other' variable. Otherwise return the value of the variable.

This is useful for filling in a template and to prevent the word 'Other' from appearing in the output.

Arguments​

  • variable_name - the name of the variable to check
  • other_variable_name - the name of the variable to return if the value of the first variable is 'Other'

Returns​

the value of the variable if it is not 'Other', otherwise the value of the other variable

Example​

With users[0].contact_method = "Other" and users[0].contact_method_other = "Postal mail":

Input (Mako)

${ option_or_other("users[0].contact_method") }

Input (Jinja2)

{{ option_or_other("users[0].contact_method") }}

Output

Postal mail

true_values_with_other​

def true_values_with_other(
variable_name: str,
other_variable_name: Optional[str] = None) -> List[str]

Return a list of values that are True, with the value of the 'other' variable appended to the end of the list.

This is useful for filling in a template and to prevent the word 'Other' from appearing in the output.

Arguments​

  • variable_name str - The dictionary of variables to check.
  • other_variable_name Optional[str], optional - The name of the variable (as a string) to return if the value of the first variable is 'Other'. Defaults to None (uses variable_name + "_other").

Returns​

A list of values that are True, with the value of the 'other' variable appended to the end of the list if 'other'/'Other' was selected.

Example​

With a DADict at users[0].contact_methods containing email=True and other=True, and users[0].contact_methods_other = "Postal mail", in an English interview:

Input (Mako)

${ comma_and_list(true_values_with_other("users[0].contact_methods")) }

Input (Jinja2)

{{ comma_and_list(true_values_with_other("users[0].contact_methods")) }}

Output

email and Postal mail

include_a_year​

def include_a_year(text: str, field: Optional[str] = None) -> bool

Validates whether the input text contains at least one 4-digit year.

Validates whether the input text contains at least one 4-digit sequence that occurs within a range of ~ 200 years (1800-2199), indicating a valid "year" for an event that should be reported on most court forms, like a birthdate or a moving date.

Arguments​

  • text str - The text to search for a year pattern.
  • field Optional[str], optional - The field name to use in validation error messages. Defaults to None.

Returns​

  • bool - True if a valid year is found, otherwise raises a DAValidationError.

Raises​

  • DAValidationError - If no valid year pattern is found in the text.

Example​

Require a year in the narrative, for example "The problem began in 2020":

Input (interview YAML)

question: |
Describe what happened
fields:
- Your description: incident_description
datatype: area
validate: include_a_year

is_leap_year​

def is_leap_year(year: int) -> bool

Helper function for age_in_years to determine if a year is a leap year.

Arguments​

  • year - The year to check.

Returns​

True if the year is a leap year, False otherwise.

age_in_years​

def age_in_years(the_date: Union[str, DADateTime]) -> int

Calculate the age in years from a date (treated like a date of birth).

Arguments​

  • the_date - A string or DADateTime object representing the date of birth.

Returns​

The age in years as an integer.

Example​

After gathering users[0].birthdate, show their age as of today:

Input (Mako)

${ age_in_years(users[0].birthdate) }

Input (Jinja2)

{{ age_in_years(users[0].birthdate) }}

format_date_if_defined​

def format_date_if_defined(date_object_name: str,
*pargs,
default: str = "",
**kwargs) -> str

Format a date string if it is defined, otherwise return an empty string.

Passes all additional arguments to the format_date function.

Arguments​

  • date_object_name - The date string to format.
  • *pargs - Additional positional arguments to pass to format_date.
  • default - A default string to return if date_object_name is not defined.
  • **kwargs - Additional keyword arguments to pass to format_date. E.g., format="yyyy-MM-dd"

Returns​

A formatted date string if date_object_name is defined, otherwise an empty string.

Example​

With users[0].birthdate set to January 2, 1990:

Input (Mako)

${ format_date_if_defined("users[0].birthdate", format="yyyy-MM-dd") }

Input (Jinja2)

{{ format_date_if_defined("users[0].birthdate", format="yyyy-MM-dd") }}

Output

1990-01-02