docassemble.AssemblyLine 2.27.1__tar.gz → 2.28.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-2.27.1/docassemble.AssemblyLine.egg-info → docassemble_assemblyline-2.28.0}/PKG-INFO +1 -1
- docassemble_assemblyline-2.28.0/docassemble/AssemblyLine/__init__.py +1 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/al_courts.py +4 -1
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/al_document.py +63 -1
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/al_general.py +30 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_code.yml +19 -3
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions.yml +7 -2
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_visual.yml +5 -4
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/ql_baseline.yml +1 -1
- docassemble_assemblyline-2.28.0/docassemble/AssemblyLine/data/questions/test_bundle_parity.yml +79 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/language.py +5 -3
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/sessions.py +54 -13
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/test_al_general.py +9 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0/docassemble.AssemblyLine.egg-info}/PKG-INFO +1 -1
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble.AssemblyLine.egg-info/SOURCES.txt +1 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/setup.py +1 -1
- docassemble.AssemblyLine-2.27.1/docassemble/AssemblyLine/__init__.py +0 -1
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/LICENSE +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/MANIFEST.in +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/README.md +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_document.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_language.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_package.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_package_unstyled.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_question_test.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_reminders.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions_store.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_settings.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/al_terms_of_use.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/assembly_line.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/assembly_line_unstyled.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/feedback.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/interview_list.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/ql_catchall.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/reserved_words.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/test_al_table_document.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/test_aladdendum.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/test_alcourts.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/test_aldocument.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/test_alexhibit.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/test_alexhibit_maxsize.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/questions/test_question_library.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/README.md +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/es-words.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/languages.yml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/test_aldocument.feature +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_docx_1.docx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_jpg_1.jpg +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_pdf_1.pdf +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_png_1.png +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/test_question_library.feature +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/translation_es.xlsx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/translation_ht.xlsx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/sources/translation_pt.xlsx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/README.md +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/al_audio.css +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/al_audio.js +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/aldocument.css +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/aldocument.js +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/interview_list.css +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/limit_upload_size.js +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/lt1-pullout-10-getting-organized.pdf +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/ma_logo.png +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/placeholder.png +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/seal.jpg +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/static/styles.css +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/README.md +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/al_basic_addendum.docx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/exhibit_cover_sheet.docx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/exhibit_table_of_contents.docx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/general_cover_sheet.docx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/sample_word_template.docx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/test_aldocument_docx_1.docx +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/data/templates/test_aldocument_pdf_1.pdf +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/project_maintenance.py +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/py.typed +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/requirements.txt +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/test_al_document.py +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/AssemblyLine/test_language.py +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble/__init__.py +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble.AssemblyLine.egg-info/dependency_links.txt +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble.AssemblyLine.egg-info/namespace_packages.txt +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble.AssemblyLine.egg-info/not-zip-safe +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble.AssemblyLine.egg-info/requires.txt +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/docassemble.AssemblyLine.egg-info/top_level.txt +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/pyproject.toml +0 -0
- {docassemble.AssemblyLine-2.27.1 → docassemble_assemblyline-2.28.0}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.28.0'
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Package for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
import os
|
|
5
6
|
from typing import Any, Dict, List, Optional, Union, Set
|
|
6
7
|
import pandas as pd
|
|
@@ -109,7 +110,9 @@ class ALCourt(Court):
|
|
|
109
110
|
all_info = f"{ all_info }[BR]{ self.address.on_one_line() }"
|
|
110
111
|
return f"{ all_info }[BR]{ self.description }"
|
|
111
112
|
|
|
112
|
-
def from_row(
|
|
113
|
+
def from_row(
|
|
114
|
+
self, df_row: Union[pd.Series, pd.DataFrame], ensure_lat_long: bool = True
|
|
115
|
+
) -> None:
|
|
113
116
|
"""
|
|
114
117
|
Loads data from a single Pandas Dataframe into the current court object.
|
|
115
118
|
Note: It will try to convert column names that don't make valid
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import os
|
|
3
3
|
import mimetypes
|
|
4
|
-
from typing import Any, Dict, List, Union, Callable, Optional
|
|
4
|
+
from typing import Any, Dict, List, Literal, Union, Callable, Optional
|
|
5
5
|
from docassemble.base.util import (
|
|
6
6
|
Address,
|
|
7
7
|
LatitudeLongitude,
|
|
@@ -34,6 +34,7 @@ from textwrap import wrap
|
|
|
34
34
|
from math import floor
|
|
35
35
|
import subprocess
|
|
36
36
|
from collections import ChainMap
|
|
37
|
+
import pikepdf
|
|
37
38
|
|
|
38
39
|
__all__ = [
|
|
39
40
|
"ALAddendumField",
|
|
@@ -180,6 +181,50 @@ def table_row(title: str, button_htmls: List[str] = []) -> str:
|
|
|
180
181
|
return html
|
|
181
182
|
|
|
182
183
|
|
|
184
|
+
def pdf_page_parity(pdf_path: str) -> Literal["even", "odd"]:
|
|
185
|
+
"""
|
|
186
|
+
Count the number of pages in the PDF and
|
|
187
|
+
return "even" if it is divisible by 2 and "odd"
|
|
188
|
+
if it is not divisible by 2.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
pdf_path (str): Path to the PDF in the filesystem
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Literal["even", "odd"]: The parity of the number of pages in the PDF
|
|
195
|
+
"""
|
|
196
|
+
with pikepdf.open(pdf_path) as pdf:
|
|
197
|
+
num_pages = len(pdf.pages)
|
|
198
|
+
if num_pages % 2 == 0:
|
|
199
|
+
return "even"
|
|
200
|
+
return "odd"
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def add_blank_page(pdf_path: str) -> None:
|
|
204
|
+
"""
|
|
205
|
+
Add a blank page to the end of a PDF.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
pdf_path (str): Path to the PDF in the filesystem
|
|
209
|
+
"""
|
|
210
|
+
# Load the PDF
|
|
211
|
+
with pikepdf.open(pdf_path, allow_overwriting_input=True) as pdf:
|
|
212
|
+
# Retrieve the last page
|
|
213
|
+
last_page = pdf.pages[-1]
|
|
214
|
+
|
|
215
|
+
# Extract the size of the last page
|
|
216
|
+
media_box = last_page.MediaBox
|
|
217
|
+
|
|
218
|
+
# Create a new blank page with the same dimensions as the last page
|
|
219
|
+
blank_page = pikepdf.Page(pikepdf.Dictionary(MediaBox=media_box))
|
|
220
|
+
|
|
221
|
+
# Add the blank page to the end of the PDF
|
|
222
|
+
pdf.pages.append(blank_page)
|
|
223
|
+
|
|
224
|
+
# Overwrite the original PDF with the modified version
|
|
225
|
+
pdf.save(pdf_path)
|
|
226
|
+
|
|
227
|
+
|
|
183
228
|
class ALAddendumField(DAObject):
|
|
184
229
|
"""
|
|
185
230
|
Represents a field with attributes determining its display in an addendum, typically for PDF templates.
|
|
@@ -1441,6 +1486,7 @@ class ALDocumentBundle(DAList):
|
|
|
1441
1486
|
enabled (bool, optional): Determines if the bundle is active. Defaults to True.
|
|
1442
1487
|
auto_gather (bool, optional): Automatically gathers attributes. Defaults to False.
|
|
1443
1488
|
gathered (bool, optional): Specifies if attributes have been gathered. Defaults to True.
|
|
1489
|
+
default_parity (Optional[Literal["even", "odd"]]): Default parity to enforce on the PDF. Defaults to None.
|
|
1444
1490
|
|
|
1445
1491
|
Examples:
|
|
1446
1492
|
Given three documents: `Cover page`, `Main motion form`, and `Notice of Interpreter Request`,
|
|
@@ -1481,6 +1527,7 @@ class ALDocumentBundle(DAList):
|
|
|
1481
1527
|
refresh: bool = True,
|
|
1482
1528
|
pdfa: bool = False,
|
|
1483
1529
|
append_matching_suffix: bool = True,
|
|
1530
|
+
ensure_parity: Optional[Literal["even", "odd"]] = None,
|
|
1484
1531
|
) -> Optional[DAFile]:
|
|
1485
1532
|
"""
|
|
1486
1533
|
Returns a consolidated PDF of all enabled documents in the bundle.
|
|
@@ -1491,6 +1538,8 @@ class ALDocumentBundle(DAList):
|
|
|
1491
1538
|
pdfa (bool): If True, generates a PDF/A compliant document, defaults to False.
|
|
1492
1539
|
append_matching_suffix (bool): Flag to determine if matching suffix should be appended to file name, default is True.
|
|
1493
1540
|
Used primarily to enhance automated tests.
|
|
1541
|
+
ensure_parity (Optional[Literal["even", "odd"]]): Ensures the number of pages in the PDF is even or odd. If omitted,
|
|
1542
|
+
no parity is enforced. Defaults to None.
|
|
1494
1543
|
|
|
1495
1544
|
Returns:
|
|
1496
1545
|
Optional[DAFile]: Combined PDF file or None if no documents are enabled.
|
|
@@ -1533,6 +1582,19 @@ class ALDocumentBundle(DAList):
|
|
|
1533
1582
|
)
|
|
1534
1583
|
pdf.title = self.title
|
|
1535
1584
|
setattr(self.cache, safe_key, pdf)
|
|
1585
|
+
|
|
1586
|
+
if hasattr(self, "default_parity") and not ensure_parity:
|
|
1587
|
+
ensure_parity = self.default_parity
|
|
1588
|
+
|
|
1589
|
+
if ensure_parity not in [None, "even", "odd"]:
|
|
1590
|
+
raise ValueError("ensure_parity must be either 'even', 'odd' or None")
|
|
1591
|
+
|
|
1592
|
+
if ensure_parity: # Check for odd/even requirement
|
|
1593
|
+
if pdf_page_parity(pdf.path()) == ensure_parity:
|
|
1594
|
+
return pdf
|
|
1595
|
+
else:
|
|
1596
|
+
add_blank_page(pdf.path())
|
|
1597
|
+
|
|
1536
1598
|
return pdf
|
|
1537
1599
|
|
|
1538
1600
|
def __str__(self) -> str:
|
|
@@ -1672,6 +1672,36 @@ class ALIndividual(Individual):
|
|
|
1672
1672
|
return capitalize(output)
|
|
1673
1673
|
return output
|
|
1674
1674
|
|
|
1675
|
+
def name_full(self) -> str:
|
|
1676
|
+
"""Returns the individual's full name.
|
|
1677
|
+
|
|
1678
|
+
Returns:
|
|
1679
|
+
str: The individual's full name.
|
|
1680
|
+
"""
|
|
1681
|
+
return self.name.full(middle="full")
|
|
1682
|
+
|
|
1683
|
+
def name_initials(self) -> str:
|
|
1684
|
+
"""
|
|
1685
|
+
Returns the individual's name with the middle name as an initial.
|
|
1686
|
+
Equivalent to `name.full(middle="initial")`, which is also the default.
|
|
1687
|
+
Defined only to make it possible to be explicit about the name form.
|
|
1688
|
+
|
|
1689
|
+
Returns:
|
|
1690
|
+
str: The individual's name with the middle name as an initial.
|
|
1691
|
+
"""
|
|
1692
|
+
return self.name.full(middle="initial")
|
|
1693
|
+
|
|
1694
|
+
def name_short(self) -> str:
|
|
1695
|
+
"""
|
|
1696
|
+
Returns the individual's name without any middle name.
|
|
1697
|
+
|
|
1698
|
+
Equivalent to self.name.firstlast()
|
|
1699
|
+
|
|
1700
|
+
Returns:
|
|
1701
|
+
str: The individual'
|
|
1702
|
+
"""
|
|
1703
|
+
return self.name.firstlast()
|
|
1704
|
+
|
|
1675
1705
|
|
|
1676
1706
|
# (DANav isn't in public DA API, but currently in functions.py)
|
|
1677
1707
|
def section_links(nav) -> List[str]: # type: ignore
|
|
@@ -186,8 +186,24 @@ code: |
|
|
|
186
186
|
# If the user role was set to "unknown" at the time wizard run
|
|
187
187
|
user_role = user_ask_role
|
|
188
188
|
---
|
|
189
|
-
#
|
|
190
|
-
#
|
|
189
|
+
# HTML for interviews using ALKiln tests at ALKiln
|
|
190
|
+
# Necessary for servers that set their `restrict input variables` config value to `True`
|
|
191
|
+
# If you are using al_package_unstyled.yml, copy it into your `default screen parts: post`
|
|
191
192
|
template: alkiln_trigger_html
|
|
192
193
|
content: |
|
|
193
|
-
|
|
194
|
+
<div data-variable="${ encode_name(str( user_info().variable )) }" id="trigger" aria-hidden="true" style="display: none;"></div>
|
|
195
|
+
---
|
|
196
|
+
# HTML for interviews using ALKiln tests at ALKiln versions 5.9.0 and above.
|
|
197
|
+
# Necessary for interviews that use docassemble generic objects or index variables
|
|
198
|
+
# If you are using al_package_unstyled.yml, copy it into your `default screen parts: post`
|
|
199
|
+
template: alkiln_proxy_html
|
|
200
|
+
content: |
|
|
201
|
+
<div id="alkiln_proxy_var_values"
|
|
202
|
+
data-generic_object="${ encode_name(str( x.instanceName if defined('x') else '' )) }"
|
|
203
|
+
% for letter in [ 'i', 'j', 'k', 'l', 'm', 'n' ]:
|
|
204
|
+
data-index_var_${ letter }="${ encode_name(str( value( letter ) if defined( letter ) else '' )) }"
|
|
205
|
+
% endfor
|
|
206
|
+
aria-hidden="true" style="display: none;"></div>
|
|
207
|
+
---
|
|
208
|
+
code: |
|
|
209
|
+
al_sessions_additional_variables_to_filter = []
|
|
@@ -180,13 +180,18 @@ code: |
|
|
|
180
180
|
event: al_sessions_fast_forward_session
|
|
181
181
|
code: |
|
|
182
182
|
# set_save_status('ignore')
|
|
183
|
-
al_sessions_snapshot_results = load_interview_answers(
|
|
183
|
+
al_sessions_snapshot_results = load_interview_answers(
|
|
184
|
+
action_argument("i"),
|
|
185
|
+
action_argument("session"),
|
|
186
|
+
new_session=False,
|
|
187
|
+
additional_variables_to_filter=al_sessions_additional_variables_to_filter)
|
|
184
188
|
force_ask('al_sessions_load_status')
|
|
185
189
|
---
|
|
186
190
|
code: |
|
|
187
191
|
if user_logged_in():
|
|
188
192
|
new_session_id = save_interview_answers(
|
|
189
|
-
metadata = { "title": al_sessions_snapshot_label }
|
|
193
|
+
metadata = { "title": al_sessions_snapshot_label },
|
|
194
|
+
additional_variables_to_filter=al_sessions_additional_variables_to_filter,
|
|
190
195
|
)
|
|
191
196
|
log(f"Saved interview {al_sessions_snapshot_label} with id {new_session_id}")
|
|
192
197
|
else:
|
|
@@ -41,16 +41,17 @@ default screen parts:
|
|
|
41
41
|
corner back button label: |
|
|
42
42
|
Undo
|
|
43
43
|
pre: |
|
|
44
|
-
% if get_config('debug'):
|
|
45
|
-
`id: ${ user_info().question_id }`
|
|
46
|
-
`Variable
|
|
47
|
-
`
|
|
44
|
+
% if get_config('debug') and not url_args.get("hide_hud", "").lower() in ["1", "on", "true", "yes"]:
|
|
45
|
+
`id: ${ user_info().question_id }`[BR]
|
|
46
|
+
`Variable: ${ user_info().variable }`[BR]
|
|
47
|
+
`Version: ${ user_info().package.replace("docassemble.", "") + " " if not user_info().package.startswith("docassemble.playground") else "" }${ package_version_number }; ${ al_version }`
|
|
48
48
|
<div data-variable="${ encode_name(str( user_info().variable )) }" id="sought_variable" aria-hidden="true" style="display: none;"></div>
|
|
49
49
|
% endif
|
|
50
50
|
# We need both pre and post until old interviews are updated to v2 of the testing framework or v1 of the testing framework is updated. In future, we will need this in `post` so that it will work on signature pages.
|
|
51
51
|
# Uses `alkiln_trigger_html` template in al_code.yml
|
|
52
52
|
post: |
|
|
53
53
|
${ alkiln_trigger_html }
|
|
54
|
+
${ alkiln_proxy_html }
|
|
54
55
|
---
|
|
55
56
|
features:
|
|
56
57
|
small screen navigation: dropdown
|
|
@@ -924,7 +924,7 @@ continue button field: users.revisit
|
|
|
924
924
|
id: other parties revisit
|
|
925
925
|
question: |
|
|
926
926
|
Edit your answers about people on the other side of your case
|
|
927
|
-
|
|
927
|
+
subquestion: |
|
|
928
928
|
${ other_parties.table }
|
|
929
929
|
|
|
930
930
|
${ other_parties.add_action() }
|
docassemble_assemblyline-2.28.0/docassemble/AssemblyLine/data/questions/test_bundle_parity.yml
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
include:
|
|
3
|
+
- assembly_line.yml
|
|
4
|
+
---
|
|
5
|
+
objects:
|
|
6
|
+
- the_doc: ALDocument.using(
|
|
7
|
+
title="The document",
|
|
8
|
+
filename="the_document",
|
|
9
|
+
enabled=True,
|
|
10
|
+
has_addendum=False
|
|
11
|
+
)
|
|
12
|
+
---
|
|
13
|
+
objects:
|
|
14
|
+
- even_bundle: ALDocumentBundle.using(
|
|
15
|
+
title="Even bundle",
|
|
16
|
+
filename="the_bundle",
|
|
17
|
+
elements=[
|
|
18
|
+
the_doc
|
|
19
|
+
],
|
|
20
|
+
default_parity="even",
|
|
21
|
+
enabled=True
|
|
22
|
+
)
|
|
23
|
+
- odd_bundle: ALDocumentBundle.using(
|
|
24
|
+
title="Even bundle",
|
|
25
|
+
filename="the_bundle",
|
|
26
|
+
elements=[
|
|
27
|
+
the_doc,
|
|
28
|
+
the_doc
|
|
29
|
+
],
|
|
30
|
+
enabled=True
|
|
31
|
+
)
|
|
32
|
+
- bundle_with_default: ALDocumentBundle.using(
|
|
33
|
+
title="Even bundle",
|
|
34
|
+
filename="the_bundle",
|
|
35
|
+
elements=[
|
|
36
|
+
the_doc
|
|
37
|
+
],
|
|
38
|
+
default_parity="even",
|
|
39
|
+
enabled=True
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
objects:
|
|
44
|
+
- bundle_of_bundles: ALDocumentBundle.using(
|
|
45
|
+
title="Bundle of bundles",
|
|
46
|
+
filename="the_bundle",
|
|
47
|
+
elements=[
|
|
48
|
+
even_bundle,
|
|
49
|
+
bundle_with_default
|
|
50
|
+
],
|
|
51
|
+
enabled=True
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
attachment:
|
|
56
|
+
variable name: the_doc[i]
|
|
57
|
+
content: |
|
|
58
|
+
Test content
|
|
59
|
+
---
|
|
60
|
+
mandatory: True
|
|
61
|
+
question: |
|
|
62
|
+
About to make a PDF
|
|
63
|
+
continue button field: the_field
|
|
64
|
+
---
|
|
65
|
+
mandatory: True
|
|
66
|
+
question: |
|
|
67
|
+
Download
|
|
68
|
+
subquestion: |
|
|
69
|
+
# Should be even
|
|
70
|
+
${ even_bundle.as_pdf(ensure_parity="even") }
|
|
71
|
+
|
|
72
|
+
# should be odd
|
|
73
|
+
${ odd_bundle.as_pdf(ensure_parity="odd") }
|
|
74
|
+
|
|
75
|
+
# should be even
|
|
76
|
+
${ bundle_with_default.as_pdf() }
|
|
77
|
+
|
|
78
|
+
# Should be even
|
|
79
|
+
${ bundle_of_bundles.as_pdf() }
|
|
@@ -76,9 +76,11 @@ def get_tuples(
|
|
|
76
76
|
# Get the english name for the language code from pycountry as a fallback
|
|
77
77
|
return [
|
|
78
78
|
(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
(
|
|
80
|
+
pycountry.languages.get(alpha_2=lang).name
|
|
81
|
+
if pycountry.languages.get(alpha_2=lang)
|
|
82
|
+
else lang
|
|
83
|
+
),
|
|
82
84
|
lang,
|
|
83
85
|
)
|
|
84
86
|
for lang in lang_codes
|
|
@@ -143,6 +143,7 @@ al_sessions_variables_to_remove: Set = {
|
|
|
143
143
|
"al_sessions_url_ask_snapshot",
|
|
144
144
|
"al_sessions_variables_to_remove_from_new_interview",
|
|
145
145
|
"al_sessions_variables_to_remove",
|
|
146
|
+
"al_sessions_additional_variables_to_filter",
|
|
146
147
|
"al_simple_filtered_vars",
|
|
147
148
|
"filtered_vars_tmp",
|
|
148
149
|
"is_file_like",
|
|
@@ -510,6 +511,7 @@ def interview_list_html(
|
|
|
510
511
|
limit: int = 50,
|
|
511
512
|
offset: int = 0,
|
|
512
513
|
display_interview_title: bool = True,
|
|
514
|
+
show_view_button: bool = True,
|
|
513
515
|
) -> str:
|
|
514
516
|
"""Return a string containing an HTML-formatted table with the list of saved answers
|
|
515
517
|
associated with the specified filename.
|
|
@@ -538,6 +540,7 @@ def interview_list_html(
|
|
|
538
540
|
limit (int, optional): Limit for the number of sessions returned. Defaults to 50.
|
|
539
541
|
offset (int, optional): Offset for the session list. Defaults to 0.
|
|
540
542
|
display_interview_title (bool, optional): If True, displays the title of the interview. Defaults to True.
|
|
543
|
+
show_view_button (bool, optional): If True, shows the view button. Defaults to True.
|
|
541
544
|
|
|
542
545
|
Returns:
|
|
543
546
|
str: HTML-formatted table containing the list of saved answers.
|
|
@@ -596,10 +599,15 @@ def interview_list_html(
|
|
|
596
599
|
</td>
|
|
597
600
|
<td>
|
|
598
601
|
<a href="{ url_action(delete_action, filename=answer.get("filename"), session=answer.get("key")) }"><i class="far fa-trash-alt" title="{ delete_label }" aria-hidden="true"></i><span class="sr-only">{ delete_label }</span></a>
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
602
|
+
"""
|
|
603
|
+
if show_view_button:
|
|
604
|
+
table += f"""
|
|
605
|
+
<a target="_blank" href="{ interview_url(i=answer.get("filename"), session=answer.get("key")) }">
|
|
606
|
+
<i class="far fa-eye" aria-hidden="true" title="{ view_label }"></i>
|
|
607
|
+
<span class="sr-only">{ view_label }</span>
|
|
608
|
+
</a>
|
|
609
|
+
"""
|
|
610
|
+
table += """
|
|
603
611
|
</td>
|
|
604
612
|
"""
|
|
605
613
|
table += "</tr>"
|
|
@@ -746,6 +754,7 @@ def session_list_html(
|
|
|
746
754
|
copy_action: str = "interview_list_copy_action",
|
|
747
755
|
clone_label: str = word("Copy as answer set"),
|
|
748
756
|
show_title: bool = True,
|
|
757
|
+
show_copy_button: bool = True,
|
|
749
758
|
limit: int = 50,
|
|
750
759
|
offset: int = 0,
|
|
751
760
|
) -> str:
|
|
@@ -772,6 +781,7 @@ def session_list_html(
|
|
|
772
781
|
copy_action (str, optional): Name of the copy action. Defaults to "interview_list_copy_action".
|
|
773
782
|
clone_label (str, optional): Label for the action to copy as an answer set. Defaults to translated word "Copy as answer set".
|
|
774
783
|
show_title (bool, optional): If True, shows the title of the session. Defaults to True.
|
|
784
|
+
show_copy_button (bool, optional): If True, show a copy button for answer sets. Defaults to True.
|
|
775
785
|
limit (int, optional): Limit for the number of sessions returned. Defaults to 50.
|
|
776
786
|
offset (int, optional): Offset for the session list. Defaults to 0.
|
|
777
787
|
|
|
@@ -823,7 +833,8 @@ def session_list_html(
|
|
|
823
833
|
"arguments": {
|
|
824
834
|
"session": answer.get("key"),
|
|
825
835
|
"filename": answer.get("filename"),
|
|
826
|
-
"title": nice_interview_subtitle(answer)
|
|
836
|
+
"title": nice_interview_subtitle(answer)
|
|
837
|
+
or nice_interview_title(answer),
|
|
827
838
|
},
|
|
828
839
|
},
|
|
829
840
|
]
|
|
@@ -879,7 +890,10 @@ def session_list_html(
|
|
|
879
890
|
<td>
|
|
880
891
|
<a class="al-sessions-action-rename" href="{ url_ask_rename }"><i class="fa-solid fa-tag" aria-hidden="true" title="{ rename_label }"></i><span class="sr-only">{ rename_label }</span></a>
|
|
881
892
|
"""
|
|
882
|
-
if
|
|
893
|
+
if (
|
|
894
|
+
get_config("assembly line", {}).get("enable answer sets")
|
|
895
|
+
and show_copy_button
|
|
896
|
+
):
|
|
883
897
|
table += f"""
|
|
884
898
|
|
|
885
899
|
<a class="al-sessions-actions-clone" href="{ url_ask_copy }"><i class="fa-regular fa-clone" aria-hidden="true" title="{clone_label}"></i><span class="sr-only">{ clone_label }</span></a>
|
|
@@ -981,18 +995,20 @@ def save_interview_answers(
|
|
|
981
995
|
original_interview_filename=None,
|
|
982
996
|
source_filename=None,
|
|
983
997
|
source_session=None,
|
|
998
|
+
additional_variables_to_filter=None,
|
|
984
999
|
) -> str:
|
|
985
1000
|
"""
|
|
986
1001
|
Copies the answers from a given session into a new session with a specified interview filename.
|
|
987
1002
|
|
|
988
1003
|
Args:
|
|
989
1004
|
filename (str, optional): The desired filename for the new session. Defaults to `al_session_store_default_filename`.
|
|
990
|
-
variables_to_filter (Union[Set[str], List[str], None], optional):
|
|
1005
|
+
variables_to_filter (Union[Set[str], List[str], None], optional): The "base" list or set of variables to filter out. Defaults to `al_sessions_variables_to_remove`. There's usually no reason to change this and changing it might break sessions.
|
|
991
1006
|
metadata (Optional[Dict], optional): Dictionary containing metadata. Defaults to an empty dictionary.
|
|
992
1007
|
metadata_key_name (str, optional): Key name for metadata storage. Defaults to "metadata".
|
|
993
1008
|
original_interview_filename (str, optional): Original filename of the interview. Defaults to None.
|
|
994
1009
|
source_filename (str, optional): Source filename to get session variables from. Defaults to None.
|
|
995
1010
|
source_session (str, optional): Session ID of the source file. Defaults to None.
|
|
1011
|
+
additional_variables_to_filter (Union[Set[str], List[str], None], optional): List or set of variables to filter out. Defaults to None.
|
|
996
1012
|
|
|
997
1013
|
Returns:
|
|
998
1014
|
str: ID of the new session.
|
|
@@ -1000,6 +1016,8 @@ def save_interview_answers(
|
|
|
1000
1016
|
# Avoid using mutable default parameter
|
|
1001
1017
|
if not variables_to_filter:
|
|
1002
1018
|
variables_to_filter = al_sessions_variables_to_remove
|
|
1019
|
+
if not additional_variables_to_filter:
|
|
1020
|
+
additional_variables_to_filter = []
|
|
1003
1021
|
if not metadata:
|
|
1004
1022
|
metadata = {}
|
|
1005
1023
|
|
|
@@ -1008,6 +1026,7 @@ def save_interview_answers(
|
|
|
1008
1026
|
filename=source_filename,
|
|
1009
1027
|
session_id=source_session,
|
|
1010
1028
|
variables_to_filter=variables_to_filter,
|
|
1029
|
+
additional_variables_to_filter=additional_variables_to_filter,
|
|
1011
1030
|
)
|
|
1012
1031
|
|
|
1013
1032
|
try:
|
|
@@ -1056,7 +1075,8 @@ def save_interview_answers(
|
|
|
1056
1075
|
def get_filtered_session_variables(
|
|
1057
1076
|
filename: Optional[str] = None,
|
|
1058
1077
|
session_id: Optional[int] = None,
|
|
1059
|
-
variables_to_filter: Union[Set[str], List[str]
|
|
1078
|
+
variables_to_filter: Optional[Union[Set[str], List[str]]] = None,
|
|
1079
|
+
additional_variables_to_filter: Optional[Union[Set[str], List[str]]] = None,
|
|
1060
1080
|
) -> Dict[str, Any]:
|
|
1061
1081
|
"""
|
|
1062
1082
|
Retrieves a filtered subset of variables from a specified interview and session.
|
|
@@ -1067,12 +1087,18 @@ def get_filtered_session_variables(
|
|
|
1067
1087
|
filename (Optional[str], optional): Filename of the session. Defaults to None.
|
|
1068
1088
|
session_id (Optional[int], optional): Session ID to retrieve variables from. Defaults to None.
|
|
1069
1089
|
variables_to_filter (Union[Set[str], List[str], None], optional): List or set of variables to exclude. Defaults to `al_sessions_variables_to_remove`.
|
|
1090
|
+
additional_variables_to_filter (Union[Set[str], List[str], None], optional): List or set of additional variables to exclude. Defaults to None.
|
|
1070
1091
|
|
|
1071
1092
|
Returns:
|
|
1072
1093
|
Dict[str, Any]: A dictionary of filtered session variables.
|
|
1073
1094
|
"""
|
|
1074
1095
|
if not variables_to_filter:
|
|
1075
1096
|
variables_to_filter = al_sessions_variables_to_remove
|
|
1097
|
+
if not additional_variables_to_filter:
|
|
1098
|
+
additional_variables_to_filter = []
|
|
1099
|
+
variables_to_filter = set(variables_to_filter).union(
|
|
1100
|
+
set(additional_variables_to_filter)
|
|
1101
|
+
)
|
|
1076
1102
|
|
|
1077
1103
|
if filename and session_id:
|
|
1078
1104
|
all_vars = get_session_variables(filename, session_id, simplify=False)
|
|
@@ -1124,6 +1150,7 @@ def get_filtered_session_variables_string(
|
|
|
1124
1150
|
filename: Optional[str] = None,
|
|
1125
1151
|
session_id: Optional[int] = None,
|
|
1126
1152
|
variables_to_filter: Union[Set[str], List[str], None] = None,
|
|
1153
|
+
additional_variables_to_filter: Optional[Union[Set[str], List[str]]] = None,
|
|
1127
1154
|
) -> str:
|
|
1128
1155
|
"""
|
|
1129
1156
|
Returns a JSON string that represents the filtered contents of a specified filename and session ID.
|
|
@@ -1133,12 +1160,18 @@ def get_filtered_session_variables_string(
|
|
|
1133
1160
|
filename (Optional[str], optional): Filename of the session. Defaults to None.
|
|
1134
1161
|
session_id (Optional[int], optional): Session ID to retrieve variables from. Defaults to None.
|
|
1135
1162
|
variables_to_filter (Union[Set[str], List[str], None], optional): List or set of variables to exclude. Defaults to `al_sessions_variables_to_remove`.
|
|
1163
|
+
additional_variables_to_filter (Union[Set[str], List[str], None], optional): List or set of additional variables to exclude. Defaults to None.
|
|
1136
1164
|
|
|
1137
1165
|
Returns:
|
|
1138
1166
|
str: A JSON-formatted string of filtered session variables.
|
|
1139
1167
|
"""
|
|
1140
1168
|
simple_vars = serializable_dict(
|
|
1141
|
-
get_filtered_session_variables(
|
|
1169
|
+
get_filtered_session_variables(
|
|
1170
|
+
filename=filename,
|
|
1171
|
+
session_id=session_id,
|
|
1172
|
+
variables_to_filter=variables_to_filter,
|
|
1173
|
+
additional_variables_to_filter=additional_variables_to_filter,
|
|
1174
|
+
)
|
|
1142
1175
|
)
|
|
1143
1176
|
return json.dumps(simple_vars)
|
|
1144
1177
|
|
|
@@ -1149,6 +1182,7 @@ def load_interview_answers(
|
|
|
1149
1182
|
new_session: bool = False,
|
|
1150
1183
|
new_interview_filename: Optional[str] = None,
|
|
1151
1184
|
variables_to_filter: Optional[List[str]] = None,
|
|
1185
|
+
additional_variables_to_filter: Optional[List[str]] = None,
|
|
1152
1186
|
) -> Optional[Union[int, bool]]:
|
|
1153
1187
|
"""
|
|
1154
1188
|
Loads answers from a specified session. If the parameter `new_session` is set to True, it will create
|
|
@@ -1161,13 +1195,17 @@ def load_interview_answers(
|
|
|
1161
1195
|
new_session (bool, optional): Determines whether to create a new session. Defaults to False.
|
|
1162
1196
|
new_interview_filename (Optional[str], optional): Filename for the new session. Defaults to None.
|
|
1163
1197
|
variables_to_filter (Optional[List[str]], optional): List of variables to exclude. Defaults to None.
|
|
1198
|
+
additional_variables_to_filter (Optional[List[str]], optional): List of additional variables to exclude. Defaults to None.
|
|
1164
1199
|
|
|
1165
1200
|
Returns:
|
|
1166
1201
|
Optional[Union[int, bool]]: ID of the newly created session if `new_session` is True, otherwise True or False based on success.
|
|
1167
1202
|
"""
|
|
1168
1203
|
|
|
1169
1204
|
old_variables = get_filtered_session_variables(
|
|
1170
|
-
old_interview_filename,
|
|
1205
|
+
filename=old_interview_filename,
|
|
1206
|
+
session_id=old_session_id,
|
|
1207
|
+
variables_to_filter=variables_to_filter,
|
|
1208
|
+
additional_variables_to_filter=additional_variables_to_filter,
|
|
1171
1209
|
)
|
|
1172
1210
|
|
|
1173
1211
|
if new_session:
|
|
@@ -1227,6 +1265,7 @@ def export_interview_variables(
|
|
|
1227
1265
|
session_id: Optional[int] = None,
|
|
1228
1266
|
variables_to_filter: Union[Set, List[str], None] = None,
|
|
1229
1267
|
output: DAFile = None,
|
|
1268
|
+
additional_variables_to_filter: Union[Set, List[str], None] = None,
|
|
1230
1269
|
) -> DAFile:
|
|
1231
1270
|
"""
|
|
1232
1271
|
Generates a DAFile containing a JSON representation of a specified session's interview answers.
|
|
@@ -1238,6 +1277,7 @@ def export_interview_variables(
|
|
|
1238
1277
|
session_id (Optional[int], optional): Session ID to retrieve variables from. Defaults to None.
|
|
1239
1278
|
variables_to_filter (Union[Set, List[str], None], optional): List or set of variables to exclude. Defaults to None.
|
|
1240
1279
|
output (DAFile, optional): DAFile to write the JSON output to. If None, a new DAFile is created.
|
|
1280
|
+
additional_variables_to_filter (Union[Set, List[str], None], optional): List or set of additional variables to exclude. Defaults to None.
|
|
1241
1281
|
|
|
1242
1282
|
Returns:
|
|
1243
1283
|
DAFile: DAFile with a JSON representation of the answers
|
|
@@ -1246,9 +1286,10 @@ def export_interview_variables(
|
|
|
1246
1286
|
output = DAFile()
|
|
1247
1287
|
output.initialize(filename="variables.json")
|
|
1248
1288
|
variables_string = get_filtered_session_variables_string(
|
|
1249
|
-
filename,
|
|
1250
|
-
session_id,
|
|
1251
|
-
variables_to_filter,
|
|
1289
|
+
filename=filename,
|
|
1290
|
+
session_id=session_id,
|
|
1291
|
+
variables_to_filter=variables_to_filter,
|
|
1292
|
+
additional_variables_to_filter=additional_variables_to_filter,
|
|
1252
1293
|
)
|
|
1253
1294
|
|
|
1254
1295
|
output.write(variables_string)
|
|
@@ -427,6 +427,15 @@ class TestALIndividual(unittest.TestCase):
|
|
|
427
427
|
with self.assertRaises(DAAttributeError):
|
|
428
428
|
self.individual.pronoun_objective()
|
|
429
429
|
|
|
430
|
+
def test_name_methods(self):
|
|
431
|
+
self.individual.name.first = "John"
|
|
432
|
+
self.individual.name.middle = "Jacob"
|
|
433
|
+
self.individual.name.last = "Jingleheimer"
|
|
434
|
+
|
|
435
|
+
self.assertEqual(self.individual.name_full(), "John Jacob Jingleheimer")
|
|
436
|
+
self.assertEqual(self.individual.name_initials(), "John J. Jingleheimer")
|
|
437
|
+
self.assertEqual(self.individual.name_short(), "John Jingleheimer")
|
|
438
|
+
|
|
430
439
|
|
|
431
440
|
class test_get_visible_al_nav_items(unittest.TestCase):
|
|
432
441
|
def test_case_1(self):
|
|
@@ -49,6 +49,7 @@ docassemble/AssemblyLine/data/questions/test_alcourts.yml
|
|
|
49
49
|
docassemble/AssemblyLine/data/questions/test_aldocument.yml
|
|
50
50
|
docassemble/AssemblyLine/data/questions/test_alexhibit.yml
|
|
51
51
|
docassemble/AssemblyLine/data/questions/test_alexhibit_maxsize.yml
|
|
52
|
+
docassemble/AssemblyLine/data/questions/test_bundle_parity.yml
|
|
52
53
|
docassemble/AssemblyLine/data/questions/test_question_library.yml
|
|
53
54
|
docassemble/AssemblyLine/data/sources/README.md
|
|
54
55
|
docassemble/AssemblyLine/data/sources/es-words.yml
|
|
@@ -44,7 +44,7 @@ def find_package_data(where='.', package='', exclude=standard_exclude, exclude_d
|
|
|
44
44
|
return out
|
|
45
45
|
|
|
46
46
|
setup(name='docassemble.AssemblyLine',
|
|
47
|
-
version='2.
|
|
47
|
+
version='2.28.0',
|
|
48
48
|
description=(''),
|
|
49
49
|
long_description='# Suffolk LIT Lab Document Assembly Line\r\n\r\n[](https://badge.fury.io/py/docassemble-AssemblyLine)\r\n\r\n<img src="https://user-images.githubusercontent.com/7645641/142245862-c2eb02ab-3090-4e97-9653-bb700bf4c54d.png" alt="drawing" width="300" alt="work together" style="align: center;"/>\r\n\r\nThe Assembly Line Project is a collection of volunteers, students, and institutions who joined together\r\nduring the COVID-19 pandemic to help increase access to the court system. Our vision is mobile-friendly,\r\neasy to use **guided** online forms that help empower litigants to access the court remotely.\r\n\r\nOur signature project is [CourtFormsOnline.org](https://courtformsonline.org).\r\n\r\nWe designed a step-by-step, assembly line style process for automating court forms on top of Docassemble\r\nand built several tools along the way that **you** can use in your home jurisdiction.\r\n\r\nThis package contains **runtime code** and **pre-written questions** to support authoring robust, \r\nconsistent, and attractive Docassemble interviews that help complete court forms.\r\n\r\nRead more on our [documentation page](https://suffolklitlab.org/docassemble-AssemblyLine-documentation/).\r\n\r\n\r\n# Related repositories\r\n\r\n* https://github.com/SuffolkLitLab/docassemble-ALWeaver\r\n* https://github.com/SuffolkLitLab/docassemble-ALMassachusetts\r\n* https://github.com/SuffolkLitLab/docassemble-MassAccess\r\n* https://github.com/SuffolkLitLab/docassemble-ALThemeTemplate\r\n* https://github.com/SuffolkLitLab/EfileProxyServer\r\n\r\n# Documentation\r\n\r\nhttps://suffolklitlab.org/docassemble-AssemblyLine-documentation/\r\n\r\n# Installation\r\n\r\n## Menu-driven installation\r\n\r\nThe recommended installation method is with the [guided installation script](https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/installation).\r\n\r\n## Manual installation\r\n\r\nNormally you do not need to manually install the Assembly Line. Use the [installation script](https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/installation)\r\nif you can. The instructions below are for your optional reference.\r\n\r\nThis package depends on the following configuration changes on your Docassemble server:\r\n\r\n* Ensure that [font-awesome](https://docassemble.org/docs/config.html#default%20icons) is enabled (this may be on by default:\r\n```yaml\r\ndefault icons: font awesome\r\n```\r\n* Add a [Google API key](https://docassemble.org/docs/config.html#google) that has access to:\r\n * Google Places API\r\n * Google Geocoding API\r\n* Add a [VoiceRSS API key](https://docassemble.org/docs/config.html#voicerss)\r\n* Add a [Twilio API key](https://docassemble.org/docs/config.html#twilio) for SMS support\r\n* Add an email account: [Mailgun](https://docassemble.org/docs/config.html#mailgun%20api) or [SendGrid](https://docassemble.org/docs/config.html#sendgrid%20api) recommended for email support\r\n* To show package update time and to enable the feedback form, add a GitHub Private Access token to your config.yml file, like this:\r\n```yaml\r\n# Needs access to create new issues on repositories\r\ngithub issues:\r\n username: "suffolklitlab-issues"\r\n token: "12345"\r\n# Does not need any special access to public repositories \r\ngithub readonly:\r\n username: "suffolklitlab-issues"\r\n password: "45678"\r\n type: "basic"\r\n```\r\n* If you are also using the [Assembly Line Weaver](https://github.com/SuffolkLITLab/docassemble-assemblylinewizard), you may want to set up a [Docassemble API key](https://docassemble.org/docs/api.html#manage_api) in your config.yml file to allow you to install packages automatically, like this:\r\n```yaml\r\ninstall packages api key: 12345\r\n```\r\n\r\n# Migration\r\n\r\nSee [discussion here](https://github.com/SuffolkLITLab/docassemble-AssemblyLine/issues/69)\r\n\r\n\r\n# ALDocument class\r\n\r\n## Purpose\r\n\r\nThe ALDocument class is a small utility library that makes it simpler to use the following features in an interview:\r\n\r\n* Conditional assembly of multiple, optional documents that are triggered in different ways in your interview\r\n* An addendum for PDF files that makes it simple to deal with overflow text\r\n* A customizable download screen that lists the documents in a neat table\r\n* A customizable "send" button that allows the user to email the final forms to a location of their choice\r\n\r\nHere is a small snippet that you can copy and modify that shows how to use the most important features of the ALDocument class.\r\n\r\n```\r\n---\r\nobjects:\r\n - CRA_Motion_to_Dismiss_attachment: ALDocument.using(filename="CRA_Motion_to_Dismiss", title="Motion to Dismiss CRA", enabled=True, has_addendum=True, default_overflow_message="[See addendum]") \r\n---\r\nobjects:\r\n - al_user_bundle: ALDocumentBundle.using(elements=[CRA_Motion_to_Dismiss_attachment], title="Forms to download and deliver to court", filename="motion_to_dismiss_CRA.pdf")\r\n - al_court_bundle: ALDocumentBundle.using(elements=[CRA_Motion_to_Dismiss_attachment], title="Forms to download and deliver to court", filename="motion_to_dismiss_CRA.pdf")\r\n---\r\ngeneric object: ALDocument\r\nattachment:\r\n variable name: x.addendum\r\n docx template file: docx_addendum.docx\r\n---\r\ncode: |\r\n CRA_Motion_to_Dismiss_attachment.overflow_fields[\'reasons_for_request\'].overflow_trigger = 640\r\n CRA_Motion_to_Dismiss_attachment.overflow_fields[\'reasons_for_request\'].label = "Reasons for request"\r\n CRA_Motion_to_Dismiss_attachment.overflow_fields.gathered = True\r\n \r\n---\r\nattachment:\r\n variable name: CRA_Motion_to_Dismiss_attachment[i]\r\n name: CRA Motion to Dismiss\r\n filename: CRA_Motion_to_Dismiss\r\n skip undefined: True\r\n pdf template file: CRA_Motion_to_Dismiss.pdf\r\n fields: \r\n - "court_county": ${ trial_court.address.county }\r\n - "docket_number": ${ docket_number }\r\n - "user_signature": ${ users[0].signature_if_final(i) }\r\n - "signature_date": ${ signature_date }\r\n```\r\n\r\nIt is very common to have a *contingent* document in ALDocument. If your document is contingent, remove the `enabled=True` from the object declaration, and use\r\nsome other method to "turn on" the attachment.\r\n\r\nE.g.,\r\n\r\n```\r\ncode: |\r\n CRA_Motion_to_Dismiss_attachment.enabled = condition1 and condition2\r\n```\r\n\r\n# Changelog\r\n\r\nSee [CHANGELOG.MD](https://github.com/SuffolkLITLab/docassemble-AssemblyLine/blob/main/CHANGELOG.md)\r\n',
|
|
50
50
|
long_description_content_type='text/markdown',
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.27.1'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|