docassemble.AssemblyLine 3.5.0__tar.gz → 4.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {docassemble_assemblyline-3.5.0/docassemble.AssemblyLine.egg-info → docassemble_assemblyline-4.0.0}/PKG-INFO +1 -1
- docassemble_assemblyline-4.0.0/docassemble/AssemblyLine/__init__.py +1 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/al_document.py +138 -42
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/al_general.py +58 -49
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/custom_jinja_filters.py +109 -1
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_document.yml +29 -3
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions.yml +4 -7
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_visual.yml +4 -6
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/ql_baseline.yml +87 -22
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/ql_catchall.yml +26 -5
- docassemble_assemblyline-4.0.0/docassemble/AssemblyLine/data/questions/test_catchall.yml +45 -0
- docassemble_assemblyline-4.0.0/docassemble/AssemblyLine/data/questions/test_preferred_formats.yml +75 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_question_library.yml +25 -2
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/test_question_library.feature +1 -1
- docassemble_assemblyline-4.0.0/docassemble/AssemblyLine/data/sources/translation_es.xlsx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/aldocument.js +11 -5
- docassemble_assemblyline-4.0.0/docassemble/AssemblyLine/data/templates/test_catchall.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/sessions.py +107 -3
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/test_al_general.py +4 -3
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/test_language.py +12 -13
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0/docassemble.AssemblyLine.egg-info}/PKG-INFO +1 -1
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble.AssemblyLine.egg-info/SOURCES.txt +4 -2
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/setup.py +1 -1
- docassemble_assemblyline-3.5.0/docassemble/AssemblyLine/__init__.py +0 -1
- docassemble_assemblyline-3.5.0/docassemble/AssemblyLine/data/sources/translation_es.xlsx +0 -0
- docassemble_assemblyline-3.5.0/docassemble/AssemblyLine/project_maintenance.py +0 -432
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/LICENSE +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/MANIFEST.in +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/README.md +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/al_courts.py +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_code.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_language.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_package.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_package_unstyled.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_question_test.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_reminders.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions_store.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_settings.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/al_terms_of_use.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/assembly_line.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/assembly_line_unstyled.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/demo_search_sessions.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/feedback.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/interview_list.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/ql_namechange.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/reserved_words.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_al_table_document.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_aladdendum.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_alcourts.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_aldocument.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_aldocument_background_assembly.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_alexhibit.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_alexhibit_maxsize.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_bundle_parity.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_familiar_disambiguation.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/questions/test_signature.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/README.md +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/es-words.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/languages.yml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/test_aldocument.feature +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_docx_1.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_jpg_1.jpg +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_pdf_1.pdf +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_png_1.png +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/translation_ht.xlsx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/sources/translation_pt.xlsx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/README.md +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/al_audio.css +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/al_audio.js +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/aldocument.css +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/interview_list.css +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/limit_upload_size.js +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/lt1-pullout-10-getting-organized.pdf +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/ma_logo.png +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/placeholder.png +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/seal.jpg +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/static/styles.css +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/README.md +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/al_basic_addendum.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/exhibit_cover_sheet.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/exhibit_table_of_contents.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/general_cover_sheet.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/sample_word_template.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/test_aldocument_docx_1.docx +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/data/templates/test_aldocument_pdf_1.pdf +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/language.py +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/py.typed +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/requirements.txt +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/sign.py +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/AssemblyLine/test_al_document.py +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble/__init__.py +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble.AssemblyLine.egg-info/dependency_links.txt +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble.AssemblyLine.egg-info/not-zip-safe +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble.AssemblyLine.egg-info/requires.txt +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/docassemble.AssemblyLine.egg-info/top_level.txt +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/pyproject.toml +0 -0
- {docassemble_assemblyline-3.5.0 → docassemble_assemblyline-4.0.0}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '4.0.0'
|
|
@@ -36,6 +36,9 @@ import subprocess
|
|
|
36
36
|
from collections import ChainMap
|
|
37
37
|
import pikepdf
|
|
38
38
|
from typing import Tuple
|
|
39
|
+
import secrets
|
|
40
|
+
import string
|
|
41
|
+
|
|
39
42
|
|
|
40
43
|
__all__ = [
|
|
41
44
|
"ALAddendumField",
|
|
@@ -59,6 +62,22 @@ __all__ = [
|
|
|
59
62
|
DEBUG_MODE = get_config("debug")
|
|
60
63
|
|
|
61
64
|
|
|
65
|
+
def random_suffix(length: int = 8) -> str:
|
|
66
|
+
"""Return a random string for use in unique IDs.
|
|
67
|
+
|
|
68
|
+
Note: this is powerful enough for the expected usecase of distinguishing a few
|
|
69
|
+
HTML elements from each other, but not cryptographically secure or as strong as
|
|
70
|
+
a true GUID.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
length (int): The length of the random string to generate. Defaults to 8.
|
|
74
|
+
Returns:
|
|
75
|
+
str: A random string of lowercase letters and digits.
|
|
76
|
+
"""
|
|
77
|
+
alphabet = string.ascii_lowercase + string.digits
|
|
78
|
+
return "".join(secrets.choice(alphabet) for _ in range(length))
|
|
79
|
+
|
|
80
|
+
|
|
62
81
|
def base_name(filename: str) -> str:
|
|
63
82
|
"""
|
|
64
83
|
Extracts the base name of a file without its extension.
|
|
@@ -1653,8 +1672,8 @@ class ALDocumentBundle(DAList):
|
|
|
1653
1672
|
refresh: bool = True,
|
|
1654
1673
|
pdfa: bool = False,
|
|
1655
1674
|
title: str = "",
|
|
1656
|
-
format="pdf",
|
|
1657
|
-
include_pdf=True,
|
|
1675
|
+
format: Optional[str] = "pdf",
|
|
1676
|
+
include_pdf: Optional[bool] = True,
|
|
1658
1677
|
) -> DAFile:
|
|
1659
1678
|
"""
|
|
1660
1679
|
Returns a zip file containing all enabled documents in the bundle in the specified format.
|
|
@@ -1670,6 +1689,11 @@ class ALDocumentBundle(DAList):
|
|
|
1670
1689
|
Returns:
|
|
1671
1690
|
DAFile: A zip file containing the enabled documents.
|
|
1672
1691
|
"""
|
|
1692
|
+
if format is None:
|
|
1693
|
+
format = "pdf"
|
|
1694
|
+
|
|
1695
|
+
if include_pdf is None:
|
|
1696
|
+
include_pdf = True
|
|
1673
1697
|
|
|
1674
1698
|
zip_key = f"{ space_to_underscore( key )}_zip"
|
|
1675
1699
|
|
|
@@ -1679,6 +1703,7 @@ class ALDocumentBundle(DAList):
|
|
|
1679
1703
|
|
|
1680
1704
|
# strip out a possible '.pdf' ending then add '.zip'
|
|
1681
1705
|
zipname = os.path.splitext(self.filename)[0]
|
|
1706
|
+
|
|
1682
1707
|
if format == "docx":
|
|
1683
1708
|
docs = []
|
|
1684
1709
|
for doc in self.enabled_documents(refresh=refresh):
|
|
@@ -1864,6 +1889,8 @@ class ALDocumentBundle(DAList):
|
|
|
1864
1889
|
include_zip: bool = True,
|
|
1865
1890
|
include_full_pdf: bool = False,
|
|
1866
1891
|
append_matching_suffix: bool = True,
|
|
1892
|
+
zip_include_pdf: Optional[bool] = None,
|
|
1893
|
+
zip_format: Optional[str] = None,
|
|
1867
1894
|
) -> Tuple[List[Dict[str, DAFile]], Optional[DAFile], Optional[DAFile]]:
|
|
1868
1895
|
"""
|
|
1869
1896
|
Generates a cache of all enabled documents in the bundle, and returns it in a structure that can be cached
|
|
@@ -1887,6 +1914,8 @@ class ALDocumentBundle(DAList):
|
|
|
1887
1914
|
include_zip (bool): Flag to include a zip option, default is True.
|
|
1888
1915
|
include_full_pdf (bool): Flag to include a PDF version of the whole bundle, default is False.
|
|
1889
1916
|
append_matching_suffix (bool): Flag to determine if matching suffix should be appended to file name, default is True.
|
|
1917
|
+
zip_include_pdf (Optional[bool]): If True, includes a PDF version in the zip file even if original is in DOCX format.
|
|
1918
|
+
zip_format (Optional[str]): Format of the primary version of each document.
|
|
1890
1919
|
|
|
1891
1920
|
Returns:
|
|
1892
1921
|
Tuple[List[Dict[str, DAFile]], Optional[DAFile], Optional[DAFile]]: A list of dictionaries containing the enabled documents, a zip file of the whole bundle, and a PDF of the whole
|
|
@@ -1940,9 +1969,14 @@ class ALDocumentBundle(DAList):
|
|
|
1940
1969
|
pass
|
|
1941
1970
|
results.append(result)
|
|
1942
1971
|
|
|
1972
|
+
if zip_format is None:
|
|
1973
|
+
zip_format = "original" if original else "docx" if docx else "pdf"
|
|
1974
|
+
|
|
1943
1975
|
if len(enabled_docs) > 1 and include_zip:
|
|
1944
1976
|
bundled_zip = self.as_zip(
|
|
1945
|
-
key=key,
|
|
1977
|
+
key=key,
|
|
1978
|
+
format=zip_format,
|
|
1979
|
+
include_pdf=zip_include_pdf,
|
|
1946
1980
|
)
|
|
1947
1981
|
else:
|
|
1948
1982
|
bundled_zip = None
|
|
@@ -1976,6 +2010,8 @@ class ALDocumentBundle(DAList):
|
|
|
1976
2010
|
use_previously_cached_files: bool = False,
|
|
1977
2011
|
include_full_pdf: bool = False,
|
|
1978
2012
|
full_pdf_label: Optional[str] = None,
|
|
2013
|
+
zip_include_pdf: Optional[bool] = True,
|
|
2014
|
+
zip_format: Optional[str] = None,
|
|
1979
2015
|
) -> str:
|
|
1980
2016
|
"""
|
|
1981
2017
|
Constructs an HTML table displaying a list of documents with 'view' and 'download' buttons.
|
|
@@ -2002,6 +2038,8 @@ class ALDocumentBundle(DAList):
|
|
|
2002
2038
|
use_previously_cached_files (bool): Flag to use previously cached files (e.g., made in background) if defined. default is False.
|
|
2003
2039
|
include_full_pdf (bool): Flag to include a full PDF option, default is False.
|
|
2004
2040
|
full_pdf_label (Optional[str]): Label for the full PDF option. If not provided, uses the generic template for `self.full_pdf_label` ("Download all").
|
|
2041
|
+
zip_include_pdf (Optional[bool]): Flag to include PDF files in the zip archive, default is True. If `None` value of `view` will be used.
|
|
2042
|
+
zip_format (Optional[str]): Format of the files in the zip archive. If None, defaults to value of "format" parameter.
|
|
2005
2043
|
|
|
2006
2044
|
Returns:
|
|
2007
2045
|
str: HTML representation of a table with documents and their associated actions.
|
|
@@ -2012,6 +2050,12 @@ class ALDocumentBundle(DAList):
|
|
|
2012
2050
|
if not hasattr(self, "_cached_full_pdf_label"):
|
|
2013
2051
|
self._cached_full_pdf_label = str(self.full_pdf_label)
|
|
2014
2052
|
|
|
2053
|
+
if zip_format is None:
|
|
2054
|
+
zip_format = format
|
|
2055
|
+
|
|
2056
|
+
if zip_include_pdf is None:
|
|
2057
|
+
zip_include_pdf = view
|
|
2058
|
+
|
|
2015
2059
|
if use_previously_cached_files and hasattr(self, "_downloadable_files"):
|
|
2016
2060
|
downloadable_files, bundled_zip, bundled_pdf = self._downloadable_files
|
|
2017
2061
|
else:
|
|
@@ -2025,6 +2069,8 @@ class ALDocumentBundle(DAList):
|
|
|
2025
2069
|
include_zip=include_zip,
|
|
2026
2070
|
include_full_pdf=include_full_pdf,
|
|
2027
2071
|
append_matching_suffix=append_matching_suffix,
|
|
2072
|
+
zip_include_pdf=zip_include_pdf,
|
|
2073
|
+
zip_format=zip_format,
|
|
2028
2074
|
)
|
|
2029
2075
|
|
|
2030
2076
|
html = f'<div class="container al_table al_doc_table" id="{ html_safe_str(self.instanceName) }">'
|
|
@@ -2215,7 +2261,7 @@ class ALDocumentBundle(DAList):
|
|
|
2215
2261
|
self._cached_include_editable_documents = str(
|
|
2216
2262
|
self.include_editable_documents
|
|
2217
2263
|
)
|
|
2218
|
-
name = html_safe_str(self.instanceName)
|
|
2264
|
+
name = html_safe_str(self.instanceName) + random_suffix()
|
|
2219
2265
|
al_wants_editable_input_id = "_ignore_al_wants_editable_" + name
|
|
2220
2266
|
al_email_input_id = "_ignore_al_doc_email_" + name
|
|
2221
2267
|
al_send_button_id = "al_send_email_button_" + name
|
|
@@ -2250,12 +2296,13 @@ class ALDocumentBundle(DAList):
|
|
|
2250
2296
|
def send_button_to_html(
|
|
2251
2297
|
self,
|
|
2252
2298
|
email: str,
|
|
2253
|
-
editable: bool =
|
|
2299
|
+
editable: Optional[bool] = None,
|
|
2254
2300
|
template_name: str = "",
|
|
2255
2301
|
label: str = "Send",
|
|
2256
2302
|
icon: str = "envelope",
|
|
2257
2303
|
color: str = "primary",
|
|
2258
2304
|
key: str = "final",
|
|
2305
|
+
preferred_formats: Optional[Union[str, List[str]]] = None,
|
|
2259
2306
|
) -> str:
|
|
2260
2307
|
"""
|
|
2261
2308
|
Generate HTML for a button that allows someone to send the bundle to a
|
|
@@ -2264,12 +2311,13 @@ class ALDocumentBundle(DAList):
|
|
|
2264
2311
|
|
|
2265
2312
|
Args:
|
|
2266
2313
|
email (str): The recipient's email address.
|
|
2267
|
-
editable (bool, optional): Flag indicating if the bundle is editable. Defaults to False.
|
|
2314
|
+
editable (bool, optional): Flag indicating if the bundle is editable. Defaults to False. (deprecated; use preferred_formats instead)
|
|
2268
2315
|
template_name (str, optional): The name of the template to be used. Defaults to an empty string.
|
|
2269
2316
|
label (str, optional): The label for the button. Defaults to "Send".
|
|
2270
2317
|
icon (str, optional): The Fontawesome icon for the button. Defaults to "envelope".
|
|
2271
2318
|
color (str, optional): The Bootstrap color of the button. Defaults to "primary".
|
|
2272
2319
|
key (str, optional): A key used to identify which version of the ALDocument to send. Defaults to "final".
|
|
2320
|
+
preferred_formats (Optional[Union[str,List[str]]], optional): A list of allowed formats for the document. Defaults to "pdf" if not specified.
|
|
2273
2321
|
|
|
2274
2322
|
Returns:
|
|
2275
2323
|
str: The generated HTML string for the button.
|
|
@@ -2278,9 +2326,16 @@ class ALDocumentBundle(DAList):
|
|
|
2278
2326
|
return "" # Don't let people email an empty set of documents
|
|
2279
2327
|
if not hasattr(self, "_cached_get_email_copy"):
|
|
2280
2328
|
self._cached_get_email_copy = str(self.get_email_copy)
|
|
2281
|
-
name = html_safe_str(self.instanceName)
|
|
2329
|
+
name = html_safe_str(self.instanceName) + random_suffix()
|
|
2282
2330
|
al_send_button_id = "al_send_email_to_button_" + name
|
|
2283
2331
|
|
|
2332
|
+
if isinstance(preferred_formats, (list, tuple)):
|
|
2333
|
+
formats_js = "[" + ",".join(f"'{fmt}'" for fmt in preferred_formats) + "]"
|
|
2334
|
+
elif preferred_formats:
|
|
2335
|
+
formats_js = f"'{preferred_formats}'"
|
|
2336
|
+
else:
|
|
2337
|
+
formats_js = "null"
|
|
2338
|
+
|
|
2284
2339
|
javascript_string = (
|
|
2285
2340
|
f"javascript:aldocument_send_to_action("
|
|
2286
2341
|
f"'{self.attr_name('send_email_to_action_event')}',"
|
|
@@ -2288,7 +2343,9 @@ class ALDocumentBundle(DAList):
|
|
|
2288
2343
|
f"'{email}',"
|
|
2289
2344
|
f"'{al_send_button_id}',"
|
|
2290
2345
|
f"'{template_name}',"
|
|
2291
|
-
f"'{key}'
|
|
2346
|
+
f"'{key}',"
|
|
2347
|
+
f"{formats_js}"
|
|
2348
|
+
f")"
|
|
2292
2349
|
)
|
|
2293
2350
|
send_button = action_button_html(
|
|
2294
2351
|
javascript_string,
|
|
@@ -2309,6 +2366,7 @@ class ALDocumentBundle(DAList):
|
|
|
2309
2366
|
template_name: str = "",
|
|
2310
2367
|
label: str = "Send",
|
|
2311
2368
|
icon: str = "envelope",
|
|
2369
|
+
preferred_formats: Optional[Union[str, List[str]]] = None,
|
|
2312
2370
|
) -> str:
|
|
2313
2371
|
"""
|
|
2314
2372
|
Generate HTML for an input box and button that allows someone to send the bundle
|
|
@@ -2321,12 +2379,13 @@ class ALDocumentBundle(DAList):
|
|
|
2321
2379
|
key (str, optional): A key used to identify which version of the ALDocument to send. Defaults to "final".
|
|
2322
2380
|
show_editable_checkbox (bool, optional): Flag indicating if the checkbox
|
|
2323
2381
|
for deciding the inclusion of an editable (Word) copy should be displayed.
|
|
2324
|
-
Defaults to True.
|
|
2382
|
+
Defaults to True. If preferred_formats = ["pdf"], this will be ignored and no checkbox will be shown.
|
|
2325
2383
|
template_name (str, optional): Name of the template variable that is used to fill
|
|
2326
2384
|
the email contents. By default, the `x.send_email_template` template will be used.
|
|
2327
2385
|
label (str, optional): The label for the button. Defaults to "Send".
|
|
2328
2386
|
icon (str, optional): The Fontawesome icon for the button. Defaults
|
|
2329
2387
|
to "envelope".
|
|
2388
|
+
preferred_formats (Optional[Union[str,List[str]]], optional): A list of allowed formats for the document. Defaults to "pdf" if not specified.
|
|
2330
2389
|
|
|
2331
2390
|
Returns:
|
|
2332
2391
|
str: The generated HTML string for the input box and button.
|
|
@@ -2339,31 +2398,52 @@ class ALDocumentBundle(DAList):
|
|
|
2339
2398
|
self._cached_include_editable_documents = str(
|
|
2340
2399
|
self.include_editable_documents
|
|
2341
2400
|
)
|
|
2342
|
-
|
|
2401
|
+
|
|
2402
|
+
if isinstance(preferred_formats, str):
|
|
2403
|
+
preferred_formats = [preferred_formats]
|
|
2404
|
+
|
|
2405
|
+
if not preferred_formats:
|
|
2406
|
+
preferred_formats = ["pdf", "docx"] if show_editable_checkbox else ["pdf"]
|
|
2407
|
+
|
|
2408
|
+
name = html_safe_str(self.instanceName) + random_suffix()
|
|
2343
2409
|
al_wants_editable_input_id = "_ignore_al_wants_editable_" + name
|
|
2344
2410
|
al_email_input_id = "_ignore_al_doc_email_" + name
|
|
2345
2411
|
al_send_button_id = "al_send_email_button_" + name
|
|
2346
2412
|
|
|
2413
|
+
if isinstance(preferred_formats, (list, tuple)):
|
|
2414
|
+
formats_js = "[" + ",".join(f"'{fmt}'" for fmt in preferred_formats) + "]"
|
|
2415
|
+
elif preferred_formats:
|
|
2416
|
+
formats_js = f"'{preferred_formats}'"
|
|
2417
|
+
else:
|
|
2418
|
+
formats_js = "null"
|
|
2419
|
+
|
|
2347
2420
|
javascript_string = (
|
|
2348
2421
|
f"javascript:aldocument_send_action("
|
|
2349
2422
|
f"'{self.attr_name('send_email_action_event')}',"
|
|
2350
2423
|
f"'{al_wants_editable_input_id}',"
|
|
2351
2424
|
f"'{al_email_input_id}',"
|
|
2352
2425
|
f"'{template_name}',"
|
|
2353
|
-
f"'{key}'
|
|
2426
|
+
f"'{key}',"
|
|
2427
|
+
f"{formats_js}"
|
|
2428
|
+
")"
|
|
2354
2429
|
)
|
|
2355
2430
|
|
|
2356
2431
|
# Container of whole email section with header
|
|
2357
2432
|
return_str = f"""
|
|
2358
|
-
<fieldset class="al_send_bundle al_send_section_alone {
|
|
2433
|
+
<fieldset class="al_send_bundle al_send_section_alone {html_safe_str(self.instanceName)}" id="al_send_bundle_{name}" name="al_send_bundle_{name}">
|
|
2359
2434
|
<legend class="h4 al_doc_email_header">{self._cached_get_email_copy}</legend>
|
|
2360
2435
|
"""
|
|
2361
2436
|
# "Editable" checkbox
|
|
2362
|
-
if
|
|
2437
|
+
if (
|
|
2438
|
+
show_editable_checkbox
|
|
2439
|
+
and preferred_formats
|
|
2440
|
+
and isinstance(preferred_formats, list)
|
|
2441
|
+
and len(preferred_formats) > 1
|
|
2442
|
+
): # Do not need to show if only one valid format allowed
|
|
2363
2443
|
return_str += f"""
|
|
2364
2444
|
<div class="form-check-container">
|
|
2365
2445
|
<div class="form-check">
|
|
2366
|
-
<input class="form-check-input" type="checkbox"
|
|
2446
|
+
<input class="form-check-input al_wants_editable" type="checkbox" id="{al_wants_editable_input_id}">
|
|
2367
2447
|
<label class="al_wants_editable form-check-label" for="{al_wants_editable_input_id}">{self._cached_include_editable_documents}
|
|
2368
2448
|
</label>
|
|
2369
2449
|
</div>
|
|
@@ -2373,7 +2453,7 @@ class ALDocumentBundle(DAList):
|
|
|
2373
2453
|
return_str += f"""
|
|
2374
2454
|
<div class="al_email_container">
|
|
2375
2455
|
|
|
2376
|
-
<span class="al_email_address {
|
|
2456
|
+
<span class="al_email_address {html_safe_str(self.instanceName)} container form-group row da-field-container da-field-container-datatype-email">
|
|
2377
2457
|
<label for="{al_email_input_id}" class="col-form-label da-form-label datext-right">Email</label>
|
|
2378
2458
|
<input value="{user_info().email if user_logged_in() else ''}" alt="Email address for document" class="form-control" type="email" size="35" name="{al_email_input_id}" id="{al_email_input_id}">
|
|
2379
2459
|
</span>
|
|
@@ -2389,8 +2469,9 @@ class ALDocumentBundle(DAList):
|
|
|
2389
2469
|
self,
|
|
2390
2470
|
to: Any = None,
|
|
2391
2471
|
key: str = "final",
|
|
2392
|
-
editable: bool =
|
|
2393
|
-
template: Any = None,
|
|
2472
|
+
editable: Optional[bool] = None,
|
|
2473
|
+
template: Optional[Any] = None,
|
|
2474
|
+
preferred_formats: Optional[Union[str, List[str]]] = "pdf",
|
|
2394
2475
|
**kwargs,
|
|
2395
2476
|
) -> bool:
|
|
2396
2477
|
"""
|
|
@@ -2399,39 +2480,54 @@ class ALDocumentBundle(DAList):
|
|
|
2399
2480
|
https://docassemble.org/docs/functions.html#send_email with additional parameters.
|
|
2400
2481
|
|
|
2401
2482
|
Args:
|
|
2402
|
-
to (Any): The email address or list of
|
|
2403
|
-
or objects with such. Similar to da send_email `to`.
|
|
2483
|
+
to (Any): The email address, list of email addresses, or list of Individuals with a .email attribute to send to.
|
|
2404
2484
|
key (str, optional): Specifies which version of the document to send. Defaults to "final".
|
|
2405
|
-
editable (bool, optional): If True, sends the editable documents. Defaults to False.
|
|
2406
|
-
template (Any): The template variable, similar to da `send_email` `template` variable.
|
|
2485
|
+
editable (bool, optional): If True, sends the editable documents. Defaults to False. (Deprecated)
|
|
2486
|
+
template (Any): The template variable for the subject and body of the email, similar to da `send_email` `template` variable.
|
|
2487
|
+
preferred_formats (str): Specifies the format of the files to send. Can be "pdf" or "docx", or a list of these formats. Overrides deprecated `editable` keyword.
|
|
2407
2488
|
**kwargs: Additional parameters to pass to the da `send_email` function.
|
|
2408
2489
|
|
|
2409
2490
|
Returns:
|
|
2410
2491
|
bool: Indicates if the email was sent successfully.
|
|
2411
2492
|
"""
|
|
2412
|
-
if not
|
|
2493
|
+
if editable is not None:
|
|
2494
|
+
log(
|
|
2495
|
+
"The 'editable' parameter is deprecated; use 'preferred_formats' instead."
|
|
2496
|
+
)
|
|
2497
|
+
|
|
2498
|
+
if template is None:
|
|
2413
2499
|
template = self.send_email_template
|
|
2414
2500
|
|
|
2415
|
-
if
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2501
|
+
if preferred_formats is None:
|
|
2502
|
+
preferred_formats = ["docx", "pdf"] if editable else ["pdf"]
|
|
2503
|
+
|
|
2504
|
+
if isinstance(preferred_formats, str):
|
|
2505
|
+
preferred_formats = [preferred_formats]
|
|
2506
|
+
|
|
2507
|
+
allowed = {fmt.lower() for fmt in preferred_formats}
|
|
2508
|
+
attachments = []
|
|
2509
|
+
|
|
2510
|
+
for item in self.enabled_documents():
|
|
2511
|
+
primary = None
|
|
2512
|
+
|
|
2513
|
+
if "docx" in allowed:
|
|
2514
|
+
primary = item.as_docx(key=key)
|
|
2515
|
+
attachments.append(primary)
|
|
2516
|
+
|
|
2517
|
+
if "pdf" in allowed:
|
|
2518
|
+
if not (
|
|
2519
|
+
primary
|
|
2520
|
+
and hasattr(primary, "extension")
|
|
2521
|
+
and primary.extension == "pdf"
|
|
2522
|
+
):
|
|
2523
|
+
attachments.append(item.as_pdf(key=key))
|
|
2524
|
+
|
|
2525
|
+
return send_email(
|
|
2526
|
+
to=to,
|
|
2527
|
+
template=template,
|
|
2528
|
+
attachments=attachments,
|
|
2529
|
+
**kwargs,
|
|
2530
|
+
)
|
|
2435
2531
|
|
|
2436
2532
|
def _is_self_enabled(self, refresh=True) -> bool:
|
|
2437
2533
|
"""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from copy import deepcopy
|
|
2
|
-
from typing import Dict, List, Literal, Union, Optional, Any
|
|
2
|
+
from typing import Callable, Dict, List, Literal, Union, Optional, Any
|
|
3
3
|
from docassemble.base.util import (
|
|
4
4
|
Address,
|
|
5
5
|
as_datetime,
|
|
@@ -21,7 +21,6 @@ from docassemble.base.util import (
|
|
|
21
21
|
Individual,
|
|
22
22
|
IndividualName,
|
|
23
23
|
its,
|
|
24
|
-
name_suffix,
|
|
25
24
|
phone_number_formatted,
|
|
26
25
|
phone_number_is_valid,
|
|
27
26
|
showifdef,
|
|
@@ -32,8 +31,11 @@ from docassemble.base.util import (
|
|
|
32
31
|
this_thread,
|
|
33
32
|
url_action,
|
|
34
33
|
validation_error,
|
|
34
|
+
value,
|
|
35
35
|
word,
|
|
36
36
|
your,
|
|
37
|
+
log,
|
|
38
|
+
value,
|
|
37
39
|
)
|
|
38
40
|
import random
|
|
39
41
|
import re
|
|
@@ -1068,9 +1070,11 @@ class ALIndividual(Individual):
|
|
|
1068
1070
|
person_or_business: str = "person",
|
|
1069
1071
|
show_suffix: bool = True,
|
|
1070
1072
|
show_title: bool = False,
|
|
1071
|
-
|
|
1073
|
+
title_choices: Optional[Union[List[str], Callable]] = None,
|
|
1072
1074
|
show_if: Union[str, Dict[str, str], None] = None,
|
|
1073
1075
|
maxlengths: Optional[Dict[str, int]] = None,
|
|
1076
|
+
suffix_choices: Optional[Union[List[str], Callable]] = None,
|
|
1077
|
+
title_options: Optional[Union[List[str], Callable]] = None,
|
|
1074
1078
|
) -> List[Dict[str, str]]:
|
|
1075
1079
|
"""
|
|
1076
1080
|
Generates suitable field prompts for a name based on the type of entity (person or business)
|
|
@@ -1083,11 +1087,13 @@ class ALIndividual(Individual):
|
|
|
1083
1087
|
Default is True.
|
|
1084
1088
|
show_title: (bool, optional): Determines if the name's title (e.g., Mr., Ms.) should be included in the prompts.
|
|
1085
1089
|
Default is False.
|
|
1086
|
-
|
|
1087
|
-
of common titles in English-speaking countries
|
|
1090
|
+
title_choices (Union[List[str], Callable], optional): A list or callable of title options to use in the prompts. Default is defined as a list
|
|
1091
|
+
of common titles in English-speaking countries, or overridden by value of global `al_name_titles`.
|
|
1088
1092
|
show_if (Union[str, Dict[str, str], None], optional): Condition to determine which fields to show.
|
|
1089
1093
|
It can be a string, a dictionary with conditions, or None. Default is None.
|
|
1090
1094
|
maxlengths (Dict[str, int], optional): A dictionary of field names and their maximum lengths. Default is None.
|
|
1095
|
+
suffix_choices (Union[List[str], Callable], optional): A list of suffix options or a callable to generate suffix options, or overridden by value of global `al_name_suffixes`.
|
|
1096
|
+
title_options: (Union[List[str], Callable], optional): Deprecated parameter, use `title_choices` instead. If provided, it will be used to set the title choices.
|
|
1091
1097
|
|
|
1092
1098
|
Returns:
|
|
1093
1099
|
List[Dict[str, str]]: A list of dictionaries where each dictionary contains field prompt details.
|
|
@@ -1096,29 +1102,23 @@ class ALIndividual(Individual):
|
|
|
1096
1102
|
If `person_or_business` is set to None, the method will offer the end user a choice
|
|
1097
1103
|
and will set appropriate "show ifs" conditions for each type.
|
|
1098
1104
|
"""
|
|
1099
|
-
if
|
|
1100
|
-
|
|
1101
|
-
"
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
"Capt.",
|
|
1117
|
-
"Lt.",
|
|
1118
|
-
"Sgt.",
|
|
1119
|
-
"Fr.",
|
|
1120
|
-
"Sr.",
|
|
1121
|
-
]
|
|
1105
|
+
if title_options:
|
|
1106
|
+
log(
|
|
1107
|
+
"title_options parameter to name_fields() is deprecated: use title_choices instead"
|
|
1108
|
+
)
|
|
1109
|
+
title_choices = title_options
|
|
1110
|
+
|
|
1111
|
+
if not suffix_choices:
|
|
1112
|
+
suffix_choices = value("al_name_suffixes")
|
|
1113
|
+
if callable(suffix_choices):
|
|
1114
|
+
suffix_choices = suffix_choices()
|
|
1115
|
+
|
|
1116
|
+
if not title_choices:
|
|
1117
|
+
title_choices = value("al_name_titles")
|
|
1118
|
+
|
|
1119
|
+
if callable(title_choices):
|
|
1120
|
+
title_choices = title_choices()
|
|
1121
|
+
|
|
1122
1122
|
if person_or_business == "person":
|
|
1123
1123
|
fields = [
|
|
1124
1124
|
{
|
|
@@ -1140,7 +1140,7 @@ class ALIndividual(Individual):
|
|
|
1140
1140
|
{
|
|
1141
1141
|
"label": str(self.suffix_label),
|
|
1142
1142
|
"field": self.attr_name("name.suffix"),
|
|
1143
|
-
"choices":
|
|
1143
|
+
"choices": suffix_choices,
|
|
1144
1144
|
"required": False,
|
|
1145
1145
|
}
|
|
1146
1146
|
)
|
|
@@ -1150,7 +1150,7 @@ class ALIndividual(Individual):
|
|
|
1150
1150
|
{
|
|
1151
1151
|
"label": str(self.name_title_label),
|
|
1152
1152
|
"field": self.attr_name("name.title"),
|
|
1153
|
-
"choices":
|
|
1153
|
+
"choices": title_choices,
|
|
1154
1154
|
"required": False,
|
|
1155
1155
|
},
|
|
1156
1156
|
)
|
|
@@ -1159,8 +1159,6 @@ class ALIndividual(Individual):
|
|
|
1159
1159
|
field["show if"] = show_if
|
|
1160
1160
|
return fields
|
|
1161
1161
|
elif person_or_business == "business":
|
|
1162
|
-
# Note: we don't make use of the name.text field for simplicity
|
|
1163
|
-
# TODO: this could be reconsidered`, but name.text tends to lead to developer error
|
|
1164
1162
|
fields = [
|
|
1165
1163
|
{
|
|
1166
1164
|
"label": str(self.business_name_label),
|
|
@@ -1218,7 +1216,7 @@ class ALIndividual(Individual):
|
|
|
1218
1216
|
{
|
|
1219
1217
|
"label": str(self.suffix_label),
|
|
1220
1218
|
"field": self.attr_name("name.suffix"),
|
|
1221
|
-
"choices":
|
|
1219
|
+
"choices": suffix_choices,
|
|
1222
1220
|
"required": False,
|
|
1223
1221
|
"show if": show_if_indiv,
|
|
1224
1222
|
}
|
|
@@ -1286,6 +1284,7 @@ class ALIndividual(Individual):
|
|
|
1286
1284
|
show_help=False,
|
|
1287
1285
|
show_if: Union[str, Dict[str, str], None] = None,
|
|
1288
1286
|
maxlengths: Optional[Dict[str, int]] = None,
|
|
1287
|
+
choices: Optional[Union[List[Dict[str, str]], Callable]] = None,
|
|
1289
1288
|
) -> List[Dict[str, str]]:
|
|
1290
1289
|
"""
|
|
1291
1290
|
Generate fields for capturing gender information, including a
|
|
@@ -1295,18 +1294,26 @@ class ALIndividual(Individual):
|
|
|
1295
1294
|
show_help (bool): Whether to show additional help text. Defaults to False.
|
|
1296
1295
|
show_if (Union[str, Dict[str, str], None]): Condition to determine if the field should be shown. Defaults to None.
|
|
1297
1296
|
maxlengths (Dict[str, int], optional): A dictionary of field names and their maximum lengths. Default is None.
|
|
1297
|
+
choices (Optional[Union[List[Dict[str, str]], Callable]]): A list of choices of genders to use in the prompts, or a callable that returns such a list. Default set of choices includes male, female, nonbinary, prefer-not-to-say, self-described, and unknown.
|
|
1298
1298
|
|
|
1299
1299
|
Returns:
|
|
1300
1300
|
List[Dict[str, str]]: A list of dictionaries with field prompts for gender.
|
|
1301
|
+
|
|
1302
|
+
Note:
|
|
1303
|
+
self-described will provide an input that overrides the value of `gender` and is not persisted.
|
|
1301
1304
|
"""
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1305
|
+
if not choices:
|
|
1306
|
+
choices = [
|
|
1307
|
+
{str(self.gender_female_label): "female"},
|
|
1308
|
+
{str(self.gender_male_label): "male"},
|
|
1309
|
+
{str(self.gender_nonbinary_label): "nonbinary"},
|
|
1310
|
+
{str(self.gender_prefer_not_to_say_label): "prefer-not-to-say"},
|
|
1311
|
+
{str(self.gender_prefer_self_described_label): "self-described"},
|
|
1312
|
+
{str(self.gender_unknown_label): "unknown"},
|
|
1313
|
+
]
|
|
1314
|
+
if callable(choices):
|
|
1315
|
+
choices = choices()
|
|
1316
|
+
|
|
1310
1317
|
self_described_input = {
|
|
1311
1318
|
"label": str(self.gender_self_described_label),
|
|
1312
1319
|
"field": self.attr_name("gender"),
|
|
@@ -1341,6 +1348,7 @@ class ALIndividual(Individual):
|
|
|
1341
1348
|
shuffle: bool = False,
|
|
1342
1349
|
show_unknown: Optional[Union[Literal["guess"], bool]] = "guess",
|
|
1343
1350
|
maxlengths: Optional[Dict[str, int]] = None,
|
|
1351
|
+
choices: Optional[List[Dict[str, str]]] = None,
|
|
1344
1352
|
) -> List[Dict[str, str]]:
|
|
1345
1353
|
"""
|
|
1346
1354
|
Generate fields for capturing pronoun information.
|
|
@@ -1352,16 +1360,15 @@ class ALIndividual(Individual):
|
|
|
1352
1360
|
shuffle (bool): Whether to shuffle the order of pronouns. Defaults to False.
|
|
1353
1361
|
show_unknown (Union[Literal["guess"], bool]): Whether to show an "unknown" option. Can be "guess", True, or False. Defaults to "guess".
|
|
1354
1362
|
maxlengths (Dict[str, int], optional): A dictionary of field names and their maximum lengths. Default is None.
|
|
1363
|
+
choices (Optional[List[Dict[str, str]]]): A list of custom pronoun choices. Defaults to None. If not provided, global magic variable `al_pronoun_choices` will be used.
|
|
1355
1364
|
|
|
1356
1365
|
Returns:
|
|
1357
1366
|
List[Dict[str, str]]: A list of dictionaries with field prompts for pronouns.
|
|
1358
1367
|
"""
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
{str(self.pronoun_zir_label): "ze/zir/zirs"},
|
|
1364
|
-
]
|
|
1368
|
+
if choices:
|
|
1369
|
+
shuffled_choices = choices
|
|
1370
|
+
else:
|
|
1371
|
+
shuffled_choices = value("al_pronoun_choices")
|
|
1365
1372
|
if shuffle:
|
|
1366
1373
|
random.shuffle(shuffled_choices)
|
|
1367
1374
|
final_choices = [
|
|
@@ -1432,7 +1439,7 @@ class ALIndividual(Individual):
|
|
|
1432
1439
|
|
|
1433
1440
|
def language_fields(
|
|
1434
1441
|
self,
|
|
1435
|
-
choices: Optional[List[Dict[str, str]]] = None,
|
|
1442
|
+
choices: Optional[Union[List[Dict[str, str]], Callable]] = None,
|
|
1436
1443
|
style: str = "radio",
|
|
1437
1444
|
show_if: Union[str, Dict[str, str], None] = None,
|
|
1438
1445
|
maxlengths: Optional[Dict[str, int]] = None,
|
|
@@ -1441,7 +1448,7 @@ class ALIndividual(Individual):
|
|
|
1441
1448
|
Generate fields for capturing language preferences.
|
|
1442
1449
|
|
|
1443
1450
|
Args:
|
|
1444
|
-
choices (Optional[List[Dict[str, str]]]): A list of language choices. Defaults to None.
|
|
1451
|
+
choices (Optional[Union[List[Dict[str, str]], Callable]]): A list or callable of language choices. Defaults to None.
|
|
1445
1452
|
style (str): The display style of choices. Defaults to "radio".
|
|
1446
1453
|
show_if (Union[str, Dict[str, str], None]): Condition to determine if the field should be shown. Defaults to None.
|
|
1447
1454
|
maxlengths (Dict[str, int], optional): A dictionary of field names and their maximum lengths. Default is None.
|
|
@@ -1455,6 +1462,8 @@ class ALIndividual(Individual):
|
|
|
1455
1462
|
{"Spanish": "es"},
|
|
1456
1463
|
{"Other": "other"},
|
|
1457
1464
|
]
|
|
1465
|
+
if callable(choices):
|
|
1466
|
+
choices = choices()
|
|
1458
1467
|
other = {
|
|
1459
1468
|
"label": str(self.language_other_label),
|
|
1460
1469
|
"field": self.attr_name("language_other"),
|