diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7a6c6429a..f7b6bbca4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -48,6 +48,7 @@ jobs: pydoc-markdown ./make_interview_docs.py ../docassemble-ALDashboard ./fix-doc-titles.sh + ./fix-doc-anchors.py - uses: actions/setup-node@v3 with: node-version: 20 diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index f5e2f5ac6..0f375d7fc 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -48,6 +48,7 @@ jobs: pydoc-markdown ./make_interview_docs.py ../docassemble-ALDashboard ./fix-doc-titles.sh + ./fix-doc-anchors.py - uses: actions/setup-node@v3 with: node-version: 20 diff --git a/docs/authoring/writing_review_screen.md b/docs/authoring/writing_review_screen.md index 4747edc58..265ce5b55 100644 --- a/docs/authoring/writing_review_screen.md +++ b/docs/authoring/writing_review_screen.md @@ -24,7 +24,7 @@ This page is a step-by-step tutorial on how to write a review screen, and covers - [Step 1: AL Review Generator](#step-1-al-review-generator) - [Step 2: Understanding and Editing the Generated Review Screen](#step-2-understanding-and-editing-the-generated-review-screen) - [Edits to the Review Screen](#edits-to-the-review-screen) - - [Step 4: Things to add to the review screen](#step-4-things-to-add-to-the-review-screen) + - [Step 3: Things to add to the review screen](#step-3-things-to-add-to-the-review-screen) ## Why make a review screen? diff --git a/docs/components/ALDashboard/aldashboard.md b/docs/components/ALDashboard/aldashboard.md index 72843872f..388095e2a 100644 --- a/docs/components/ALDashboard/aldashboard.md +++ b/docs/components/ALDashboard/aldashboard.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALDashboard.aldashboard](#ALDashboard.aldashboard) +* ALDashboard.aldashboard * [speedy\_get\_users](#ALDashboard.aldashboard.speedy_get_users) * [speedy\_get\_sessions](#ALDashboard.aldashboard.speedy_get_sessions) * [dashboard\_get\_session\_variables](#ALDashboard.aldashboard.dashboard_get_session_variables) @@ -19,9 +19,7 @@ sidebar_label: aldashboard title: ALDashboard.aldashboard --- - - -#### speedy\_get\_users() +#### speedy\_get\_users() {#ALDashboard.aldashboard.speedy\_get\_users} ```python def speedy_get_users() -> List[Dict[int, str]] @@ -29,9 +27,7 @@ def speedy_get_users() -> List[Dict[int, str]] Return a list of all users in the database. Possibly faster than get_user_list(). - - -#### speedy\_get\_sessions(user\_id: Optional[int] = None, filename: Optional[str] = None, filter\_step1: bool = True, metadata\_key\_name: str = "metadata") +#### speedy\_get\_sessions(user\_id: Optional[int] = None, filename: Optional[str] = None, filter\_step1: bool = True, metadata\_key\_name: str = "metadata") {#ALDashboard.aldashboard.speedy\_get\_sessions} ```python def speedy_get_sessions(user_id: Optional[int] = None, @@ -48,9 +44,7 @@ user_id, modtime, key - - -#### dashboard\_get\_session\_variables(session\_id: str, filename: str) +#### dashboard\_get\_session\_variables(session\_id: str, filename: str) {#ALDashboard.aldashboard.dashboard\_get\_session\_variables} ```python def dashboard_get_session_variables(session_id: str, filename: str) @@ -58,9 +52,7 @@ def dashboard_get_session_variables(session_id: str, filename: str) Return the variables and steps for a given session ID and YAML filename in serializable dictionary format. - - -## ALPackageInstaller Objects +## ALPackageInstaller Objects {#ALDashboard.aldashboard.ALPackageInstaller} ```python class ALPackageInstaller(DAObject) @@ -68,9 +60,7 @@ class ALPackageInstaller(DAObject) Methods and state for installing AssemblyLine. - - -#### get\_validated\_github\_username(access\_token: str) +#### get\_validated\_github\_username(access\_token: str) {#ALDashboard.aldashboard.ALPackageInstaller.get\_validated\_github\_username} ```python def get_validated_github_username(access_token: str) @@ -79,9 +69,7 @@ def get_validated_github_username(access_token: str) Given a valid GitHub `access_token`, returns the username associated with it. Otherwise, adds one or more errors to the installer. - - -## ErrorList Objects +## ErrorList Objects {#ALDashboard.aldashboard.ErrorList} ```python class ErrorList(DAList) @@ -89,9 +77,7 @@ class ErrorList(DAList) Contains `ErrorLikeObject`s so they can be recognized by docassemble. - - -## ErrorLikeObject Objects +## ErrorLikeObject Objects {#ALDashboard.aldashboard.ErrorLikeObject} ```python class ErrorLikeObject(DAObject) @@ -101,9 +87,7 @@ An object with a `template_name` that identifies the DALazyTemplate that will show its error. It can contain any other attributes so its template can access them as needed. DAObject doesn't seem to be enough to allow template definition. - - -#### install\_fonts(the\_font\_files: DAFileList) +#### install\_fonts(the\_font\_files: DAFileList) {#ALDashboard.aldashboard.install\_fonts} ```python def install_fonts(the_font_files: DAFileList) @@ -111,9 +95,7 @@ def install_fonts(the_font_files: DAFileList) Install fonts to the server and restart both supervisor and unoconv. - - -#### list\_installed\_fonts() +#### list\_installed\_fonts() {#ALDashboard.aldashboard.list\_installed\_fonts} ```python def list_installed_fonts() @@ -121,9 +103,7 @@ def list_installed_fonts() List the fonts installed on the server. - - -#### nicer\_interview\_filename(filename: str) +#### nicer\_interview\_filename(filename: str) {#ALDashboard.aldashboard.nicer\_interview\_filename} ```python def nicer_interview_filename(filename: str) -> str @@ -132,9 +112,7 @@ def nicer_interview_filename(filename: str) -> str Given a filename like docassemble.playground10ALWeaver:data/questions/assembly_line.yml, return a less cluttered name like: playground10ALWeaver:assembly_line - - -#### list\_question\_files\_in\_package(package\_name: str) +#### list\_question\_files\_in\_package(package\_name: str) {#ALDashboard.aldashboard.list\_question\_files\_in\_package} ```python def list_question_files_in_package(package_name: str) -> Optional[List[str]] @@ -151,9 +129,7 @@ List all the files in the 'data/questions' directory of a package. - `List[str]` - A list of filenames in the 'data/questions' directory of the package. - - -#### list\_question\_files\_in\_docassemble\_packages() +#### list\_question\_files\_in\_docassemble\_packages() {#ALDashboard.aldashboard.list\_question\_files\_in\_docassemble\_packages} ```python def list_question_files_in_docassemble_packages() diff --git a/docs/components/ALDashboard/create_package.md b/docs/components/ALDashboard/create_package.md index 0322b122f..ccbb7355a 100644 --- a/docs/components/ALDashboard/create_package.md +++ b/docs/components/ALDashboard/create_package.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALDashboard.create\_package](#ALDashboard.create_package) +* ALDashboard.create\_package * [create\_package\_zip](#ALDashboard.create_package.create_package_zip) --- @@ -8,9 +8,7 @@ sidebar_label: create_package title: ALDashboard.create_package --- - - -#### create\_package\_zip(pkgname: str, info: dict, author\_info: dict, folders\_and\_files: dict, fileobj: Optional[DAFile] = None) +#### create\_package\_zip(pkgname: str, info: dict, author\_info: dict, folders\_and\_files: dict, fileobj: Optional[DAFile] = None) {#ALDashboard.create\_package.create\_package\_zip} ```python def create_package_zip(pkgname: str, diff --git a/docs/components/ALDashboard/docx_wrangling.md b/docs/components/ALDashboard/docx_wrangling.md index 0c08978f8..6b907d708 100644 --- a/docs/components/ALDashboard/docx_wrangling.md +++ b/docs/components/ALDashboard/docx_wrangling.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALDashboard.docx\_wrangling](#ALDashboard.docx_wrangling) +* ALDashboard.docx\_wrangling * [update\_docx](#ALDashboard.docx_wrangling.update_docx) * [get\_labeled\_docx\_runs](#ALDashboard.docx_wrangling.get_labeled_docx_runs) * [modify\_docx\_with\_openai\_guesses](#ALDashboard.docx_wrangling.modify_docx_with_openai_guesses) @@ -10,9 +10,7 @@ sidebar_label: docx_wrangling title: ALDashboard.docx_wrangling --- - - -#### update\_docx(document: Union[docx.document.Document, str], modified\_runs: List[Tuple[int, int, str, int]]) +#### update\_docx(document: Union[docx.document.Document, str], modified\_runs: List[Tuple[int, int, str, int]]) {#ALDashboard.docx\_wrangling.update\_docx} ```python def update_docx( @@ -35,9 +33,7 @@ Update the document with modified runs. The modified document. - - -#### get\_labeled\_docx\_runs(docx\_path: str, custom\_people\_names: Optional[Tuple[str, str]] = None, openai\_client: Optional[OpenAI] = None) +#### get\_labeled\_docx\_runs(docx\_path: str, custom\_people\_names: Optional[Tuple[str, str]] = None, openai\_client: Optional[OpenAI] = None) {#ALDashboard.docx\_wrangling.get\_labeled\_docx\_runs} ```python def get_labeled_docx_runs( @@ -59,9 +55,7 @@ Scan the DOCX and return a list of modified text with Jinja2 variable names inse A list of tuples, each containing a paragraph number, run number, and the modified text of the run. - - -#### modify\_docx\_with\_openai\_guesses(docx\_path: str) +#### modify\_docx\_with\_openai\_guesses(docx\_path: str) {#ALDashboard.docx\_wrangling.modify\_docx\_with\_openai\_guesses} ```python def modify_docx_with_openai_guesses(docx_path: str) -> docx.document.Document diff --git a/docs/components/ALDashboard/package_scanner.md b/docs/components/ALDashboard/package_scanner.md index 4a98a74ce..db9f5e76c 100644 --- a/docs/components/ALDashboard/package_scanner.md +++ b/docs/components/ALDashboard/package_scanner.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALDashboard.package\_scanner](#ALDashboard.package_scanner) +* ALDashboard.package\_scanner * [URL](#ALDashboard.package_scanner.URL) * [PARAMETERS](#ALDashboard.package_scanner.PARAMETERS) * [DELAY\_BETWEEN\_QUERYS](#ALDashboard.package_scanner.DELAY_BETWEEN_QUERYS) @@ -12,27 +12,19 @@ sidebar_label: package_scanner title: ALDashboard.package_scanner --- - - -#### URL +#### URL {#ALDashboard.package\_scanner.URL} The basic URL to use the GitHub API - - -#### PARAMETERS +#### PARAMETERS {#ALDashboard.package\_scanner.PARAMETERS} Additional parameters for the query (by default 100 items per page) - - -#### DELAY\_BETWEEN\_QUERYS +#### DELAY\_BETWEEN\_QUERYS {#ALDashboard.package\_scanner.DELAY\_BETWEEN\_QUERYS} The time to wait between different queries to GitHub - - -#### getUrl(url) +#### getUrl(url) {#ALDashboard.package\_scanner.getUrl} ```python def getUrl(url) @@ -40,9 +32,7 @@ def getUrl(url) Given a URL it returns its body - - -#### fetch\_github\_repos(github\_user, sub\_queries) +#### fetch\_github\_repos(github\_user, sub\_queries) {#ALDashboard.package\_scanner.fetch\_github\_repos} ```python def fetch_github_repos(github_user, sub_queries) -> dict diff --git a/docs/components/ALDashboard/project_maintenance.md b/docs/components/ALDashboard/project_maintenance.md index 56cd1c59b..1c2cfaa39 100644 --- a/docs/components/ALDashboard/project_maintenance.md +++ b/docs/components/ALDashboard/project_maintenance.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALDashboard.project\_maintenance](#ALDashboard.project_maintenance) +* ALDashboard.project\_maintenance * [get\_package\_names](#ALDashboard.project_maintenance.get_package_names) * [add\_tag\_to\_repos](#ALDashboard.project_maintenance.add_tag_to_repos) * [process\_packages\_and\_add\_tag](#ALDashboard.project_maintenance.process_packages_and_add_tag) @@ -17,9 +17,7 @@ sidebar_label: project_maintenance title: ALDashboard.project_maintenance --- - - -#### get\_package\_names(server\_name: str) +#### get\_package\_names(server\_name: str) {#ALDashboard.project\_maintenance.get\_package\_names} ```python def get_package_names(server_name: str) -> List[str] @@ -36,9 +34,7 @@ Fetches the JSON file from the given docassemble server and extracts package nam - `List[str]` - List of package names. - - -#### add\_tag\_to\_repos(token: str, org\_name: str, repo\_names: List[str], tag: str) +#### add\_tag\_to\_repos(token: str, org\_name: str, repo\_names: List[str], tag: str) {#ALDashboard.project\_maintenance.add\_tag\_to\_repos} ```python def add_tag_to_repos(token: str, org_name: str, repo_names: List[str], @@ -67,9 +63,7 @@ Adds a specific tag to each repository in the given list. add_tag_to_repos(personal_access_token, organization_name, repositories, tag_to_add) - - -#### process\_packages\_and\_add\_tag(server\_name: str, token: str, org\_name: str, tag: str) +#### process\_packages\_and\_add\_tag(server\_name: str, token: str, org\_name: str, tag: str) {#ALDashboard.project\_maintenance.process\_packages\_and\_add\_tag} ```python def process_packages_and_add_tag(server_name: str, token: str, org_name: str, @@ -86,9 +80,7 @@ and adds a specified tag to each repository. - `org_name` _str_ - Name of the GitHub organization. - `tag` _str_ - Tag to be added to each repository. - - -#### get\_project\_by\_name(token: str, org\_name: str, project\_name: str) +#### get\_project\_by\_name(token: str, org\_name: str, project\_name: str) {#ALDashboard.project\_maintenance.get\_project\_by\_name} ```python def get_project_by_name(token: str, org_name: str, @@ -108,9 +100,7 @@ Finds a GitHub Next-Generation project by its name within an organization using - `dict` - The GitHub project object, or None if not found. - - -#### get\_repos\_by\_topic(token: str, org\_name: str, topic: str) +#### get\_repos\_by\_topic(token: str, org\_name: str, topic: str) {#ALDashboard.project\_maintenance.get\_repos\_by\_topic} ```python def get_repos_by_topic(token: str, org_name: str, @@ -130,9 +120,7 @@ Fetches repositories in an organization that have a specific topic. - `List[Repository]` - A list of repository objects that have the specified topic. - - -#### add\_issues\_and\_create\_cards(token: str, org\_name: str, project\_name: str, topic: str, issue\_title: str, issue\_body: str) +#### add\_issues\_and\_create\_cards(token: str, org\_name: str, project\_name: str, topic: str, issue\_title: str, issue\_body: str) {#ALDashboard.project\_maintenance.add\_issues\_and\_create\_cards} ```python def add_issues_and_create_cards(token: str, org_name: str, project_name: str, @@ -151,9 +139,7 @@ Adds an issue to each repository with a specific topic and creates a card for ea - `issue_title` _str_ - Title of the issue. - `issue_body` _str_ - Body of the issue. - - -#### find\_issues\_by\_title(token: str, org\_name: str, repo\_names: List[str], issue\_title: str) +#### find\_issues\_by\_title(token: str, org\_name: str, repo\_names: List[str], issue\_title: str) {#ALDashboard.project\_maintenance.find\_issues\_by\_title} ```python def find_issues_by_title(token: str, org_name: str, repo_names: List[str], @@ -174,9 +160,7 @@ Finds issues in a list of repositories with a specific title. - `list` - A list of issue node IDs. - - -#### add\_issue\_to\_project(token: str, project\_id: str, issue\_node\_id: str) +#### add\_issue\_to\_project(token: str, project\_id: str, issue\_node\_id: str) {#ALDashboard.project\_maintenance.add\_issue\_to\_project} ```python def add_issue_to_project(token: str, project_id: str, @@ -191,9 +175,7 @@ Adds an issue to a Next-Generation GitHub project. - `project_id` _str_ - Node ID of the GitHub project. - `issue_node_id` _str_ - Node ID of the GitHub issue. - - -#### link\_issue\_title\_to\_project(token: str, org\_name: str, project\_name: str, topic: str, issue\_title: str) +#### link\_issue\_title\_to\_project(token: str, org\_name: str, project\_name: str, topic: str, issue\_title: str) {#ALDashboard.project\_maintenance.link\_issue\_title\_to\_project} ```python def link_issue_title_to_project(token: str, org_name: str, project_name: str, @@ -210,9 +192,7 @@ Links issues with a specific title in repositories with a certain topic to a Nex - `topic` _str_ - The GitHub topic to filter repositories by. - `issue_title` _str_ - Title of the issue to link. - - -#### main() +#### main() {#ALDashboard.project\_maintenance.main} ```python def main() -> None diff --git a/docs/components/ALDashboard/translation.md b/docs/components/ALDashboard/translation.md index a617dc70a..320c41e49 100644 --- a/docs/components/ALDashboard/translation.md +++ b/docs/components/ALDashboard/translation.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALDashboard.translation](#ALDashboard.translation) +* ALDashboard.translation * [gpt\_is\_available](#ALDashboard.translation.gpt_is_available) * [may\_have\_mako](#ALDashboard.translation.may_have_mako) * [may\_have\_html](#ALDashboard.translation.may_have_html) @@ -15,9 +15,7 @@ sidebar_label: translation title: ALDashboard.translation --- - - -#### gpt\_is\_available() +#### gpt\_is\_available() {#ALDashboard.translation.gpt\_is\_available} ```python def gpt_is_available() -> bool @@ -25,9 +23,7 @@ def gpt_is_available() -> bool Return True if the GPT API is available. - - -#### may\_have\_mako(text: str) +#### may\_have\_mako(text: str) {#ALDashboard.translation.may\_have\_mako} ```python def may_have_mako(text: str) -> bool @@ -35,9 +31,7 @@ def may_have_mako(text: str) -> bool Return True if the text appears to contain any Mako code, such as $\{...\} or % at the beginning of a line. - - -#### may\_have\_html(text: str) +#### may\_have\_html(text: str) {#ALDashboard.translation.may\_have\_html} ```python def may_have_html(text: str) -> bool @@ -45,9 +39,7 @@ def may_have_html(text: str) -> bool Return True if the text appears to contain any HTML code, such as <p> or <div>. - - -#### translate\_fragments\_gpt(fragments: Union[str, List[Tuple[int, str]]], source\_language: str, tr\_lang: str, interview\_context: Optional[str] = None, special\_words: Optional[Dict[int, str]] = None, model="gpt-4.1-nano", openai\_base\_url: Optional[str] = None, max\_output\_tokens: Optional[int] = None, max\_input\_tokens: Optional[int] = None, openai\_api: Optional[str] = None) +#### translate\_fragments\_gpt(fragments: Union[str, List[Tuple[int, str]]], source\_language: str, tr\_lang: str, interview\_context: Optional[str] = None, special\_words: Optional[Dict[int, str]] = None, model="gpt-4.1-nano", openai\_base\_url: Optional[str] = None, max\_output\_tokens: Optional[int] = None, max\_input\_tokens: Optional[int] = None, openai\_api: Optional[str] = None) {#ALDashboard.translation.translate\_fragments\_gpt} ```python def translate_fragments_gpt( @@ -84,29 +76,21 @@ You can optionally provide an alternative model, but it must support JSON mode. A dictionary where the keys are the indices of the fragments and the values are the translated text. - - -## Translation Objects +## Translation Objects {#ALDashboard.translation.Translation} ```python class Translation(NamedTuple) ``` - - -#### file: `DAFile` +#### file: `DAFile` {#ALDashboard.translation.Translation.file} an XLSX or XLIFF file - - -#### untranslated\_segments: `int` +#### untranslated\_segments: `int` {#ALDashboard.translation.Translation.untranslated\_segments} Number of rows in the output that have untranslated text - one for each question, subquestion, field, etc. - - -#### translation\_file(yaml\_filename: str, tr\_lang: str, use\_gpt=False, use\_google\_translate=False, openai\_api: Optional[str] = None, max\_tokens=4000, interview\_context: Optional[str] = None, special\_words: Optional[Dict[int, str]] = None, model: Optional[str] = None, openai\_base\_url: Optional[str] = None, max\_input\_tokens: Optional[int] = None, max\_output\_tokens: Optional[int] = None) +#### translation\_file(yaml\_filename: str, tr\_lang: str, use\_gpt=False, use\_google\_translate=False, openai\_api: Optional[str] = None, max\_tokens=4000, interview\_context: Optional[str] = None, special\_words: Optional[Dict[int, str]] = None, model: Optional[str] = None, openai\_base\_url: Optional[str] = None, max\_input\_tokens: Optional[int] = None, max\_output\_tokens: Optional[int] = None) {#ALDashboard.translation.translation\_file} ```python def translation_file(yaml_filename: str, diff --git a/docs/components/ALDashboard/validate_docx.md b/docs/components/ALDashboard/validate_docx.md index 0f47d4d65..5dbf7d9f9 100644 --- a/docs/components/ALDashboard/validate_docx.md +++ b/docs/components/ALDashboard/validate_docx.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALDashboard.validate\_docx](#ALDashboard.validate_docx) +* ALDashboard.validate\_docx * [CallAndDebugUndefined](#ALDashboard.validate_docx.CallAndDebugUndefined) * [\_\_getitem\_\_](#ALDashboard.validate_docx.CallAndDebugUndefined.__getitem__) * [get\_jinja\_errors](#ALDashboard.validate_docx.get_jinja_errors) @@ -10,9 +10,7 @@ sidebar_label: validate_docx title: ALDashboard.validate_docx --- - - -## CallAndDebugUndefined Objects +## CallAndDebugUndefined Objects {#ALDashboard.validate\_docx.CallAndDebugUndefined} ```python class CallAndDebugUndefined(DebugUndefined) @@ -21,15 +19,11 @@ class CallAndDebugUndefined(DebugUndefined) Handles Jinja2 undefined errors by printing the name of the undefined variable. Extended to handle callable methods. - - -#### \_\_getitem\_\_ +#### \_\_getitem\_\_ {#ALDashboard.validate\_docx.CallAndDebugUndefined.\_\_getitem\_\_} type: ignore - - -#### get\_jinja\_errors(the\_file: str) +#### get\_jinja\_errors(the\_file: str) {#ALDashboard.validate\_docx.get\_jinja\_errors} ```python def get_jinja_errors(the_file: str) -> Optional[str] diff --git a/docs/components/ALKiln/automated_testing.mdx b/docs/components/ALKiln/automated_testing.mdx index 73cbe53db..2a649682f 100644 --- a/docs/components/ALKiln/automated_testing.mdx +++ b/docs/components/ALKiln/automated_testing.mdx @@ -460,7 +460,7 @@ The `value` for a row setting a signature doesn't matter. All signatures will be ### Other story table notes -([Moving](writing_tests.mdx#unused-rows)) +([Moving](writing_tests.mdx#unused_rows)) Don't worry about accidentally including variables that won't show up during the test. Extra rows will be ignored. @@ -626,7 +626,7 @@ The phrase should be inside double quotation marks and should NOT itself contain ([Moving](writing_tests.mdx#a11y)) -The `accessibility` Step can check a page for its accessibility by running [aXe-core](https://github.com/dequelabs/axe-core) on the page. +The `accessibility` Step can check a page for its accessibility by running [aXe-core](https://github.com/dequelabs/axe-core) on the page. ``` Then I check the page for accessibility issues @@ -1389,7 +1389,7 @@ When you want to update to a new version of the ALKiln, update that sha manually ([Moving](security.mdx#freeze)) -This section requires prior technical knowledge about [npm](https://docs.npmjs.com/about-npm) and [GitHub workflow files](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions). Feel free to [ask us](/docs/get_started/beginners_guide.md#join) any questions you might have. +This section requires prior technical knowledge about [npm](https://docs.npmjs.com/about-npm) and [GitHub workflow files](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions). Feel free to [ask us](/docs/get_started/intro.md#join-the-community) any questions you might have. You can use an exact npm version of ALKiln by using your workflow file's `ALKILN_VERSION` input. The default uses a carat, for example `^4.0.0`. That means it will use the latest minor or patch in version 4 of ALKiln. You can instead use an exact version, for example `4.3.0`. See our section on [setting optional inputs](#optional-inputs). @@ -1491,7 +1491,7 @@ Among other things, the workflow file: You can also use the whole suite of GitHub's workflow and action functionality to do other things, like creating issues when tests fail. -These following sections probably require prior technical knowledge about [GitHub workflow files](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions). Feel free to [ask us](/docs/get_started/beginners_guide.md#join) any questions you might have. +These following sections probably require prior technical knowledge about [GitHub workflow files](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions). Feel free to [ask us](/docs/get_started/intro.md#join-the-community) any questions you might have. ### Required inputs diff --git a/docs/components/ALKiln/troubleshooting.mdx b/docs/components/ALKiln/troubleshooting.mdx index d02a09db0..c52b75954 100644 --- a/docs/components/ALKiln/troubleshooting.mdx +++ b/docs/components/ALKiln/troubleshooting.mdx @@ -154,7 +154,7 @@ This is a reference error. It means docassemble tried to get the value for a var - It may be that you have a typo in a [variable name or value](#var-val) in your test. - It may be that you are [setting the value incorrectly](writing_tests.mdx#values) in your test. [Checkboxes are especially complex fields to set](writing_tests.mdx#checkboxes). -The mistake may have happened on a page much farther back than you expect with a field ALKiln [skipped](writing_tests.mdx#unused-rows). +The mistake may have happened on a page much farther back than you expect with a field ALKiln [skipped](writing_tests.mdx#unused_rows). **Debugging:** @@ -188,7 +188,7 @@ Some possible causes: ## Skipped rows or variables {#skipped} -If you look in a [test suite report](writing_tests.mdx#report) and see that ALKiln [skipped setting a variable](writing_tests.mdx#unused-rows), your test code might be [missing a field or value](#missing) that it needs in order to fill out that field. +If you look in a [test suite report](writing_tests.mdx#report) and see that ALKiln [skipped setting a variable](writing_tests.mdx#unused_rows), your test code might be [missing a field or value](#missing) that it needs in order to fill out that field. If the test still passed, the variable probably belongs to a field that was optional. @@ -205,7 +205,7 @@ You can check your test code for incorrect variable or value names in a few diff -1. If you give every question in your interview an id, the [report](writing_tests.mdx#report) can help show you where the test failed or where ALKiln skipped setting variables. For each test, the report often has a list of question ids. For each question id, the report has a list of variables that ALKiln set on the page that had the error. If the test failed, you can see what question id the test got to. You can also check previous questions to see what variables are missing from each of those pages - what [fields ALKiln skipped](writing_tests.mdx#unused-rows). +1. If you give every question in your interview an id, the [report](writing_tests.mdx#report) can help show you where the test failed or where ALKiln skipped setting variables. For each test, the report often has a list of question ids. For each question id, the report has a list of variables that ALKiln set on the page that had the error. If the test failed, you can see what question id the test got to. You can also check previous questions to see what variables are missing from each of those pages - what [fields ALKiln skipped](writing_tests.mdx#unused_rows). 1. It is more annoying, but in most cases[^except] you can copy the variable name from your test and search for it in your interview code. You can do the same for values of multiple choice questions. 1. Alternatively, in most cases[^except] you can go through the interview manually, but follow this procedure: 1. For every single page (even if you think this page has nothing to do with the problem), click on the `` in the nav bar to see the source of the page. diff --git a/docs/components/ALKiln/writing_tests.mdx b/docs/components/ALKiln/writing_tests.mdx index 73c505b6e..550d94fdc 100644 --- a/docs/components/ALKiln/writing_tests.mdx +++ b/docs/components/ALKiln/writing_tests.mdx @@ -2174,7 +2174,7 @@ alkiln: `ALKILN_BEAR_SIZE` is the name of the environment variable. `"small_bear"` is the value of the environment variable. All the interviews on your server can see these config values, including the interview that runs your tests, so you are actually setting these values for all the tests that you run on your server with tests. -# GitHub env vars {#github-vars} +### GitHub env vars {#github-vars} In GitHub, you can make [GitHub workflow environment variables](https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow) by putting them in the `env` key in your [workflow file](#workflows): diff --git a/docs/components/ALThemeTemplate/althemetemplate_overview.md b/docs/components/ALThemeTemplate/althemetemplate_overview.md index 907a97c38..ea02a321c 100644 --- a/docs/components/ALThemeTemplate/althemetemplate_overview.md +++ b/docs/components/ALThemeTemplate/althemetemplate_overview.md @@ -162,7 +162,7 @@ cd bootstrap-5.1.3 npm install ``` -Place the `custom.scss` file you wrote from [the above section](#creating-a-custom-theme-from-source-instead-of-with-a-theme-generator) +Place the `custom.scss` file you wrote from [the above section](#creating-a-custom-theme) in the unzipped bootstrap-5.1.3 folder, and use `npm` to compile the theme file. ```bash diff --git a/docs/components/ALToolbox/Addup.md b/docs/components/ALToolbox/Addup.md index 2675eff84..c8484f736 100644 --- a/docs/components/ALToolbox/Addup.md +++ b/docs/components/ALToolbox/Addup.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.Addup](#ALToolbox.Addup) +* ALToolbox.Addup * [Addup](#ALToolbox.Addup.Addup) * [\_\_init\_\_](#ALToolbox.Addup.Addup.__init__) * [g](#ALToolbox.Addup.Addup.g) @@ -10,9 +10,7 @@ sidebar_label: Addup title: ALToolbox.Addup --- - - -## Addup Objects +## Addup Objects {#ALToolbox.Addup.Addup} ```python class Addup() @@ -24,9 +22,7 @@ This class provides functionality to sum specific numeric fields from all items in a docassemble DAList, which is useful for financial calculations and data aggregation in legal document automation. - - -#### \_\_init\_\_(listName, varName) +#### \_\_init\_\_(listName, varName) {#ALToolbox.Addup.Addup.\_\_init\_\_} ```python def __init__(listName, varName) @@ -40,9 +36,7 @@ Initialize the Addup calculator and compute the sum immediately. - `listName` - A DAList object containing items with numeric fields. - `varName` _str_ - The name of the field to sum across all list items. - - -#### g(listName, varName) +#### g(listName, varName) {#ALToolbox.Addup.Addup.g} ```python def g(listName, varName) -> float diff --git a/docs/components/ALToolbox/ThreePartsDate.md b/docs/components/ALToolbox/ThreePartsDate.md index c00b794ff..8a2a280a4 100644 --- a/docs/components/ALToolbox/ThreePartsDate.md +++ b/docs/components/ALToolbox/ThreePartsDate.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.ThreePartsDate](#ALToolbox.ThreePartsDate) +* ALToolbox.ThreePartsDate * [check\_empty\_parts](#ALToolbox.ThreePartsDate.check_empty_parts) * [ThreePartsDate](#ALToolbox.ThreePartsDate.ThreePartsDate) * [validate](#ALToolbox.ThreePartsDate.ThreePartsDate.validate) @@ -14,9 +14,7 @@ sidebar_label: ThreePartsDate title: ALToolbox.ThreePartsDate --- - - -#### check\_empty\_parts(item: str, default\_msg="{} is not a valid date") +#### check\_empty\_parts(item: str, default\_msg="{} is not a valid date") {#ALToolbox.ThreePartsDate.check\_empty\_parts} ```python def check_empty_parts(item: str, @@ -52,17 +50,13 @@ what needs to be entered. Currently only handles US date format. >>> check_empty_parts("12/25/2023") None - - -## ThreePartsDate Objects +## ThreePartsDate Objects {#ALToolbox.ThreePartsDate.ThreePartsDate} ```python class ThreePartsDate(CustomDataType) ``` - - -#### validate(cls, item: str) +#### validate(cls, item: str) {#ALToolbox.ThreePartsDate.ThreePartsDate.validate} ```python @classmethod @@ -85,9 +79,7 @@ Validate a date string in MM/DD/YYYY format. - `DAValidationError` - If the date string is invalid or cannot be parsed. - - -#### transform(cls, item) +#### transform(cls, item) {#ALToolbox.ThreePartsDate.ThreePartsDate.transform} ```python @classmethod @@ -105,9 +97,7 @@ Transform a date string into a datetime object. datetime or None: The parsed datetime object, or None if empty. - - -#### default\_for(cls, item) +#### default\_for(cls, item) {#ALToolbox.ThreePartsDate.ThreePartsDate.default\_for} ```python @classmethod @@ -125,17 +115,13 @@ Convert a datetime object to MM/dd/yyyy format string. str or None: The formatted date string, or None if empty. - - -## BirthDate Objects +## BirthDate Objects {#ALToolbox.ThreePartsDate.BirthDate} ```python class BirthDate(ThreePartsDate) ``` - - -#### validate(cls, item: str) +#### validate(cls, item: str) {#ALToolbox.ThreePartsDate.BirthDate.validate} ```python @classmethod diff --git a/docs/components/ALToolbox/addenda.md b/docs/components/ALToolbox/addenda.md index 3b3971b4e..c4a7d05d9 100644 --- a/docs/components/ALToolbox/addenda.md +++ b/docs/components/ALToolbox/addenda.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.addenda](#ALToolbox.addenda) +* ALToolbox.addenda * [myTable](#ALToolbox.addenda.myTable) * [\_\_init\_\_](#ALToolbox.addenda.myTable.__init__) * [myTextList](#ALToolbox.addenda.myTextList) @@ -14,9 +14,7 @@ sidebar_label: addenda title: ALToolbox.addenda --- - - -## myTable Objects +## myTable Objects {#ALToolbox.addenda.myTable} ```python class myTable() @@ -28,9 +26,7 @@ This class processes DAList objects containing 'Individual' or 'T and converts them into structured table format suitable for document addenda. It handles data sanitization and formatting for display purposes. - - -#### \_\_init\_\_(tblData, tblTitle, tblHeader) +#### \_\_init\_\_(tblData, tblTitle, tblHeader) {#ALToolbox.addenda.myTable.\_\_init\_\_} ```python def __init__(tblData, tblTitle, tblHeader) @@ -44,9 +40,7 @@ Initialize a table from DAList data with title and headers. - `tblTitle` _str_ - The title for the table. - `tblHeader` - The column headers for the table. - - -## myTextList Objects +## myTextList Objects {#ALToolbox.addenda.myTextList} ```python class myTextList() @@ -58,9 +52,7 @@ This class handles text content that might be too long to fit in the main form by truncating it at a specified limit and storing the overflow text for use in addenda or continuation pages. - - -#### \_\_init\_\_(text, limit, title) +#### \_\_init\_\_(text, limit, title) {#ALToolbox.addenda.myTextList.\_\_init\_\_} ```python def __init__(text, limit, title) @@ -74,9 +66,7 @@ Initialize text processing with truncation limits. - `limit` _int_ - The character limit for the main form field. - `title` _str_ - The title or identifier for the text field. - - -#### g(text, limit, title) +#### g(text, limit, title) {#ALToolbox.addenda.myTextList.g} ```python def g(text, limit, title) -> None @@ -106,9 +96,7 @@ in an addendum section if truncation occurs. >>> text_handler = myTextList("Very long text...", 100, "Description") >>> # If text > 100 chars, text_cutoff will end with " (See Addendum.)" - - -#### safe\_json2(the\_object, level=0, is\_key=False) +#### safe\_json2(the\_object, level=0, is\_key=False) {#ALToolbox.addenda.safe\_json2} ```python def safe_json2(the_object, level=0, is_key=False) -> Any @@ -144,9 +132,7 @@ ISO strings. >>> safe_json2(obj) - `\{"date"` - "12/25/2023"\} - - -#### type\_name(the\_object) +#### type\_name(the\_object) {#ALToolbox.addenda.type\_name} ```python def type_name(the_object) -> str diff --git a/docs/components/ALToolbox/al_income.md b/docs/components/ALToolbox/al_income.md index fdcbc107a..bc574237a 100644 --- a/docs/components/ALToolbox/al_income.md +++ b/docs/components/ALToolbox/al_income.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.al\_income](#ALToolbox.al_income) +* ALToolbox.al\_income * [times\_per\_year](#ALToolbox.al_income.times_per_year) * [recent\_years](#ALToolbox.al_income.recent_years) * [ALPeriodicAmount](#ALToolbox.al_income.ALPeriodicAmount) @@ -73,9 +73,7 @@ sidebar_label: al_income title: ALToolbox.al_income --- - - -#### times\_per\_year(times\_per\_year\_list: List[Tuple[int, str]], times\_per\_year: float) +#### times\_per\_year(times\_per\_year\_list: List[Tuple[int, str]], times\_per\_year: float) {#ALToolbox.al\_income.times\_per\_year} ```python def times_per_year(times_per_year_list: List[Tuple[int, str]], @@ -124,9 +122,7 @@ the nearest whole integer. >>> times_per_year([(12, "Monthly")], 5) 'Five times per year' - - -#### recent\_years(past: int = 25, order: str = "descending", future: int = 1) +#### recent\_years(past: int = 25, order: str = "descending", future: int = 1) {#ALToolbox.al\_income.recent\_years} ```python def recent_years(past: int = 25, @@ -160,9 +156,7 @@ birthdate. >>> recent_years(past=2, order="ascending", future=0) [2022, 2023] - - -## ALPeriodicAmount Objects +## ALPeriodicAmount Objects {#ALToolbox.al\_income.ALPeriodicAmount} ```python class ALPeriodicAmount(DAObject) @@ -182,9 +176,7 @@ is 1 (a year). - `display_name` _str, optional_ - If present, will have a translated string to show the user, as opposed to a raw english string from the program. - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#ALToolbox.al\_income.ALPeriodicAmount.\_\_str\_\_} ```python def __str__() -> str @@ -196,9 +188,7 @@ Returns the income's total value as a string representation. The string representation of this income's total value. - - -#### total(times\_per\_year: float = 1) +#### total(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALPeriodicAmount.total} ```python def total(times_per_year: float = 1) -> Decimal @@ -227,9 +217,7 @@ To calculate `.total()`, an ALPeriodicAmount must have a `.times_per_year` and ` >>> income.total(12) # Monthly total Decimal('1000') - - -## ALIncome Objects +## ALIncome Objects {#ALToolbox.al\_income.ALIncome} ```python class ALIncome(ALPeriodicAmount) @@ -254,9 +242,7 @@ is 1 (a year). - `source` _str, optional_ - The "source" of the income, like a "job" or a "house". - `owner` _str, optional_ - Full name of the income's owner as a single string. - - -#### total(times\_per\_year: float = 1) +#### total(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALIncome.total} ```python def total(times_per_year: float = 1) -> Decimal @@ -282,9 +268,7 @@ It can also have `.is_hourly` and `.hours_per_period`. The calculated income amount for the specified frequency. - - -## ALExpense Objects +## ALExpense Objects {#ALToolbox.al\_income.ALExpense} ```python class ALExpense(ALPeriodicAmount) @@ -292,9 +276,7 @@ class ALExpense(ALPeriodicAmount) Not much changes from ALPeriodic Amount, just the generic object questions - - -## ALIncomeList Objects +## ALIncomeList Objects {#ALToolbox.al\_income.ALIncomeList} ```python class ALIncomeList(DAList) @@ -309,9 +291,7 @@ This list expects its items to have the following attributes and methods: - value: Amount value - total(): Calculate total amount for a given frequency - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#ALToolbox.al\_income.ALIncomeList.init} ```python def init(*pargs, **kwargs) -> None @@ -327,9 +307,7 @@ the list contains appropriate income objects for processing. - `*pargs` - Variable length argument list passed to parent class. - `**kwargs` - Arbitrary keyword arguments passed to parent class. - - -#### sources() +#### sources() {#ALToolbox.al\_income.ALIncomeList.sources} ```python def sources() -> Set[str] @@ -352,9 +330,7 @@ Returns a set of the unique sources in the ALIncomeList. >>> income_list.sources() \{'wages', 'tips'\} - - -#### matches(source: SourceType, exclude\_source: Optional[SourceType] = None) +#### matches(source: SourceType, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALIncomeList.matches} ```python def matches(source: SourceType, @@ -389,9 +365,7 @@ by their source. The source parameter may be a string or a list. >>> len(wages_only) 2 - - -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) {#ALToolbox.al\_income.ALIncomeList.total} ```python def total(times_per_year: float = 1, @@ -432,9 +406,7 @@ exclude deductions. >>> income_list.total(source="wages") # Annual wages only Decimal('60000.00') - - -#### move\_checks\_to\_list(selected\_types: Optional[DADict] = None, selected\_terms: Optional[Mapping] = None) +#### move\_checks\_to\_list(selected\_types: Optional[DADict] = None, selected\_terms: Optional[Mapping] = None) {#ALToolbox.al\_income.ALIncomeList.move\_checks\_to\_list} ```python def move_checks_to_list(selected_types: Optional[DADict] = None, @@ -455,9 +427,7 @@ work well. - `selected_types` _Optional[DADict]_ - A dictionary of selected types. - `selected_terms` _Optional[Mapping]_ - A mapping of selected terms. - - -## ALJob Objects +## ALJob Objects {#ALToolbox.al\_income.ALJob} ```python class ALJob(ALIncome) @@ -488,9 +458,7 @@ Can be stored in an ALJobList. - `employer` _Individual, optional_ - A docassemble Individual object, employer.address is the address and employer.phone is the phone. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#ALToolbox.al\_income.ALJob.init} ```python def init(*pargs, **kwargs) @@ -501,9 +469,7 @@ Initialize an ALJob object with employer setup. Initializes the employer attribute based on the employer_type if available, defaulting to Individual type if no specific type is set. - - -#### gross\_total(times\_per\_year: float = 1) +#### gross\_total(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALJob.gross\_total} ```python def gross_total(times_per_year: float = 1) -> Decimal @@ -525,9 +491,7 @@ representing the `.value` attribute of the item. The calculated gross income amount for the specified frequency. - - -#### deductions(times\_per\_year: float = 1) +#### deductions(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALJob.deductions} ```python def deductions(times_per_year: float = 1) -> Decimal @@ -549,9 +513,7 @@ Returns the total deductions from someone's pay over the specified times_pe The calculated deduction amount for the specified frequency. - - -#### net\_total(times\_per\_year: float = 1) +#### net\_total(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALJob.net\_total} ```python def net_total(times_per_year: float = 1) -> Decimal @@ -580,9 +542,7 @@ Returns the net income over a time period, found using per hour if hourly). This will force the gathering of the ALJob's `.value` and `.deduction` attributes. - - -#### employer\_name\_address\_phone() +#### employer\_name\_address\_phone() {#ALToolbox.al\_income.ALJob.employer\_name\_address\_phone} ```python def employer_name_address_phone() -> str @@ -599,9 +559,7 @@ attributes. A formatted string containing employer name, optionally with address and/or phone number if available. - - -#### normalized\_hours(times\_per\_year: float = 1) +#### normalized\_hours(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALJob.normalized\_hours} ```python def normalized_hours(times_per_year: float = 1) -> float @@ -635,9 +593,7 @@ based on the self.hours_per_period and self.times_per_year attributes. This will force the gathering of the attributes `.hours_per_period` and `.times_per_year`. - - -## ALJobList Objects +## ALJobList Objects {#ALToolbox.al\_income.ALJobList} ```python class ALJobList(ALIncomeList) @@ -647,9 +603,7 @@ Represents a list of ALJobs. Adds the `.gross_total()` and `.net_total()` methods to the ALIncomeList class. It's a more common way of reporting income than ALItemizedJobList. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#ALToolbox.al\_income.ALJobList.init} ```python def init(*pargs, **kwargs) @@ -662,9 +616,7 @@ Initialize an ALJobList with ALJob as the default object type. - `*pargs` - Variable length argument list passed to parent class. - `**kwargs` - Arbitrary keyword arguments passed to parent class. - - -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) {#ALToolbox.al\_income.ALJobList.total} ```python def total(times_per_year: float = 1, @@ -680,9 +632,7 @@ string or a list. `times_per_year` is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year). - - -#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALJobList.gross\_total} ```python def gross_total(times_per_year: float = 1, @@ -705,9 +655,7 @@ string or a list. The sum of the gross incomes of its ALJobs divided by the time times_per_year. - - -#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALJobList.net\_total} ```python def net_total(times_per_year: float = 1, @@ -733,9 +681,7 @@ If the job is hourly, the `net_total()` may not be comparable to the The sum of the net incomes of its ALJobs divided by the time times_per_year. - - -#### deductions(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### deductions(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALJobList.deductions} ```python def deductions(times_per_year: float = 1, @@ -758,9 +704,7 @@ will use all sources. The sum of the deductions of its ALJobs divided by the time times_per_year. - - -## ALExpenseList Objects +## ALExpenseList Objects {#ALToolbox.al\_income.ALExpenseList} ```python class ALExpenseList(ALIncomeList) @@ -773,9 +717,7 @@ value: The monetary value of the expense source: The source category of the expense display_name: Human-readable name for display - - -## ALAsset Objects +## ALAsset Objects {#ALToolbox.al\_income.ALAsset} ```python class ALAsset(ALIncome) @@ -802,9 +744,7 @@ Can be stored in an ALAssetList. - `owner` _str, optional_ - Full name of the asset owner as a single string. - `source` _str, optional_ - The "source" of the asset, like "vase". - - -#### total(times\_per\_year: float = 1) +#### total(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALAsset.total} ```python def total(times_per_year: float = 1) -> Decimal @@ -823,9 +763,7 @@ Returns the .value attribute divided by the times per year you want to calculate - `Decimal` - The .value attribute divided by the times per year. - - -#### equity(loan\_attribute="balance") +#### equity(loan\_attribute="balance") {#ALToolbox.al\_income.ALAsset.equity} ```python def equity(loan_attribute="balance") -> Decimal @@ -842,9 +780,7 @@ Returns the total equity in the asset (e.g., market value minus balance). - `Decimal` - The total equity in the asset. - - -## ALAssetList Objects +## ALAssetList Objects {#ALToolbox.al\_income.ALAssetList} ```python class ALAssetList(ALIncomeList) @@ -869,9 +805,7 @@ total value of all assets, use the `market_value()` method. - `owner` _str, optional_ - Full name of the asset owner as a single string. - `source` _str, optional_ - The "source" of the asset, like "vase". - - -#### market\_value(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### market\_value(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALAssetList.market\_value} ```python def market_value(source: Optional[SourceType] = None, @@ -894,9 +828,7 @@ You can filter the assets by `source`. `source` can be a string or a list. - `Decimal` - The total market value of the assets. - - -#### balance(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### balance(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALAssetList.balance} ```python def balance(source: Optional[SourceType] = None, @@ -919,9 +851,7 @@ You can filter the assets by `source`. `source` can be a string or a list. - `Decimal` - The total balance of the assets. - - -#### equity(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, loan\_attribute: str = "balance") +#### equity(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, loan\_attribute: str = "balance") {#ALToolbox.al\_income.ALAssetList.equity} ```python def equity(source: Optional[SourceType] = None, @@ -945,9 +875,7 @@ specified, or if the asset's source satisfies the source criteria, the equi - `Decimal` - The total equity in the assets. - - -#### owners(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### owners(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALAssetList.owners} ```python def owners(source: Optional[SourceType] = None, @@ -970,9 +898,7 @@ You can filter the assets by `source`. `source` can be a string or a list. - `Set[str]` - A set of the unique owners of the assets. - - -## ALVehicle Objects +## ALVehicle Objects {#ALToolbox.al\_income.ALVehicle} ```python class ALVehicle(ALAsset) @@ -997,9 +923,7 @@ statement forms. - `owner` _str_ - Full name of the vehicle owner. - `source` _str, optional_ - The source of the asset, defaults to 'vehicle'. - - -#### year\_make\_model(separator: str = " / ") +#### year\_make\_model(separator: str = " / ") {#ALToolbox.al\_income.ALVehicle.year\_make\_model} ```python def year_make_model(separator: str = " / ") -> str @@ -1028,9 +952,7 @@ Triggers gathering those attributes and formats them as a single string. >>> vehicle.year_make_model(separator=", ") '2020, Toyota, Camry' - - -## ALVehicleList Objects +## ALVehicleList Objects {#ALToolbox.al\_income.ALVehicleList} ```python class ALVehicleList(ALAssetList) @@ -1038,9 +960,7 @@ class ALVehicleList(ALAssetList) List of ALVehicles. Extends ALAssetList. - - -## ALSimpleValue Objects +## ALSimpleValue Objects {#ALToolbox.al\_income.ALSimpleValue} ```python class ALSimpleValue(DAObject) @@ -1056,9 +976,7 @@ item in an ALSimpleValueList. negative value to the total of the item. - `source` _str, optional_ - The "source" of the item, like "vase". - - -#### total() +#### total() {#ALToolbox.al\_income.ALSimpleValue.total} ```python def total() -> Decimal @@ -1075,9 +993,7 @@ object. The `total()` method may return unexpected results in that case. The total value of the item, taking into account the transaction type. - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#ALToolbox.al\_income.ALSimpleValue.\_\_str\_\_} ```python def __str__() -> str @@ -1085,9 +1001,7 @@ def __str__() -> str Returns the total as a formatted string - - -## ALSimpleValueList Objects +## ALSimpleValueList Objects {#ALToolbox.al\_income.ALSimpleValueList} ```python class ALSimpleValueList(DAList) @@ -1095,9 +1009,7 @@ class ALSimpleValueList(DAList) Represents a filterable DAList of ALSimpleValues. - - -#### sources() +#### sources() {#ALToolbox.al\_income.ALSimpleValueList.sources} ```python def sources() -> Set @@ -1109,9 +1021,7 @@ Returns a set of the unique sources of values stored in the list. A set of the unique sources of values stored in the list. - - -#### total(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### total(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALSimpleValueList.total} ```python def total(source: Optional[SourceType] = None, @@ -1132,9 +1042,7 @@ string or a list. The total value in the list. - - -## ALItemizedValue Objects +## ALItemizedValue Objects {#ALToolbox.al\_income.ALItemizedValue} ```python class ALItemizedValue(DAObject) @@ -1165,9 +1073,7 @@ job's net total. If the ".exists" attribute is False or undefined, the item will not be used when calculating totals. - - -#### income\_fields(use\_exists=True) +#### income\_fields(use\_exists=True) {#ALToolbox.al\_income.ALItemizedValue.income\_fields} ```python def income_fields(use_exists=True) -> List[Dict[str, Any]] @@ -1185,9 +1091,7 @@ to be passed to a `code` attribute of a question's fields A list of dictionaries representing the fields for an itemized value. - - -#### total() +#### total() {#ALToolbox.al\_income.ALItemizedValue.total} ```python def total() -> Decimal @@ -1213,9 +1117,7 @@ returns 0. Otherwise returns the decimal value of the item. >>> item_disabled.total() Decimal('0') - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#ALToolbox.al\_income.ALItemizedValue.\_\_str\_\_} ```python def __str__() -> str @@ -1223,9 +1125,7 @@ def __str__() -> str Returns a string of the value of the item with two decimal places. - - -## ALItemizedValueDict Objects +## ALItemizedValueDict Objects {#ALToolbox.al\_income.ALItemizedValueDict} ```python class ALItemizedValueDict(DAOrderedDict) @@ -1242,9 +1142,7 @@ and one for deductions. Should only be accessed through an ALItemizedJob. Otherwise you may get unexpected results. - - -#### hook\_after\_gather() +#### hook\_after\_gather() {#ALToolbox.al\_income.ALItemizedValueDict.hook\_after\_gather} ```python def hook_after_gather() -> None @@ -1258,9 +1156,7 @@ See https://docassemble.org/docs/objects.html#DAList.hook_after_gather. If a developer wants to remove these items _before_ gathering is finished, they can use similar code in their question's `validation code:` - - -#### total() +#### total() {#ALToolbox.al\_income.ALItemizedValueDict.total} ```python def total() -> Decimal @@ -1284,9 +1180,7 @@ as not existing (exists=False). >>> value_dict.total() Decimal('1000') # Only includes wages, not bonus - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#ALToolbox.al\_income.ALItemizedValueDict.\_\_str\_\_} ```python def __str__() -> str @@ -1295,9 +1189,7 @@ def __str__() -> str Returns a string of the dictionary's key/value pairs as two-element lists in a list. E.g. '[["federal_taxes", "2500.00"], ["wages", "15.50"]]' - - -## ALItemizedJob Objects +## ALItemizedJob Objects {#ALToolbox.al\_income.ALItemizedJob} ```python class ALItemizedJob(DAObject) @@ -1359,9 +1251,7 @@ income in code. and the total of money going in and money coming out. - A user must be able to add their own arbitrary items. - - -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJob.total} ```python def total(times_per_year: float = 1, @@ -1382,9 +1272,7 @@ Alias for ALItemizedJob.gross_total to integrate with ALIncomeList math. The gross total of the job. - - -#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJob.gross\_total} ```python def gross_total(times_per_year: float = 1, @@ -1410,9 +1298,7 @@ If you use sources from deductions, they will be ignored. - `Decimal` - The sum of positive values for the given parameters. - - -#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJob.deduction\_total} ```python def deduction_total(times_per_year: float = 1, @@ -1438,9 +1324,7 @@ filter the items by `source`. `source` can be a string or a list. - `Decimal` - The sum of deductions for the given parameters as a positive value. - - -#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJob.net\_total} ```python def net_total(times_per_year: float = 1, @@ -1466,9 +1350,7 @@ string or a list. E.g. "full time" or ["full time", "un - `Decimal` - The net value (gross minus deductions) for the given parameters. - - -#### employer\_name\_address\_phone() +#### employer\_name\_address\_phone() {#ALToolbox.al\_income.ALItemizedJob.employer\_name\_address\_phone} ```python def employer_name_address_phone() -> str @@ -1481,9 +1363,7 @@ address and phone number. A string containing the employer's name, address, and phone number. - - -#### normalized\_hours(times\_per\_year: float = 1) +#### normalized\_hours(times\_per\_year: float = 1) {#ALToolbox.al\_income.ALItemizedJob.normalized\_hours} ```python def normalized_hours(times_per_year: float = 1) -> float @@ -1504,9 +1384,7 @@ For example, if the person works 10 hours a week, it will return The normalized number of hours worked in the given time period. - - -## ALItemizedJobList Objects +## ALItemizedJobList Objects {#ALToolbox.al\_income.ALItemizedJobList} ```python class ALItemizedJobList(DAList) @@ -1515,9 +1393,7 @@ class ALItemizedJobList(DAList) Represents a list of ALItemizedJobs that can have both payments and money out. This is a less common way of reporting income. - - -#### sources(which\_side: Optional[str] = None) +#### sources(which\_side: Optional[str] = None) {#ALToolbox.al\_income.ALItemizedJobList.sources} ```python def sources(which_side: Optional[str] = None) -> Set[str] @@ -1535,9 +1411,7 @@ By default gets from both sides, if which_side is "deductions", only g A set of the unique sources in all of the jobs. - - -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJobList.total} ```python def total(times_per_year: float = 1, @@ -1559,9 +1433,7 @@ ALIncomeList math. The gross total of the list. - - -#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJobList.gross\_total} ```python def gross_total(times_per_year: float = 1, @@ -1588,9 +1460,7 @@ string or a list. - `Decimal` - The sum of the gross incomes for the given parameters. - - -#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJobList.deduction\_total} ```python def deduction_total(times_per_year: float = 1, @@ -1617,9 +1487,7 @@ string or a list. - `Decimal` - The sum of the deductions for the given parameters. - - -#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) {#ALToolbox.al\_income.ALItemizedJobList.net\_total} ```python def net_total(times_per_year: float = 1, diff --git a/docs/components/ALToolbox/altoolbox_overview.md b/docs/components/ALToolbox/altoolbox_overview.md index a9b6e8990..16add7d38 100644 --- a/docs/components/ALToolbox/altoolbox_overview.md +++ b/docs/components/ALToolbox/altoolbox_overview.md @@ -71,7 +71,7 @@ content: | Context-specific help goes here. ``` -[API for `collapse_template`](misc#collapse_template), and [Code for `collapse_template`](https://github.com/SuffolkLITLab/docassemble-ALToolbox/blob/main/docassemble/ALToolbox/misc.py) +[API for `collapse_template`](misc#ALToolbox.misc.collapse_template), and [Code for `collapse_template`](https://github.com/SuffolkLITLab/docassemble-ALToolbox/blob/main/docassemble/ALToolbox/misc.py) ## Display markdown template with a scroll bar diff --git a/docs/components/ALToolbox/business_days.md b/docs/components/ALToolbox/business_days.md index f82be3a6d..fe97777f2 100644 --- a/docs/components/ALToolbox/business_days.md +++ b/docs/components/ALToolbox/business_days.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.business\_days](#ALToolbox.business_days) +* ALToolbox.business\_days * [standard\_holidays](#ALToolbox.business_days.standard_holidays) * [non\_business\_days](#ALToolbox.business_days.non_business_days) * [is\_business\_day](#ALToolbox.business_days.is_business_day) @@ -12,9 +12,7 @@ sidebar_label: business_days title: ALToolbox.business_days --- - - -#### standard\_holidays(year, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) +#### standard\_holidays(year, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) {#ALToolbox.business\_days.standard\_holidays} ```python def standard_holidays( @@ -77,9 +75,7 @@ holidays observed by a local court, but should be very close to accurate. ) ``` - - -#### non\_business\_days(year, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None, first\_n\_dates=0, last\_n\_dates=0) +#### non\_business\_days(year, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None, first\_n\_dates=0, last\_n\_dates=0) {#ALToolbox.business\_days.non\_business\_days} ```python def non_business_days(year, @@ -132,9 +128,7 @@ both weekends (Saturdays and Sundays) and official holidays. ) ``` - - -#### is\_business\_day(date: Union[str, DADateTime], country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) +#### is\_business\_day(date: Union[str, DADateTime], country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) {#ALToolbox.business\_days.is\_business\_day} ```python def is_business_day(date: Union[str, DADateTime], @@ -186,9 +180,7 @@ in the specified jurisdiction. Business days are considered to be: is_business_uk = is_business_day("2023-12-26", country="UK") # Boxing Day ``` - - -#### get\_next\_business\_day(start\_date: Union[str, DADateTime], wait\_n\_days=1, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) +#### get\_next\_business\_day(start\_date: Union[str, DADateTime], wait\_n\_days=1, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) {#ALToolbox.business\_days.get\_next\_business\_day} ```python def get_next_business_day( @@ -252,9 +244,7 @@ https://github.com/dr-prodigy/python-holidays/tree/master/holidays/countries # Will skip March 17th as it's now considered a holiday ``` - - -#### get\_date\_after\_n\_business\_days(start\_date: Union[str, DADateTime], wait\_n\_days=1, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) +#### get\_date\_after\_n\_business\_days(start\_date: Union[str, DADateTime], wait\_n\_days=1, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) {#ALToolbox.business\_days.get\_date\_after\_n\_business\_days} ```python def get_date_after_n_business_days( diff --git a/docs/components/ALToolbox/copy_button.md b/docs/components/ALToolbox/copy_button.md index eddfa8a32..6d518f0d6 100644 --- a/docs/components/ALToolbox/copy_button.md +++ b/docs/components/ALToolbox/copy_button.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.copy\_button](#ALToolbox.copy_button) +* ALToolbox.copy\_button * [copy\_button\_html](#ALToolbox.copy_button.copy_button_html) --- @@ -8,9 +8,7 @@ sidebar_label: copy_button title: ALToolbox.copy_button --- - - -#### copy\_button\_html(text\_to\_copy: str, text\_before: str = "", label: str = "Copy", tooltip\_inert\_text: str = "Copy to clipboard", tooltip\_copied\_text: str = "Copied!", copy\_template\_block: bool = False, scroll\_class: str = "", style\_class: str = "", adjust\_height: str = "") +#### copy\_button\_html(text\_to\_copy: str, text\_before: str = "", label: str = "Copy", tooltip\_inert\_text: str = "Copy to clipboard", tooltip\_copied\_text: str = "Copied!", copy\_template\_block: bool = False, scroll\_class: str = "", style\_class: str = "", adjust\_height: str = "") {#ALToolbox.copy\_button.copy\_button\_html} ```python def copy_button_html(text_to_copy: str, diff --git a/docs/components/ALToolbox/display_template.md b/docs/components/ALToolbox/display_template.md index c79cdfe02..e2f1cfcf5 100644 --- a/docs/components/ALToolbox/display_template.md +++ b/docs/components/ALToolbox/display_template.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.display\_template](#ALToolbox.display_template) +* ALToolbox.display\_template * [display\_template](#ALToolbox.display_template.display_template) --- @@ -8,9 +8,7 @@ sidebar_label: display_template title: ALToolbox.display_template --- - - -#### display\_template(template, scrollable=True, collapse=False, copy=False, classname="bg-light", class\_name=None) +#### display\_template(template, scrollable=True, collapse=False, copy=False, classname="bg-light", class\_name=None) {#ALToolbox.display\_template.display\_template} ```python def display_template(template, diff --git a/docs/components/ALToolbox/llms.md b/docs/components/ALToolbox/llms.md index c0aad096b..243f14636 100644 --- a/docs/components/ALToolbox/llms.md +++ b/docs/components/ALToolbox/llms.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.llms](#ALToolbox.llms) +* ALToolbox.llms * [chat\_completion](#ALToolbox.llms.chat_completion) * [extract\_fields\_from\_text](#ALToolbox.llms.extract_fields_from_text) * [match\_goals\_from\_text](#ALToolbox.llms.match_goals_from_text) @@ -32,9 +32,7 @@ sidebar_label: llms title: ALToolbox.llms --- - - -#### chat\_completion(system\_message: Optional[str] = None, user\_message: Optional[str] = None, openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0.5, json\_mode=False, model: str = "gpt-4o", messages: Optional[List[Dict[str, str]]] = None, skip\_moderation: bool = True, openai\_base\_url: Optional[str] = None, max\_output\_tokens: Optional[int] = None, max\_input\_tokens: Optional[int] = None) +#### chat\_completion(system\_message: Optional[str] = None, user\_message: Optional[str] = None, openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0.5, json\_mode=False, model: str = "gpt-4o", messages: Optional[List[Dict[str, str]]] = None, skip\_moderation: bool = True, openai\_base\_url: Optional[str] = None, max\_output\_tokens: Optional[int] = None, max\_input\_tokens: Optional[int] = None) {#ALToolbox.llms.chat\_completion} ```python def chat_completion( @@ -77,9 +75,7 @@ Includes support for token limits, minimal error handling, and moderation. A string with the response from the API endpoint or JSON data if json_mode is True - - -#### extract\_fields\_from\_text(text: str, field\_list: Dict[str, str], openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model="gpt-4o-mini") +#### extract\_fields\_from\_text(text: str, field\_list: Dict[str, str], openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model="gpt-4o-mini") {#ALToolbox.llms.extract\_fields\_from\_text} ```python def extract_fields_from_text(text: str, @@ -106,9 +102,7 @@ Extracts fields from text. A dictionary of fields extracted from the text - - -#### match\_goals\_from\_text(question: str, user\_response: str, goals: Dict[str, str], openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model="gpt-4o-mini") +#### match\_goals\_from\_text(question: str, user\_response: str, goals: Dict[str, str], openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model="gpt-4o-mini") {#ALToolbox.llms.match\_goals\_from\_text} ```python def match_goals_from_text(question: str, @@ -137,9 +131,7 @@ Reads a user's message and determines whether it meets a set of goals, with A dictionary of fields extracted from the text - - -#### classify\_text(text: str, choices: Dict[str, str], default\_response: str = "null", openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model="gpt-4o-mini") +#### classify\_text(text: str, choices: Dict[str, str], default\_response: str = "null", openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model="gpt-4o-mini") {#ALToolbox.llms.classify\_text} ```python def classify_text(text: str, @@ -168,9 +160,7 @@ Given a text, classify it into one of the provided choices with the assistance o The classification of the text. - - -#### synthesize\_user\_responses(messages: List[Dict[str, str]], custom\_instructions: Optional[str] = "", openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model: str = "gpt-4o-mini") +#### synthesize\_user\_responses(messages: List[Dict[str, str]], custom\_instructions: Optional[str] = "", openai\_client: Optional[OpenAI] = None, openai\_api: Optional[str] = None, temperature: float = 0, model: str = "gpt-4o-mini") {#ALToolbox.llms.synthesize\_user\_responses} ```python def synthesize_user_responses(messages: List[Dict[str, str]], @@ -198,9 +188,7 @@ into a single, coherent reply. A synthesized response from the user. - - -#### define\_fields\_from\_dict(field\_dict: Dict[str, Any], fields\_to\_ignore: Optional[List] = None) +#### define\_fields\_from\_dict(field\_dict: Dict[str, Any], fields\_to\_ignore: Optional[List] = None) {#ALToolbox.llms.define\_fields\_from\_dict} ```python def define_fields_from_dict(field_dict: Dict[str, Any], @@ -221,9 +209,7 @@ fields_to_ignore is provided, those fields will also be ignored. None. Should be used to ensure safety when defining fields from untrusted sources. E.g., ["user_is_logged_in"] - - -## Goal Objects +## Goal Objects {#ALToolbox.llms.Goal} ```python class Goal(DAObject) @@ -237,9 +223,7 @@ A class to represent a goal. - `description` _str_ - A description of the goal - `satisfied` _bool_ - Whether the goal is satisfied - - -#### response\_satisfies\_me\_or\_follow\_up(messages: List[Dict[str, str]], openai\_client: Optional[OpenAI] = None, model="gpt-4o-mini", system\_message: Optional[str] = None, llm\_assumed\_role: Optional[str] = "teacher", user\_assumed\_role: Optional[str] = "student") +#### response\_satisfies\_me\_or\_follow\_up(messages: List[Dict[str, str]], openai\_client: Optional[OpenAI] = None, model="gpt-4o-mini", system\_message: Optional[str] = None, llm\_assumed\_role: Optional[str] = "teacher", user\_assumed\_role: Optional[str] = "student") {#ALToolbox.llms.Goal.response\_satisfies\_me\_or\_follow\_up} ```python def response_satisfies_me_or_follow_up( @@ -268,9 +252,7 @@ if the user's response satisfies the goal. The text of the next question to ask the user or the string "satisfied" - - -#### get\_next\_question(thread\_so\_far: List[Dict[str, str]], openai\_client: Optional[OpenAI] = None, model="gpt-4o-mini") +#### get\_next\_question(thread\_so\_far: List[Dict[str, str]], openai\_client: Optional[OpenAI] = None, model="gpt-4o-mini") {#ALToolbox.llms.Goal.get\_next\_question} ```python def get_next_question(thread_so_far: List[Dict[str, str]], @@ -291,9 +273,7 @@ Returns the text of the next question to ask the user. The text of the next question to ask the user. - - -## GoalDict Objects +## GoalDict Objects {#ALToolbox.llms.GoalDict} ```python class GoalDict(DADict) @@ -301,9 +281,7 @@ class GoalDict(DADict) A class to represent a DADict of Goals. - - -#### satisfied() +#### satisfied() {#ALToolbox.llms.GoalDict.satisfied} ```python def satisfied() -> bool @@ -315,9 +293,7 @@ Returns True if all goals are satisfied, False otherwise. True if all goals are satisfied, False otherwise. - - -## GoalQuestion Objects +## GoalQuestion Objects {#ALToolbox.llms.GoalQuestion} ```python class GoalQuestion(DAObject) @@ -331,9 +307,7 @@ A class to represent a question about a goal. - `question` _str_ - The question to ask the user - `response` _str_ - The user's response to the question - - -#### complete() +#### complete() {#ALToolbox.llms.GoalQuestion.complete} ```python @property @@ -342,9 +316,7 @@ def complete() Returns True if the goal, question, and response attributes are present. - - -## GoalSatisfactionList Objects +## GoalSatisfactionList Objects {#ALToolbox.llms.GoalSatisfactionList} ```python class GoalSatisfactionList(DAList) @@ -379,9 +351,7 @@ open ai: - `initial_draft` _str_ - The initial draft of the user's response - `initial_question` _str_ - The original question posed in the interview - - -#### mark\_satisfied\_goals() +#### mark\_satisfied\_goals() {#ALToolbox.llms.GoalSatisfactionList.mark\_satisfied\_goals} ```python def mark_satisfied_goals() -> None @@ -390,9 +360,7 @@ def mark_satisfied_goals() -> None Marks goals as satisfied if the user's response satisfies the goal. This should be used as soon as the user gives their initial reply. - - -#### keep\_going() +#### keep\_going() {#ALToolbox.llms.GoalSatisfactionList.keep\_going} ```python def keep_going() -> bool @@ -404,9 +372,7 @@ Returns True if there is at least one unsatisfied goal and if the number of foll True if there is at least one unsatisfied goal and if the number of follow-up questions asked is less than the question limit, False otherwise. - - -#### need\_more\_questions() +#### need\_more\_questions() {#ALToolbox.llms.GoalSatisfactionList.need\_more\_questions} ```python def need_more_questions() -> bool @@ -421,9 +387,7 @@ and updating the next question to be asked. True if there is at least one unsatisfied goal, False otherwise. - - -#### satisfied() +#### satisfied() {#ALToolbox.llms.GoalSatisfactionList.satisfied} ```python def satisfied() -> bool @@ -435,9 +399,7 @@ Returns True if all goals are satisfied, False otherwise. True if all goals are satisfied, False otherwise. - - -#### get\_next\_goal\_and\_question() +#### get\_next\_goal\_and\_question() {#ALToolbox.llms.GoalSatisfactionList.get\_next\_goal\_and\_question} ```python def get_next_goal_and_question() -> tuple @@ -450,9 +412,7 @@ Returns the next unsatisfied goal, along with a follow-up question to ask the us A tuple of (Goal, str) where the first item is the next unsatisfied goal and the second item is the next question to ask the user, if relevant. If the user's response to the last question satisfied the goal, returns (None, None). - - -#### synthesize\_draft\_response() +#### synthesize\_draft\_response() {#ALToolbox.llms.GoalSatisfactionList.synthesize\_draft\_response} ```python def synthesize_draft_response() -> str @@ -464,9 +424,7 @@ Returns a draft response that synthesizes the user's responses to the quest A draft response that synthesizes the user's responses to the questions. - - -#### provide\_feedback(feedback\_prompt: str = "") +#### provide\_feedback(feedback\_prompt: str = "") {#ALToolbox.llms.GoalSatisfactionList.provide\_feedback} ```python def provide_feedback( @@ -484,9 +442,7 @@ Returns feedback to the user based on the goals they satisfied. Feedback to the user based on the goals they satisfied. - - -## IntakeQuestion Objects +## IntakeQuestion Objects {#ALToolbox.llms.IntakeQuestion} ```python class IntakeQuestion(DAObject) @@ -499,9 +455,7 @@ A class to represent a question in an LLM-assisted intake questionnaire. - `question` _str_ - The question to ask the user - `response` _str_ - The user's response to the question - - -#### complete() +#### complete() {#ALToolbox.llms.IntakeQuestion.complete} ```python @property @@ -510,9 +464,7 @@ def complete() Returns True if the question and response attributes are present. - - -## IntakeQuestionList Objects +## IntakeQuestionList Objects {#ALToolbox.llms.IntakeQuestionList} ```python class IntakeQuestionList(DAList) @@ -544,9 +496,7 @@ embeddings at the moment. - `out_of_questions` _bool_ - Whether the user has run out of questions to answer - `qualifies` _bool_ - Whether the user qualifies based on the criteria - - -#### need\_more\_questions() +#### need\_more\_questions() {#ALToolbox.llms.IntakeQuestionList.need\_more\_questions} ```python def need_more_questions() -> bool diff --git a/docs/components/ALToolbox/misc.md b/docs/components/ALToolbox/misc.md index 96de280b3..d2267d946 100644 --- a/docs/components/ALToolbox/misc.md +++ b/docs/components/ALToolbox/misc.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.misc](#ALToolbox.misc) +* ALToolbox.misc * [thousands](#ALToolbox.misc.thousands) * [tel](#ALToolbox.misc.tel) * [fa\_icon](#ALToolbox.misc.fa_icon) @@ -28,9 +28,7 @@ sidebar_label: misc title: ALToolbox.misc --- - - -#### thousands(num: Union[float, str, Decimal], show\_decimals=False) +#### thousands(num: Union[float, str, Decimal], show\_decimals=False) {#ALToolbox.misc.thousands} ```python def thousands(num: Union[float, str, Decimal], show_decimals=False) -> str @@ -63,9 +61,7 @@ closest int. >>> thousands(1234.56, show_decimals=True) '1,234.56' - - -#### tel(phone\_number) +#### tel(phone\_number) {#ALToolbox.misc.tel} ```python def tel(phone_number) -> str @@ -91,9 +87,7 @@ and dial the number on mobile devices or applications that support tel links. >>> tel("555-123-4567") '<a href="tel:555-123-4567">555-123-4567</a>' - - -#### 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) +#### 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) {#ALToolbox.misc.fa\_icon} ```python def fa_icon(icon: str, @@ -129,9 +123,7 @@ you more control over the icon that is inserted. HTML for a font-awesome icon of the specified size and color. - - -#### space(var\_name: str, prefix=" ", suffix="") +#### space(var\_name: str, prefix=" ", suffix="") {#ALToolbox.misc.space} ```python def space(var_name: str, prefix=" ", suffix="") -> str @@ -163,9 +155,7 @@ if the variable name is valid and the variable is defined and has a value. >>> space("undefined_var") "" # if variable is not defined - - -#### yes\_no\_unknown(var\_name: str, condition: Optional[bool], unknown="Unknown", placeholder=0) +#### yes\_no\_unknown(var\_name: str, condition: Optional[bool], unknown="Unknown", placeholder=0) {#ALToolbox.misc.yes\_no\_unknown} ```python def yes_no_unknown(var_name: str, @@ -204,9 +194,7 @@ False (explicitly no) and None (unknown/not answered). >>> yes_no_unknown("user_answer", False, "Unknown", 0) 0 - - -#### number\_to\_letter(n: Optional[int]) +#### number\_to\_letter(n: Optional[int]) {#ALToolbox.misc.number\_to\_letter} ```python def number_to_letter(n: Optional[int]) -> str @@ -236,9 +224,7 @@ with Excel/Google Sheets column naming conventions. 27=AA, 28=AB... >>> number_to_letter(27) 'AA' - - -#### collapse\_template(template: DALazyTemplate, classname: str | None = None, closed\_icon: str = "caret-right", open\_icon: str = "caret-down", collapsed: bool = True) +#### collapse\_template(template: DALazyTemplate, classname: str | None = None, closed\_icon: str = "caret-right", open\_icon: str = "caret-down", collapsed: bool = True) {#ALToolbox.misc.collapse\_template} ```python def collapse_template(template: DALazyTemplate, @@ -280,9 +266,7 @@ The default icons are "right caret" which displays when the text is co >>> collapse_template(my_template, classname="bg-primary", collapsed=False) '<div id="..." class="al_collapse_template">...</div>' - - -#### tabbed\_templates\_html(tab\_group\_name: str, \*pargs) +#### tabbed\_templates\_html(tab\_group\_name: str, \*pargs) {#ALToolbox.misc.tabbed\_templates\_html} ```python def tabbed_templates_html(tab_group_name: str, *pargs) -> str @@ -312,9 +296,7 @@ subject becomes the tab label and the content becomes the tab panel content. >>> tabbed_templates_html("my_tabs", template1, template2, template3) '<ul class="nav nav-tabs" id="my_tabs">...</ul><div class="tab-content">...</div>' - - -#### 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!") +#### 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!") {#ALToolbox.misc.review\_widget} ```python def review_widget( @@ -353,9 +335,7 @@ a submit button appears, and once the text review is submitted (or after the thu the HTML string of the widget - - -#### sum\_if\_defined(\*pargs) +#### sum\_if\_defined(\*pargs) {#ALToolbox.misc.sum\_if\_defined} ```python def sum_if_defined(*pargs) -> Union[int, float, Decimal] @@ -382,9 +362,7 @@ that are defined. Undefined variables are skipped rather than causing errors. >>> sum_if_defined("income1", "income2", "income3") # Returns sum of defined income variables, skipping any undefined ones - - -#### add\_records(obj, labels) +#### add\_records(obj, labels) {#ALToolbox.misc.add\_records} ```python def add_records(obj, labels) -> Any @@ -413,9 +391,7 @@ including name, description, and reference for creating a demo landing page. >>> add_records(my_list, interviews) # my_list[0].name = "intake", description = "Intake Interview", etc. - - -#### output\_checkbox(value\_to\_check: bool, checked\_value: str = "[X]", unchecked\_value: str = "[ ]") +#### output\_checkbox(value\_to\_check: bool, checked\_value: str = "[X]", unchecked\_value: str = "[ ]") {#ALToolbox.misc.output\_checkbox} ```python def output_checkbox(value_to_check: bool, @@ -450,9 +426,7 @@ useful for creating checkboxes in document templates. >>> output_checkbox(False, checked_value="YES", unchecked_value="NO") 'NO' - - -#### nice\_county\_name(address: Address) +#### nice\_county\_name(address: Address) {#ALToolbox.misc.nice\_county\_name} ```python def nice_county_name(address: Address) -> str @@ -481,9 +455,7 @@ Autocomplete does by default, remove it to get a cleaner display name. >>> nice_county_name(address_without_county) '' - - -#### button\_array(buttons: List[ButtonDict], custom\_container\_class="", custom\_link\_class="") +#### button\_array(buttons: List[ButtonDict], custom\_container\_class="", custom\_link\_class="") {#ALToolbox.misc.button\_array} ```python def button_array(buttons: List[ButtonDict], @@ -519,9 +491,7 @@ of privileges. - `str` - HTML for a grid of buttons that mimics docassemble's button field type. - - -#### none\_to\_empty(val: Any) +#### none\_to\_empty(val: Any) {#ALToolbox.misc.none\_to\_empty} ```python def none_to_empty(val: Any) -> Any @@ -543,9 +513,7 @@ without raising an error. a DAEmpty if the value is None, otherwise the value - - -#### option\_or\_other(variable\_name: str, other\_variable\_name: Optional[str] = None) +#### option\_or\_other(variable\_name: str, other\_variable\_name: Optional[str] = None) {#ALToolbox.misc.option\_or\_other} ```python def option_or_other(variable_name: str, @@ -565,9 +533,7 @@ This is useful for filling in a template and to prevent the word 'Other the value of the variable if it is not 'Other', otherwise the value of the other variable - - -#### true\_values\_with\_other(variable\_name: str, other\_variable\_name: Optional[str] = None) +#### true\_values\_with\_other(variable\_name: str, other\_variable\_name: Optional[str] = None) {#ALToolbox.misc.true\_values\_with\_other} ```python def true_values_with_other( @@ -592,9 +558,7 @@ This is useful for filling in a template and to prevent the word 'Other 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. - - -#### include\_a\_year(text: str, field: Optional[str] = None) +#### include\_a\_year(text: str, field: Optional[str] = None) {#ALToolbox.misc.include\_a\_year} ```python def include_a_year(text: str, field: Optional[str] = None) -> bool @@ -630,9 +594,7 @@ birthdate or a moving date. True >>> include_a_year("Born long ago") # raises DAValidationError - - -#### is\_leap\_year(year: int) +#### is\_leap\_year(year: int) {#ALToolbox.misc.is\_leap\_year} ```python def is_leap_year(year: int) -> bool @@ -648,9 +610,7 @@ Helper function for `age_in_years` to determine if a year is a leap year. True if the year is a leap year, False otherwise. - - -#### age\_in\_years(the\_date: Union[str, DADateTime]) +#### age\_in\_years(the\_date: Union[str, DADateTime]) {#ALToolbox.misc.age\_in\_years} ```python def age_in_years(the_date: Union[str, DADateTime]) -> int @@ -666,9 +626,7 @@ Calculate the age in years from a date (treated like a date of birth). The age in years as an integer. - - -#### format\_date\_if\_defined(date\_object\_name: str, \*pargs, default: str = "", \*\*kwargs) +#### format\_date\_if\_defined(date\_object\_name: str, \*pargs, default: str = "", \*\*kwargs) {#ALToolbox.misc.format\_date\_if\_defined} ```python def format_date_if_defined(date_object_name: str, diff --git a/docs/components/ALToolbox/save_input_data.md b/docs/components/ALToolbox/save_input_data.md index fa05e3fc4..6771fc445 100644 --- a/docs/components/ALToolbox/save_input_data.md +++ b/docs/components/ALToolbox/save_input_data.md @@ -1,6 +1,6 @@ # Table of Contents -* [ALToolbox.save\_input\_data](#ALToolbox.save_input_data) +* ALToolbox.save\_input\_data * [save\_input\_data](#ALToolbox.save_input_data.save_input_data) --- @@ -8,9 +8,7 @@ sidebar_label: save_input_data title: ALToolbox.save_input_data --- - - -#### save\_input\_data(title: str = "", input\_dict: Optional[Dict[str, Any]] = None, tags: Optional[List[str]] = None) +#### save\_input\_data(title: str = "", input\_dict: Optional[Dict[str, Any]] = None, tags: Optional[List[str]] = None) {#ALToolbox.save\_input\_data.save\_input\_data} ```python def save_input_data(title: str = "", diff --git a/docs/components/AssemblyLine/al_courts.md b/docs/components/AssemblyLine/al_courts.md index 05aeed8e8..98da4ab92 100644 --- a/docs/components/AssemblyLine/al_courts.md +++ b/docs/components/AssemblyLine/al_courts.md @@ -1,6 +1,6 @@ # Table of Contents -* [AssemblyLine.al\_courts](#AssemblyLine.al_courts) +* AssemblyLine.al\_courts * [ALCourt](#AssemblyLine.al_courts.ALCourt) * [init](#AssemblyLine.al_courts.ALCourt.init) * [short\_label](#AssemblyLine.al_courts.ALCourt.short_label) @@ -27,9 +27,7 @@ title: AssemblyLine.al_courts Package for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now - - -## ALCourt Objects +## ALCourt Objects {#AssemblyLine.al\_courts.ALCourt} ```python class ALCourt(Court) @@ -42,9 +40,7 @@ address and can use any of those three features of the court to do the filtering A list of cities? A list of counties? Instead, we use a function on the CourtList object that filters courts by address and can use any of those three features of the court to do the filtering.--> - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_courts.ALCourt.init} ```python def init(*pargs, **kwargs) -> None @@ -57,9 +53,7 @@ Create a new court object. - `*pargs` - Standard DAObject positional arguments - `**kwargs` - Standard DAObject keyword arguments - - -#### short\_label() +#### short\_label() {#AssemblyLine.al\_courts.ALCourt.short\_label} ```python def short_label() -> str @@ -74,9 +68,7 @@ list. - `str` - string representing the court's name, with city if needed to disambiguate - - -#### short\_label\_and\_address() +#### short\_label\_and\_address() {#AssemblyLine.al\_courts.ALCourt.short\_label\_and\_address} ```python def short_label_and_address() -> str @@ -89,9 +81,7 @@ More concise version without description; suitable for a responsive case. - `str` - string representing the court's name and address - - -#### short\_description() +#### short\_description() {#AssemblyLine.al\_courts.ALCourt.short\_description} ```python def short_description() -> str @@ -105,9 +95,7 @@ buttons. - `str` - string representing the court's name and description - - -#### from\_row(df\_row: Union[pd.Series, pd.DataFrame], ensure\_lat\_long: bool = True) +#### from\_row(df\_row: Union[pd.Series, pd.DataFrame], ensure\_lat\_long: bool = True) {#AssemblyLine.al\_courts.ALCourt.from\_row} ```python def from_row(df_row: Union[pd.Series, pd.DataFrame], @@ -124,9 +112,7 @@ with existing attributes or methods of DAObject - `df_row` - Pandas Series object - `ensure_lat_long` - bool, whether to use Google Maps to geocode the address if we don't have coordinates - - -#### geolocate() +#### geolocate() {#AssemblyLine.al\_courts.ALCourt.geolocate} ```python def geolocate() -> None @@ -136,9 +122,7 @@ Use Google Maps to geocode the court's address and store the result in the Deprecated: use geocode() instead. - - -#### geocode() +#### geocode() {#AssemblyLine.al\_courts.ALCourt.geocode} ```python def geocode() -> None @@ -146,9 +130,7 @@ def geocode() -> None Use Google Maps to geocode the court's address and store the result in the location attribute. - - -## ALCourtLoader Objects +## ALCourtLoader Objects {#AssemblyLine.al\_courts.ALCourtLoader} ```python class ALCourtLoader(DAObject) @@ -163,9 +145,7 @@ Built around Pandas dataframe. - `filename` _str_ - Path to the file containing court information. - `converters` _Dict[str, Callable]_ - A dictionary of functions to apply to columns in the dataframe. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_courts.ALCourtLoader.init} ```python def init(*pargs, **kwargs) -> None @@ -178,9 +158,7 @@ Create a new courtloader object. - `*pargs` - Standard DAObject positional arguments - `**kwargs` - Standard DAObject keyword arguments - - -#### all\_courts() +#### all\_courts() {#AssemblyLine.al\_courts.ALCourtLoader.all\_courts} ```python def all_courts() -> List[Tuple[int, str]] @@ -192,9 +170,7 @@ Return a list of all courts in the spreadsheet. List[Tuple[int, str]]: List of tuples where each tuple contains (dataframe_index, display_value). The dataframe_index (int) can be used with as_court() to retrieve the full court object. The display_value (str) is the court's name or other display column value. - - -#### unique\_column\_values(column\_name: str) +#### unique\_column\_values(column\_name: str) {#AssemblyLine.al\_courts.ALCourtLoader.unique\_column\_values} ```python def unique_column_values(column_name: str) -> Set[str] @@ -213,9 +189,7 @@ Retrieve a set of unique values present in a specified dataframe column. - A set containing unique values from the specified column. - Returns an empty set if the column does not exist or an error occurs. - - -#### county\_list(column\_name: str = "address\_county") +#### county\_list(column\_name: str = "address\_county") {#AssemblyLine.al\_courts.ALCourtLoader.county\_list} ```python def county_list(column_name: str = "address_county") -> Set[str] @@ -233,9 +207,7 @@ Typically used to get a list of all possible counties that have a court. - `Set[str]` - A list of all unique values in the specified row in the given spreadsheet - - -#### county\_has\_one\_court(county\_name: str, county\_column: str = "address\_county") +#### county\_has\_one\_court(county\_name: str, county\_column: str = "address\_county") {#AssemblyLine.al\_courts.ALCourtLoader.county\_has\_one\_court} ```python def county_has_one_court(county_name: str, @@ -256,9 +228,7 @@ in the spreadsheet. Returns False otherwise. - `bool` - True if there is only one court associated with the specified county in the spreadsheet. - - -#### county\_court(intrinsicName: str, county\_name: str, county\_column: str = "address\_county") +#### county\_court(intrinsicName: str, county\_name: str, county\_column: str = "address\_county") {#AssemblyLine.al\_courts.ALCourtLoader.county\_court} ```python def county_court(intrinsicName: str, @@ -281,9 +251,7 @@ when you know there is exactly one match - `ALCourt` - The first court matching the county name. - - -#### matching\_courts\_in\_county(county\_name: str, county\_column: str = "address\_county", display\_column: str = "name", search\_string: Optional[str] = None, search\_columns: Optional[Union[List[str], str]] = None) +#### matching\_courts\_in\_county(county\_name: str, county\_column: str = "address\_county", display\_column: str = "name", search\_string: Optional[str] = None, search\_columns: Optional[Union[List[str], str]] = None) {#AssemblyLine.al\_courts.ALCourtLoader.matching\_courts\_in\_county} ```python def matching_courts_in_county( @@ -316,9 +284,7 @@ the second element is the display value from the specified display_column. List[Tuple[int, str]]: List of tuples where each tuple contains (dataframe_index, display_value). The dataframe_index (int) can be used with as_court() to retrieve the full court object. The display_value (str) is the court's name or other display column value. - - -#### filter\_courts(court\_types: Optional[Union[List[str], str]], column: str = "department", display\_column: str = "name", search\_string: Optional[str] = None, search\_columns: Optional[Union[List[str], str]] = None) +#### filter\_courts(court\_types: Optional[Union[List[str], str]], column: str = "department", display\_column: str = "name", search\_string: Optional[str] = None, search\_columns: Optional[Union[List[str], str]] = None) {#AssemblyLine.al\_courts.ALCourtLoader.filter\_courts} ```python def filter_courts( @@ -350,9 +316,7 @@ is determined by the `display_column`. List[Tuple[int, str]]: List of tuples where each tuple contains (dataframe_index, display_value). The dataframe_index (int) can be used with as_court() to retrieve the full court object. The display_value (str) is the court's name or other display column value. - - -#### as\_court(intrinsicName: str, index: Union[int, str], ensure\_lat\_long: bool = True) +#### as\_court(intrinsicName: str, index: Union[int, str], ensure\_lat\_long: bool = True) {#AssemblyLine.al\_courts.ALCourtLoader.as\_court} ```python def as_court(intrinsicName: str, diff --git a/docs/components/AssemblyLine/al_document.md b/docs/components/AssemblyLine/al_document.md index acd0998f7..0aab38a99 100644 --- a/docs/components/AssemblyLine/al_document.md +++ b/docs/components/AssemblyLine/al_document.md @@ -1,6 +1,6 @@ # Table of Contents -* [AssemblyLine.al\_document](#AssemblyLine.al_document) +* AssemblyLine.al\_document * [random\_suffix](#AssemblyLine.al_document.random_suffix) * [base\_name](#AssemblyLine.al_document.base_name) * [label](#AssemblyLine.al_document.label) @@ -122,9 +122,7 @@ sidebar_label: al_document title: AssemblyLine.al_document --- - - -#### random\_suffix(length: int = 8) +#### random\_suffix(length: int = 8) {#AssemblyLine.al\_document.random\_suffix} ```python def random_suffix(length: int = 8) -> str @@ -144,9 +142,7 @@ a true GUID. - `str` - A random string of lowercase letters and digits. - - -#### base\_name(filename: str) +#### base\_name(filename: str) {#AssemblyLine.al\_document.base\_name} ```python def base_name(filename: str) -> str @@ -163,9 +159,7 @@ Extracts the base name of a file without its extension. - `str` - The base name of the file without its extension. - - -#### label(dictionary: dict) +#### label(dictionary: dict) {#AssemblyLine.al\_document.label} ```python def label(dictionary: dict) -> str @@ -185,9 +179,7 @@ dictionary item. Useful for working with the `columns` method of an ALAddendumFi - `str` - The value of the first dictionary item or an empty string if not found. - - -#### key(dictionary: dict) +#### key(dictionary: dict) {#AssemblyLine.al\_document.key} ```python def key(dictionary: dict) -> str @@ -207,9 +199,7 @@ dictionary item. Useful for working with the `columns` method of an ALAddendumFi - `str` - The key of the first dictionary item or an empty string if not found. - - -#### safeattr(object: Any, key: str) +#### safeattr(object: Any, key: str) {#AssemblyLine.al\_document.safeattr} ```python def safeattr(object: Any, key: str) -> str @@ -232,9 +222,7 @@ Safely retrieve an attribute or key value from an object. The `location` attribute of an Address object or any LatitudeLongitude attribute of a DAObject is always skipped. - - -#### html\_safe\_str(the\_string: str) +#### html\_safe\_str(the\_string: str) {#AssemblyLine.al\_document.html\_safe\_str} ```python def html_safe_str(the_string: str) -> str @@ -251,9 +239,7 @@ Convert a string into a format that's safe for use as an HTML class or ID. - `str` - A string that's safe for use as an HTML class or ID. - - -#### table\_row(title: str, button\_htmls: List[str] = []) +#### table\_row(title: str, button\_htmls: List[str] = []) {#AssemblyLine.al\_document.table\_row} ```python def table_row(title: str, button_htmls: List[str] = []) -> str @@ -271,9 +257,7 @@ Generate an HTML row string for an AL document-styled table. - `str` - An HTML string representing a row in an AL document-styled table. - - -#### pdf\_page\_parity(pdf\_path: str) +#### pdf\_page\_parity(pdf\_path: str) {#AssemblyLine.al\_document.pdf\_page\_parity} ```python def pdf_page_parity(pdf_path: str) -> Literal["even", "odd"] @@ -292,9 +276,7 @@ if it is not divisible by 2. Literal["even", "odd"]: The parity of the number of pages in the PDF - - -#### add\_blank\_page(pdf\_path: str) +#### add\_blank\_page(pdf\_path: str) {#AssemblyLine.al\_document.add\_blank\_page} ```python def add_blank_page(pdf_path: str) -> None @@ -306,9 +288,7 @@ Add a blank page to the end of a PDF. - `pdf_path` _str_ - Path to the PDF in the filesystem - - -## ALAddendumField Objects +## ALAddendumField Objects {#AssemblyLine.al\_document.ALAddendumField} ```python class ALAddendumField(DAObject) @@ -336,9 +316,7 @@ is not currently supported. The attributes `headers` and `field_style` are planned for future releases and are not currently implemented. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALAddendumField.init} ```python def init(*pargs, **kwargs) -> None @@ -351,9 +329,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### overflow\_value(preserve\_newlines: bool = False, input\_width: int = 80, overflow\_message: str = "", preserve\_words: bool = True) +#### overflow\_value(preserve\_newlines: bool = False, input\_width: int = 80, overflow\_message: str = "", preserve\_words: bool = True) {#AssemblyLine.al\_document.ALAddendumField.overflow\_value} ```python def overflow_value(preserve_newlines: bool = False, @@ -388,9 +364,7 @@ content adheres to whitespace preferences specified by the parameters. - `Any` - The portion of the variable exceeding the content safe for display, considered as overflow. - - -#### max\_lines(input\_width: int = 80) +#### max\_lines(input\_width: int = 80) {#AssemblyLine.al\_document.ALAddendumField.max\_lines} ```python def max_lines(input_width: int = 80) -> int @@ -407,9 +381,7 @@ Compute the maximum number of lines that can fit in the input given the specifie - `int` - The maximum number of lines accommodated by the input width. - - -#### value() +#### value() {#AssemblyLine.al\_document.ALAddendumField.value} ```python def value() -> Any @@ -424,9 +396,7 @@ without the necessity of toggling between various sections or pages. - `Any` - The whole value of the field, irrespective of overflow. - - -#### has\_overflow(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) +#### has\_overflow(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) {#AssemblyLine.al\_document.ALAddendumField.has\_overflow} ```python def has_overflow(overflow_message: str = "", @@ -457,9 +427,7 @@ Return True only if the value's length exceeds the overflow trigger. - `bool` - True if the value's length exceeds the overflow trigger, False otherwise. - - -#### original\_or\_overflow\_message(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) +#### original\_or\_overflow\_message(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) {#AssemblyLine.al\_document.ALAddendumField.original\_or\_overflow\_message} ```python def original_or_overflow_message( @@ -493,9 +461,7 @@ Unlike safe_value(), this will never output a partial value. Union[str, List[Any]]: Either a string representing the overflow message or the original value - - -#### safe\_value(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) +#### safe\_value(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) {#AssemblyLine.al\_document.ALAddendumField.safe\_value} ```python def safe_value(overflow_message: str = "", @@ -536,9 +502,7 @@ with a single space. Union[str, List[Any]]: The portion of the variable that fits within the overflow trigger. - - -#### value\_if\_defined() +#### value\_if\_defined() {#AssemblyLine.al\_document.ALAddendumField.value\_if\_defined} ```python def value_if_defined() -> Any @@ -552,9 +516,7 @@ This method ensures that the addendum does not inadvertently trigger docassemble - `Any` - The value of the field if it exists, otherwise an empty string. - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#AssemblyLine.al\_document.ALAddendumField.\_\_str\_\_} ```python def __str__() @@ -566,9 +528,7 @@ Represent the ALAddendumField instance as a string. - `str` - The string representation of the value contained within the field. - - -#### columns(skip\_empty\_attributes: bool = True, skip\_attributes: Optional[set] = None) +#### columns(skip\_empty\_attributes: bool = True, skip\_attributes: Optional[set] = None) {#AssemblyLine.al\_document.ALAddendumField.columns} ```python def columns(skip_empty_attributes: bool = True, @@ -597,9 +557,7 @@ from the first value in the list. Empty attributes and the `complete` attribute The "location" attribute of an Address object is always skipped in the column list. - - -#### type() +#### type() {#AssemblyLine.al\_document.ALAddendumField.type} ```python def type() -> str @@ -616,9 +574,7 @@ Categories: - `str` - The type category of the value. - - -#### is\_list() +#### is\_list() {#AssemblyLine.al\_document.ALAddendumField.is\_list} ```python def is_list() -> bool @@ -630,9 +586,7 @@ Check if the field contains a list value, whether it consists of objects, dictio - `bool` - True if the field contains a list, otherwise False. - - -#### is\_object\_list() +#### is\_object\_list() {#AssemblyLine.al\_document.ALAddendumField.is\_object\_list} ```python def is_object_list() -> bool @@ -644,9 +598,7 @@ Determine if the field contains a list of dictionaries or objects. - `bool` - True if the field contains a list of dictionaries or objects, otherwise False. - - -#### overflow\_markdown() +#### overflow\_markdown() {#AssemblyLine.al\_document.ALAddendumField.overflow\_markdown} ```python def overflow_markdown() -> str @@ -662,9 +614,7 @@ to manually control the output's format. - `str` - A markdown representation of the overflow values. - - -#### overflow\_docx(path: str = "docassemble.ALDocumentDict:data/templates/addendum\_table.docx") +#### overflow\_docx(path: str = "docassemble.ALDocumentDict:data/templates/addendum\_table.docx") {#AssemblyLine.al\_document.ALAddendumField.overflow\_docx} ```python def overflow_docx( @@ -688,9 +638,7 @@ fetching the overflow values using the `overflow_value()` method. A docx template with the inserted table. - - -## ALAddendumFieldDict Objects +## ALAddendumFieldDict Objects {#AssemblyLine.al\_document.ALAddendumFieldDict} ```python class ALAddendumFieldDict(DAOrderedDict) @@ -710,9 +658,7 @@ Adding a new entry will implicitly set the `field_name` attribute of the field - `style` _str_ - Determines the display behavior. If set to "overflow_only", only the overflow text will be displayed. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALAddendumFieldDict.init} ```python def init(*pargs, **kwargs) -> None @@ -725,9 +671,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### initializeObject(\*pargs, \*\*kwargs) +#### initializeObject(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALAddendumFieldDict.initializeObject} ```python def initializeObject(*pargs, **kwargs) -> Any @@ -749,9 +693,7 @@ its own field name by setting the `field_name` attribute. The new dictionary entry created - - -#### from\_list(data: List[Dict]) +#### from\_list(data: List[Dict]) {#AssemblyLine.al\_document.ALAddendumFieldDict.from\_list} ```python def from_list(data: List[Dict]) -> None @@ -764,9 +706,7 @@ Populate the dictionary using a list of field data. - `data` _list_ - List of dictionaries containing ield data with keys "field_name" and "overflow_trigger". - - -#### defined\_fields(style: str = "overflow\_only") +#### defined\_fields(style: str = "overflow\_only") {#AssemblyLine.al\_document.ALAddendumFieldDict.defined\_fields} ```python def defined_fields(style: str = "overflow_only") -> list @@ -784,9 +724,7 @@ Fetch a list of fields that are defined. - `list` - List of defined fields based on the specified style. - - -#### overflow() +#### overflow() {#AssemblyLine.al\_document.ALAddendumFieldDict.overflow} ```python def overflow() -> list @@ -798,9 +736,7 @@ Retrieve fields that have overflowed their character limits. - `list` - A list of fields with overflow values. - - -#### has\_overflow() +#### has\_overflow() {#AssemblyLine.al\_document.ALAddendumFieldDict.has\_overflow} ```python def has_overflow() -> bool @@ -812,9 +748,7 @@ Determine if any field within the dictionary exceeds its overflow limit. - `bool` - True if at least one field overflows, False otherwise. - - -## DALazyAttribute Objects +## DALazyAttribute Objects {#AssemblyLine.al\_document.DALazyAttribute} ```python class DALazyAttribute(DAObject) @@ -830,9 +764,7 @@ The implementation leverages docassemble's object pickling process by custo - `instanceName` _str_ - A unique identifier for the object instance, if available. - - -#### \_\_getstate\_\_() +#### \_\_getstate\_\_() {#AssemblyLine.al\_document.DALazyAttribute.\_\_getstate\_\_} ```python def __getstate__() -> dict @@ -848,9 +780,7 @@ persisted across page loads. - `dict` - A dictionary containing only the `instanceName` if it exists, or empty otherwise. - - -## ALDocument Objects +## ALDocument Objects {#AssemblyLine.al\_document.ALDocument} ```python class ALDocument(DADict) @@ -983,9 +913,7 @@ on the final download screen. my_doc.overflow_fields.gathered = True ``` - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALDocument.init} ```python def init(*pargs, **kwargs) -> None @@ -998,9 +926,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True) +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALDocument.as\_pdf} ```python def as_pdf(key: str = "final", @@ -1023,9 +949,7 @@ Generates a PDF version of the assembled document. - `DAFile` - Assembled document in PDF format, possibly combined with addendum. - - -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALDocument.as\_docx} ```python def as_docx(key: str = "final", @@ -1046,9 +970,7 @@ Generates a DOCX version of the assembled document, if possible. Falls back to P - `DAFile` - Assembled document in DOCX or PDF format. - - -#### as\_list(key: str = "final", refresh: bool = True) +#### as\_list(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALDocument.as\_list} ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1066,9 +988,7 @@ Generates a list containing the main document and its addendum, if applicable. - `List[DAFile]` - List containing the main document and possibly its addendum. - - -#### need\_addendum() +#### need\_addendum() {#AssemblyLine.al\_document.ALDocument.need\_addendum} ```python def need_addendum() -> bool @@ -1081,9 +1001,7 @@ First checks if the addendum is enabled, and then checks if there's overflo - `bool` - True if an addendum is needed, False otherwise. - - -#### has\_overflow() +#### has\_overflow() {#AssemblyLine.al\_document.ALDocument.has\_overflow} ```python def has_overflow() -> bool @@ -1095,9 +1013,7 @@ Checks if the document has fields that exceed their character limits. - `bool` - True if there are overflow fields, False otherwise. - - -#### overflow() +#### overflow() {#AssemblyLine.al\_document.ALDocument.overflow} ```python def overflow() -> list @@ -1109,9 +1025,7 @@ Retrieves a list of fields that have overflowed their character limits. - `list` - List of overflow fields. - - -#### original\_or\_overflow\_message(field\_name: str, overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) +#### original\_or\_overflow\_message(field\_name: str, overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) {#AssemblyLine.al\_document.ALDocument.original\_or\_overflow\_message} ```python def original_or_overflow_message( @@ -1149,9 +1063,7 @@ Unlike safe_value(), this will never output a partial value. Union[str, List[Any]]: Either the original value or the overflow message, never a truncated value. - - -#### safe\_value(field\_name: str, overflow\_message: Optional[str] = None, preserve\_newlines: bool = False, input\_width: int = 80, preserve\_words: bool = True) +#### safe\_value(field\_name: str, overflow\_message: Optional[str] = None, preserve\_newlines: bool = False, input\_width: int = 80, preserve\_words: bool = True) {#AssemblyLine.al\_document.ALDocument.safe\_value} ```python def safe_value(field_name: str, @@ -1176,9 +1088,7 @@ Retrieve the "safe" value of a specified field, which is shorter than - `str` - The "safe" value of the specified field. - - -#### overflow\_value(field\_name: str, overflow\_message: Optional[str] = None, preserve\_newlines: bool = False, input\_width: int = 80, preserve\_words: bool = True) +#### overflow\_value(field\_name: str, overflow\_message: Optional[str] = None, preserve\_newlines: bool = False, input\_width: int = 80, preserve\_words: bool = True) {#AssemblyLine.al\_document.ALDocument.overflow\_value} ```python def overflow_value(field_name: str, @@ -1203,9 +1113,7 @@ Retrieve the "overflow" value of a specified field, which is the amoun - `str` - The "overflow" value of the specified field. - - -#### is\_enabled(refresh: bool = True) +#### is\_enabled(refresh: bool = True) {#AssemblyLine.al\_document.ALDocument.is\_enabled} ```python def is_enabled(refresh: bool = True) -> bool @@ -1227,9 +1135,7 @@ A document is "enabled" if: - `bool` - True if the document is enabled, otherwise False. - - -## ALStaticDocument Objects +## ALStaticDocument Objects {#AssemblyLine.al\_document.ALStaticDocument} ```python class ALStaticDocument(DAStaticFile) @@ -1265,9 +1171,7 @@ A class for initializing static documents for inclusion in an ALDocumentBundle w Consider handling files in `/data/templates` if deemed useful, potentially by copying into a DAFile using `pdf_concatenate()`. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALStaticDocument.init} ```python def init(*pargs, **kwargs) -> None @@ -1280,9 +1184,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### \_\_getitem\_\_(key) +#### \_\_getitem\_\_(key) {#AssemblyLine.al\_document.ALStaticDocument.\_\_getitem\_\_} ```python def __getitem__(key) @@ -1294,9 +1196,7 @@ Override to ensure 'final' and 'private' keys always exist a - `ALStaticDocument` - Returns self. - - -#### as\_list(key: str = "final", refresh: bool = True) +#### as\_list(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALStaticDocument.as\_list} ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAStaticFile] @@ -1314,9 +1214,7 @@ Get the document as a list. - `List[DAStaticFile]` - A list containing this document. - - -#### as\_pdf(key: str = "final", pdfa: bool = False, filename: str = "", append\_matching\_suffix: bool = True, refresh: bool = False) +#### as\_pdf(key: str = "final", pdfa: bool = False, filename: str = "", append\_matching\_suffix: bool = True, refresh: bool = False) {#AssemblyLine.al\_document.ALStaticDocument.as\_pdf} ```python def as_pdf(key: str = "final", @@ -1341,9 +1239,7 @@ Convert the document into PDF format. Union[DAStaticFile, DAFile]: The document in PDF format. - - -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = False) +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = False) {#AssemblyLine.al\_document.ALStaticDocument.as\_docx} ```python def as_docx( @@ -1365,9 +1261,7 @@ Convert the document into DOCX format, if possible. If not, return as PDF. Union[DAStaticFile, DAFile]: The document in DOCX or PDF format. - - -#### show(\*\*kwargs) +#### show(\*\*kwargs) {#AssemblyLine.al\_document.ALStaticDocument.show} ```python def show(**kwargs) -> DAFile @@ -1386,9 +1280,7 @@ This method provides a workaround for problems generating thumbnails. - `DAFile` - Displayable version of the document. - - -#### is\_enabled(\*\*kwargs) +#### is\_enabled(\*\*kwargs) {#AssemblyLine.al\_document.ALStaticDocument.is\_enabled} ```python def is_enabled(**kwargs) -> bool @@ -1405,9 +1297,7 @@ Check if the document is enabled. - `bool` - True if the document is enabled, otherwise False. - - -## ALDocumentBundle Objects +## ALDocumentBundle Objects {#AssemblyLine.al\_document.ALDocumentBundle} ```python class ALDocumentBundle(DAList) @@ -1452,9 +1342,7 @@ bundles, each can be rendered as a merged PDF or a list of documents. zipped_files = bundle.as_zip() ``` - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALDocumentBundle.init} ```python def init(*pargs, **kwargs) -> None @@ -1467,9 +1355,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, ensure\_parity: Optional[Literal["even", "odd"]] = None) +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, ensure\_parity: Optional[Literal["even", "odd"]] = None) {#AssemblyLine.al\_document.ALDocumentBundle.as\_pdf} ```python def as_pdf( @@ -1498,9 +1384,7 @@ Returns a consolidated PDF of all enabled documents in the bundle. - `Optional[DAFile]` - Combined PDF file or None if no documents are enabled. - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#AssemblyLine.al\_document.ALDocumentBundle.\_\_str\_\_} ```python def __str__() -> str @@ -1514,9 +1398,7 @@ the PDF by default. - `str` - String representation of the PDF. - - -#### as\_zip(key: str = "final", refresh: bool = True, pdfa: bool = False, title: str = "", format: Optional[str] = "pdf", include\_pdf: Optional[bool] = True) +#### as\_zip(key: str = "final", refresh: bool = True, pdfa: bool = False, title: str = "", format: Optional[str] = "pdf", include\_pdf: Optional[bool] = True) {#AssemblyLine.al\_document.ALDocumentBundle.as\_zip} ```python def as_zip(key: str = "final", @@ -1543,9 +1425,7 @@ Returns a zip file containing all enabled documents in the bundle in the specifi - `DAFile` - A zip file containing the enabled documents. - - -#### preview(refresh: bool = True) +#### preview(refresh: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.preview} ```python def preview(refresh: bool = True) -> Optional[DAFile] @@ -1562,9 +1442,7 @@ Returns a preview version of the bundle as a PDF. - `Optional[DAFile]` - Preview PDF file or None if no documents are enabled. - - -#### has\_enabled\_documents(refresh=False) +#### has\_enabled\_documents(refresh=False) {#AssemblyLine.al\_document.ALDocumentBundle.has\_enabled\_documents} ```python def has_enabled_documents(refresh=False) -> bool @@ -1581,9 +1459,7 @@ Checks if there is at least one enabled document in the bundle. - `bool` - True if there's at least one enabled document, otherwise False. - - -#### enabled\_documents(refresh: bool = True) +#### enabled\_documents(refresh: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.enabled\_documents} ```python def enabled_documents(refresh: bool = True) -> List[Any] @@ -1600,9 +1476,7 @@ Retrieves all enabled documents within the bundle. - `List[Any]` - List of enabled documents. - - -#### as\_flat\_list(key: str = "final", refresh: bool = True) +#### as\_flat\_list(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.as\_flat\_list} ```python def as_flat_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1620,9 +1494,7 @@ Flattens and returns all enabled documents in the bundle, even from nested bundl - `List[DAFile]` - Flattened list of enabled documents. - - -#### get\_titles(key: str = "final", refresh: bool = True) +#### get\_titles(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.get\_titles} ```python def get_titles(key: str = "final", refresh: bool = True) -> List[str] @@ -1640,9 +1512,7 @@ Retrieves the titles of all enabled documents in the bundle. - `List[str]` - Titles of the enabled documents. - - -#### as\_pdf\_list(key: str = "final", refresh: bool = True, pdfa: bool = False) +#### as\_pdf\_list(key: str = "final", refresh: bool = True, pdfa: bool = False) {#AssemblyLine.al\_document.ALDocumentBundle.as\_pdf\_list} ```python def as_pdf_list(key: str = "final", @@ -1663,9 +1533,7 @@ Returns all enabled documents in the bundle as individual PDFs, even from nested - `List[DAFile]` - List of enabled documents as individual PDFs. - - -#### as\_docx\_list(key: str = "final", refresh: bool = True) +#### as\_docx\_list(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.as\_docx\_list} ```python def as_docx_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1685,9 +1553,7 @@ If a particular document can't be represented as a DOCX, its original forma - `List[DAFile]` - List of documents represented as DOCX files or in their original format. - - -#### as\_editable\_list(key: str = "final", refresh: bool = True) +#### as\_editable\_list(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.as\_editable\_list} ```python def as_editable_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1707,9 +1573,7 @@ For documents that are not in DOCX or RTF formats, the original file format is r - `List[DAFile]` - Flat list of documents in DOCX or RTF formats or their original format. - - -#### get\_cacheable\_documents(key: str = "final", pdf: bool = True, docx: bool = False, original: bool = False, refresh: bool = True, pdfa: bool = False, include\_zip: bool = True, include\_full\_pdf: bool = False, append\_matching\_suffix: bool = True, zip\_include\_pdf: Optional[bool] = None, zip\_format: Optional[str] = None) +#### get\_cacheable\_documents(key: str = "final", pdf: bool = True, docx: bool = False, original: bool = False, refresh: bool = True, pdfa: bool = False, include\_zip: bool = True, include\_full\_pdf: bool = False, append\_matching\_suffix: bool = True, zip\_include\_pdf: Optional[bool] = None, zip\_format: Optional[str] = None) {#AssemblyLine.al\_document.ALDocumentBundle.get\_cacheable\_documents} ```python def get_cacheable_documents( @@ -1757,9 +1621,7 @@ DAFile # PDF of whole bundle 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 - - -#### download\_list\_html(key: str = "final", format: str = "pdf", view: bool = True, refresh: bool = True, pdfa: bool = False, include\_zip: bool = True, view\_label="View", view\_icon: str = "eye", download\_label: str = "Download", download\_icon: str = "download", send\_label: str = "Send", send\_icon: str = "envelope", zip\_label: Optional[str] = None, zip\_icon: str = "file-archive", zip\_row\_label: Optional[str] = "", append\_matching\_suffix: bool = True, include\_email: bool = False, use\_previously\_cached\_files: bool = False, include\_full\_pdf: bool = False, full\_pdf\_label: Optional[str] = None, zip\_include\_pdf: Optional[bool] = True, zip\_format: Optional[str] = None) +#### download\_list\_html(key: str = "final", format: str = "pdf", view: bool = True, refresh: bool = True, pdfa: bool = False, include\_zip: bool = True, view\_label="View", view\_icon: str = "eye", download\_label: str = "Download", download\_icon: str = "download", send\_label: str = "Send", send\_icon: str = "envelope", zip\_label: Optional[str] = None, zip\_icon: str = "file-archive", zip\_row\_label: Optional[str] = "", append\_matching\_suffix: bool = True, include\_email: bool = False, use\_previously\_cached\_files: bool = False, include\_full\_pdf: bool = False, full\_pdf\_label: Optional[str] = None, zip\_include\_pdf: Optional[bool] = True, zip\_format: Optional[str] = None) {#AssemblyLine.al\_document.ALDocumentBundle.download\_list\_html} ```python def download_list_html(key: str = "final", @@ -1819,9 +1681,7 @@ Constructs an HTML table displaying a list of documents with 'view' an - `str` - HTML representation of a table with documents and their associated actions. - - -#### download\_html(key: str = "final", format: str = "pdf", pdfa: bool = False, view: bool = True, refresh: bool = True, view\_label: str = "View", view\_icon: str = "eye", download\_label: str = "Download", download\_icon: str = "download") +#### download\_html(key: str = "final", format: str = "pdf", pdfa: bool = False, view: bool = True, refresh: bool = True, view\_label: str = "View", view\_icon: str = "eye", download\_label: str = "Download", download\_icon: str = "download") {#AssemblyLine.al\_document.ALDocumentBundle.download\_html} ```python def download_html(key: str = "final", @@ -1857,9 +1717,7 @@ Deprecated; use download_list_html instead - `str` - HTML representation of a table with documents and their associated actions. - - -#### send\_email\_table\_row(key: str = "final", send\_label: str = "Send", send\_icon: str = "envelope") +#### send\_email\_table\_row(key: str = "final", send\_label: str = "Send", send\_icon: str = "envelope") {#AssemblyLine.al\_document.ALDocumentBundle.send\_email\_table\_row} ```python def send_email_table_row(key: str = "final", @@ -1881,9 +1739,7 @@ someone to send the bundle to the specified email address. - `str` - The generated HTML string for the table row. - - -#### send\_button\_to\_html(email: str, editable: Optional[bool] = None, template\_name: str = "", label: str = "Send", icon: str = "envelope", color: str = "primary", key: str = "final", preferred\_formats: Optional[Union[str, List[str]]] = None) +#### send\_button\_to\_html(email: str, editable: Optional[bool] = None, template\_name: str = "", label: str = "Send", icon: str = "envelope", color: str = "primary", key: str = "final", preferred\_formats: Optional[Union[str, List[str]]] = None) {#AssemblyLine.al\_document.ALDocumentBundle.send\_button\_to\_html} ```python def send_button_to_html( @@ -1917,9 +1773,7 @@ in contrast to send_button_html. - `str` - The generated HTML string for the button. - - -#### send\_button\_html(key: str = "final", show\_editable\_checkbox: bool = True, template\_name: str = "", label: str = "Send", icon: str = "envelope", preferred\_formats: Optional[Union[str, List[str]]] = None) +#### send\_button\_html(key: str = "final", show\_editable\_checkbox: bool = True, template\_name: str = "", label: str = "Send", icon: str = "envelope", preferred\_formats: Optional[Union[str, List[str]]] = None) {#AssemblyLine.al\_document.ALDocumentBundle.send\_button\_html} ```python def send_button_html( @@ -1955,9 +1809,7 @@ include an editable (Word) copy of the file, if and only if it is available. - `str` - The generated HTML string for the input box and button. - - -#### send\_email(to: Any = None, key: str = "final", editable: Optional[bool] = None, template: Optional[Any] = None, preferred\_formats: Optional[Union[str, List[str]]] = "pdf", \*\*kwargs) +#### send\_email(to: Any = None, key: str = "final", editable: Optional[bool] = None, template: Optional[Any] = None, preferred\_formats: Optional[Union[str, List[str]]] = "pdf", \*\*kwargs) {#AssemblyLine.al\_document.ALDocumentBundle.send\_email} ```python def send_email(to: Any = None, @@ -1986,9 +1838,7 @@ https://docassemble.org/docs/functions.html#send_email with additional parameter - `bool` - Indicates if the email was sent successfully. - - -#### is\_enabled(refresh=True) +#### is\_enabled(refresh=True) {#AssemblyLine.al\_document.ALDocumentBundle.is\_enabled} ```python def is_enabled(refresh=True) -> bool @@ -2005,9 +1855,7 @@ Check if the bundle itself is enabled, and if it has at least one enabled child - `bool` - Indicates if the bundle and its child documents are enabled. - - -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.as\_docx} ```python def as_docx(key: str = "final", @@ -2028,9 +1876,7 @@ Convert the enabled documents to a single DOCX file or PDF file if conversion fa - `DAFile` - A DAFile object containing the concatenated DOCX or PDF file. - - -#### as\_list(key: str = "final", refresh: bool = True) +#### as\_list(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALDocumentBundle.as\_list} ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -2048,9 +1894,7 @@ Return a list of enabled documents. - `List[DAFile]` - A list of enabled DAFile objects. - - -## ALExhibit Objects +## ALExhibit Objects {#AssemblyLine.al\_document.ALExhibit} ```python class ALExhibit(DAObject) @@ -2066,9 +1910,7 @@ Class to represent a single exhibit, with cover page, which may contain multiple - `label` _str_ - A label, like "A" or "1" for this exhibit in the cover page and table of contents - `starting_page` _int_ - first page number to use in table of contents - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALExhibit.init} ```python def init(*pargs, **kwargs) -> None @@ -2081,9 +1923,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### ocr\_ready() +#### ocr\_ready() {#AssemblyLine.al\_document.ALExhibit.ocr\_ready} ```python def ocr_ready() -> bool @@ -2100,9 +1940,7 @@ That situation is likely a developer error, as you shouldn't wait for OCR i - `bool` - True iff OCR process has finished on all pages. - - -#### ocr\_pages() +#### ocr\_pages() {#AssemblyLine.al\_document.ALExhibit.ocr\_pages} ```python def ocr_pages() -> List[DAFile] @@ -2114,9 +1952,7 @@ Retrieve the OCR-processed version of pages if available, else return the origin - `List[DAFile]` - List of pages, either OCR-processed or original. - - -#### as\_pdf(\*, refresh: bool = False, prefix: str = "", pdfa: bool = False, add\_page\_numbers: bool = True, add\_cover\_page: bool = True, filename: Optional[str] = None, append\_matching\_suffix: bool = True) +#### as\_pdf(\*, refresh: bool = False, prefix: str = "", pdfa: bool = False, add\_page\_numbers: bool = True, add\_cover\_page: bool = True, filename: Optional[str] = None, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALExhibit.as\_pdf} ```python def as_pdf(*, @@ -2148,9 +1984,7 @@ Note that these are keyword only parameters, not positional. - `DAFile` - PDF representation of the exhibit. - - -#### num\_pages() +#### num\_pages() {#AssemblyLine.al\_document.ALExhibit.num\_pages} ```python def num_pages() -> int @@ -2162,9 +1996,7 @@ Calculate the total number of pages in the exhibit. - `int` - Total page count. - - -#### complete() +#### complete() {#AssemblyLine.al\_document.ALExhibit.complete} ```python @property @@ -2178,9 +2010,7 @@ Indicates if the exhibit is complete. NOTE: This property always returns True after triggering the required attributes. - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#AssemblyLine.al\_document.ALExhibit.\_\_str\_\_} ```python def __str__() -> str @@ -2192,9 +2022,7 @@ Return the title of the exhibit. - `str` - Title of the exhibit. - - -#### ocrmypdf\_task(from\_file: Union[DAFile, DAFileList], to\_pdf: DAFile) +#### ocrmypdf\_task(from\_file: Union[DAFile, DAFileList], to\_pdf: DAFile) {#AssemblyLine.al\_document.ocrmypdf\_task} ```python def ocrmypdf_task(from_file: Union[DAFile, DAFileList], @@ -2223,9 +2051,7 @@ This function is designed to be executed as a background task (id: al_exhibit_oc - `subprocess.TimeoutExpired` - If the ocrmypdf process takes longer than an hour. - - -## ALExhibitList Objects +## ALExhibitList Objects {#AssemblyLine.al\_document.ALExhibitList} ```python class ALExhibitList(DAList) @@ -2242,9 +2068,7 @@ and rendering them into a single PDF file. Uses A..Z labels by default. - `auto_ocr` _bool_ - If True, automatically starts OCR processing for uploaded exhibits. Defaults to True. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALExhibitList.init} ```python def init(*pargs, **kwargs) -> None @@ -2257,9 +2081,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### as\_pdf(filename="file.pdf", pdfa: bool = False, add\_page\_numbers: bool = False, toc\_pages: int = 0, append\_matching\_suffix: bool = True) +#### as\_pdf(filename="file.pdf", pdfa: bool = False, add\_page\_numbers: bool = False, toc\_pages: int = 0, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALExhibitList.as\_pdf} ```python def as_pdf(filename="file.pdf", @@ -2284,9 +2106,7 @@ Compiles all exhibits in the list into a single PDF. - `DAFile` - A single PDF containing all exhibits. - - -#### size\_in\_bytes() +#### size\_in\_bytes() {#AssemblyLine.al\_document.ALExhibitList.size\_in\_bytes} ```python def size_in_bytes() -> int @@ -2298,9 +2118,7 @@ Calculates the total size in bytes of all exhibits in the list. - `int` - Total size of all exhibits in bytes. - - -#### ocr\_ready() +#### ocr\_ready() {#AssemblyLine.al\_document.ALExhibitList.ocr\_ready} ```python def ocr_ready() -> bool @@ -2312,9 +2130,7 @@ Checks if all exhibits in the list have completed the OCR process. - `bool` - True if all exhibits are OCRed or if OCR hasn't started. False otherwise. - - -#### hook\_after\_gather() +#### hook\_after\_gather() {#AssemblyLine.al\_document.ALExhibitList.hook\_after\_gather} ```python def hook_after_gather() -> None @@ -2323,9 +2139,7 @@ def hook_after_gather() -> None Callback function executed after the entire list of exhibits is collected. Manages auto-labeling and initiates OCR if necessary. - - -## ALExhibitDocument Objects +## ALExhibitDocument Objects {#AssemblyLine.al\_document.ALExhibitDocument} ```python class ALExhibitDocument(ALDocument) @@ -2376,9 +2190,7 @@ objects: - exhibit_attachment: ALExhibitDocument.using(title="Exhibits", filename="exhibits" , auto_labeler=item_label) ``` - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALExhibitDocument.init} ```python def init(*pargs, **kwargs) -> None @@ -2391,9 +2203,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### has\_overflow() +#### has\_overflow() {#AssemblyLine.al\_document.ALExhibitDocument.has\_overflow} ```python def has_overflow() -> bool @@ -2407,9 +2217,7 @@ This is for compatibility with ALDocument; Exhibits inherently don't have o - `bool` - Always False for this implementation. - - -#### ocr\_ready() +#### ocr\_ready() {#AssemblyLine.al\_document.ALExhibitDocument.ocr\_ready} ```python def ocr_ready() -> bool @@ -2421,9 +2229,7 @@ Determine if all exhibits within the document have undergone OCR processing. - `bool` - True if all exhibits have been OCRed or if the OCR process hasn't been initiated. - - -#### \_\_getitem\_\_(key) +#### \_\_getitem\_\_(key) {#AssemblyLine.al\_document.ALExhibitDocument.\_\_getitem\_\_} ```python def __getitem__(key) @@ -2440,9 +2246,7 @@ Overridden method to ensure 'final' and 'private' keys alway - `ALExhibitDocument` - Returns the current instance of the class. - - -#### as\_list(key: str = "final", refresh: bool = True) +#### as\_list(key: str = "final", refresh: bool = True) {#AssemblyLine.al\_document.ALExhibitDocument.as\_list} ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -2460,9 +2264,7 @@ Retrieve the document as a list. - `List[DAFile]` - A list containing the document. - - -#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True) +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALExhibitDocument.as\_pdf} ```python def as_pdf(key: str = "final", @@ -2487,9 +2289,7 @@ Render the document as a PDF. - `DAFile` - The document rendered as a PDF. - - -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALExhibitDocument.as\_docx} ```python def as_docx(key: str = "final", @@ -2510,9 +2310,7 @@ Despite the name, renders the document as a PDF. Provided for signature compatib - `DAFile` - The document rendered as a PDF. - - -## ALTableDocument Objects +## ALTableDocument Objects {#AssemblyLine.al\_document.ALTableDocument} ```python class ALTableDocument(ALDocument) @@ -2528,9 +2326,7 @@ This class provides functionality to export data as a table in various formats s - `file` _DAFile, optional_ - Reference to the generated file (can be PDF, DOCX, etc.). - `table` _???_ - Represents the actual table data. Type and attributes need more context to document. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALTableDocument.init} ```python def init(*pargs, **kwargs) -> None @@ -2543,9 +2339,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### has\_overflow() +#### has\_overflow() {#AssemblyLine.al\_document.ALTableDocument.has\_overflow} ```python def has_overflow() -> bool @@ -2559,9 +2353,7 @@ For compatibility with ALDocument; Tables inherently don't have overflow. - `bool` - Always False for this implementation. - - -#### \_\_getitem\_\_(key) +#### \_\_getitem\_\_(key) {#AssemblyLine.al\_document.ALTableDocument.\_\_getitem\_\_} ```python def __getitem__(key) @@ -2580,9 +2372,7 @@ Overridden to ensure 'final' and 'private' keys always retur - `DAFile` - The document in its PDF format. - - -#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) +#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) {#AssemblyLine.al\_document.ALTableDocument.as\_list} ```python def as_list(key: str = "final", @@ -2602,9 +2392,7 @@ Retrieve the document as a list. - `List[DAFile]` - A list containing the document. - - -#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, \*\*kwargs) +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, \*\*kwargs) {#AssemblyLine.al\_document.ALTableDocument.as\_pdf} ```python def as_pdf(key: str = "final", @@ -2629,9 +2417,7 @@ Name retained for signature compatibility. - `DAFile` - The table rendered as an XLSX spreadsheet - - -#### as\_docx(key: str = "bool", refresh: bool = True, append\_matching\_suffix: bool = True) +#### as\_docx(key: str = "bool", refresh: bool = True, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALTableDocument.as\_docx} ```python def as_docx(key: str = "bool", @@ -2654,9 +2440,7 @@ Name retained for signature compatibility. - `DAFile` - The table rendered as an XLSX spreadsheet - - -## ALUntransformedDocument Objects +## ALUntransformedDocument Objects {#AssemblyLine.al\_document.ALUntransformedDocument} ```python class ALUntransformedDocument(ALDocument) @@ -2671,9 +2455,7 @@ compatibility with ALDocument. - `has_addendum` _bool_ - A flag indicating the presence of an addendum in the document. - `suffix_to_append` _str_ - Suffix that can be appended to file names, defaulting to "preview". - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_document.ALUntransformedDocument.init} ```python def init(*pargs, **kwargs) -> None @@ -2686,9 +2468,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### has\_overflow() +#### has\_overflow() {#AssemblyLine.al\_document.ALUntransformedDocument.has\_overflow} ```python def has_overflow() -> bool @@ -2702,9 +2482,7 @@ For compatibility with ALDocument. Untransformed documents inherently don't - `bool` - Always False for this implementation. - - -#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) +#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) {#AssemblyLine.al\_document.ALUntransformedDocument.as\_list} ```python def as_list(key: str = "final", @@ -2724,9 +2502,7 @@ Retrieve the document as a list. - `List[DAFile]` - A list containing the document. - - -#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, \*\*kwargs) +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, \*\*kwargs) {#AssemblyLine.al\_document.ALUntransformedDocument.as\_pdf} ```python def as_pdf(key: str = "final", @@ -2752,9 +2528,7 @@ This method is primarily for duck-typing compatibility with ALDocument. - `DAFile` - The original, untransformed document. - - -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) {#AssemblyLine.al\_document.ALUntransformedDocument.as\_docx} ```python def as_docx(key: str = "final", @@ -2777,9 +2551,7 @@ This method is primarily for duck-typing compatibility with ALDocument. - `DAFile` - The original, untransformed document. - - -## ALDocumentUpload Objects +## ALDocumentUpload Objects {#AssemblyLine.al\_document.ALDocumentUpload} ```python class ALDocumentUpload(ALUntransformedDocument) @@ -2788,9 +2560,7 @@ class ALDocumentUpload(ALUntransformedDocument) Simplified class to handle uploaded documents, without any of the complexity of the ALExhibitDocument class. - - -#### unpack\_dafilelist(the\_file: DAFileList) +#### unpack\_dafilelist(the\_file: DAFileList) {#AssemblyLine.al\_document.unpack\_dafilelist} ```python def unpack_dafilelist(the_file: DAFileList) -> DAFile diff --git a/docs/components/AssemblyLine/al_general.md b/docs/components/AssemblyLine/al_general.md index e2b074b97..cb8f679cd 100644 --- a/docs/components/AssemblyLine/al_general.md +++ b/docs/components/AssemblyLine/al_general.md @@ -1,6 +1,6 @@ # Table of Contents -* [AssemblyLine.al\_general](#AssemblyLine.al_general) +* AssemblyLine.al\_general * [safe\_subdivision\_type](#AssemblyLine.al_general.safe_subdivision_type) * [ALAddress](#AssemblyLine.al_general.ALAddress) * [address\_fields](#AssemblyLine.al_general.ALAddress.address_fields) @@ -79,9 +79,7 @@ sidebar_label: al_general title: AssemblyLine.al_general --- - - -#### safe\_subdivision\_type(country\_code: str) +#### safe\_subdivision\_type(country\_code: str) {#AssemblyLine.al\_general.safe\_subdivision\_type} ```python def safe_subdivision_type(country_code: str) -> Optional[str] @@ -99,9 +97,7 @@ If no subdivision type is found, returns None. - `Optional[str]` - The subdivision type for the country with the given country code. - - -## ALAddress Objects +## ALAddress Objects {#AssemblyLine.al\_general.ALAddress} ```python class ALAddress(Address) @@ -121,9 +117,7 @@ handling of the unit attribute when printing a formatted address. - `country` _str_ - The country where the person lives. - `impounded` _Optional[bool]_ - Whether the address is impounded. - - -#### address\_fields(country\_code: Optional[str] = None, default\_state: Optional[str] = None, show\_country: bool = False, show\_county: bool = False, show\_if: Union[str, Dict[str, str], None] = None, allow\_no\_address: bool = False, ask\_if\_impounded: Optional[bool] = False, maxlengths: Optional[Dict[str, int]] = None, required: Optional[Dict[str, bool]] = None) +#### address\_fields(country\_code: Optional[str] = None, default\_state: Optional[str] = None, show\_country: bool = False, show\_county: bool = False, show\_if: Union[str, Dict[str, str], None] = None, allow\_no\_address: bool = False, ask\_if\_impounded: Optional[bool] = False, maxlengths: Optional[Dict[str, int]] = None, required: Optional[Dict[str, bool]] = None) {#AssemblyLine.al\_general.ALAddress.address\_fields} ```python def address_fields( @@ -176,9 +170,7 @@ NOTE: This function is stateful under specific conditions. Refer to the conditio - Link to ISO-3166-1 alpha-2 codes: [Officially assigned code elements](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). - - -#### formatted\_unit(language: Optional[str] = None, require: bool = False, bare: bool = False) +#### formatted\_unit(language: Optional[str] = None, require: bool = False, bare: bool = False) {#AssemblyLine.al\_general.ALAddress.formatted\_unit} ```python def formatted_unit(language: Optional[str] = None, @@ -205,9 +197,7 @@ Returns the unit, formatted appropriately. the unit number, possibly prefixed with 'Unit'. If the unit attribute exists and is None or an empty string, the function will return an empty string. - - -#### block(language: Optional[str] = None, international: bool = False, show\_country: Optional[bool] = None, bare: bool = False, long\_state: bool = False, show\_impounded: bool = False) +#### block(language: Optional[str] = None, international: bool = False, show\_country: Optional[bool] = None, bare: bool = False, long\_state: bool = False, show\_impounded: bool = False) {#AssemblyLine.al\_general.ALAddress.block} ```python def block(language: Optional[str] = None, @@ -235,9 +225,7 @@ Returns a one-line formatted address, primarily for geocoding. - `str` - The one-line formatted address. - - -#### line\_one(language: Optional[str] = None, bare: bool = False, show\_impounded: bool = False) +#### line\_one(language: Optional[str] = None, bare: bool = False, show\_impounded: bool = False) {#AssemblyLine.al\_general.ALAddress.line\_one} ```python def line_one(language: Optional[str] = None, @@ -258,9 +246,7 @@ Returns the first line of the address, including the unit number if it exists. - `str` - The first line of the address. - - -#### line\_two(language: Optional[str] = None, long\_state: bool = False, show\_impounded: bool = False) +#### line\_two(language: Optional[str] = None, long\_state: bool = False, show\_impounded: bool = False) {#AssemblyLine.al\_general.ALAddress.line\_two} ```python def line_two(language: Optional[str] = None, @@ -281,9 +267,7 @@ Returns the second line of the address, including city, state, and postal code. - `str` - The second line of the address. - - -#### on\_one\_line(include\_unit: bool = True, omit\_default\_country: bool = True, language: Optional[str] = None, show\_country: Optional[bool] = None, bare: bool = False, long\_state: bool = False, show\_impounded: bool = False) +#### on\_one\_line(include\_unit: bool = True, omit\_default\_country: bool = True, language: Optional[str] = None, show\_country: Optional[bool] = None, bare: bool = False, long\_state: bool = False, show\_impounded: bool = False) {#AssemblyLine.al\_general.ALAddress.on\_one\_line} ```python def on_one_line(include_unit: bool = True, @@ -313,9 +297,7 @@ Returns a one-line formatted address. - `str` - The one-line formatted address. - - -#### normalized\_address() +#### normalized\_address() {#AssemblyLine.al\_general.ALAddress.normalized\_address} ```python def normalized_address() -> Union[Address, "ALAddress"] @@ -337,9 +319,7 @@ Warning: currently the normalized address will not be redacted if the address is Normalized address if geocoding is successful, otherwise the original address. - - -#### state\_name(country\_code: Optional[str] = None) +#### state\_name(country\_code: Optional[str] = None) {#AssemblyLine.al\_general.ALAddress.state\_name} ```python def state_name(country_code: Optional[str] = None) -> str @@ -365,9 +345,7 @@ object. Otherwise, the method uses, in order: - `str` - The full state name corresponding to the state abbreviation. If an error occurs or the full name cannot be determined, returns the state abbreviation. - - -## ALAddressList Objects +## ALAddressList Objects {#AssemblyLine.al\_general.ALAddressList} ```python class ALAddressList(DAList) @@ -379,9 +357,7 @@ Extends the DAList class and specifically caters to ALAddress objects. It provides methods to initialize the list and get a string representation of the list in a formatted manner. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_general.ALAddressList.init} ```python def init(*pargs, **kwargs) -> None @@ -394,9 +370,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#AssemblyLine.al\_general.ALAddressList.\_\_str\_\_} ```python def __str__() -> str @@ -411,9 +385,7 @@ comma-separated manner using the on_one_line method of ALAddress. - `str` - Formatted string of all addresses in the list. - - -## ALNameList Objects +## ALNameList Objects {#AssemblyLine.al\_general.ALNameList} ```python class ALNameList(DAList) @@ -423,9 +395,7 @@ A class to store a list of IndividualName objects. Extends the DAList class and is tailored for IndividualName objects. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_general.ALNameList.init} ```python def init(*pargs, **kwargs) -> None @@ -438,9 +408,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#AssemblyLine.al\_general.ALNameList.\_\_str\_\_} ```python def __str__() -> str @@ -452,9 +420,7 @@ Provide a string representation of the ALNameList. - `str` - Formatted string of all names in the list. - - -## ALPeopleList Objects +## ALPeopleList Objects {#AssemblyLine.al\_general.ALPeopleList} ```python class ALPeopleList(DAList) @@ -464,9 +430,7 @@ Class to store a list of ALIndividual objects, representing people. For example, defendants, plaintiffs, or children. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_general.ALPeopleList.init} ```python def init(*pargs, **kwargs) -> None @@ -479,9 +443,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### names\_and\_addresses\_on\_one\_line(comma\_string: str = "; ", bare=False) +#### names\_and\_addresses\_on\_one\_line(comma\_string: str = "; ", bare=False) {#AssemblyLine.al\_general.ALPeopleList.names\_and\_addresses\_on\_one\_line} ```python def names_and_addresses_on_one_line(comma_string: str = "; ", @@ -500,9 +462,7 @@ Provide names and addresses of individuals on one line. - `str` - Formatted string of names followed by addresses. - - -#### familiar(\*\*kwargs) +#### familiar(\*\*kwargs) {#AssemblyLine.al\_general.ALPeopleList.familiar} ```python def familiar(**kwargs) -> str @@ -518,9 +478,7 @@ Provide a list of familiar forms of names of individuals. - `str` - Formatted string of familiar names. - - -#### familiar\_or(\*\*kwargs) +#### familiar\_or(\*\*kwargs) {#AssemblyLine.al\_general.ALPeopleList.familiar\_or} ```python def familiar_or(**kwargs) -> str @@ -537,9 +495,7 @@ Provide a list of familiar forms of names of individuals separated by 'or&# - `str` - Formatted string of familiar names separated by 'or'. - - -#### short\_list(limit: int, truncate\_string: str = ", et. al.") +#### short\_list(limit: int, truncate\_string: str = ", et. al.") {#AssemblyLine.al\_general.ALPeopleList.short\_list} ```python def short_list(limit: int, truncate_string: str = ", et. al.") -> str @@ -557,9 +513,7 @@ Return a subset of the list, truncated with 'et. al.' if it exceeds a - `str` - Formatted string of names, truncated if needed. - - -#### full\_names(comma\_string=", ", and\_string=word("and")) +#### full\_names(comma\_string=", ", and\_string=word("and")) {#AssemblyLine.al\_general.ALPeopleList.full\_names} ```python def full_names(comma_string=", ", and_string=word("and")) -> str @@ -577,9 +531,7 @@ Return a formatted list of full names of individuals. - `str` - Formatted string of full names. - - -#### pronoun\_reflexive(\*\*kwargs) +#### pronoun\_reflexive(\*\*kwargs) {#AssemblyLine.al\_general.ALPeopleList.pronoun\_reflexive} ```python def pronoun_reflexive(**kwargs) -> str @@ -602,9 +554,7 @@ If it is plural, return the appropriate plural reflexive pronoun (e.g., "th - `str` - The reflexive pronoun for the list. - - -## ALIndividual Objects +## ALIndividual Objects {#AssemblyLine.al\_general.ALIndividual} ```python class ALIndividual(Individual) @@ -632,9 +582,7 @@ other addresses, mailing addresses, previous names, aliases, and a preferred nam Objects as attributes should not be passed directly to the constructor due to initialization requirements in the docassemble framework. See the `init` method. - - -#### init(\*pargs, \*\*kwargs) +#### init(\*pargs, \*\*kwargs) {#AssemblyLine.al\_general.ALIndividual.init} ```python def init(*pargs, **kwargs) -> None @@ -647,9 +595,7 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments - - -#### signature\_if\_final(i: str) +#### signature\_if\_final(i: str) {#AssemblyLine.al\_general.ALIndividual.signature\_if\_final} ```python def signature_if_final(i: str) -> Union[DAFile, str] @@ -666,9 +612,7 @@ Returns the individual's signature if `i` is "final", which usual Union[DAFile, str]: The signature if the condition is met, otherwise an empty string. - - -#### phone\_numbers(country: Optional[str] = None, show\_impounded: bool = False) +#### phone\_numbers(country: Optional[str] = None, show\_impounded: bool = False) {#AssemblyLine.al\_general.ALIndividual.phone\_numbers} ```python def phone_numbers(country: Optional[str] = None, @@ -695,9 +639,7 @@ Supports the following attributes: - `str` - Formatted string of phone numbers. - - -#### contact\_methods() +#### contact\_methods() {#AssemblyLine.al\_general.ALIndividual.contact\_methods} ```python def contact_methods() -> str @@ -709,9 +651,7 @@ Generates a formatted string of all provided contact methods. - `str` - A formatted string indicating the available methods to contact the individual. - - -#### merge\_letters(new\_letters: str) +#### merge\_letters(new\_letters: str) {#AssemblyLine.al\_general.ALIndividual.merge\_letters} ```python def merge_letters(new_letters: str) -> None @@ -725,9 +665,7 @@ Avoid using. Only used in 209A. - `new_letters` _str_ - The new letters to add to the existing list of letters - - -#### formatted\_age() +#### formatted\_age() {#AssemblyLine.al\_general.ALIndividual.formatted\_age} ```python def formatted_age() -> str @@ -739,9 +677,7 @@ Calculates and formats the age of the individual based on their birthdate. - `str` - Formatted age string that shows the most relevant time unit; for example, if under 2 years, it will return "X months". - - -#### normalized\_address() +#### normalized\_address() {#AssemblyLine.al\_general.ALIndividual.normalized\_address} ```python def normalized_address() -> Union[Address, ALAddress] @@ -753,9 +689,7 @@ Fetches the normalized version of the address. Union[Address, ALAddress]: The normalized address object. - - -#### name\_fields(person\_or\_business: str = "person", show\_suffix: bool = True, show\_title: bool = False, title\_choices: Optional[Union[List[str], Callable]] = None, show\_if: Union[str, Dict[str, str], None] = None, maxlengths: Optional[Dict[str, int]] = None, suffix\_choices: Optional[Union[List[str], Callable]] = None, title\_options: Optional[Union[List[str], Callable]] = None) +#### name\_fields(person\_or\_business: str = "person", show\_suffix: bool = True, show\_title: bool = False, title\_choices: Optional[Union[List[str], Callable]] = None, show\_if: Union[str, Dict[str, str], None] = None, maxlengths: Optional[Dict[str, int]] = None, suffix\_choices: Optional[Union[List[str], Callable]] = None, title\_options: Optional[Union[List[str], Callable]] = None) {#AssemblyLine.al\_general.ALIndividual.name\_fields} ```python def name_fields( @@ -800,9 +734,7 @@ and other provided parameters. If `person_or_business` is set to None, the method will offer the end user a choice and will set appropriate "show ifs" conditions for each type. - - -#### address\_fields(country\_code: str = "US", default\_state: Optional[str] = None, show\_country: bool = False, show\_county: bool = False, show\_if: Union[str, Dict[str, str], None] = None, allow\_no\_address: bool = False, ask\_if\_impounded: bool = False, maxlengths: Optional[Dict[str, int]] = None, required: Optional[Dict[str, bool]] = None) +#### address\_fields(country\_code: str = "US", default\_state: Optional[str] = None, show\_country: bool = False, show\_county: bool = False, show\_if: Union[str, Dict[str, str], None] = None, allow\_no\_address: bool = False, ask\_if\_impounded: bool = False, maxlengths: Optional[Dict[str, int]] = None, required: Optional[Dict[str, bool]] = None) {#AssemblyLine.al\_general.ALIndividual.address\_fields} ```python def address_fields( @@ -836,9 +768,7 @@ Generate field prompts for capturing an address. List[Dict[str, str]]: A list of dictionaries with field prompts for addresses. - - -#### gender\_fields(show\_help=False, show\_if: Union[str, Dict[str, str], None] = None, maxlengths: Optional[Dict[str, int]] = None, choices: Optional[Union[List[Dict[str, str]], Callable]] = None) +#### gender\_fields(show\_help=False, show\_if: Union[str, Dict[str, str], None] = None, maxlengths: Optional[Dict[str, int]] = None, choices: Optional[Union[List[Dict[str, str]], Callable]] = None) {#AssemblyLine.al\_general.ALIndividual.gender\_fields} ```python def gender_fields( @@ -869,9 +799,7 @@ self-described option. self-described will provide an input that overrides the value of `gender` and is not persisted. - - -#### pronoun\_fields(show\_help=False, show\_if: Union[str, Dict[str, str], None] = None, required: bool = False, shuffle: bool = False, show\_unknown: Optional[Union[Literal["guess"], bool]] = "guess", maxlengths: Optional[Dict[str, int]] = None, choices: Optional[List[Dict[str, str]]] = None) +#### pronoun\_fields(show\_help=False, show\_if: Union[str, Dict[str, str], None] = None, required: bool = False, shuffle: bool = False, show\_unknown: Optional[Union[Literal["guess"], bool]] = "guess", maxlengths: Optional[Dict[str, int]] = None, choices: Optional[List[Dict[str, str]]] = None) {#AssemblyLine.al\_general.ALIndividual.pronoun\_fields} ```python def pronoun_fields( @@ -902,9 +830,7 @@ Generate fields for capturing pronoun information. List[Dict[str, str]]: A list of dictionaries with field prompts for pronouns. - - -#### get\_pronouns() +#### get\_pronouns() {#AssemblyLine.al\_general.ALIndividual.get\_pronouns} ```python def get_pronouns() -> set @@ -920,9 +846,7 @@ Can be formatted however the author likes. - `set` - A set of strings representing the individual's pronouns. - - -#### list\_pronouns() +#### list\_pronouns() {#AssemblyLine.al\_general.ALIndividual.list\_pronouns} ```python def list_pronouns() -> str @@ -935,9 +859,7 @@ the comma_list() function. - `str` - A formatted string of the individual's pronouns. - - -#### language\_fields(choices: Optional[Union[List[Dict[str, str]], Callable]] = None, style: str = "radio", show\_if: Union[str, Dict[str, str], None] = None, maxlengths: Optional[Dict[str, int]] = None) +#### language\_fields(choices: Optional[Union[List[Dict[str, str]], Callable]] = None, style: str = "radio", show\_if: Union[str, Dict[str, str], None] = None, maxlengths: Optional[Dict[str, int]] = None) {#AssemblyLine.al\_general.ALIndividual.language\_fields} ```python def language_fields( @@ -961,9 +883,7 @@ Generate fields for capturing language preferences. List[Dict[str, str]]: A list of dictionaries with field prompts for language preferences. - - -#### language\_name() +#### language\_name() {#AssemblyLine.al\_general.ALIndividual.language\_name} ```python def language_name() -> str @@ -977,9 +897,7 @@ Get the human-readable version of the individual's selected language. it returns the value in `language_other`. Otherwise, it uses the `language_name` function. - - -#### gender\_male() +#### gender\_male() {#AssemblyLine.al\_general.ALIndividual.gender\_male} ```python @property @@ -991,9 +909,7 @@ Returns True only if the gender is male. Used to assist with checkbox filling in PDFs with "skip undefined" turned on. - - -#### gender\_female() +#### gender\_female() {#AssemblyLine.al\_general.ALIndividual.gender\_female} ```python @property @@ -1005,9 +921,7 @@ Returns True only if the gender is female. Used to assist with checkbox filling in PDFs with "skip undefined" turned on. - - -#### gender\_other() +#### gender\_other() {#AssemblyLine.al\_general.ALIndividual.gender\_other} ```python @property @@ -1019,9 +933,7 @@ Returns True only if the gender is not male or female. Used to assist with checkbox filling in PDFs with "skip undefined" turned on. - - -#### gender\_nonbinary() +#### gender\_nonbinary() {#AssemblyLine.al\_general.ALIndividual.gender\_nonbinary} ```python @property @@ -1033,9 +945,7 @@ Returns True only if the gender is nonbinary. Used to assist with checkbox filling in PDFs with "skip undefined" turned on. - - -#### gender\_unknown() +#### gender\_unknown() {#AssemblyLine.al\_general.ALIndividual.gender\_unknown} ```python @property @@ -1047,9 +957,7 @@ Returns True only if the gender is unknown. Used to assist with checkbox filling in PDFs with "skip undefined" turned on. - - -#### gender\_undisclosed() +#### gender\_undisclosed() {#AssemblyLine.al\_general.ALIndividual.gender\_undisclosed} ```python @property @@ -1061,9 +969,7 @@ Returns True only if the gender is not disclosed ("prefer-not-to-say") Used to assist with checkbox filling in PDFs with "skip undefined" turned on. - - -#### gender\_self\_described() +#### gender\_self\_described() {#AssemblyLine.al\_general.ALIndividual.gender\_self\_described} ```python @property @@ -1075,9 +981,7 @@ Returns True only if the gender is self described. Used to assist with checkbox filling in PDFs with "skip undefined" turned on. - - -#### contact\_fields() +#### contact\_fields() {#AssemblyLine.al\_general.ALIndividual.contact\_fields} ```python def contact_fields() -> None @@ -1085,9 +989,7 @@ def contact_fields() -> None Return field prompts for other contact info - - -#### initials() +#### initials() {#AssemblyLine.al\_general.ALIndividual.initials} ```python @property @@ -1098,9 +1000,7 @@ Returns the initials of the individual as a string. For example, "Quinten K Steenhuis" would return "QKS". - - -#### address\_block(language=None, international=False, show\_country=False, bare=False, show\_impounded=False) +#### address\_block(language=None, international=False, show\_country=False, bare=False, show\_impounded=False) {#AssemblyLine.al\_general.ALIndividual.address\_block} ```python def address_block(language=None, @@ -1125,9 +1025,7 @@ Generate a formatted address block for mailings. - `str` - The formatted address block. - - -#### pronoun(\*\*kwargs) +#### pronoun(\*\*kwargs) {#AssemblyLine.al\_general.ALIndividual.pronoun} ```python def pronoun(**kwargs) -> str @@ -1151,9 +1049,7 @@ with `pronouns` taking precedence. As a default, it will either use the value of - `str` - The appropriate pronoun. - - -#### pronoun\_objective(\*\*kwargs) +#### pronoun\_objective(\*\*kwargs) {#AssemblyLine.al\_general.ALIndividual.pronoun\_objective} ```python def pronoun_objective(**kwargs) -> str @@ -1170,9 +1066,7 @@ Returns the same pronoun as the `pronoun()` method. - `str` - The appropriate objective pronoun. - - -#### pronoun\_possessive(target, \*\*kwargs) +#### pronoun\_possessive(target, \*\*kwargs) {#AssemblyLine.al\_general.ALIndividual.pronoun\_possessive} ```python def pronoun_possessive(target, **kwargs) -> str @@ -1199,9 +1093,7 @@ and whether the individual is the current user. - `str` - The appropriate possessive phrase, e.g., "her book", "their document". - - -#### pronoun\_subjective(\*\*kwargs) +#### pronoun\_subjective(\*\*kwargs) {#AssemblyLine.al\_general.ALIndividual.pronoun\_subjective} ```python def pronoun_subjective(**kwargs) -> str @@ -1223,9 +1115,7 @@ is the current user. - `str` - The appropriate subjective pronoun. - - -#### pronoun\_reflexive(\*\*kwargs) +#### pronoun\_reflexive(\*\*kwargs) {#AssemblyLine.al\_general.ALIndividual.pronoun\_reflexive} ```python def pronoun_reflexive(**kwargs) -> str @@ -1249,9 +1139,7 @@ See: https://www.merriam-webster.com/wordplay/themself - `str` - The appropriate reflexive pronoun. - - -#### name\_full() +#### name\_full() {#AssemblyLine.al\_general.ALIndividual.name\_full} ```python def name_full() -> str @@ -1267,9 +1155,7 @@ the first name, even if middle, last, or suffix are defined. - `str` - The individual or business's full name. - - -#### name\_initials() +#### name\_initials() {#AssemblyLine.al\_general.ALIndividual.name\_initials} ```python def name_initials() -> str @@ -1287,9 +1173,7 @@ the "initials" of the first name, even if middle, last, or suffix are - `str` - The individual's name with the middle name as an initial. - - -#### name\_short() +#### name\_short() {#AssemblyLine.al\_general.ALIndividual.name\_short} ```python def name_short() -> str @@ -1307,9 +1191,7 @@ the first name, even if middle, last, or suffix are defined. - `str` - The individual' - - -#### familiar(unique\_names: Optional[List[Any]] = None, default: Optional[str] = None) +#### familiar(unique\_names: Optional[List[Any]] = None, default: Optional[str] = None) {#AssemblyLine.al\_general.ALIndividual.familiar} ```python def familiar(unique_names: Optional[List[Any]] = None, @@ -1354,9 +1236,7 @@ the first name, even if middle, last, or suffix are defined. Who do you want to take care of $\{ children.familiar(unique_names=parents + petitioners, default="the minor") \} ``` - - -#### \_\_str\_\_() +#### \_\_str\_\_() {#AssemblyLine.al\_general.ALIndividual.\_\_str\_\_} ```python def __str__() -> str @@ -1373,9 +1253,7 @@ the first name, even if middle, last, or suffix are defined. - `str` - The individual's name. - - -#### section\_links(nav) +#### section\_links(nav) {#AssemblyLine.al\_general.section\_links} ```python def section_links(nav) -> List[str] @@ -1392,9 +1270,7 @@ Returns a list of clickable navigation links without animation. - `List[str]` - A list of clickable navigation links without animation. - - -#### will\_send\_to\_real\_court() +#### will\_send\_to\_real\_court() {#AssemblyLine.al\_general.will\_send\_to\_real\_court} ```python def will_send_to_real_court() -> bool @@ -1409,9 +1285,7 @@ The text "dev" or "test" needs to be in the URL root in the - `bool` - True if the form is being run on the dev, test, or production server. - - -#### filter\_letters(letter\_strings: Union[List[str], str]) +#### filter\_letters(letter\_strings: Union[List[str], str]) {#AssemblyLine.al\_general.filter\_letters} ```python def filter_letters(letter_strings: Union[List[str], str]) -> str @@ -1430,9 +1304,7 @@ Avoid using, this is created for 209A. - `str` - A string of unique letters. - - -#### fa\_icon(icon: str, color: str = "primary", color\_css: Optional[str] = None, size: str = "sm") +#### fa\_icon(icon: str, color: str = "primary", color\_css: Optional[str] = None, size: str = "sm") {#AssemblyLine.al\_general.fa\_icon} ```python def fa_icon(icon: str, @@ -1457,9 +1329,7 @@ a CSS variable (such as Bootstrap theme color) or a true CSS color reference, su - `str` - HTML for the icon. - - -#### is\_sms\_enabled() +#### is\_sms\_enabled() {#AssemblyLine.al\_general.is\_sms\_enabled} ```python def is_sms_enabled() -> bool @@ -1473,9 +1343,7 @@ See https://docassemble.org/docs/config.html#twilio for more info. - `bool` - True if there is a non-empty Twilio config on the server, False otherwise - - -#### is\_phone\_or\_email(text: str) +#### is\_phone\_or\_email(text: str) {#AssemblyLine.al\_general.is\_phone\_or\_email} ```python def is_phone_or_email(text: str) -> bool @@ -1500,9 +1368,7 @@ strings. DAValidationError if the string is neither a valid phone number nor a valid email address. - - -#### github\_modified\_date(github\_user: str, github\_repo\_name: str, auth=None) +#### github\_modified\_date(github\_user: str, github\_repo\_name: str, auth=None) {#AssemblyLine.al\_general.github\_modified\_date} ```python def github_modified_date(github_user: str, @@ -1540,9 +1406,7 @@ The GitHub API is rate-limited to 60 anonymous API queries/hour. Union[DADateTime, None]: The date that the given GitHub repository was modified or None if API call fails. - - -#### language\_name(language\_code: str) +#### language\_name(language\_code: str) {#AssemblyLine.al\_general.language\_name} ```python def language_name(language_code: str) -> str @@ -1561,9 +1425,7 @@ function. - `str` - The full name of the language. - - -#### safe\_states\_list(country\_code: str) +#### safe\_states\_list(country\_code: str) {#AssemblyLine.al\_general.safe\_states\_list} ```python def safe_states_list(country_code: str) -> List[Dict[str, str]] @@ -1581,9 +1443,7 @@ an invalid country_code (e.g., a country name spelled out) List[Dict[str, str]]: A list of dictionaries with field prompts for states. - - -#### has\_parsable\_pronouns(pronouns: str) +#### has\_parsable\_pronouns(pronouns: str) {#AssemblyLine.al\_general.has\_parsable\_pronouns} ```python def has_parsable_pronouns(pronouns: str) -> bool @@ -1600,9 +1460,7 @@ Returns True if the pronouns string can be parsed into a dictionary of pronouns. True if the pronouns string can be parsed into a dictionary of pronouns, False otherwise - - -#### parse\_custom\_pronouns(pronouns: str) +#### parse\_custom\_pronouns(pronouns: str) {#AssemblyLine.al\_general.parse\_custom\_pronouns} ```python def parse_custom_pronouns(pronouns: str) -> Dict[str, str] @@ -1619,9 +1477,7 @@ Parses a custom pronoun string into a dictionary of pronouns. a dictionary of pronouns in the format \{"o": objective, "s": subjective, "p": possessive\} - - -#### get\_visible\_al\_nav\_items(nav\_items: List[Union[str, dict]]) +#### get\_visible\_al\_nav\_items(nav\_items: List[Union[str, dict]]) {#AssemblyLine.al\_general.get\_visible\_al\_nav\_items} ```python def get_visible_al_nav_items( diff --git a/docs/components/AssemblyLine/background_assembly.md b/docs/components/AssemblyLine/background_assembly.md index 484dcfc81..ac2c1e198 100644 --- a/docs/components/AssemblyLine/background_assembly.md +++ b/docs/components/AssemblyLine/background_assembly.md @@ -161,7 +161,7 @@ Optionally, it will also produce a .ZIP and a .PDF version of the full bundle. This is called from a YAML block in the Assembly Line standard include files to define the `_downloadable_files` attribute of a bundle. -[download_list_html()](al_document.md#download_list_html) has an optional parameter, +[download_list_html()](al_document.md#AssemblyLine.al_document.ALDocumentBundle.download_list_html) has an optional parameter, `use_previously_cached_files` which must be set to `True` to make use of the `_downloadable_files` attribute of the bundle. diff --git a/docs/components/AssemblyLine/custom_jinja_filters.md b/docs/components/AssemblyLine/custom_jinja_filters.md index ec4daeaa0..1a143dc72 100644 --- a/docs/components/AssemblyLine/custom_jinja_filters.md +++ b/docs/components/AssemblyLine/custom_jinja_filters.md @@ -1,6 +1,6 @@ # Table of Contents -* [AssemblyLine.custom\_jinja\_filters](#AssemblyLine.custom_jinja_filters) +* AssemblyLine.custom\_jinja\_filters * [catchall\_options](#AssemblyLine.custom_jinja_filters.catchall_options) * [catchall\_label](#AssemblyLine.custom_jinja_filters.catchall_label) * [catchall\_datatype](#AssemblyLine.custom_jinja_filters.catchall_datatype) @@ -14,9 +14,7 @@ sidebar_label: custom_jinja_filters title: AssemblyLine.custom_jinja_filters --- - - -#### catchall\_options(value: Any, \*raw\_items: Any) +#### catchall\_options(value: Any, \*raw\_items: Any) {#AssemblyLine.custom\_jinja\_filters.catchall\_options} ```python def catchall_options(value: Any, *raw_items: Any) -> DACatchAll @@ -69,9 +67,7 @@ fields: - `DACatchAll` - The modified DACatchAll object with the assigned options. - - -#### catchall\_label(value: Any, label: str) +#### catchall\_label(value: Any, label: str) {#AssemblyLine.custom\_jinja\_filters.catchall\_label} ```python def catchall_label(value: Any, label: str) -> DACatchAll @@ -107,9 +103,7 @@ fields: - `DACatchAll` - The modified DACatchAll object with the assigned label. - - -#### catchall\_datatype(value: Any, datatype: str) +#### catchall\_datatype(value: Any, datatype: str) {#AssemblyLine.custom\_jinja\_filters.catchall\_datatype} ```python def catchall_datatype(value: Any, datatype: str) -> DACatchAll @@ -137,9 +131,7 @@ Example usage in a DOCX template: - `DACatchAll` - The modified DACatchAll object with the assigned datatype. - - -#### catchall\_question(value: Any, question: str) +#### catchall\_question(value: Any, question: str) {#AssemblyLine.custom\_jinja\_filters.catchall\_question} ```python def catchall_question(value: Any, question: str) -> DACatchAll @@ -167,9 +159,7 @@ Example usage in a DOCX template: - `DACatchAll` - The modified DACatchAll object with the assigned question. - - -#### catchall\_subquestion(value: Any, subquestion: str) +#### catchall\_subquestion(value: Any, subquestion: str) {#AssemblyLine.custom\_jinja\_filters.catchall\_subquestion} ```python def catchall_subquestion(value: Any, subquestion: str) -> DACatchAll @@ -197,9 +187,7 @@ Example usage in a DOCX template: - `DACatchAll` - The modified DACatchAll object with the assigned subquestion. - - -#### if\_final(context: Jinja2Context, value: Any, i: Optional[str] = None, expected\_i: Union[str, List[str]] = "final", placeholder: Optional[str] = None) +#### if\_final(context: Jinja2Context, value: Any, i: Optional[str] = None, expected\_i: Union[str, List[str]] = "final", placeholder: Optional[str] = None) {#AssemblyLine.custom\_jinja\_filters.if\_final} ```python @pass_context @@ -283,9 +271,7 @@ as in an ALDocument's "preview" or "final" values. - `Any` - The original `value` if `i` matches `expected_i`, otherwise the `placeholder`. - - -#### catchall\_fields\_code(value: Any) +#### catchall\_fields\_code(value: Any) {#AssemblyLine.custom\_jinja\_filters.catchall\_fields\_code} ```python def catchall_fields_code(value: Any) -> List[Dict[str, Any]] diff --git a/docs/components/AssemblyLine/language.md b/docs/components/AssemblyLine/language.md index 72d1826e4..70c864c14 100644 --- a/docs/components/AssemblyLine/language.md +++ b/docs/components/AssemblyLine/language.md @@ -1,6 +1,6 @@ # Table of Contents -* [AssemblyLine.language](#AssemblyLine.language) +* AssemblyLine.language * [get\_local\_languages\_yaml](#AssemblyLine.language.get_local_languages_yaml) * [get\_tuples](#AssemblyLine.language.get_tuples) * [get\_language\_list\_dropdown](#AssemblyLine.language.get_language_list_dropdown) @@ -13,9 +13,7 @@ sidebar_label: language title: AssemblyLine.language --- - - -#### get\_local\_languages\_yaml() +#### get\_local\_languages\_yaml() {#AssemblyLine.language.get\_local\_languages\_yaml} ```python def get_local_languages_yaml() -> str @@ -27,9 +25,7 @@ Get the path to the local languages.yml file. If it does not exist, it will retu - `str` - the path to the local languages.yml file if it exists, otherwise the path to the languages.yml file - - -#### get\_tuples(lang\_codes: List[str], languages\_path: Optional[str] = None) +#### get\_tuples(lang\_codes: List[str], languages\_path: Optional[str] = None) {#AssemblyLine.language.get\_tuples} ```python def get_tuples(lang_codes: List[str], @@ -51,9 +47,7 @@ English name from pycountry. If neither is present, it will use the language cod A list of tuples representing the language name, followed by language ISO 639-1 code. - - -#### get\_language\_list\_dropdown(lang\_codes: List[str], current: str = "", languages\_path: Optional[str] = None, event\_name="al\_change\_language", icon="fa-solid fa-language fa-xl", extra\_class: str = "text-light") +#### get\_language\_list\_dropdown(lang\_codes: List[str], current: str = "", languages\_path: Optional[str] = None, event\_name="al\_change\_language", icon="fa-solid fa-language fa-xl", extra\_class: str = "text-light") {#AssemblyLine.language.get\_language\_list\_dropdown} ```python def get_language_list_dropdown(lang_codes: List[str], @@ -79,9 +73,7 @@ Get a Bootstrap 5 dropdown menu for language selection that can be added to navi A string containing the HTML for a dropdown menu for language selection. - - -#### get\_language\_list\_dropdown\_item(language: Tuple[str, str], link: bool = True, event\_name="al\_change\_language") +#### get\_language\_list\_dropdown\_item(language: Tuple[str, str], link: bool = True, event\_name="al\_change\_language") {#AssemblyLine.language.get\_language\_list\_dropdown\_item} ```python def get_language_list_dropdown_item(language: Tuple[str, str], @@ -103,9 +95,7 @@ given in the first part of the tuple. - `str` - A string containing the HTML for a dropdown menu item for language selection. - - -#### get\_language\_list(languages: Optional[List[Tuple[str, str]]] = None, current="", lang\_codes: Optional[List[str]] = None, languages\_path: Optional[str] = None, event\_name="al\_get\_language\_list\_change\_language") +#### get\_language\_list(languages: Optional[List[Tuple[str, str]]] = None, current="", lang\_codes: Optional[List[str]] = None, languages\_path: Optional[str] = None, event\_name="al\_get\_language\_list\_change\_language") {#AssemblyLine.language.get\_language\_list} ```python def get_language_list(languages: Optional[List[Tuple[str, str]]] = None, @@ -134,9 +124,7 @@ tuples containing the language name and language code. This is deprecated and ma A string containing the HTML for an unordered inline list of language selection. - - -#### get\_language\_list\_item(language, link=True, event\_name="al\_change\_language") +#### get\_language\_list\_item(language, link=True, event\_name="al\_change\_language") {#AssemblyLine.language.get\_language\_list\_item} ```python def get_language_list_item(language, diff --git a/docs/components/AssemblyLine/sessions.md b/docs/components/AssemblyLine/sessions.md index 1e50687b0..1d0f125a2 100644 --- a/docs/components/AssemblyLine/sessions.md +++ b/docs/components/AssemblyLine/sessions.md @@ -1,6 +1,6 @@ # Table of Contents -* [AssemblyLine.sessions](#AssemblyLine.sessions) +* AssemblyLine.sessions * [is\_file\_like](#AssemblyLine.sessions.is_file_like) * [set\_interview\_metadata](#AssemblyLine.sessions.set_interview_metadata) * [get\_interview\_metadata](#AssemblyLine.sessions.get_interview_metadata) @@ -35,9 +35,7 @@ sidebar_label: sessions title: AssemblyLine.sessions --- - - -#### is\_file\_like(obj: Any) +#### is\_file\_like(obj: Any) {#AssemblyLine.sessions.is\_file\_like} ```python def is_file_like(obj: Any) -> bool @@ -54,9 +52,7 @@ Return True if the object is a file-like object. - `bool` - True if the object is a file-like object. - - -#### set\_interview\_metadata(filename: str, session\_id: str, data: Dict, metadata\_key\_name="metadata") +#### set\_interview\_metadata(filename: str, session\_id: str, data: Dict, metadata\_key\_name="metadata") {#AssemblyLine.sessions.set\_interview\_metadata} ```python def set_interview_metadata(filename: str, @@ -80,9 +76,7 @@ Standardized metadata dictionary: - `data` _Dict_ - The metadata to add - `metadata_key_name` _str, optional_ - The name of the metadata key. Defaults to "metadata". - - -#### get\_interview\_metadata(filename: str, session\_id: str, metadata\_key\_name: str = "metadata") +#### get\_interview\_metadata(filename: str, session\_id: str, metadata\_key\_name: str = "metadata") {#AssemblyLine.sessions.get\_interview\_metadata} ```python def get_interview_metadata( @@ -105,9 +99,7 @@ We implement this with the docassemble jsonstorage table and a dedicated `tag` w Dict[str, Any]: The metadata associated with the interview - - -#### get\_saved\_interview\_list(filename: Optional[str] = al\_session\_store\_default\_filename, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", limit: int = 50, offset: int = 0, filename\_to\_exclude: str = "", exclude\_current\_filename: bool = True, exclude\_filenames: Optional[List[str]] = None, exclude\_newly\_started\_sessions: bool = False) +#### get\_saved\_interview\_list(filename: Optional[str] = al\_session\_store\_default\_filename, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", limit: int = 50, offset: int = 0, filename\_to\_exclude: str = "", exclude\_current\_filename: bool = True, exclude\_filenames: Optional[List[str]] = None, exclude\_newly\_started\_sessions: bool = False) {#AssemblyLine.sessions.get\_saved\_interview\_list} ```python def get_saved_interview_list( @@ -150,9 +142,7 @@ an existing interview to the answer set. List[Dict[str, Any]]: A list of saved sessions for the specified filename. - - -#### find\_matching\_sessions(keyword: str, metadata\_column\_names: Optional[Union[Set[str], List[str]]] = None, filenames: Optional[Union[Set[str], List[str]]] = None, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", limit: int = 50, offset: int = 0, filename\_to\_exclude: str = "", exclude\_current\_filename: bool = True, exclude\_filenames: Optional[List[str]] = None, exclude\_newly\_started\_sessions: bool = False, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None, metadata\_filters: Optional[Dict[str, Tuple[Any, str, Optional[str]]]] = None) +#### find\_matching\_sessions(keyword: str, metadata\_column\_names: Optional[Union[Set[str], List[str]]] = None, filenames: Optional[Union[Set[str], List[str]]] = None, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", limit: int = 50, offset: int = 0, filename\_to\_exclude: str = "", exclude\_current\_filename: bool = True, exclude\_filenames: Optional[List[str]] = None, exclude\_newly\_started\_sessions: bool = False, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None, metadata\_filters: Optional[Dict[str, Tuple[Any, str, Optional[str]]]] = None) {#AssemblyLine.sessions.find\_matching\_sessions} ```python def find_matching_sessions( @@ -221,9 +211,7 @@ The keyword search is case-insensitive and will match any part of the metadata c - `\{"owner"` - ("samantha", "ILIKE", None), "age": (30, ">=", "int"), "status": ("%complete%", "LIKE", None)\} - - -#### delete\_interview\_sessions(user\_id: Optional[int] = None, filename\_to\_exclude: str = al\_session\_store\_default\_filename, exclude\_current\_filename: bool = True) +#### delete\_interview\_sessions(user\_id: Optional[int] = None, filename\_to\_exclude: str = al\_session\_store\_default\_filename, exclude\_current\_filename: bool = True) {#AssemblyLine.sessions.delete\_interview\_sessions} ```python def delete_interview_sessions( @@ -242,9 +230,7 @@ interview_list(action="delete_all") is both quite slow and because it - `filename_to_exclude` _str, optional_ - The filename to exclude from the results. Defaults to al_session_store_default_filename. - `exclude_current_filename` _bool, optional_ - Whether to exclude the current filename from the results. Defaults to True. - - -#### interview\_list\_html(filename: str = al\_session\_store\_default\_filename, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", exclude\_newly\_started\_sessions=False, date\_label: str = word("Date"), details\_label: str = word("Details"), actions\_label: str = word("Actions"), delete\_label: str = word("Delete"), view\_label: str = word("View"), load\_action: str = "al\_sessions\_fast\_forward\_session", delete\_action: str = "al\_sessions\_delete\_session", view\_only: bool = False, limit: int = 50, offset: int = 0, display\_interview\_title: bool = True, show\_view\_button: bool = True, answers: Optional[List[Dict[str, Any]]] = None) +#### interview\_list\_html(filename: str = al\_session\_store\_default\_filename, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", exclude\_newly\_started\_sessions=False, date\_label: str = word("Date"), details\_label: str = word("Details"), actions\_label: str = word("Actions"), delete\_label: str = word("Delete"), view\_label: str = word("View"), load\_action: str = "al\_sessions\_fast\_forward\_session", delete\_action: str = "al\_sessions\_delete\_session", view\_only: bool = False, limit: int = 50, offset: int = 0, display\_interview\_title: bool = True, show\_view\_button: bool = True, answers: Optional[List[Dict[str, Any]]] = None) {#AssemblyLine.sessions.interview\_list\_html} ```python def interview_list_html(filename: str = al_session_store_default_filename, @@ -302,9 +288,7 @@ itself in a way that adds additional steps) - `str` - HTML-formatted table containing the list of saved answers. - - -#### nice\_interview\_title(answer: Dict[str, str]) +#### nice\_interview\_title(answer: Dict[str, str]) {#AssemblyLine.sessions.nice\_interview\_title} ```python def nice_interview_title(answer: Dict[str, str]) -> str @@ -325,9 +309,7 @@ in descending priority order. - `str` - The human readable interview title - - -#### pascal\_to\_zwspace(text: str) +#### pascal\_to\_zwspace(text: str) {#AssemblyLine.sessions.pascal\_to\_zwspace} ```python def pascal_to_zwspace(text: str) -> str @@ -345,9 +327,7 @@ with word breaks on small viewports. - `str` - The text with zero-width spaces inserted - - -#### nice\_interview\_subtitle(answer: Dict[str, str], exclude\_identical=True) +#### nice\_interview\_subtitle(answer: Dict[str, str], exclude\_identical=True) {#AssemblyLine.sessions.nice\_interview\_subtitle} ```python def nice_interview_subtitle(answer: Dict[str, str], @@ -368,9 +348,7 @@ If exclude_identical, return empty string when title is the same as the subtitle - `str` - The human readable interview subtitle - - -#### radial\_progress(answer: Dict[str, Union[str, int]]) +#### radial\_progress(answer: Dict[str, Union[str, int]]) {#AssemblyLine.sessions.radial\_progress} ```python def radial_progress(answer: Dict[str, Union[str, int]]) -> str @@ -387,9 +365,7 @@ Return HTML for a radial progress bar, or the number of steps if progress isn&#x - `str` - the HTML as a string - - -#### local\_date(utcstring: Optional[str]) +#### local\_date(utcstring: Optional[str]) {#AssemblyLine.sessions.local\_date} ```python def local_date(utcstring: Optional[str]) -> DADateTime @@ -406,9 +382,7 @@ Return a localized date from a UTC string. - `DADateTime` - The localized date - - -#### session\_list\_html(filename: Optional[str] = None, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", filename\_to\_exclude: str = al\_session\_store\_default\_filename, exclude\_current\_filename: bool = True, exclude\_filenames: Optional[List[str]] = None, exclude\_newly\_started\_sessions: bool = False, name\_label: str = word("Title"), date\_label: str = word("Date modified"), details\_label: str = word("Progress"), actions\_label: str = word("Actions"), delete\_label: str = word("Delete"), rename\_label: str = word("Rename"), rename\_action: str = "interview\_list\_rename\_action", delete\_action: str = "interview\_list\_delete\_session", copy\_action: str = "interview\_list\_copy\_action", clone\_label: str = word("Copy as answer set"), show\_title: bool = True, show\_copy\_button: bool = True, limit: int = 50, offset: int = 0, answers: Optional[List[Dict[str, Any]]] = None) +#### session\_list\_html(filename: Optional[str] = None, user\_id: Union[int, str, None] = None, metadata\_key\_name: str = "metadata", filename\_to\_exclude: str = al\_session\_store\_default\_filename, exclude\_current\_filename: bool = True, exclude\_filenames: Optional[List[str]] = None, exclude\_newly\_started\_sessions: bool = False, name\_label: str = word("Title"), date\_label: str = word("Date modified"), details\_label: str = word("Progress"), actions\_label: str = word("Actions"), delete\_label: str = word("Delete"), rename\_label: str = word("Rename"), rename\_action: str = "interview\_list\_rename\_action", delete\_action: str = "interview\_list\_delete\_session", copy\_action: str = "interview\_list\_copy\_action", clone\_label: str = word("Copy as answer set"), show\_title: bool = True, show\_copy\_button: bool = True, limit: int = 50, offset: int = 0, answers: Optional[List[Dict[str, Any]]] = None) {#AssemblyLine.sessions.session\_list\_html} ```python def session_list_html( @@ -471,9 +445,7 @@ user sessions. The results exclude the answer set filename by default. - `str` - HTML-formatted table containing the list of user sessions. - - -#### rename\_interview\_answers(filename: str, session\_id: str, new\_name: str, metadata\_key\_name: str = "metadata") +#### rename\_interview\_answers(filename: str, session\_id: str, new\_name: str, metadata\_key\_name: str = "metadata") {#AssemblyLine.sessions.rename\_interview\_answers} ```python def rename_interview_answers(filename: str, @@ -494,9 +466,7 @@ metadata that may be present. If exception is raised in set_session_variables, this will silently fail but log the error. - - -#### set\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") +#### set\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") {#AssemblyLine.sessions.set\_current\_session\_metadata} ```python def set_current_session_metadata(data: Dict[str, Any], @@ -510,9 +480,7 @@ Set metadata for the current session, such as the title, in an unencrypted datab - `data` _Dict[str, Any]_ - The metadata to set - `metadata_key_name` _str, optional_ - The name of the metadata key. Defaults to "metadata". - - -#### rename\_current\_session(new\_name: str, metadata\_key\_name: str = "metadata") +#### rename\_current\_session(new\_name: str, metadata\_key\_name: str = "metadata") {#AssemblyLine.sessions.rename\_current\_session} ```python def rename_current_session(new_name: str, @@ -527,9 +495,7 @@ metadata that might be present. - `new_name` _str_ - The new name to set for the interview - `metadata_key_name` _str, optional_ - The name of the metadata key. Defaults to "metadata". - - -#### save\_interview\_answers(filename: str = al\_session\_store\_default\_filename, variables\_to\_filter: Union[Set[str], List[str], None] = None, metadata: Optional[Dict] = None, metadata\_key\_name: str = "metadata", original\_interview\_filename=None, source\_filename=None, source\_session=None, additional\_variables\_to\_filter=None) +#### save\_interview\_answers(filename: str = al\_session\_store\_default\_filename, variables\_to\_filter: Union[Set[str], List[str], None] = None, metadata: Optional[Dict] = None, metadata\_key\_name: str = "metadata", original\_interview\_filename=None, source\_filename=None, source\_session=None, additional\_variables\_to\_filter=None) {#AssemblyLine.sessions.save\_interview\_answers} ```python def save_interview_answers(filename: str = al_session_store_default_filename, @@ -561,9 +527,7 @@ Copies the answers from a given session into a new session with a specified inte - `str` - ID of the new session. - - -#### get\_filtered\_session\_variables(filename: Optional[str] = None, session\_id: Optional[str] = None, variables\_to\_filter: Optional[Union[Set[str], List[str]]] = None, additional\_variables\_to\_filter: Optional[Union[Set[str], List[str]]] = None) +#### get\_filtered\_session\_variables(filename: Optional[str] = None, session\_id: Optional[str] = None, variables\_to\_filter: Optional[Union[Set[str], List[str]]] = None, additional\_variables\_to\_filter: Optional[Union[Set[str], List[str]]] = None) {#AssemblyLine.sessions.get\_filtered\_session\_variables} ```python def get_filtered_session_variables( @@ -590,9 +554,7 @@ from the current interview. Dict[str, Any]: A dictionary of filtered session variables. - - -#### get\_filtered\_session\_variables\_string(filename: Optional[str] = None, session\_id: Optional[str] = None, variables\_to\_filter: Union[Set[str], List[str], None] = None, additional\_variables\_to\_filter: Optional[Union[Set[str], List[str]]] = None, indent: int = 4) +#### get\_filtered\_session\_variables\_string(filename: Optional[str] = None, session\_id: Optional[str] = None, variables\_to\_filter: Union[Set[str], List[str], None] = None, additional\_variables\_to\_filter: Optional[Union[Set[str], List[str]]] = None, indent: int = 4) {#AssemblyLine.sessions.get\_filtered\_session\_variables\_string} ```python def get_filtered_session_variables_string( @@ -620,9 +582,7 @@ If no filename and session ID are provided, the current session's variables - `str` - A JSON-formatted string of filtered session variables. - - -#### load\_interview\_answers(old\_interview\_filename: str, old\_session\_id: str, new\_session: bool = False, new\_interview\_filename: Optional[str] = None, variables\_to\_filter: Optional[List[str]] = None, additional\_variables\_to\_filter: Optional[List[str]] = None) +#### load\_interview\_answers(old\_interview\_filename: str, old\_session\_id: str, new\_session: bool = False, new\_interview\_filename: Optional[str] = None, variables\_to\_filter: Optional[List[str]] = None, additional\_variables\_to\_filter: Optional[List[str]] = None) {#AssemblyLine.sessions.load\_interview\_answers} ```python def load_interview_answers( @@ -653,9 +613,7 @@ the active session. This function is primarily used for migrating answers betwee Optional[Union[int, bool]]: ID of the newly created session if `new_session` is True, otherwise True or False based on success. - - -#### load\_interview\_json(json\_string: str, new\_session: bool = False, new\_interview\_filename: Optional[str] = None, variables\_to\_filter: Optional[List[str]] = None) +#### load\_interview\_json(json\_string: str, new\_session: bool = False, new\_interview\_filename: Optional[str] = None, variables\_to\_filter: Optional[List[str]] = None) {#AssemblyLine.sessions.load\_interview\_json} ```python def load_interview_json( @@ -681,9 +639,7 @@ If the `new_session` argument is not set, the JSON answers will be loaded into t Optional[Union[int, bool]]: ID of the newly created session if `new_session` is True, otherwise True or False based on success. - - -#### export\_interview\_variables(filename: Optional[str] = None, session\_id: Optional[str] = None, variables\_to\_filter: Union[Set, List[str], None] = None, output: DAFile = None, additional\_variables\_to\_filter: Union[Set, List[str], None] = None) +#### export\_interview\_variables(filename: Optional[str] = None, session\_id: Optional[str] = None, variables\_to\_filter: Union[Set, List[str], None] = None, output: DAFile = None, additional\_variables\_to\_filter: Union[Set, List[str], None] = None) {#AssemblyLine.sessions.export\_interview\_variables} ```python def export_interview_variables( @@ -712,9 +668,7 @@ The resultant output is compatible with `set_session_variables(process_objects=T - `DAFile` - DAFile with a JSON representation of the answers - - -#### is\_valid\_json(json\_string: str) +#### is\_valid\_json(json\_string: str) {#AssemblyLine.sessions.is\_valid\_json} ```python def is_valid_json(json_string: str) -> bool @@ -731,9 +685,7 @@ Checks if the provided string is a valid JSON-formatted string. - `bool` - True if the string is a valid JSON, otherwise it raises a validation error and returns False. - - -#### config\_with\_language\_fallback(config\_key: str, top\_level\_config\_key: Optional[str] = None) +#### config\_with\_language\_fallback(config\_key: str, top\_level\_config\_key: Optional[str] = None) {#AssemblyLine.sessions.config\_with\_language\_fallback} ```python def config_with_language_fallback( @@ -766,9 +718,7 @@ short title: My forms - `str` - The value of the config key, or the alternative key, or None. - - -#### get\_filenames\_having\_sessions(user\_id: Optional[Union[int, str]] = None, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None) +#### get\_filenames\_having\_sessions(user\_id: Optional[Union[int, str]] = None, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None) {#AssemblyLine.sessions.get\_filenames\_having\_sessions} ```python def get_filenames_having_sessions( @@ -790,9 +740,7 @@ to help show the user a good list of interviews to filter search results. - `List[str]` - List of filenames that have sessions saved for the user. - - -#### get\_combined\_filename\_list(user\_id: Optional[Union[int, str]] = None, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None) +#### get\_combined\_filename\_list(user\_id: Optional[Union[int, str]] = None, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None) {#AssemblyLine.sessions.get\_combined\_filename\_list} ```python def get_combined_filename_list( @@ -818,9 +766,7 @@ radio button and dropdown list expect. List[Dict[str, str]]: List of filenames that have sessions saved for the user. - - -#### update\_session\_metadata(filename: str, session\_id: str, data: Dict[str, Any], metadata\_key\_name: str = "metadata") +#### update\_session\_metadata(filename: str, session\_id: str, data: Dict[str, Any], metadata\_key\_name: str = "metadata") {#AssemblyLine.sessions.update\_session\_metadata} ```python def update_session_metadata(filename: str, @@ -839,9 +785,7 @@ Upsert session metadata into jsonstorage using a PostgreSQL advisory lock - `data` - A dict of metadata to add or update. - `metadata_key_name` - The tag for the metadata in jsonstorage. Defaults to "metadata". - - -#### update\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") +#### update\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") {#AssemblyLine.sessions.update\_current\_session\_metadata} ```python def update_current_session_metadata(data: Dict[str, Any], diff --git a/docs/components/AssemblyLine/sign.md b/docs/components/AssemblyLine/sign.md index 1d2e98e14..949776f37 100644 --- a/docs/components/AssemblyLine/sign.md +++ b/docs/components/AssemblyLine/sign.md @@ -1,6 +1,6 @@ # Table of Contents -* [AssemblyLine.sign](#AssemblyLine.sign) +* AssemblyLine.sign * [find\_font\_file\_by\_name](#AssemblyLine.sign.find_font_file_by_name) * [get\_font](#AssemblyLine.sign.get_font) * [create\_signature](#AssemblyLine.sign.create_signature) @@ -10,9 +10,7 @@ sidebar_label: sign title: AssemblyLine.sign --- - - -#### find\_font\_file\_by\_name(font\_name: str, search\_dirs: List[str]) +#### find\_font\_file\_by\_name(font\_name: str, search\_dirs: List[str]) {#AssemblyLine.sign.find\_font\_file\_by\_name} ```python def find_font_file_by_name(font_name: str, @@ -35,9 +33,7 @@ matches the font name (case-insensitive). - `Optional[str]` - The full path to the font file if found; otherwise, None. - - -#### get\_font(font\_name: Optional[str] = None, font\_size: int = 48) +#### get\_font(font\_name: Optional[str] = None, font\_size: int = 48) {#AssemblyLine.sign.get\_font} ```python def get_font( @@ -63,9 +59,7 @@ if necessary. If no font is found, the function falls back to the default Pillow - `ImageFont.ImageFont` - The loaded font instance. - - -#### create\_signature(name: str, output\_file: str, signature\_prefix: str = "/s/", font\_name: Optional[str] = None, font\_size: int = 48) +#### create\_signature(name: str, output\_file: str, signature\_prefix: str = "/s/", font\_name: Optional[str] = None, font\_size: int = 48) {#AssemblyLine.sign.create\_signature} ```python def create_signature(name: str, diff --git a/docs/components/EFSPIntegration/conversions.md b/docs/components/EFSPIntegration/conversions.md index 9e2bd902b..65ac30fb6 100644 --- a/docs/components/EFSPIntegration/conversions.md +++ b/docs/components/EFSPIntegration/conversions.md @@ -1,6 +1,6 @@ # Table of Contents -* [EFSPIntegration.conversions](#EFSPIntegration.conversions) +* EFSPIntegration.conversions * [error\_notification](#EFSPIntegration.conversions.error_notification) * [log\_error\_and\_notify](#EFSPIntegration.conversions.log_error_and_notify) * [convert\_court\_to\_id](#EFSPIntegration.conversions.convert_court_to_id) @@ -25,9 +25,7 @@ title: EFSPIntegration.conversions Functions that help convert the JSON-ized XML from the proxy server into usable information. - - -#### error\_notification(err, message=None, trace=None, referer=None, the\_vars=None) +#### error\_notification(err, message=None, trace=None, referer=None, the\_vars=None) {#EFSPIntegration.conversions.error\_notification} ```python def error_notification(err, @@ -43,9 +41,7 @@ Copied from docassemble.webapp.server.error_notification, since: Some slight modifications to work without server backends - - -#### log\_error\_and\_notify(context: str, resp: Optional[ApiResponse] = None) +#### log\_error\_and\_notify(context: str, resp: Optional[ApiResponse] = None) {#EFSPIntegration.conversions.log\_error\_and\_notify} ```python def log_error_and_notify(context: str, resp: Optional[ApiResponse] = None) @@ -54,9 +50,7 @@ def log_error_and_notify(context: str, resp: Optional[ApiResponse] = None) Similar to docassemble.webapp.server.error_notification, which will send an email to the `error_notification_email` in the config. - - -#### convert\_court\_to\_id(trial\_court) +#### convert\_court\_to\_id(trial\_court) {#EFSPIntegration.conversions.convert\_court\_to\_id} ```python def convert_court_to_id(trial_court) -> str @@ -78,9 +72,7 @@ your court object use the "tyler_court_code" attribute though. the string that should be the Tyler EFM court id, i.e. `adams` or `peoria:cr` - - -#### choices\_and\_map(codes\_list: List[Dict[str, Any]], display: str = None, backing: str = None) +#### choices\_and\_map(codes\_list: List[Dict[str, Any]], display: str = None, backing: str = None) {#EFSPIntegration.conversions.choices\_and\_map} ```python def choices_and_map(codes_list: List[Dict[str, Any]], @@ -105,9 +97,7 @@ to the full code object second, a map of each code, from the backing key to the full code element. Useful for getting all of the information about a code after a user has selected it. - - -#### pretty\_display(data, tab\_depth=0, skip\_xml=True, item\_name=None) +#### pretty\_display(data, tab\_depth=0, skip\_xml=True, item\_name=None) {#EFSPIntegration.conversions.pretty\_display} ```python def pretty_display(data, tab_depth=0, skip_xml=True, item_name=None) -> str @@ -129,20 +119,16 @@ Recursive, for subsequent calls `tab_depth` increases. The string of markdown text that displays info about the given JSON structure - - -#### debug\_display(resp: ApiResponse) +#### debug\_display(resp: ApiResponse) {#EFSPIntegration.conversions.debug\_display} ```python def debug_display(resp: ApiResponse) -> str ``` Returns a string with either the error of the response, -or it's data run through [pretty_display](#pretty_display) +or it's data run through [pretty_display](#EFSPIntegration.conversions.pretty_display) - - -#### tyler\_daterep\_to\_datetime(tyler\_daterep: Mapping) +#### tyler\_daterep\_to\_datetime(tyler\_daterep: Mapping) {#EFSPIntegration.conversions.tyler\_daterep\_to\_datetime} ```python def tyler_daterep_to_datetime(tyler_daterep: Mapping) -> DADateTime @@ -151,9 +137,7 @@ def tyler_daterep_to_datetime(tyler_daterep: Mapping) -> DADateTime Takes an jsonized-XML object of "\{http://niem.gov/niem/niem-core/2.0\}ActivityDate, returns the datetime it represents. - - -#### tyler\_timestamp\_to\_datetime(timestamp\_ms: int) +#### tyler\_timestamp\_to\_datetime(timestamp\_ms: int) {#EFSPIntegration.conversions.tyler\_timestamp\_to\_datetime} ```python def tyler_timestamp_to_datetime(timestamp_ms: int) -> DADateTime @@ -161,9 +145,7 @@ def tyler_timestamp_to_datetime(timestamp_ms: int) -> DADateTime Given a timestamp in milliseconds from epoch (in UTC), make a datetime from it - - -#### validate\_tyler\_regex(data\_field: Mapping) +#### validate\_tyler\_regex(data\_field: Mapping) {#EFSPIntegration.conversions.validate\_tyler\_regex} ```python def validate_tyler_regex(data_field: Mapping) -> Callable[[str], Any] @@ -172,9 +154,7 @@ def validate_tyler_regex(data_field: Mapping) -> Callable[[str], Any] Return a function that validates a given input with the provided regex, suitable for use with docassemble's `validate:` question modifier - - -#### parse\_service\_contacts(service\_list) +#### parse\_service\_contacts(service\_list) {#EFSPIntegration.conversions.parse\_service\_contacts} ```python def parse_service_contacts(service_list) @@ -184,9 +164,7 @@ We'll take both Tyler service contact lists and Niem service contact lists. Tyler's are just `\{"firstName": "Bob", "middleName": "P", ..., "serviceContactId": "abcrunh-13..." Niem's are more complicated - - -#### parse\_case\_info(proxy\_conn: ProxyConnection, new\_case: DAObject, entry: dict, court\_id: str, \*, fetch: bool = True, roles: dict = None) +#### parse\_case\_info(proxy\_conn: ProxyConnection, new\_case: DAObject, entry: dict, court\_id: str, \*, fetch: bool = True, roles: dict = None) {#EFSPIntegration.conversions.parse\_case\_info} ```python def parse_case_info(proxy_conn: ProxyConnection, @@ -211,9 +189,7 @@ Given sparse information about a case, gets the full details about it - `roles` - a dictionary of the party type codes to the party type name. Used so we can filter and sort participants later - - -#### fetch\_case\_info(proxy\_conn: ProxyConnection, new\_case: DAObject, roles: Optional[dict] = None) +#### fetch\_case\_info(proxy\_conn: ProxyConnection, new\_case: DAObject, roles: Optional[dict] = None) {#EFSPIntegration.conversions.fetch\_case\_info} ```python def fetch_case_info(proxy_conn: ProxyConnection, @@ -231,9 +207,7 @@ Fills in these attributes with the full case details: * date * participants - - -#### filter\_payment\_accounts(account\_list, allowable\_card\_types: List) +#### filter\_payment\_accounts(account\_list, allowable\_card\_types: List) {#EFSPIntegration.conversions.filter\_payment\_accounts} ```python def filter_payment_accounts(account_list, allowable_card_types: List) -> List @@ -247,16 +221,14 @@ accepted at a particular court. account_list: - `allowable_card_types` - a list of the accepted card types at a court, usually from the 'allowablecardtypes' dict entry in - [get_full_court_info](interview_logic#get_full_court_info)'s response + [get_full_court_info](interview_logic#EFSPIntegration.interview_logic.get_full_court_info)'s response **Returns**: the list of payment account choices that are valid for a particular court - - -#### payment\_account\_labels(resp: ApiResponse) +#### payment\_account\_labels(resp: ApiResponse) {#EFSPIntegration.conversions.payment\_account\_labels} ```python def payment_account_labels(resp: ApiResponse) -> Optional[List[Dict]] @@ -264,22 +236,18 @@ def payment_account_labels(resp: ApiResponse) -> Optional[List[Dict]] Returns all payment accounts as choices, without filters. - - -#### filing\_id\_and\_label(case: Mapping, style: str = "FILING\_ID") +#### filing\_id\_and\_label(case: Mapping, style: str = "FILING\_ID") {#EFSPIntegration.conversions.filing\_id\_and\_label} ```python def filing_id_and_label(case: Mapping, style: str = "FILING_ID") -> Dict[str, str] ``` -Converts a raw case information from [proxy_conn.get_filing_list()](py_efsp_client#get_filing_list) +Converts a raw case information from [proxy_conn.get_filing_list()](py_efsp_client#EFSPIntegration.py_efsp_client.EfspConnection.get_filing_list) into a key-value pair, where the key is the filing id and the value is the user-facing label for that filing. - - -#### get\_tyler\_roles(proxy\_conn: ProxyConnection, login\_data: Optional[Mapping], user\_details: Optional[ApiResponse] = None) +#### get\_tyler\_roles(proxy\_conn: ProxyConnection, login\_data: Optional[Mapping], user\_details: Optional[ApiResponse] = None) {#EFSPIntegration.conversions.get\_tyler\_roles} ```python def get_tyler_roles( diff --git a/docs/components/EFSPIntegration/efm_client.md b/docs/components/EFSPIntegration/efm_client.md index 8899e174f..e2a6a3ebb 100644 --- a/docs/components/EFSPIntegration/efm_client.md +++ b/docs/components/EFSPIntegration/efm_client.md @@ -1,6 +1,6 @@ # Table of Contents -* [EFSPIntegration.efm\_client](#EFSPIntegration.efm_client) +* EFSPIntegration.efm\_client * [ProxyConnection](#EFSPIntegration.efm_client.ProxyConnection) * [\_\_init\_\_](#EFSPIntegration.efm_client.ProxyConnection.__init__) * [authenticate\_user](#EFSPIntegration.efm_client.ProxyConnection.authenticate_user) @@ -13,9 +13,7 @@ sidebar_label: efm_client title: EFSPIntegration.efm_client --- - - -## ProxyConnection Objects +## ProxyConnection Objects {#EFSPIntegration.efm\_client.ProxyConnection} ```python class ProxyConnection(EfspConnection) @@ -23,12 +21,10 @@ class ProxyConnection(EfspConnection) The main class you use to communicate with the E-file proxy server from docassemble. -Many methods are unchanged from the parent class, [EfspConnection](py_efsp_client#EfspConnection), +Many methods are unchanged from the parent class, [EfspConnection](py_efsp_client#EFSPIntegration.py_efsp_client.EfspConnection), and are documented there. - - -#### \_\_init\_\_(\*, url: str = None, api\_key: str = None, credentials\_code\_block: str = "tyler\_login", default\_jurisdiction: str = None) +#### \_\_init\_\_(\*, url: str = None, api\_key: str = None, credentials\_code\_block: str = "tyler\_login", default\_jurisdiction: str = None) {#EFSPIntegration.efm\_client.ProxyConnection.\_\_init\_\_} ```python def __init__(*, @@ -41,9 +37,7 @@ def __init__(*, Creates the connection. Tries to get params from docassemble's config, but can be overriden with parameters to __init__. - - -#### authenticate\_user(tyler\_email: str = None, tyler\_password: str = None, jeffnet\_key: str = None, \*, jurisdiction: str = None) +#### authenticate\_user(tyler\_email: str = None, tyler\_password: str = None, jeffnet\_key: str = None, \*, jurisdiction: str = None) {#EFSPIntegration.efm\_client.ProxyConnection.authenticate\_user} ```python def authenticate_user(tyler_email: str = None, @@ -58,9 +52,7 @@ tyler_email (str) tyler_password (str) jeffnet_key (str) - - -#### register\_user(person: Union[Individual, dict], registration\_type: str, \*, password: str = None, firm\_name\_or\_id: str = None) +#### register\_user(person: Union[Individual, dict], registration\_type: str, \*, password: str = None, firm\_name\_or\_id: str = None) {#EFSPIntegration.efm\_client.ProxyConnection.register\_user} ```python def register_user(person: Union[Individual, dict], @@ -74,9 +66,7 @@ registration_type needs to be INDIVIDUAL, FIRM_ADMINISTRATOR, or FIRM_ADMIN_NEW_ If registration_type is INDIVIDUAL or FIRM_ADMINISTRATOR, you need a password. If it's FIRM_ADMINISTRATOR or FIRM_ADMIN_NEW_MEMBER, you need a firm_name_or_id - - -#### get\_service\_types(court\_id: str, court\_bundle: Union[ALDocumentBundle, dict] = None) +#### get\_service\_types(court\_id: str, court\_bundle: Union[ALDocumentBundle, dict] = None) {#EFSPIntegration.efm\_client.ProxyConnection.get\_service\_types} ```python def get_service_types( @@ -86,9 +76,7 @@ def get_service_types( Checks the court info: if it has conditional service types, call a special API with all filing info so far to get service types - - -#### serialize\_person(person: Union[Person, Individual]) +#### serialize\_person(person: Union[Person, Individual]) {#EFSPIntegration.efm\_client.serialize\_person} ```python def serialize_person(person: Union[Person, Individual]) -> Dict diff --git a/docs/components/EFSPIntegration/interview_logic.md b/docs/components/EFSPIntegration/interview_logic.md index 4c76b1e76..2dc9676c2 100644 --- a/docs/components/EFSPIntegration/interview_logic.md +++ b/docs/components/EFSPIntegration/interview_logic.md @@ -1,6 +1,6 @@ # Table of Contents -* [EFSPIntegration.interview\_logic](#EFSPIntegration.interview_logic) +* EFSPIntegration.interview\_logic * [EFCaseSearch](#EFSPIntegration.interview_logic.EFCaseSearch) * [search\_went\_wrong](#EFSPIntegration.interview_logic.EFCaseSearch.search_went_wrong) * [get\_lookup\_choices](#EFSPIntegration.interview_logic.EFCaseSearch.get_lookup_choices) @@ -21,9 +21,7 @@ title: EFSPIntegration.interview_logic A group of methods that were code blocks in various parts of the EFSP package, but for better python tooling support, were moved here. - - -## EFCaseSearch Objects +## EFCaseSearch Objects {#EFSPIntegration.interview\_logic.EFCaseSearch} ```python class EFCaseSearch(DAObject) @@ -31,9 +29,7 @@ class EFCaseSearch(DAObject) A data-class that has holds all of the information and state for a single case search - - -#### search\_went\_wrong() +#### search\_went\_wrong() {#EFSPIntegration.interview\_logic.EFCaseSearch.search\_went\_wrong} ```python def search_went_wrong() -> bool @@ -41,9 +37,7 @@ def search_went_wrong() -> bool Returns true if something errored during the case search process - - -#### get\_lookup\_choices(can\_file\_non\_indexed\_case: bool) +#### get\_lookup\_choices(can\_file\_non\_indexed\_case: bool) {#EFSPIntegration.interview\_logic.EFCaseSearch.get\_lookup\_choices} ```python def get_lookup_choices( @@ -58,9 +52,7 @@ Not passed as direct arguments, but the object attributes `party_search_choice`, `docket_lookup_choice`, and `non_indexed_choice` are the user-facing labels for each choice. - - -#### num\_case\_choices() +#### num\_case\_choices() {#EFSPIntegration.interview\_logic.num\_case\_choices} ```python def num_case_choices() -> int @@ -69,9 +61,7 @@ def num_case_choices() -> int The number of cases that someone should have to choose between if there are too many. Mostly to limit the amount of up-front waiting someone will have to do. - - -#### search\_case\_by\_name(\*, proxy\_conn, var\_name: str = None, court\_id: str, somebody, filter\_fn: Callable[[Any], bool], roles=None) +#### search\_case\_by\_name(\*, proxy\_conn, var\_name: str = None, court\_id: str, somebody, filter\_fn: Callable[[Any], bool], roles=None) {#EFSPIntegration.interview\_logic.search\_case\_by\_name} ```python def search_case_by_name(*, @@ -86,9 +76,7 @@ def search_case_by_name(*, Searches for cases by party name. If there are more than 10 cases found, we don't add all of the detailed information about the case, just for the first few cases - - -#### shift\_case\_select\_window(proxy\_conn, found\_cases: DAList, \*, direction: str, start\_idx: int, end\_idx: int, roles: dict = None) +#### shift\_case\_select\_window(proxy\_conn, found\_cases: DAList, \*, direction: str, start\_idx: int, end\_idx: int, roles: dict = None) {#EFSPIntegration.interview\_logic.shift\_case\_select\_window} ```python def shift_case_select_window(proxy_conn, @@ -103,9 +91,7 @@ def shift_case_select_window(proxy_conn, Specifically used in case_search.yml, with an action to only fetch a detailed information for a few cases at a time - - -#### get\_full\_court\_info(proxy\_conn, court\_id: str) +#### get\_full\_court\_info(proxy\_conn, court\_id: str) {#EFSPIntegration.interview\_logic.get\_full\_court\_info} ```python def get_full_court_info(proxy_conn, court_id: str) -> Dict @@ -113,9 +99,7 @@ def get_full_court_info(proxy_conn, court_id: str) -> Dict Gets all of the information about the court from the id - - -#### get\_max\_allowed\_sizes(proxy\_conn, court\_id: str) +#### get\_max\_allowed\_sizes(proxy\_conn, court\_id: str) {#EFSPIntegration.interview\_logic.get\_max\_allowed\_sizes} ```python def get_max_allowed_sizes(proxy_conn, @@ -124,9 +108,7 @@ def get_max_allowed_sizes(proxy_conn, Returns attachment max size, then message max size - - -#### make\_filter(search: Union[Callable[..., bool], SearchType, None]) +#### make\_filter(search: Union[Callable[..., bool], SearchType, None]) {#EFSPIntegration.interview\_logic.make\_filter} ```python def make_filter( @@ -140,9 +122,7 @@ Necessary because docassemble doesn't store lambdas and functions well in interview dicts, so the filters need to be set as primitive types and kept that way until the search actually happens (in filter_codes). - - -#### filter\_codes(options: Iterable, filters: Iterable[Union[Callable[..., bool], SearchType]], default: str, exclude: Union[Callable[..., bool], SearchType, None] = None) +#### filter\_codes(options: Iterable, filters: Iterable[Union[Callable[..., bool], SearchType]], default: str, exclude: Union[Callable[..., bool], SearchType, None] = None) {#EFSPIntegration.interview\_logic.filter\_codes} ```python def filter_codes( @@ -156,9 +136,7 @@ def filter_codes( Given a list of filter functions from most specific to least specific, (if true, use that code), filters a total list of codes. If any codes match the exclude filter, won't use them. - - -#### get\_available\_efile\_courts(proxy\_conn) +#### get\_available\_efile\_courts(proxy\_conn) {#EFSPIntegration.interview\_logic.get\_available\_efile\_courts} ```python def get_available_efile_courts(proxy_conn) -> list diff --git a/docs/components/EFSPIntegration/py_efsp_client.md b/docs/components/EFSPIntegration/py_efsp_client.md index 5559030a2..392c3b2e9 100644 --- a/docs/components/EFSPIntegration/py_efsp_client.md +++ b/docs/components/EFSPIntegration/py_efsp_client.md @@ -1,6 +1,6 @@ # Table of Contents -* [EFSPIntegration.py\_efsp\_client](#EFSPIntegration.py_efsp_client) +* EFSPIntegration.py\_efsp\_client * [EfspConnection](#EFSPIntegration.py_efsp_client.EfspConnection) * [\_\_init\_\_](#EFSPIntegration.py_efsp_client.EfspConnection.__init__) * [authenticate\_user](#EFSPIntegration.py_efsp_client.EfspConnection.authenticate_user) @@ -25,9 +25,7 @@ The base python client used to communicate with the E-file proxy server. Doesn't include anything from docassemble, and can be used without having it installed. - - -## EfspConnection Objects +## EfspConnection Objects {#EFSPIntegration.py\_efsp\_client.EfspConnection} ```python class EfspConnection() @@ -35,9 +33,7 @@ class EfspConnection() A python client that communicates with the E-file proxy server. - - -#### \_\_init\_\_(\*, url: str, api\_key: str, default\_jurisdiction: str = None) +#### \_\_init\_\_(\*, url: str, api\_key: str, default\_jurisdiction: str = None) {#EFSPIntegration.py\_efsp\_client.EfspConnection.\_\_init\_\_} ```python def __init__(*, url: str, api_key: str, default_jurisdiction: str = None) @@ -49,9 +45,7 @@ def __init__(*, url: str, api_key: str, default_jurisdiction: str = None) api_key (str) default_jurisdiction (str) - - -#### authenticate\_user(\*, tyler\_email: Optional[str] = None, tyler\_password: Optional[str] = None, jeffnet\_key: Optional[str] = None, jurisdiction: str = None) +#### authenticate\_user(\*, tyler\_email: Optional[str] = None, tyler\_password: Optional[str] = None, jeffnet\_key: Optional[str] = None, jurisdiction: str = None) {#EFSPIntegration.py\_efsp\_client.EfspConnection.authenticate\_user} ```python def authenticate_user(*, @@ -63,9 +57,7 @@ def authenticate_user(*, Authenticates the user with the EFM server (not the E-file proxy). - - -#### register\_user(person: dict, registration\_type: str, \*, password: str = None, firm\_name\_or\_id: str = None) +#### register\_user(person: dict, registration\_type: str, \*, password: str = None, firm\_name\_or\_id: str = None) {#EFSPIntegration.py\_efsp\_client.EfspConnection.register\_user} ```python def register_user(person: dict, @@ -79,9 +71,7 @@ registration_type needs to be INDIVIDUAL, FIRM_ADMINISTRATOR, or FIRM_ADMIN_NEW_ If registration_type is INDIVIDUAL or FIRM_ADMINISTRATOR, you need a password. If it's FIRM_ADMINISTRATOR or FIRM_ADMIN_NEW_MEMBER, you need a firm_name_or_id - - -#### get\_password\_rules() +#### get\_password\_rules() {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_password\_rules} ```python def get_password_rules() -> ApiResponse @@ -91,9 +81,7 @@ Password rules are stored in the global court, id 0. TODO: They're in other courts too, including 1. Could they ever be different? - - -#### get\_notification\_options() +#### get\_notification\_options() {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_notification\_options} ```python def get_notification_options() -> ApiResponse @@ -101,9 +89,7 @@ def get_notification_options() -> ApiResponse AKA NotificationPreferencesList - - -#### get\_firm() +#### get\_firm() {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_firm} ```python def get_firm() -> ApiResponse @@ -112,9 +98,7 @@ def get_firm() -> ApiResponse Gets info about the "firm" for an associated user. If a user is a pro-se, this contains their address information. - - -#### update\_firm(firm: dict) +#### update\_firm(firm: dict) {#EFSPIntegration.py\_efsp\_client.EfspConnection.update\_firm} ```python def update_firm(firm: dict) -> ApiResponse @@ -127,9 +111,7 @@ firm should have the below keys: * phoneNumber * email - - -#### get\_courts(fileable\_only: bool = False, with\_names: bool = False) +#### get\_courts(fileable\_only: bool = False, with\_names: bool = False) {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_courts} ```python def get_courts(fileable_only: bool = False, @@ -138,9 +120,7 @@ def get_courts(fileable_only: bool = False, Gets the list of courts. - - -#### get\_court(court\_id: str) +#### get\_court(court\_id: str) {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_court} ```python def get_court(court_id: str) -> ApiResponse @@ -148,20 +128,16 @@ def get_court(court_id: str) -> ApiResponse Gets codes for a specific court - - -#### get\_court\_list() +#### get\_court\_list() {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_court\_list} ```python def get_court_list() -> ApiResponse ``` Gets a list of all of the courts that you can file into. Slightly more limited than -[get_courts](#get_courts) +[get_courts](#EFSPIntegration.py_efsp_client.EfspConnection.get_courts) - - -#### get\_filing\_list(court\_id: str, user\_id: str = None, start\_date: datetime = None, before\_date: datetime = None) +#### get\_filing\_list(court\_id: str, user\_id: str = None, start\_date: datetime = None, before\_date: datetime = None) {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_filing\_list} ```python def get_filing_list(court_id: str, @@ -172,9 +148,7 @@ def get_filing_list(court_id: str, Returns a list of filings that a particular user has made with a court. - - -#### get\_service\_types(court\_id: str, all\_vars: dict = None) +#### get\_service\_types(court\_id: str, all\_vars: dict = None) {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_service\_types} ```python def get_service_types(court_id: str, all_vars: dict = None) -> ApiResponse @@ -182,9 +156,7 @@ def get_service_types(court_id: str, all_vars: dict = None) -> ApiResponse Checks the court info: if it has conditional service types, call a special API with all filing info so far to get service types - - -#### get\_cases\_raw(court\_id: str, \*, person\_name: dict = None, business\_name: str = None, docket\_number: str = None) +#### get\_cases\_raw(court\_id: str, \*, person\_name: dict = None, business\_name: str = None, docket\_number: str = None) {#EFSPIntegration.py\_efsp\_client.EfspConnection.get\_cases\_raw} ```python def get_cases_raw(court_id: str, diff --git a/docs/components/FormFyxer/docx_wrangling.md b/docs/components/FormFyxer/docx_wrangling.md index a444a2602..9123134d2 100644 --- a/docs/components/FormFyxer/docx_wrangling.md +++ b/docs/components/FormFyxer/docx_wrangling.md @@ -1,6 +1,6 @@ # Table of Contents -* [formfyxer.docx\_wrangling](#formfyxer.docx_wrangling) +* formfyxer.docx\_wrangling * [update\_docx](#formfyxer.docx_wrangling.update_docx) * [get\_docx\_repr](#formfyxer.docx_wrangling.get_docx_repr) * [get\_labeled\_docx\_runs](#formfyxer.docx_wrangling.get_labeled_docx_runs) @@ -13,9 +13,7 @@ sidebar_label: docx_wrangling title: formfyxer.docx_wrangling --- - - -#### update\_docx(document: Union[docx.document.Document, str], modified\_runs: List[Tuple[int, int, str, int]]) +#### update\_docx(document: Union[docx.document.Document, str], modified\_runs: List[Tuple[int, int, str, int]]) {#formfyxer.docx\_wrangling.update\_docx} ```python def update_docx( @@ -43,9 +41,7 @@ Take a careful look at the output document to make sure it is still correct. The modified document. - - -#### get\_docx\_repr(docx\_path: str, paragraph\_start: int = 0, paragraph\_end: Optional[int] = None) +#### get\_docx\_repr(docx\_path: str, paragraph\_start: int = 0, paragraph\_end: Optional[int] = None) {#formfyxer.docx\_wrangling.get\_docx\_repr} ```python def get_docx_repr(docx_path: str, @@ -64,9 +60,7 @@ Return a JSON representation of the paragraphs and runs in the DOCX file. A JSON representation of the paragraphs and runs in the DOCX file. - - -#### get\_labeled\_docx\_runs(docx\_path: Optional[str] = None, docx\_repr=Optional[str], custom\_people\_names: Optional[Tuple[str, str]] = None, openai\_client: Optional[OpenAI] = None, api\_key: Optional[str] = None) +#### get\_labeled\_docx\_runs(docx\_path: Optional[str] = None, docx\_repr=Optional[str], custom\_people\_names: Optional[Tuple[str, str]] = None, openai\_client: Optional[OpenAI] = None, api\_key: Optional[str] = None) {#formfyxer.docx\_wrangling.get\_labeled\_docx\_runs} ```python def get_labeled_docx_runs( @@ -90,9 +84,7 @@ Scan the DOCX and return a list of modified text with Jinja2 variable names inse A list of tuples, each containing a paragraph number, run number, and the modified text of the run. - - -#### get\_modified\_docx\_runs(docx\_path: Optional[str] = None, docx\_repr: Optional[str] = None, custom\_example: str = "", instructions: str = "", openai\_client: Optional[OpenAI] = None, api\_key: Optional[str] = None, temperature=0.5) +#### get\_modified\_docx\_runs(docx\_path: Optional[str] = None, docx\_repr: Optional[str] = None, custom\_example: str = "", instructions: str = "", openai\_client: Optional[OpenAI] = None, api\_key: Optional[str] = None, temperature=0.5) {#formfyxer.docx\_wrangling.get\_modified\_docx\_runs} ```python def get_modified_docx_runs(docx_path: Optional[str] = None, @@ -154,9 +146,7 @@ You may also want to customize the input example to better match your use case. A list of tuples, each containing a paragraph number, run number, and the modified text of the run. - - -#### make\_docx\_plain\_language(docx\_path: str) +#### make\_docx\_plain\_language(docx\_path: str) {#formfyxer.docx\_wrangling.make\_docx\_plain\_language} ```python def make_docx_plain_language(docx_path: str) -> docx.document.Document @@ -164,9 +154,7 @@ def make_docx_plain_language(docx_path: str) -> docx.document.Document Convert a DOCX file to plain language with the help of OpenAI. - - -#### modify\_docx\_with\_openai\_guesses(docx\_path: str) +#### modify\_docx\_with\_openai\_guesses(docx\_path: str) {#formfyxer.docx\_wrangling.modify\_docx\_with\_openai\_guesses} ```python def modify_docx_with_openai_guesses(docx_path: str) -> docx.document.Document diff --git a/docs/components/FormFyxer/lit_explorer.md b/docs/components/FormFyxer/lit_explorer.md index 36f2dac37..4e8978c6b 100644 --- a/docs/components/FormFyxer/lit_explorer.md +++ b/docs/components/FormFyxer/lit_explorer.md @@ -1,6 +1,6 @@ # Table of Contents -* [formfyxer.lit\_explorer](#formfyxer.lit_explorer) +* formfyxer.lit\_explorer * [recursive\_get\_id](#formfyxer.lit_explorer.recursive_get_id) * [spot](#formfyxer.lit_explorer.spot) * [re\_case](#formfyxer.lit_explorer.re_case) @@ -37,9 +37,7 @@ sidebar_label: lit_explorer title: formfyxer.lit_explorer --- - - -#### recursive\_get\_id(values\_to\_unpack: Union[dict, list], tmpl: Optional[set] = None) +#### recursive\_get\_id(values\_to\_unpack: Union[dict, list], tmpl: Optional[set] = None) {#formfyxer.lit\_explorer.recursive\_get\_id} ```python def recursive_get_id(values_to_unpack: Union[dict, list], @@ -48,9 +46,7 @@ def recursive_get_id(values_to_unpack: Union[dict, list], Pull ID values out of the LIST/NSMI results from Spot. - - -#### spot(text: str, lower: float = 0.25, pred: float = 0.5, upper: float = 0.6, verbose: float = 0, token: str = "") +#### spot(text: str, lower: float = 0.25, pred: float = 0.5, upper: float = 0.6, verbose: float = 0, token: str = "") {#formfyxer.lit\_explorer.spot} ```python def spot(text: str, @@ -64,9 +60,7 @@ def spot(text: str, Call the Spot API (https://spot.suffolklitlab.org) to classify the text of a PDF using the NSMIv2/LIST taxonomy (https://taxonomy.legal/), but returns only the IDs of issues found in the text. - - -#### re\_case(text: str) +#### re\_case(text: str) {#formfyxer.lit\_explorer.re\_case} ```python def re_case(text: str) -> str @@ -74,9 +68,7 @@ def re_case(text: str) -> str Capture PascalCase, snake_case and kebab-case terms and add spaces to separate the joined words - - -#### regex\_norm\_field(text: str) +#### regex\_norm\_field(text: str) {#formfyxer.lit\_explorer.regex\_norm\_field} ```python def regex_norm_field(text: str) @@ -85,9 +77,7 @@ def regex_norm_field(text: str) Apply some heuristics to a field name to see if we can get it to match AssemblyLine conventions. See: https://assemblyline.suffolklitlab.org/docs/document_variables - - -#### reformat\_field(text: str, max\_length: int = 30, tools\_token: Optional[str] = None) +#### reformat\_field(text: str, max\_length: int = 30, tools\_token: Optional[str] = None) {#formfyxer.lit\_explorer.reformat\_field} ```python def reformat_field(text: str, @@ -99,9 +89,7 @@ Transforms a string of text into a snake_case variable close in length to `max_l summarizing the string and stitching the summary together in snake_case. h/t https://towardsdatascience.com/nlp-building-a-summariser-68e0c19e3a93 - - -#### norm(row) +#### norm(row) {#formfyxer.lit\_explorer.norm} ```python def norm(row) @@ -109,9 +97,7 @@ def norm(row) Normalize a word vector. - - -#### vectorize(text: Union[List[str], str], tools\_token: Optional[str] = None) +#### vectorize(text: Union[List[str], str], tools\_token: Optional[str] = None) {#formfyxer.lit\_explorer.vectorize} ```python def vectorize(text: Union[List[str], str], tools_token: Optional[str] = None) @@ -128,9 +114,7 @@ Vectorize a string of text. last bit is nolonger correct, you have to use the micor-service as we have had to remove SpaCY due to a breaking change - - -#### normalize\_name(jur: str, group: str, n: int, per, last\_field: str, this\_field: str, tools\_token: Optional[str] = None) +#### normalize\_name(jur: str, group: str, n: int, per, last\_field: str, this\_field: str, tools\_token: Optional[str] = None) {#formfyxer.lit\_explorer.normalize\_name} ```python def normalize_name(jur: str, @@ -148,9 +132,7 @@ not, to a snake_case variable name of appropriate length. HACK: temporarily all we do is re-case it and normalize it using regex rules. Will be replaced with call to LLM soon. - - -#### cluster\_screens(fields: List[str] = [], damping: float = 0.7, tools\_token: Optional[str] = None) +#### cluster\_screens(fields: List[str] = [], damping: float = 0.7, tools\_token: Optional[str] = None) {#formfyxer.lit\_explorer.cluster\_screens} ```python def cluster_screens(fields: List[str] = [], @@ -169,9 +151,7 @@ Groups the given fields into screens based on how much they are related. - `Returns` - a suggested screen grouping, each screen name mapped to the list of fields on it - - -## InputType Objects +## InputType Objects {#formfyxer.lit\_explorer.InputType} ```python class InputType(Enum) @@ -180,9 +160,7 @@ class InputType(Enum) Input type maps onto the type of input the PDF author chose for the field. We only handle text, checkbox, and signature fields. - - -#### field\_types\_and\_sizes(fields: Optional[Iterable[FormField]]) +#### field\_types\_and\_sizes(fields: Optional[Iterable[FormField]]) {#formfyxer.lit\_explorer.field\_types\_and\_sizes} ```python def field_types_and_sizes( @@ -199,9 +177,7 @@ Result will look like: \} ] - - -## AnswerType Objects +## AnswerType Objects {#formfyxer.lit\_explorer.AnswerType} ```python class AnswerType(Enum) @@ -217,9 +193,7 @@ a choice, creating a narrative, or even applying legal reasoning. "Affidavi form of created answers. See Jarret and Gaffney, Forms That Work (2008) - - -#### classify\_field(field: FieldInfo, new\_name: str) +#### classify\_field(field: FieldInfo, new\_name: str) {#formfyxer.lit\_explorer.classify\_field} ```python def classify_field(field: FieldInfo, new_name: str) -> AnswerType @@ -228,9 +202,7 @@ def classify_field(field: FieldInfo, new_name: str) -> AnswerType Apply heuristics to the field's original and "normalized" name to classify it as either a "slot-in", "gathered", "third party" or "created" field type. - - -#### get\_adjusted\_character\_count(field: FieldInfo) +#### get\_adjusted\_character\_count(field: FieldInfo) {#formfyxer.lit\_explorer.get\_adjusted\_character\_count} ```python def get_adjusted_character_count(field: FieldInfo) -> float @@ -268,9 +240,7 @@ for the same data without considering the space the user actually needs. >>> get_adjusted_character_count(\{"max_length": 1200\}) 1150 - - -#### time\_to\_answer\_field(field: FieldInfo, new\_name: str, cpm: int = 40, cpm\_std\_dev: int = 17) +#### time\_to\_answer\_field(field: FieldInfo, new\_name: str, cpm: int = 40, cpm\_std\_dev: int = 17) {#formfyxer.lit\_explorer.time\_to\_answer\_field} ```python def time_to_answer_field(field: FieldInfo, @@ -285,9 +255,7 @@ It will factor in the input type, the answer type (slot in, gathered, third part amount of input text allowed in the field. The return value is a function that can return N samples of how long it will take to answer the field (in minutes) - - -#### time\_to\_answer\_form(processed\_fields, normalized\_fields) +#### time\_to\_answer\_form(processed\_fields, normalized\_fields) {#formfyxer.lit\_explorer.time\_to\_answer\_form} ```python def time_to_answer_form(processed_fields, @@ -305,9 +273,7 @@ rough estimate, based on whether the field is: a. short created (3 lines or so?) b. long created (anything over 3 lines) - - -#### cleanup\_text(text: str, fields\_to\_sentences: bool = False) +#### cleanup\_text(text: str, fields\_to\_sentences: bool = False) {#formfyxer.lit\_explorer.cleanup\_text} ```python def cleanup_text(text: str, fields_to_sentences: bool = False) -> str @@ -315,9 +281,7 @@ def cleanup_text(text: str, fields_to_sentences: bool = False) -> str Apply cleanup routines to text to provide more accurate readability statistics. - - -#### text\_complete(prompt: str, max\_tokens: int = 500, creds: Optional[OpenAiCreds] = None, temperature: float = 0) +#### text\_complete(prompt: str, max\_tokens: int = 500, creds: Optional[OpenAiCreds] = None, temperature: float = 0) {#formfyxer.lit\_explorer.text\_complete} ```python def text_complete(prompt: str, @@ -335,9 +299,7 @@ Run a prompt via openAI's API and return the result. - `creds` _Optional[OpenAiCreds], optional_ - The credentials to use. Defaults to None. - `temperature` _float, optional_ - The temperature to use. Defaults to 0. - - -#### complete\_with\_command(text, command, tokens, creds: Optional[OpenAiCreds] = None) +#### complete\_with\_command(text, command, tokens, creds: Optional[OpenAiCreds] = None) {#formfyxer.lit\_explorer.complete\_with\_command} ```python def complete_with_command(text, @@ -348,9 +310,7 @@ def complete_with_command(text, Combines some text with a command to send to open ai. - - -#### needs\_calculations(text: Union[str]) +#### needs\_calculations(text: Union[str]) {#formfyxer.lit\_explorer.needs\_calculations} ```python def needs_calculations(text: Union[str]) -> bool @@ -359,9 +319,7 @@ def needs_calculations(text: Union[str]) -> bool A conservative guess at if a given form needs the filler to make math calculations, something that should be avoided. If - - -#### tools\_passive(input: Union[List[str], str], tools\_token: Optional[str] = None) +#### tools\_passive(input: Union[List[str], str], tools\_token: Optional[str] = None) {#formfyxer.lit\_explorer.tools\_passive} ```python def tools_passive(input: Union[List[str], str], @@ -370,9 +328,7 @@ def tools_passive(input: Union[List[str], str], Ping passive voice API for list of sentences using the passive voice - - -#### get\_passive\_sentences(text: Union[List, str], tools\_token: Optional[str] = None) +#### get\_passive\_sentences(text: Union[List, str], tools\_token: Optional[str] = None) {#formfyxer.lit\_explorer.get\_passive\_sentences} ```python def get_passive_sentences( @@ -391,9 +347,7 @@ Text can either be a string or a list of strings. If provided a single string, it will be tokenized with NTLK and sentences containing fewer than 2 words will be ignored. - - -#### get\_citations(text: str, tokenized\_sentences: List[str]) +#### get\_citations(text: str, tokenized\_sentences: List[str]) {#formfyxer.lit\_explorer.get\_citations} ```python def get_citations(text: str, tokenized_sentences: List[str]) -> List[str] @@ -403,9 +357,7 @@ Get citations and some extra surrounding context (the full sentence), if the cit fewer than 5 characters (often eyecite only captures a section symbol for state-level short citation formats) - - -#### get\_sensitive\_data\_types(fields: List[str], fields\_old: Optional[List[str]] = None) +#### get\_sensitive\_data\_types(fields: List[str], fields\_old: Optional[List[str]] = None) {#formfyxer.lit\_explorer.get\_sensitive\_data\_types} ```python def get_sensitive_data_types( @@ -421,9 +373,7 @@ will not contain the old field name, only the corresponding field name from the The sensitive data types are: Bank Account Number, Credit Card Number, Driver's License Number, and Social Security Number. - - -#### substitute\_phrases(input\_string: str, substitution\_phrases: Dict[str, str]) +#### substitute\_phrases(input\_string: str, substitution\_phrases: Dict[str, str]) {#formfyxer.lit\_explorer.substitute\_phrases} ```python def substitute_phrases( @@ -457,9 +407,7 @@ Substitute phrases in the input string and return the new string and positions o >>> print(positions) [(4, 17), (35, 48)] - - -#### substitute\_neutral\_gender(input\_string: str) +#### substitute\_neutral\_gender(input\_string: str) {#formfyxer.lit\_explorer.substitute\_neutral\_gender} ```python def substitute_neutral_gender( @@ -469,9 +417,7 @@ def substitute_neutral_gender( Substitute gendered phrases with neutral phrases in the input string. Primary source is https://github.com/joelparkerhenderson/inclusive-language - - -#### substitute\_plain\_language(input\_string: str) +#### substitute\_plain\_language(input\_string: str) {#formfyxer.lit\_explorer.substitute\_plain\_language} ```python def substitute_plain_language( @@ -481,9 +427,7 @@ def substitute_plain_language( Substitute complex phrases with simpler alternatives. Source of terms is drawn from https://www.plainlanguage.gov/guidelines/words/ - - -#### transformed\_sentences(sentence\_list: List[str], fun: Callable) +#### transformed\_sentences(sentence\_list: List[str], fun: Callable) {#formfyxer.lit\_explorer.transformed\_sentences} ```python def transformed_sentences( @@ -495,9 +439,7 @@ Apply a function to a list of sentences and return only the sentences with chang The result is a tuple of the original sentence, new sentence, and the starting and ending position of each changed fragment in the sentence. - - -#### parse\_form(in\_file: str, title: Optional[str] = None, jur: Optional[str] = None, cat: Optional[str] = None, normalize: bool = True, spot\_token: Optional[str] = None, tools\_token: Optional[str] = None, openai\_creds: Optional[OpenAiCreds] = None, rewrite: bool = False, debug: bool = False) +#### parse\_form(in\_file: str, title: Optional[str] = None, jur: Optional[str] = None, cat: Optional[str] = None, normalize: bool = True, spot\_token: Optional[str] = None, tools\_token: Optional[str] = None, openai\_creds: Optional[OpenAiCreds] = None, rewrite: bool = False, debug: bool = False) {#formfyxer.lit\_explorer.parse\_form} ```python def parse_form(in_file: str, @@ -516,9 +458,7 @@ Read in a pdf, pull out basic stats, attempt to normalize its form fields, and r in_file with the new fields (if `rewrite=1`). If you pass a spot token, we will guess the NSMI code. If you pass openai creds, we will give suggestions for the title and description. - - -#### form\_complexity(stats) +#### form\_complexity(stats) {#formfyxer.lit\_explorer.form\_complexity} ```python def form_complexity(stats) diff --git a/docs/components/FormFyxer/pdf_wrangling.md b/docs/components/FormFyxer/pdf_wrangling.md index 7268a80d7..eaa487b8b 100644 --- a/docs/components/FormFyxer/pdf_wrangling.md +++ b/docs/components/FormFyxer/pdf_wrangling.md @@ -1,6 +1,6 @@ # Table of Contents -* [formfyxer.pdf\_wrangling](#formfyxer.pdf_wrangling) +* formfyxer.pdf\_wrangling * [FieldType](#formfyxer.pdf_wrangling.FieldType) * [TEXT](#formfyxer.pdf_wrangling.FieldType.TEXT) * [AREA](#formfyxer.pdf_wrangling.FieldType.AREA) @@ -36,41 +36,29 @@ sidebar_label: pdf_wrangling title: formfyxer.pdf_wrangling --- - - -## FieldType Objects +## FieldType Objects {#formfyxer.pdf\_wrangling.FieldType} ```python class FieldType(Enum) ``` - - -#### TEXT +#### TEXT {#formfyxer.pdf\_wrangling.FieldType.TEXT} Text input Field - - -#### AREA +#### AREA {#formfyxer.pdf\_wrangling.FieldType.AREA} Text input Field, but an area - - -#### LIST\_BOX +#### LIST\_BOX {#formfyxer.pdf\_wrangling.FieldType.LIST\_BOX} allows multiple selection - - -#### CHOICE +#### CHOICE {#formfyxer.pdf\_wrangling.FieldType.CHOICE} allows only one selection - - -## FormField Objects +## FormField Objects {#formfyxer.pdf\_wrangling.FormField} ```python class FormField() @@ -78,9 +66,7 @@ class FormField() A data holding class, used to easily specify how a PDF form field should be created. - - -#### \_\_init\_\_(field\_name: str, type\_name: Union[FieldType, str], x: int, y: int, font\_size: Optional[int] = None, tooltip: str = "", configs: Optional[Dict[str, Any]] = None) +#### \_\_init\_\_(field\_name: str, type\_name: Union[FieldType, str], x: int, y: int, font\_size: Optional[int] = None, tooltip: str = "", configs: Optional[Dict[str, Any]] = None) {#formfyxer.pdf\_wrangling.FormField.\_\_init\_\_} ```python def __init__(field_name: str, @@ -107,9 +93,7 @@ Constructor [reportlab User Guide](https://www.reportlab.com/docs/reportlab-userguide.pdf) - `field_name` - the name of the field, exposed to via most APIs. Not the tooltip, but `users1_name__0` - - -#### set\_fields(in\_file: Union[str, Path, BinaryIO], out\_file: Union[str, Path, BinaryIO], fields\_per\_page: Iterable[Iterable[FormField]], \*, overwrite=False) +#### set\_fields(in\_file: Union[str, Path, BinaryIO], out\_file: Union[str, Path, BinaryIO], fields\_per\_page: Iterable[Iterable[FormField]], \*, overwrite=False) {#formfyxer.pdf\_wrangling.set\_fields} ```python def set_fields(in_file: Union[str, Path, BinaryIO], @@ -157,9 +141,7 @@ set_fields('no_fields.pdf', 'four_fields_on_second_page.pdf', Nothing. - - -#### rename\_pdf\_fields(in\_file: Union[str, Path, BinaryIO], out\_file: Union[str, Path, BinaryIO], mapping: Mapping[str, str]) +#### rename\_pdf\_fields(in\_file: Union[str, Path, BinaryIO], out\_file: Union[str, Path, BinaryIO], mapping: Mapping[str, str]) {#formfyxer.pdf\_wrangling.rename\_pdf\_fields} ```python def rename_pdf_fields(in_file: Union[str, Path, BinaryIO], @@ -185,9 +167,9 @@ Args: Returns: Nothing - +``` -#### unlock\_pdf\_in\_place(in\_file: Union[str, Path, BinaryIO]) +#### unlock\_pdf\_in\_place(in\_file: Union[str, Path, BinaryIO]) {#formfyxer.pdf\_wrangling.unlock\_pdf\_in\_place} ```python def unlock_pdf_in_place(in_file: Union[str, Path, BinaryIO]) -> None @@ -195,9 +177,7 @@ def unlock_pdf_in_place(in_file: Union[str, Path, BinaryIO]) -> None Try using pikePDF to unlock the PDF it it is locked. This won't work if it has a non-zero length password. - - -#### has\_fields(pdf\_file: str) +#### has\_fields(pdf\_file: str) {#formfyxer.pdf\_wrangling.has\_fields} ```python def has_fields(pdf_file: str) -> bool @@ -214,9 +194,7 @@ Check if a PDF has at least one form field using PikePDF. - `bool` - True if the PDF has at least one form field, False otherwise. - - -#### get\_existing\_pdf\_fields(in\_file: Union[str, Path, BinaryIO, Pdf]) +#### get\_existing\_pdf\_fields(in\_file: Union[str, Path, BinaryIO, Pdf]) {#formfyxer.pdf\_wrangling.get\_existing\_pdf\_fields} ```python def get_existing_pdf_fields( @@ -225,9 +203,7 @@ def get_existing_pdf_fields( Use PikePDF to get fields from the PDF - - -#### swap\_pdf\_page(\*, source\_pdf: Union[str, Path, Pdf], destination\_pdf: Union[str, Path, Pdf], source\_offset: int = 0, destination\_offset: int = 0, append\_fields: bool = False) +#### swap\_pdf\_page(\*, source\_pdf: Union[str, Path, Pdf], destination\_pdf: Union[str, Path, Pdf], source\_offset: int = 0, destination\_offset: int = 0, append\_fields: bool = False) {#formfyxer.pdf\_wrangling.swap\_pdf\_page} ```python def swap_pdf_page(*, @@ -242,9 +218,7 @@ def swap_pdf_page(*, the source and destination PDFs. By default, it will remove any existing annotations (which include form fields) in the destination PDF. If you wish to append annotations instead, specify `append_fields = True` - - -#### copy\_pdf\_fields(\*, source\_pdf: Union[str, Path, Pdf], destination\_pdf: Union[str, Path, Pdf], source\_offset: int = 0, destination\_offset: int = 0, append\_fields: bool = False) +#### copy\_pdf\_fields(\*, source\_pdf: Union[str, Path, Pdf], destination\_pdf: Union[str, Path, Pdf], source\_offset: int = 0, destination\_offset: int = 0, append\_fields: bool = False) {#formfyxer.pdf\_wrangling.copy\_pdf\_fields} ```python def copy_pdf_fields(*, @@ -288,9 +262,7 @@ new_pdf_with_fields.save("new_pdf_with_fields.pdf") A pikepdf.Pdf object with new fields. If `blank_pdf` was a pikepdf.Pdf object, the same object is returned. - - -#### get\_textboxes\_in\_pdf(in\_file: Union[str, Path, BinaryIO], line\_margin=0.02, char\_margin=2.0) +#### get\_textboxes\_in\_pdf(in\_file: Union[str, Path, BinaryIO], line\_margin=0.02, char\_margin=2.0) {#formfyxer.pdf\_wrangling.get\_textboxes\_in\_pdf} ```python def get_textboxes_in_pdf(in_file: Union[str, Path, BinaryIO], @@ -300,9 +272,7 @@ def get_textboxes_in_pdf(in_file: Union[str, Path, BinaryIO], Gets all of the text boxes found by pdfminer in a PDF, as well as their bounding boxes - - -#### get\_bracket\_chars\_in\_pdf(in\_file: Union[str, Path, BinaryIO], line\_margin=0.02, char\_margin=0.0) +#### get\_bracket\_chars\_in\_pdf(in\_file: Union[str, Path, BinaryIO], line\_margin=0.02, char\_margin=0.0) {#formfyxer.pdf\_wrangling.get\_bracket\_chars\_in\_pdf} ```python def get_bracket_chars_in_pdf(in_file: Union[str, Path, BinaryIO], @@ -315,9 +285,7 @@ TODO: Will eventually be used to find [ ] as checkboxes, but right now we can&#x This simply gets all of the brackets, and the characters of [hi] in a PDF and [ ] are the exact same distance apart. Currently going with just "[hi]" doesn't happen, let's hope that assumption holds. - - -#### intersect\_bbox(bbox\_a, bbox\_b, vert\_dilation=2, horiz\_dilation=2) +#### intersect\_bbox(bbox\_a, bbox\_b, vert\_dilation=2, horiz\_dilation=2) {#formfyxer.pdf\_wrangling.intersect\_bbox} ```python def intersect_bbox(bbox_a, bbox_b, vert_dilation=2, horiz_dilation=2) -> bool @@ -325,9 +293,7 @@ def intersect_bbox(bbox_a, bbox_b, vert_dilation=2, horiz_dilation=2) -> bool bboxes are [left edge, bottom edge, horizontal length, vertical length] - - -#### intersect\_bboxs(bbox\_a, bboxes, vert\_dilation=2, horiz\_dilation=2) +#### intersect\_bboxs(bbox\_a, bboxes, vert\_dilation=2, horiz\_dilation=2) {#formfyxer.pdf\_wrangling.intersect\_bboxs} ```python def intersect_bboxs(bbox_a, @@ -338,9 +304,7 @@ def intersect_bboxs(bbox_a, Returns an iterable of booleans, one of each of the input bboxes, true if it collides with bbox_a - - -#### contain\_boxes(bbox\_a: BoundingBoxF, bbox\_b: BoundingBoxF) +#### contain\_boxes(bbox\_a: BoundingBoxF, bbox\_b: BoundingBoxF) {#formfyxer.pdf\_wrangling.contain\_boxes} ```python def contain_boxes(bbox_a: BoundingBoxF, bbox_b: BoundingBoxF) -> BoundingBoxF @@ -348,9 +312,7 @@ def contain_boxes(bbox_a: BoundingBoxF, bbox_b: BoundingBoxF) -> BoundingBoxF Given two bounding boxes, return a single bounding box that contains both of them. - - -#### get\_dist\_sq(point\_a: XYPair, point\_b: XYPair) +#### get\_dist\_sq(point\_a: XYPair, point\_b: XYPair) {#formfyxer.pdf\_wrangling.get\_dist\_sq} ```python def get_dist_sq(point_a: XYPair, point_b: XYPair) -> float @@ -358,9 +320,7 @@ def get_dist_sq(point_a: XYPair, point_b: XYPair) -> float returns the distance squared between two points. Faster than the true euclidean dist - - -#### get\_dist(point\_a: XYPair, point\_b: XYPair) +#### get\_dist(point\_a: XYPair, point\_b: XYPair) {#formfyxer.pdf\_wrangling.get\_dist} ```python def get_dist(point_a: XYPair, point_b: XYPair) -> float @@ -368,9 +328,7 @@ def get_dist(point_a: XYPair, point_b: XYPair) -> float euclidean (L^2 norm) distance between two points - - -#### get\_connected\_edges(point: XYPair, point\_list: Sequence) +#### get\_connected\_edges(point: XYPair, point\_list: Sequence) {#formfyxer.pdf\_wrangling.get\_connected\_edges} ```python def get_connected_edges(point: XYPair, point_list: Sequence) @@ -379,9 +337,7 @@ def get_connected_edges(point: XYPair, point_list: Sequence) point list is always ordered clockwise from the bottom left, i.e. bottom left, top left, top right, bottom right - - -#### bbox\_distance(bbox\_a: BoundingBoxF, bbox\_b: BoundingBoxF) +#### bbox\_distance(bbox\_a: BoundingBoxF, bbox\_b: BoundingBoxF) {#formfyxer.pdf\_wrangling.bbox\_distance} ```python def bbox_distance( @@ -396,9 +352,7 @@ around a field, is the most likely to be the actual text label for the PDF field bboxes are 4 floats, x, y, width and height - - -#### get\_possible\_fields(in\_pdf\_file: Union[str, Path], textboxes: Optional[List[List[Textbox]]] = None) +#### get\_possible\_fields(in\_pdf\_file: Union[str, Path], textboxes: Optional[List[List[Textbox]]] = None) {#formfyxer.pdf\_wrangling.get\_possible\_fields} ```python def get_possible_fields( @@ -432,9 +386,7 @@ print(fields[0][0]) For each page in the input PDF, a list of predicted form fields - - -#### get\_possible\_checkboxes(img: Union[str, cv2.Mat], find\_small=False) +#### get\_possible\_checkboxes(img: Union[str, cv2.Mat], find\_small=False) {#formfyxer.pdf\_wrangling.get\_possible\_checkboxes} ```python def get_possible_checkboxes(img: Union[str, cv2.Mat], @@ -447,9 +399,7 @@ Assumes the checkbox is square. find_small: if true, finds smaller checkboxes. Sometimes will "find" a checkbox in letters, like O and D, if the font is too small - - -#### get\_possible\_radios(img: Union[str, BinaryIO, cv2.Mat]) +#### get\_possible\_radios(img: Union[str, BinaryIO, cv2.Mat]) {#formfyxer.pdf\_wrangling.get\_possible\_radios} ```python def get_possible_radios(img: Union[str, BinaryIO, cv2.Mat]) @@ -458,9 +408,7 @@ def get_possible_radios(img: Union[str, BinaryIO, cv2.Mat]) Even though it's called "radios", it just gets things shaped like circles, not doing any semantic analysis yet. - - -#### get\_possible\_text\_fields(img: Union[str, BinaryIO, cv2.Mat], text\_lines: List[Textbox], default\_line\_height: int = 44) +#### get\_possible\_text\_fields(img: Union[str, BinaryIO, cv2.Mat], text\_lines: List[Textbox], default\_line\_height: int = 44) {#formfyxer.pdf\_wrangling.get\_possible\_text\_fields} ```python def get_possible_text_fields( @@ -476,9 +424,7 @@ Won't find field inputs as boxes default_line_height: the default height (16 pt), in pixels (at 200 dpi), which is 45 - - -#### auto\_add\_fields(in\_pdf\_file: Union[str, Path], out\_pdf\_file: Union[str, Path]) +#### auto\_add\_fields(in\_pdf\_file: Union[str, Path], out\_pdf\_file: Union[str, Path]) {#formfyxer.pdf\_wrangling.auto\_add\_fields} ```python def auto_add_fields(in_pdf_file: Union[str, Path], out_pdf_file: Union[str, @@ -508,9 +454,7 @@ auto_add_fields('no_fields.pdf', 'newly_added_fields.pdf') Nothing - - -#### is\_tagged(in\_pdf\_file: Union[str, Path, pikepdf.Pdf]) +#### is\_tagged(in\_pdf\_file: Union[str, Path, pikepdf.Pdf]) {#formfyxer.pdf\_wrangling.is\_tagged} ```python def is_tagged(in_pdf_file: Union[str, Path, pikepdf.Pdf]) -> bool diff --git a/docs/components/GithubFeedbackForm/github_feedback.md b/docs/components/GithubFeedbackForm/github_feedback.md index e41dd91eb..deef50458 100644 --- a/docs/components/GithubFeedbackForm/github_feedback.md +++ b/docs/components/GithubFeedbackForm/github_feedback.md @@ -157,7 +157,7 @@ The key lines in the above are: The `only_once_review_widget` will ask two questions, one is a simple "Did we help you?" with thumbs up and thumbs down options, and the second is an open text box for users to write more. If they answer the first question and refresh the screen or continue through the interview, the feedback widget won't be shown again, given that the user doesn't go back past the widget's screen in the interview. -You can change several aspects of the review widget. For more information, see [the API reference of `review_widget` in ALToolbox](../ALToolbox/misc.md#review_widget). That is the function `only_once_review_widget` is using. +You can change several aspects of the review widget. For more information, see [the API reference of `review_widget` in ALToolbox](../ALToolbox/misc.md#ALToolbox.misc.review_widget). That is the function `only_once_review_widget` is using. The `only_once_review_widget` review information is only stored on the docassemble server, and can be viewed [using the feedback browsing interview](#how-to-browse-feedback-on-the-server). diff --git a/docs/get_started/beginners_guide.md b/docs/get_started/beginners_guide.md index 5c265125b..d90585b35 100644 --- a/docs/get_started/beginners_guide.md +++ b/docs/get_started/beginners_guide.md @@ -13,11 +13,11 @@ You will need access to a [docassemble playground](https://docassemble.org/docs/ ## Quick introduction -[The Hello, World exercise](#do-the-hello-world-exercise) is a quick, friendly introduction to docassemble. +[The Hello, World exercise](../docassemble_intro/hello-world.md) is a quick, friendly introduction to docassemble. After doing the exercise, [watch a demonstration of the Weaver](https://www.youtube.com/live/1zF_omoCm1c?si=u9MqDGm_1G3iAH7t&t=1595), a Document Assembly Line tool for quickly turning prepared forms into draft docassemble interviews. The code generated by the Weaver is not a finished interview; it is a starting point intended for further editing. -Finally, [review the interview project management page](#review-the-interview-project-management-guide) to get an idea of what an interview-building project is like. +Finally, [review the interview project management page](project_management.md) to get an idea of what an interview-building project is like. ## Interview builder training diff --git a/docs/volunteer/volunteer.mdx b/docs/volunteer/volunteer.mdx index c416452ab..adab48eff 100644 --- a/docs/volunteer/volunteer.mdx +++ b/docs/volunteer/volunteer.mdx @@ -110,6 +110,6 @@ And more! Whatever your skills and interests, we can probably put them to good u We expect volunteers who are actively training or working on a project to check in regularly. We generally check in weekly by responding to a post in Teams with a status update. (This is also a regular reminder to let us know if you need something else to work on!) -## Ready? Sign up to volunteer +## Ready? Sign up to volunteer {#sign-up-to-volunteer} diff --git a/fix-doc-anchors.py b/fix-doc-anchors.py new file mode 100755 index 000000000..6ecd6a1ec --- /dev/null +++ b/fix-doc-anchors.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 +"""Post-process the auto-generated API reference pages so their in-page anchors +work with Docusaurus' broken-anchor checker. + +``pydoc-markdown`` emits raw ```` tags before every +heading and a "Table of Contents" whose links point at those ids. Docusaurus +only registers anchors that come from Markdown headings (or a handful of theme +components), so every one of those links is reported as a broken anchor at +build time. + +This script rewrites each generated page under ``docs/components`` so that: + +* ```` immediately followed by a heading becomes an explicit + Docusaurus heading id: ``#### heading {#X}``. +* the "Table of Contents" entry that links a module to itself (an ``

``, + which Docusaurus never gives an id) loses its now-danglink link. +* short cross-references copied out of Python docstrings + (``[foo](#foo)``, ``[bar](other_module#bar)``) are expanded to the fully + qualified id that the heading now carries. + +It is idempotent: once a page has been processed the ```` tags are gone +and the headings already carry ``{#...}``, so re-running it is a no-op. It runs +locally against the committed pages and again in CI after ``fix-doc-titles.sh``. +""" + +from __future__ import annotations + +import re +from pathlib import Path + +COMPONENTS_DIR = Path("docs/components") + +A_ID_RE = re.compile(r'^\s*$') +HEADING_RE = re.compile(r"^(#{1,6})\s+\S") +HEADING_HAS_ID_RE = re.compile(r"\{#[^}]+\}\s*$") +FENCE_RE = re.compile(r"^(`{3,}|~{3,})(.*)$") +TOP_TOC_LINK_RE = re.compile(r"^\* \[(?P[^\]]+)\]\(#(?P[^)]+)\)\s*$") +TOC_TITLE_RE = re.compile(r"^# (Table of Contents|[\w.]+\.[\w.]+)\s*$") +# [label](target) where target is `#name` or `path/to/module#name` or +# `module.md#name` and `name` is a plain (dot-free) identifier. +SHORT_XREF_RE = re.compile( + r"\]\((?P[^)#\s]*?)#(?P[A-Za-z_][A-Za-z0-9_]*)\)" +) + + +def iter_pages() -> list[Path]: + return sorted(COMPONENTS_DIR.rglob("*.md")) + + +def build_id_index(pages: list[Path]) -> dict[str, dict[str, str]]: + """stem -> {last dotted segment -> fully qualified id}. + + Ambiguous short names (two members that share a final segment) are dropped + so we never rewrite a link to the wrong target. + """ + index: dict[str, dict[str, str]] = {} + for page in pages: + mapping: dict[str, str] = {} + ambiguous: set[str] = set() + for line in page.read_text(encoding="utf-8").splitlines(): + match = A_ID_RE.match(line) + if not match: + continue + full = match.group(1) + short = full.rsplit(".", 1)[-1] + if short in mapping and mapping[short] != full: + ambiguous.add(short) + mapping.setdefault(short, full) + for name in ambiguous: + mapping.pop(name, None) + index[page.stem] = mapping + return index + + +def _fence_delimiter(line: str) -> tuple[str, str] | None: + match = FENCE_RE.match(line.lstrip()) + if not match: + return None + return match.group(1), match.group(2).strip() + + +def _heading_id_suffix(anchor: str) -> str: + # Underscores in the raw id would be parsed as Markdown emphasis + # ("__init__" -> "init"), corrupting the anchor. pydoc + # already escapes them in the visible heading text; do the same here. + return f" {{#{anchor.replace('_', r'\_')}}}" + + +def attach_heading_ids(lines: list[str]) -> tuple[list[str], bool]: + out: list[str] = [] + changed = False + fence: tuple[str, int] | None = None + i = 0 + while i < len(lines): + line = lines[i] + delimiter = _fence_delimiter(line) + if delimiter is not None: + marker, info = delimiter + if fence is None: + if marker[0] not in info: # an opening ``` can't have ` in its info string + fence = (marker[0], len(marker)) + elif marker[0] == fence[0] and len(marker) >= fence[1] and info == "": + fence = None + + anchor_match = A_ID_RE.match(line) + if not anchor_match: + out.append(line) + i += 1 + continue + + # Look past blank lines for the heading this anchor belongs to. + j = i + 1 + while j < len(lines) and lines[j].strip() == "": + j += 1 + if j < len(lines) and HEADING_RE.match(lines[j]): + if fence is not None: + # A malformed docstring code fence upstream never closed; the + # heading below would be swallowed by it. Close it first. + out.append(fence[0] * fence[1]) + out.append("") + fence = None + heading = lines[j].rstrip() + if not HEADING_HAS_ID_RE.search(heading): + heading = f"{heading}{_heading_id_suffix(anchor_match.group(1))}" + out.append(heading) + changed = True + i = j + 1 + else: + # No heading follows - drop the tag, it is invisible to Docusaurus. + changed = True + i += 1 + return out, changed + + +def drop_module_self_link(lines: list[str]) -> tuple[list[str], bool]: + # Only the pydoc-generated pages carry a "Table of Contents" heading. + if not lines or not TOC_TITLE_RE.match(lines[0]): + return lines, False + for idx, line in enumerate(lines[:6]): + match = TOP_TOC_LINK_RE.match(line) + if not match or "." not in match.group("anchor"): + continue + # The first top-level ("* [x](...)") bullet is the module heading, which + # Docusaurus renders as an

and never assigns an id. + lines[idx] = f"* {match.group('text')}" + return lines, True + return lines, False + + +def expand_short_xrefs( + text: str, stem: str, index: dict[str, dict[str, str]] +) -> tuple[str, bool]: + changed = False + + def replace(match: re.Match[str]) -> str: + nonlocal changed + path = match.group("path") + frag = match.group("frag") + target_stem = Path(path).name[:-3] if path.endswith(".md") else Path(path).name + target_stem = target_stem or stem + full = index.get(target_stem, {}).get(frag) + if not full or "." not in full: + return match.group(0) + changed = True + return f"]({path}#{full})" + + return SHORT_XREF_RE.sub(replace, text), changed + + +def process(page: Path, index: dict[str, dict[str, str]]) -> bool: + with page.open("r", encoding="utf-8", newline="") as handle: + original = handle.read() + newline = "\r\n" if "\r\n" in original else "\n" + trailing_newline = original.endswith(newline) + lines = original.split(newline) + if trailing_newline: + lines = lines[:-1] + + lines, a = attach_heading_ids(lines) + lines, b = drop_module_self_link(lines) + + text = newline.join(lines) + if trailing_newline: + text += newline + text, c = expand_short_xrefs(text, page.stem, index) + + if a or b or c: + with page.open("w", encoding="utf-8", newline="") as handle: + handle.write(text) + return True + return False + + +def main() -> None: + if not COMPONENTS_DIR.is_dir(): + raise SystemExit(f"expected to run from the docs root; {COMPONENTS_DIR} not found") + pages = iter_pages() + index = build_id_index(pages) + touched = [page for page in pages if process(page, index)] + print(f"fix-doc-anchors: updated {len(touched)} of {len(pages)} reference pages") + + +if __name__ == "__main__": + main() diff --git a/src/pages/index.tsx b/src/pages/index.tsx index a5953c89d..ff48e9000 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -10,6 +10,7 @@ import Link from '@docusaurus/Link'; import Translate, {translate} from '@docusaurus/Translate'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useBaseUrl from '@docusaurus/useBaseUrl'; +import useBrokenLinks from '@docusaurus/useBrokenLinks'; import Layout from '@theme/Layout'; import clsx from 'clsx'; import styles from './styles.module.css'; @@ -22,6 +23,10 @@ function Home() { }, } = useDocusaurusContext(); + // The "#partners" section below is a plain
, which Docusaurus' broken + // anchor checker doesn't see on its own; register it explicitly. + useBrokenLinks().collectAnchor('partners'); + return (