From 20aa2054c40c9a4e2e89d273a3dad12ddfee3481 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:19:20 +0000 Subject: [PATCH 1/7] Initial plan From 20888ab94d87d2071d80194139d1c54e5b01a6ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:25:05 +0000 Subject: [PATCH 2/7] Initial analysis: Document current API documentation formatting issues Co-authored-by: nonprofittechy <7645641+nonprofittechy@users.noreply.github.com> --- docs/components/sidebar.json | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/components/sidebar.json b/docs/components/sidebar.json index 1dd9f9fc0..3ad375fb4 100644 --- a/docs/components/sidebar.json +++ b/docs/components/sidebar.json @@ -1,5 +1,12 @@ { - "items": [], - "label": null, + "items": [ + "components/ALToolbox/al_income", + "components/ALToolbox/business_days", + "components/ALToolbox/copy_button", + "components/ALToolbox/llms", + "components/ALToolbox/misc", + "components/ALToolbox/save_input_data" + ], + "label": "ALToolbox", "type": "category" } \ No newline at end of file From b88e11d051e567c23dca097b4f4e8f4f68903bf6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:31:53 +0000 Subject: [PATCH 3/7] Implement major improvements to API documentation formatting and navigation Co-authored-by: nonprofittechy <7645641+nonprofittechy@users.noreply.github.com> --- docs/components/ALToolbox/al_income.md | 490 ++++++- docs/components/ALToolbox/business_days.md | 62 +- docs/components/ALToolbox/copy_button.md | 21 +- docs/components/ALToolbox/llms.md | 219 +++- docs/components/ALToolbox/misc.md | 224 +++- docs/components/ALToolbox/save_input_data.md | 15 +- docs/components/AssemblyLine/al_courts.md | 172 ++- docs/components/AssemblyLine/al_document.md | 1123 +++++++++++++++-- docs/components/AssemblyLine/al_general.md | 704 ++++++++++- .../AssemblyLine/custom_jinja_filters.md | 72 +- docs/components/AssemblyLine/language.md | 72 +- docs/components/AssemblyLine/sessions.md | 382 +++++- docs/components/AssemblyLine/sign.md | 39 +- .../components/EFSPIntegration/conversions.md | 162 ++- docs/components/EFSPIntegration/efm_client.md | 78 +- .../EFSPIntegration/interview_logic.md | 118 +- .../EFSPIntegration/py_efsp_client.md | 150 ++- .../EFSPIntegration/test/test_proxy_conn.md | 7 + docs/components/formfyxer/docx_wrangling.md | 185 +++ docs/components/formfyxer/lit_explorer.md | 528 ++++++++ docs/components/formfyxer/pdf_wrangling.md | 529 ++++++++ pydoc-markdown.yml | 25 +- src/css/custom.css | 138 ++ 23 files changed, 5150 insertions(+), 365 deletions(-) create mode 100644 docs/components/formfyxer/docx_wrangling.md create mode 100644 docs/components/formfyxer/lit_explorer.md create mode 100644 docs/components/formfyxer/pdf_wrangling.md diff --git a/docs/components/ALToolbox/al_income.md b/docs/components/ALToolbox/al_income.md index 83dfa0dc1..ee254a586 100644 --- a/docs/components/ALToolbox/al_income.md +++ b/docs/components/ALToolbox/al_income.md @@ -1,9 +1,81 @@ +# Table of Contents + +* [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) + * [\_\_str\_\_](#ALToolbox.al_income.ALPeriodicAmount.__str__) + * [total](#ALToolbox.al_income.ALPeriodicAmount.total) + * [ALIncome](#ALToolbox.al_income.ALIncome) + * [total](#ALToolbox.al_income.ALIncome.total) + * [ALExpense](#ALToolbox.al_income.ALExpense) + * [ALIncomeList](#ALToolbox.al_income.ALIncomeList) + * [sources](#ALToolbox.al_income.ALIncomeList.sources) + * [matches](#ALToolbox.al_income.ALIncomeList.matches) + * [total](#ALToolbox.al_income.ALIncomeList.total) + * [move\_checks\_to\_list](#ALToolbox.al_income.ALIncomeList.move_checks_to_list) + * [ALJob](#ALToolbox.al_income.ALJob) + * [gross\_total](#ALToolbox.al_income.ALJob.gross_total) + * [deductions](#ALToolbox.al_income.ALJob.deductions) + * [net\_total](#ALToolbox.al_income.ALJob.net_total) + * [employer\_name\_address\_phone](#ALToolbox.al_income.ALJob.employer_name_address_phone) + * [normalized\_hours](#ALToolbox.al_income.ALJob.normalized_hours) + * [ALJobList](#ALToolbox.al_income.ALJobList) + * [total](#ALToolbox.al_income.ALJobList.total) + * [gross\_total](#ALToolbox.al_income.ALJobList.gross_total) + * [net\_total](#ALToolbox.al_income.ALJobList.net_total) + * [deductions](#ALToolbox.al_income.ALJobList.deductions) + * [ALExpenseList](#ALToolbox.al_income.ALExpenseList) + * [ALAsset](#ALToolbox.al_income.ALAsset) + * [total](#ALToolbox.al_income.ALAsset.total) + * [equity](#ALToolbox.al_income.ALAsset.equity) + * [ALAssetList](#ALToolbox.al_income.ALAssetList) + * [market\_value](#ALToolbox.al_income.ALAssetList.market_value) + * [balance](#ALToolbox.al_income.ALAssetList.balance) + * [equity](#ALToolbox.al_income.ALAssetList.equity) + * [owners](#ALToolbox.al_income.ALAssetList.owners) + * [ALVehicle](#ALToolbox.al_income.ALVehicle) + * [year\_make\_model](#ALToolbox.al_income.ALVehicle.year_make_model) + * [ALVehicleList](#ALToolbox.al_income.ALVehicleList) + * [ALSimpleValue](#ALToolbox.al_income.ALSimpleValue) + * [total](#ALToolbox.al_income.ALSimpleValue.total) + * [\_\_str\_\_](#ALToolbox.al_income.ALSimpleValue.__str__) + * [ALSimpleValueList](#ALToolbox.al_income.ALSimpleValueList) + * [sources](#ALToolbox.al_income.ALSimpleValueList.sources) + * [total](#ALToolbox.al_income.ALSimpleValueList.total) + * [ALItemizedValue](#ALToolbox.al_income.ALItemizedValue) + * [income\_fields](#ALToolbox.al_income.ALItemizedValue.income_fields) + * [\_\_str\_\_](#ALToolbox.al_income.ALItemizedValue.__str__) + * [ALItemizedValueDict](#ALToolbox.al_income.ALItemizedValueDict) + * [hook\_after\_gather](#ALToolbox.al_income.ALItemizedValueDict.hook_after_gather) + * [\_\_str\_\_](#ALToolbox.al_income.ALItemizedValueDict.__str__) + * [ALItemizedJob](#ALToolbox.al_income.ALItemizedJob) + * [total](#ALToolbox.al_income.ALItemizedJob.total) + * [gross\_total](#ALToolbox.al_income.ALItemizedJob.gross_total) + * [deduction\_total](#ALToolbox.al_income.ALItemizedJob.deduction_total) + * [net\_total](#ALToolbox.al_income.ALItemizedJob.net_total) + * [employer\_name\_address\_phone](#ALToolbox.al_income.ALItemizedJob.employer_name_address_phone) + * [normalized\_hours](#ALToolbox.al_income.ALItemizedJob.normalized_hours) + * [ALItemizedJobList](#ALToolbox.al_income.ALItemizedJobList) + * [sources](#ALToolbox.al_income.ALItemizedJobList.sources) + * [total](#ALToolbox.al_income.ALItemizedJobList.total) + * [gross\_total](#ALToolbox.al_income.ALItemizedJobList.gross_total) + * [deduction\_total](#ALToolbox.al_income.ALItemizedJobList.deduction_total) + * [net\_total](#ALToolbox.al_income.ALItemizedJobList.net_total) + --- sidebar_label: al_income title: ALToolbox.al_income --- -#### times\_per\_year + + +#### times\_per\_year(times\_per\_year\_list: List[Tuple[int, str]], times\_per\_year: float) + +```python +def times_per_year(times_per_year_list: List[Tuple[int, str]], + times_per_year: float) -> str +``` Get the lower-case textual description that matches a time period contained in a "times per year" list. @@ -27,7 +99,15 @@ represent "every two years". Items not contained in the list (to provi specific lookup name) will have a string representation that is rounded to the nearest whole integer. -#### recent\_years + + +#### recent\_years(past: int = 25, order: str = "descending", future: int = 1) + +```python +def recent_years(past: int = 25, + order: str = "descending", + future: int = 1) -> List[int] +``` Returns a list of the most recent past years, continuing into the future. Defaults to most recent 15 years+1. Useful to populate a combobox of years @@ -40,6 +120,8 @@ The default is 15 * order \{string\} 'descending' or 'ascending'. Default is `descending`. * future (defaults to 1). + + ## ALPeriodicAmount Objects ```python @@ -60,16 +142,30 @@ 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\_\_() + +```python +def __str__() -> str +``` Returns the income's `.total()` as string, not its object name. -#### total + + +#### total(times\_per\_year: float = 1) + +```python +def total(times_per_year: float = 1) -> Decimal +``` Returns the income over the specified times_per_year, To calculate `.total()`, an ALPeriodicAmount must have a `.times_per_year` and `.value`. + + ## ALIncome Objects ```python @@ -95,7 +191,13 @@ 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 + + +#### total(times\_per\_year: float = 1) + +```python +def total(times_per_year: float = 1) -> Decimal +``` Returns the income over the specified times_per_year, taking into account hours per period for hourly items. For example, for an hourly income of 10 @@ -105,6 +207,8 @@ and `income.total(52)` would be 400, the weekly income. To calculate `.total()`, an ALIncome must have a `.times_per_year` and `.value`. It can also have `.is_hourly` and `.hours_per_period`. + + ## ALExpense Objects ```python @@ -113,6 +217,8 @@ class ALExpense(ALPeriodicAmount) Not much changes from ALPeriodic Amount, just the generic object questions + + ## ALIncomeList Objects ```python @@ -128,17 +234,39 @@ use of these attributes and methods in its items: .value .total() -#### sources + + +#### sources() + +```python +def sources() -> Set[str] +``` Returns a set of the unique sources in the ALIncomeList. -#### matches + + +#### matches(source: SourceType, exclude\_source: Optional[SourceType] = None) + +```python +def matches(source: SourceType, + exclude_source: Optional[SourceType] = None) -> "ALIncomeList" +``` Returns an ALIncomeList consisting only of elements matching the specified income source, assisting in filling PDFs with predefined spaces. `source` may be a list. -#### total + + +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) + +```python +def total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None, + owner: Optional[str] = None) -> Decimal +``` Returns the total periodic value in the list, gathering the list items if necessary. You can optionally filter by `source`. `source` can be a @@ -148,7 +276,14 @@ To calculate `.total()` correctly, all items must have a `.total()` and it should be a positive value. Job-type incomes should automatically exclude deductions. -#### move\_checks\_to\_list + + +#### move\_checks\_to\_list(selected\_types: Optional[DADict] = None, selected\_terms: Optional[Mapping] = None) + +```python +def move_checks_to_list(selected_types: Optional[DADict] = None, + selected_terms: Optional[Mapping] = None) +``` Gives a 'gather by checklist' option. If no selected_types param is passed, requires that a .selected_types @@ -159,6 +294,8 @@ Sets the attribute "moved" to true, doesn't set gathered, because idempotent, so trying to also gather all info about the checks in the list doesn't work well. + + ## ALJob Objects ```python @@ -190,7 +327,13 @@ Can be stored in an ALJobList. .employer \{Individual\} (Optional) A docassemble Individual object, employer.address is the address and employer.phone is the phone -#### gross\_total + + +#### gross\_total(times\_per\_year: float = 1) + +```python +def gross_total(times_per_year: float = 1) -> Decimal +``` Same as ALIncome total. Returns the income over the specified times_per_year, representing the `.value` attribute of the item. @@ -198,7 +341,13 @@ representing the `.value` attribute of the item. `times_per_year` is some denominator of a year. E.g. to express a weekly period, use 52. The default is 1 (a year). -#### deductions + + +#### deductions(times\_per\_year: float = 1) + +```python +def deductions(times_per_year: float = 1) -> Decimal +``` Returns the total deductions from someone's pay over the specificed times_per_year (not per hour if hourly). @@ -206,7 +355,13 @@ Returns the total deductions from someone's pay over the specificed times_p `times_per_year` is some denominator of a year. E.g. to express a weekly period, use 52. The default is 1 (a year). -#### net\_total + + +#### net\_total(times\_per\_year: float = 1) + +```python +def net_total(times_per_year: float = 1) -> Decimal +``` Returns the net income over a time period, found using `self.value` and `self.deduction`. @@ -219,13 +374,25 @@ 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() + +```python +def employer_name_address_phone() -> str +``` Returns name, address and phone number of employer as a string. Forces gathering the `.employer`, `.employer_address`, and `.employer_phone` attributes. -#### normalized\_hours + + +#### normalized\_hours(times\_per\_year: float = 1) + +```python +def normalized_hours(times_per_year: float = 1) -> float +``` Returns the normalized number of hours worked in a given times_per_year, based on the self.hours_per_period and self.times_per_year attributes. @@ -239,6 +406,8 @@ period, use 52. The default is 1 (a year). This will force the gathering of the attributes `.hours_per_period` and `.times_per_year` + + ## ALJobList Objects ```python @@ -249,7 +418,16 @@ 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. -#### total + + +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) + +```python +def total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None, + owner: Optional[str] = None) -> Decimal +``` Returns the sum of the gross incomes of its ALJobs divided by the time times_per_year. You can filter the jobs by `source`. `source` can be a @@ -258,7 +436,15 @@ 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 + + +#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def gross_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the sum of the gross incomes of its ALJobs divided by the time times_per_year. You can filter the jobs by `source`. `source` can be a @@ -267,7 +453,15 @@ 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). -#### net\_total + + +#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def net_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the sum of the net incomes of its ALJobs divided by the time times_per_year. You can filter the jobs by `source`. `source` can be a @@ -279,12 +473,22 @@ If the job is hourly, the `net_total()` may not be comparable to the `times_per_year` is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year). -#### deductions + + +#### deductions(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def deductions(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the sum of the deductions of its ALJobs divided by the time times_per_year. You can filter the jobs by `source`. Leaving out `source` will use all sources. + + ## ALExpenseList Objects ```python @@ -298,6 +502,8 @@ A list of expenses * source * display name + + ## ALAsset Objects ```python @@ -325,7 +531,13 @@ 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 + + +#### total(times\_per\_year: float = 1) + +```python +def total(times_per_year: float = 1) -> Decimal +``` Returns the .value attribute divided by the times per year you want to calculate. The value defaults to 0. @@ -340,7 +552,13 @@ 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 + + +#### equity(loan\_attribute="balance") + +```python +def equity(loan_attribute="balance") -> Decimal +``` Returns the total equity in the asset (e.g., market value minus balance). @@ -353,6 +571,8 @@ Returns the total equity in the asset (e.g., market value minus balance). - `Decimal` - The total equity in the asset. + + ## ALAssetList Objects ```python @@ -378,7 +598,14 @@ 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 + + +#### market\_value(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def market_value(source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the total `.market_value` of assets in the list. @@ -396,7 +623,14 @@ You can filter the assets by `source`. `source` can be a string or a list. - `Decimal` - The total market value of the assets. -#### balance + + +#### balance(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def balance(source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the total `.balance` of assets in the list, which typically corresponds to the available funds in a financial account. @@ -414,7 +648,15 @@ You can filter the assets by `source`. `source` can be a string or a list. - `Decimal` - The total balance of the assets. -#### equity + + +#### equity(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, loan\_attribute: str = "balance") + +```python +def equity(source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None, + loan_attribute: str = "balance") -> Decimal +``` Calculates and returns the total equity in the assets. @@ -432,7 +674,14 @@ specified, or if the asset's source satisfies the source criteria, the equi - `Decimal` - The total equity in the assets. -#### owners + + +#### owners(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def owners(source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Set[str] +``` Returns a set of the unique owners of the assets. @@ -450,6 +699,8 @@ 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 ```python @@ -475,7 +726,13 @@ statement forms. - `owner` _str_ - Full name of the vehicle owner. - `source` _str, optional_ - The source of the asset, defaults to 'vehicle'. -#### year\_make\_model + + +#### year\_make\_model(separator: str = " / ") + +```python +def year_make_model(separator: str = " / ") -> str +``` Returns a string of the format year/make/model of the vehicle. Triggers gathering those attributes. @@ -489,6 +746,8 @@ gathering those attributes. A string of the format year/make/model of the vehicle. + + ## ALVehicleList Objects ```python @@ -497,6 +756,8 @@ class ALVehicleList(ALAssetList) List of ALVehicles. Extends ALAssetList. + + ## ALSimpleValue Objects ```python @@ -513,7 +774,13 @@ item in an ALSimpleValueList. negative value to the total of the item. .source \{str\} (Optional) The "source" of the item, like "vase". -#### total + + +#### total() + +```python +def total() -> Decimal +``` If desired, to use as a ledger, values can be signed (mixed positive and negative). Setting transaction_type = 'expense' makes the value negative. @@ -522,10 +789,18 @@ Use min=0 in that case. If you use signed values, be careful when placing in an ALIncomeList object. The `total()` method may return unexpected results in that case. -#### \_\_str\_\_ + + +#### \_\_str\_\_() + +```python +def __str__() -> str +``` Returns the total as a formatted string + + ## ALSimpleValueList Objects ```python @@ -534,16 +809,31 @@ class ALSimpleValueList(DAList) Represents a filterable DAList of ALSimpleValues. -#### sources + + +#### sources() + +```python +def sources() -> Set +``` Returns a set of the unique sources of values stored in the list. -#### total + + +#### total(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def total(source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the total value in the list, gathering the list items if necessary. You can filter the values by `source`. `source` can be a string or a list. + + ## ALItemizedValue Objects ```python @@ -572,15 +862,29 @@ filtering methods of the ALItemizedJob that contains it. If the ".exists" attribute is False or undefined, the item will not be used when calculating totals. -#### income\_fields + + +#### income\_fields(use\_exists=True) + +```python +def income_fields(use_exists=True) -> List[Dict[str, Any]] +``` Returns a YAML structure representing the list of fields for an itemized value, to be passed to a `code` attribute of a question's fields -#### \_\_str\_\_ + + +#### \_\_str\_\_() + +```python +def __str__() -> str +``` Returns a string of the value of the item with two decimal places. + + ## ALItemizedValueDict Objects ```python @@ -596,7 +900,13 @@ and one for deductions. WARNING: Should only be accessed through an ALItemizedJob. Otherwise you may get unexpected results. -#### hook\_after\_gather + + +#### hook\_after\_gather() + +```python +def hook_after_gather() -> None +``` Update item lists after they've been gathered or edited to remove non-existent items. Will still allow the developer to set `auto_gather=False` if they @@ -606,11 +916,19 @@ 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:` -#### \_\_str\_\_ + + +#### \_\_str\_\_() + +```python +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 ```python @@ -670,11 +988,27 @@ 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 + + +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Alias for ALItemizedJob.gross_total to integrate with ALIncomeList math. -#### gross\_total + + +#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def gross_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the sum of positive values (payments) for a given times_per_year. You can filter the items by `source`. `source` can be a string or a list. @@ -687,7 +1021,15 @@ If you use sources from deductions, they will be ignored. - `kwarg` - source \{str | [str]\} (Optional) Source or list of sources of desired item(s). -#### deduction\_total + + +#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def deduction_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the sum of money going out (normally, deductions like union dues) divided by a pay times_per_year as a positive value. You can @@ -700,7 +1042,15 @@ filter the items by `source`. `source` can be a string or a list. - `kwarg` - source \{str | List[str]\} (Optional) Source or list of sources of desired item(s). -#### net\_total + + +#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def net_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the net (gross minus deductions) value of the job divided by `times_per_year`. You can filter the items by `source`. `source` can be a @@ -713,12 +1063,24 @@ string or a list. E.g. "full time" or ["full time", "un - `kwarg` - source \{str | List[str]\} (Optional) Source or list of sources of desired item(s). -#### employer\_name\_address\_phone + + +#### employer\_name\_address\_phone() + +```python +def employer_name_address_phone() -> str +``` Returns concatenation of employer name and, if they exist, employer address and phone number. -#### normalized\_hours + + +#### normalized\_hours(times\_per\_year: float = 1) + +```python +def normalized_hours(times_per_year: float = 1) -> float +``` Returns the normalized number of hours worked in a given times_per_year, based on the self.hours_per_period and self.times_per_year attributes. @@ -726,6 +1088,8 @@ based on the self.hours_per_period and self.times_per_year attributes. For example, if the person works 10 hours a week, it will return 520 when the times_per_year parameter is 1. + + ## ALItemizedJobList Objects ```python @@ -735,17 +1099,39 @@ 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 + + +#### sources(which\_side: Optional[str] = None) + +```python +def sources(which_side: Optional[str] = None) -> Set[str] +``` Returns a set of the unique sources in all of the jobs. By default gets from both sides, if which_side is "deductions", only gets from deductions. -#### total + + +#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Alias for ALItemizedJobList.gross_total to integrate with ALIncomeList math. -#### gross\_total + + +#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def gross_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the sum of the gross incomes of the list's jobs divided by the times_per_year. You can filter the items by `source`. `source` can be a @@ -759,7 +1145,15 @@ string or a list. - `kwarg` - times_per_year \{float\} (Optional) Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Default is 1. -#### deduction\_total + + +#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def deduction_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the sum of the deductions of the list's jobs divided by the times_per_year. You can filter the items by `source`. `source` can be a @@ -773,7 +1167,15 @@ string or a list. - `kwarg` - times_per_year \{float\} (Optional) Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Default is 1. -#### net\_total + + +#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) + +```python +def net_total(times_per_year: float = 1, + source: Optional[SourceType] = None, + exclude_source: Optional[SourceType] = None) -> Decimal +``` Returns the net of the list's jobs (money in minus money out) divided by the times_per_year. You can filter the items by `source`. `source` can be a diff --git a/docs/components/ALToolbox/business_days.md b/docs/components/ALToolbox/business_days.md index 04e46c571..4edf85447 100644 --- a/docs/components/ALToolbox/business_days.md +++ b/docs/components/ALToolbox/business_days.md @@ -1,9 +1,29 @@ +# Table of Contents + +* [ALToolbox.business\_days](#ALToolbox.business_days) + * [standard\_holidays](#ALToolbox.business_days.standard_holidays) + * [is\_business\_day](#ALToolbox.business_days.is_business_day) + * [get\_next\_business\_day](#ALToolbox.business_days.get_next_business_day) + * [get\_date\_after\_n\_business\_days](#ALToolbox.business_days.get_date_after_n_business_days) + --- sidebar_label: business_days title: ALToolbox.business_days --- -#### standard\_holidays + + +#### standard\_holidays(year, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) + +```python +def standard_holidays( + year, + country="US", + subdiv="MA", + add_holidays: Optional[Mapping] = None, + remove_holidays: Optional[Iterable[str]] = None +) -> holidays.HolidayBase +``` Get all holidays in the specified year, country, and state (or other subdivision). Note that this draws on the "holidays" package which may deviate slightly from @@ -24,7 +44,17 @@ the keys are datetime.date objects. \} ``` -#### is\_business\_day + + +#### is\_business\_day(date: Union[str, DADateTime], country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) + +```python +def is_business_day(date: Union[str, DADateTime], + country="US", + subdiv="MA", + add_holidays: Optional[Mapping] = None, + remove_holidays: Optional[Iterable[str]] = None) -> bool +``` Returns true if and only if the specified date is a business day (i.e., not a holiday) in the specified jurisdiction. Business days are considered to be: @@ -37,7 +67,19 @@ in the specified jurisdiction. Business days are considered to be: assert(is_business_day("2023-03-26") == False) ``` -#### get\_next\_business\_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) + +```python +def 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) -> DADateTime +``` Returns the first day AFTER the specified start date that is not a federal or state holiday, Saturday or Sunday. Optionally, @@ -61,7 +103,19 @@ https://github.com/dr-prodigy/python-holidays/tree/master/holidays/countries will add those holidays to be considered - `remove_holidays` - the list of date strings ("12/25") of dates that are no longer holidays -#### get\_date\_after\_n\_business\_days + + +#### 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) + +```python +def 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) -> DADateTime +``` Returns a time period which contains a minimum of `n` business days. diff --git a/docs/components/ALToolbox/copy_button.md b/docs/components/ALToolbox/copy_button.md index 9e55cc063..6c42cc731 100644 --- a/docs/components/ALToolbox/copy_button.md +++ b/docs/components/ALToolbox/copy_button.md @@ -1,9 +1,28 @@ +# Table of Contents + +* [ALToolbox.copy\_button](#ALToolbox.copy_button) + * [copy\_button\_html](#ALToolbox.copy_button.copy_button_html) + --- sidebar_label: copy_button title: ALToolbox.copy_button --- -#### copy\_button\_html + + +#### 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 = "") + +```python +def 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 = "") -> str +``` Return the html for a button that will let a user copy the given text diff --git a/docs/components/ALToolbox/llms.md b/docs/components/ALToolbox/llms.md index 62ba91373..5d536e4cb 100644 --- a/docs/components/ALToolbox/llms.md +++ b/docs/components/ALToolbox/llms.md @@ -1,9 +1,55 @@ +# Table of Contents + +* [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) + * [classify\_text](#ALToolbox.llms.classify_text) + * [synthesize\_user\_responses](#ALToolbox.llms.synthesize_user_responses) + * [define\_fields\_from\_dict](#ALToolbox.llms.define_fields_from_dict) + * [Goal](#ALToolbox.llms.Goal) + * [response\_satisfies\_me\_or\_follow\_up](#ALToolbox.llms.Goal.response_satisfies_me_or_follow_up) + * [get\_next\_question](#ALToolbox.llms.Goal.get_next_question) + * [GoalDict](#ALToolbox.llms.GoalDict) + * [satisfied](#ALToolbox.llms.GoalDict.satisfied) + * [GoalQuestion](#ALToolbox.llms.GoalQuestion) + * [GoalSatisfactionList](#ALToolbox.llms.GoalSatisfactionList) + * [mark\_satisfied\_goals](#ALToolbox.llms.GoalSatisfactionList.mark_satisfied_goals) + * [keep\_going](#ALToolbox.llms.GoalSatisfactionList.keep_going) + * [need\_more\_questions](#ALToolbox.llms.GoalSatisfactionList.need_more_questions) + * [satisfied](#ALToolbox.llms.GoalSatisfactionList.satisfied) + * [get\_next\_goal\_and\_question](#ALToolbox.llms.GoalSatisfactionList.get_next_goal_and_question) + * [synthesize\_draft\_response](#ALToolbox.llms.GoalSatisfactionList.synthesize_draft_response) + * [provide\_feedback](#ALToolbox.llms.GoalSatisfactionList.provide_feedback) + * [IntakeQuestion](#ALToolbox.llms.IntakeQuestion) + * [IntakeQuestionList](#ALToolbox.llms.IntakeQuestionList) + * [need\_more\_questions](#ALToolbox.llms.IntakeQuestionList.need_more_questions) + --- sidebar_label: llms title: ALToolbox.llms --- -#### chat\_completion + + +#### 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 = False, openai\_base\_url: Optional[str] = None, max\_output\_tokens: Optional[int] = None, max\_input\_tokens: Optional[int] = None) + +```python +def 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 = False, + openai_base_url: Optional[str] = None, + max_output_tokens: Optional[int] = None, + max_input_tokens: Optional[int] = None +) -> Union[List[Any], Dict[str, Any], str] +``` A light wrapper on the OpenAI chat endpoint. @@ -29,7 +75,18 @@ 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 + + +#### 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") + +```python +def 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") -> Dict[str, Any] +``` Extracts fields from text. @@ -43,7 +100,19 @@ Extracts fields from text. A dictionary of fields extracted from the text -#### match\_goals\_from\_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") + +```python +def 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") -> Dict[str, Any] +``` Reads a user's message and determines whether it meets a set of goals, with the help of an LLM. @@ -57,7 +126,19 @@ 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 + + +#### 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") + +```python +def 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") -> str +``` Given a text, classify it into one of the provided choices with the assistance of a large language model. @@ -70,7 +151,18 @@ Given a text, classify it into one of the provided choices with the assistance o - `temperature` _float_ - The temperature to use for GPT. Defaults to 0. - `model` _str_ - The model to use for the GPT API -#### synthesize\_user\_responses + + +#### 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") + +```python +def 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") -> str +``` Given a first draft and a series of follow-up questions and answers, use an LLM to synthesize the user's responses into a single, coherent reply. @@ -85,7 +177,14 @@ into a single, coherent reply. - `temperature` _float_ - The temperature to use for GPT. Defaults to 0. - `model` _str_ - The model to use for the GPT API -#### define\_fields\_from\_dict + + +#### define\_fields\_from\_dict(field\_dict: Dict[str, Any], fields\_to\_ignore: Optional[List] = None) + +```python +def define_fields_from_dict(field_dict: Dict[str, Any], + fields_to_ignore: Optional[List] = None) -> None +``` Assigns the values in a dictionary of fields to the corresponding fields in a Docassemble interview. @@ -103,6 +202,8 @@ Docassemble and built-in keywords are never defined by this function. If fields_ None + + ## Goal Objects ```python @@ -117,7 +218,19 @@ 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 + + +#### 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") + +```python +def 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") -> str +``` Returns the text of the next question to ask the user or the string "satisfied" if the user's response satisfies the goal. @@ -131,10 +244,20 @@ if the user's response satisfies the goal. True if the response satisfies the goal, False otherwise -#### get\_next\_question + + +#### get\_next\_question(thread\_so\_far: List[Dict[str, str]], openai\_client: Optional[OpenAI] = None, model="gpt-4o-mini") + +```python +def get_next_question(thread_so_far: List[Dict[str, str]], + openai_client: Optional[OpenAI] = None, + model="gpt-4o-mini") -> str +``` Returns the text of the next question to ask the user. + + ## GoalDict Objects ```python @@ -143,10 +266,18 @@ class GoalDict(DADict) A class to represent a DADict of Goals. -#### satisfied + + +#### satisfied() + +```python +def satisfied() +``` Returns True if all goals are satisfied, False otherwise. + + ## GoalQuestion Objects ```python @@ -161,6 +292,8 @@ 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 + + ## GoalSatisfactionList Objects ```python @@ -196,7 +329,13 @@ 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() + +```python +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. @@ -205,22 +344,46 @@ This should be used as soon as the user gives their initial reply. None -#### keep\_going + + +#### keep\_going() + +```python +def keep_going() +``` Returns 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() + +```python +def need_more_questions() +``` Returns True if there is at least one unsatisfied goal, False otherwise. Also has the side effect of checking the user's most recent response to see if it satisfies the goal and updating the next question to be asked. -#### satisfied + + +#### satisfied() + +```python +def satisfied() +``` Returns True if all goals are satisfied, False otherwise. -#### get\_next\_goal\_and\_question + + +#### get\_next\_goal\_and\_question() + +```python +def get_next_goal_and_question() +``` Returns the next unsatisfied goal, along with a follow-up question to ask the user, if relevant. @@ -229,14 +392,28 @@ 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() + +```python +def synthesize_draft_response() +``` Returns a draft response that synthesizes the user's responses to the questions. -#### provide\_feedback + + +#### provide\_feedback(feedback\_prompt: str = "") + +```python +def provide_feedback(feedback_prompt: str = "") +``` Returns feedback to the user based on the goals they satisfied. + + ## IntakeQuestion Objects ```python @@ -250,6 +427,8 @@ 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 + + ## IntakeQuestionList Objects ```python @@ -282,7 +461,13 @@ 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() + +```python +def need_more_questions() +``` Returns True if the user needs to answer more questions, False otherwise. diff --git a/docs/components/ALToolbox/misc.md b/docs/components/ALToolbox/misc.md index 08a8db4c3..3411cefcd 100644 --- a/docs/components/ALToolbox/misc.md +++ b/docs/components/ALToolbox/misc.md @@ -1,9 +1,40 @@ +# Table of Contents + +* [ALToolbox.misc](#ALToolbox.misc) + * [thousands](#ALToolbox.misc.thousands) + * [tel](#ALToolbox.misc.tel) + * [fa\_icon](#ALToolbox.misc.fa_icon) + * [space](#ALToolbox.misc.space) + * [yes\_no\_unknown](#ALToolbox.misc.yes_no_unknown) + * [number\_to\_letter](#ALToolbox.misc.number_to_letter) + * [collapse\_template](#ALToolbox.misc.collapse_template) + * [tabbed\_templates\_html](#ALToolbox.misc.tabbed_templates_html) + * [review\_widget](#ALToolbox.misc.review_widget) + * [sum\_if\_defined](#ALToolbox.misc.sum_if_defined) + * [add\_records](#ALToolbox.misc.add_records) + * [output\_checkbox](#ALToolbox.misc.output_checkbox) + * [nice\_county\_name](#ALToolbox.misc.nice_county_name) + * [button\_array](#ALToolbox.misc.button_array) + * [none\_to\_empty](#ALToolbox.misc.none_to_empty) + * [option\_or\_other](#ALToolbox.misc.option_or_other) + * [true\_values\_with\_other](#ALToolbox.misc.true_values_with_other) + * [include\_a\_year](#ALToolbox.misc.include_a_year) + * [is\_leap\_year](#ALToolbox.misc.is_leap_year) + * [age\_in\_years](#ALToolbox.misc.age_in_years) + * [format\_date\_if\_defined](#ALToolbox.misc.format_date_if_defined) + --- sidebar_label: misc title: ALToolbox.misc --- -#### thousands + + +#### thousands(num: Union[float, str, Decimal], show\_decimals=False) + +```python +def thousands(num: Union[float, str, Decimal], show_decimals=False) -> str +``` Return a whole number formatted with thousands separator. Optionally, format with 2 decimal points (for a PDF form with the @@ -12,11 +43,28 @@ currency symbol already present in the form) If `show_decimals`, will call `int(num)`, truncating the decimals instead of rounding to the closest int. -#### tel + + +#### tel(phone\_number) + +```python +def tel(phone_number) -> str +``` Format a phone number so you can click on it to open in your phone dialer -#### fa\_icon + + +#### 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) + +```python +def fa_icon(icon: str, + color: Optional[str] = "primary", + color_css: Optional[str] = None, + size: Optional[str] = "sm", + fa_class: str = "fa-solid", + aria_hidden: bool = True) -> str +``` Display a fontawesome icon inline. @@ -43,23 +91,54 @@ you more control over the icon that is inserted. HTML for a font-awesome icon of the specified size and color. -#### space + + +#### space(var\_name: str, prefix=" ", suffix="") + +```python +def space(var_name: str, prefix=" ", suffix="") -> str +``` If the value as a string is defined, return it prefixed/suffixed. Defaults to prefix of a space. Helps build a sentence with less cruft. Equivalent to SPACE function in HotDocs. -#### yes\_no\_unknown + + +#### yes\_no\_unknown(var\_name: str, condition: Optional[bool], unknown="Unknown", placeholder=0) + +```python +def yes_no_unknown(var_name: str, + condition: Optional[bool], + unknown="Unknown", + placeholder=0) +``` Return 'unknown' if the value is None rather than False. Helper for PDF filling with yesnomaybe fields -#### number\_to\_letter + + +#### number\_to\_letter(n: Optional[int]) + +```python +def number_to_letter(n: Optional[int]) -> str +``` Returns a capital letter representing ordinal position. E.g., 1=A, 2=B, etc. Appends letters once you reach 26 in a way compatible with Excel/Google Sheets column naming conventions. 27=AA, 28=AB... -#### collapse\_template + + +#### collapse\_template(template: DALazyTemplate, classname: str | None = None, closed\_icon: str = "caret-right", open\_icon: str = "caret-down", collapsed: bool = True) + +```python +def collapse_template(template: DALazyTemplate, + classname: str | None = None, + closed_icon: str = "caret-right", + open_icon: str = "caret-down", + collapsed: bool = True) -> str +``` Insert HTML for a Bootstrap "collapse" div. @@ -68,11 +147,32 @@ Optionally, you can specify a custom icon to override the defaults: The default icons are "right caret" which displays when the text is collapsed (`closed_icon`) and "down caret" which displays when the text is open (`open_icon`). -#### tabbed\_templates\_html + + +#### tabbed\_templates\_html(tab\_group\_name: str, \*pargs) + +```python +def tabbed_templates_html(tab_group_name: str, *pargs) -> str +``` Provided a list of templates, create Bootstrap v 4.5 tabs with the `subject` as the tab label. -#### review\_widget + + +#### 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!") + +```python +def review_widget( + *, + up_action: str, + down_action: str, + review_action: Optional[str] = None, + thumbs_display: str = "Did we help you?", + review_display: + str = "Thank you for your feedback. Let us know what we could do better", + submit_review_button: str = "Add your review", + post_review_display: str = "Thank you for your review!") -> str +``` A widget that allows people to give a quick review (thumbs up and down, with an optional text component) in the middle of an interview without triggering a page reload. @@ -98,15 +198,35 @@ a submit button appears, and once the text review is submitted (or after the thu the HTML string of the widget -#### sum\_if\_defined + + +#### sum\_if\_defined(\*pargs) + +```python +def sum_if_defined(*pargs) +``` Lets you add up the value of variables that are not in a list -#### add\_records + + +#### add\_records(obj, labels) + +```python +def add_records(obj, labels) +``` List demo interviews in the current package to be run from the landing page -#### output\_checkbox + + +#### output\_checkbox(value\_to\_check: bool, checked\_value: str = "[X]", unchecked\_value: str = "[ ]") + +```python +def output_checkbox(value_to_check: bool, + checked_value: str = "[X]", + unchecked_value: str = "[ ]") +``` Generate a conditional checkbox for docx templates @@ -116,12 +236,26 @@ Generate a conditional checkbox for docx templates with the image of a checkbox - `unchecked_value` - opposite meaning of `checked_value` and defaults to `[ ]` -#### nice\_county\_name + + +#### nice\_county\_name(address: Address) + +```python +def nice_county_name(address: Address) -> str +``` If the county name contains the word "County", which Google Address Autocomplete does by default, remove it. -#### button\_array + + +#### button\_array(buttons: List[ButtonDict], custom\_container\_class="", custom\_link\_class="") + +```python +def button_array(buttons: List[ButtonDict], + custom_container_class="", + custom_link_class="") -> str +``` Create a grid of da-buttons from a dictionary of links and icons @@ -148,7 +282,13 @@ of privileges. HTML for a grid of buttons -#### none\_to\_empty + + +#### none\_to\_empty(val: Any) + +```python +def none_to_empty(val: Any) +``` If the value is None or "None", return a DAEmpty value. Otherwise return the value. @@ -166,7 +306,14 @@ without raising an error. a DAEmpty if the value is None, otherwise the value -#### option\_or\_other + + +#### option\_or\_other(variable\_name: str, other\_variable\_name: Optional[str] = None) + +```python +def option_or_other(variable_name: str, + other_variable_name: Optional[str] = None) -> str +``` If the variable is set to 'Other', return the value of the 'other' variable. Otherwise return the value of the variable. @@ -181,7 +328,15 @@ 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 + + +#### true\_values\_with\_other(variable\_name: str, other\_variable\_name: Optional[str] = None) + +```python +def true_values_with_other( + variable_name: str, + other_variable_name: Optional[str] = None) -> List[str] +``` Return a list of values that are True, with the value of the 'other' variable appended to the end of the list. @@ -196,7 +351,13 @@ 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. -#### include\_a\_year + + +#### include\_a\_year(text: str, field: Optional[str] = None) + +```python +def include_a_year(text: str, field: Optional[str] = None) -> bool +``` Validates whether the input text contains at least one 4-digit sequence that occurs within a range of ~ 200 years, indicating a valid "year" @@ -205,7 +366,13 @@ or a moving date. Returns True if found, otherwise raises a DAValidationError. -#### is\_leap\_year + + +#### is\_leap\_year(year: int) + +```python +def is_leap_year(year: int) -> bool +``` Helper function for `age_in_years` to determine if a year is a leap year. @@ -217,7 +384,13 @@ 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 + + +#### age\_in\_years(the\_date: Union[str, DADateTime]) + +```python +def age_in_years(the_date: Union[str, DADateTime]) -> int +``` Calculate the age in years from a date (treated like a date of birth). @@ -229,7 +402,16 @@ 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 + + +#### format\_date\_if\_defined(date\_object\_name: str, \*pargs, default: str = "", \*\*kwargs) + +```python +def format_date_if_defined(date_object_name: str, + *pargs, + default: str = "", + **kwargs) -> str +``` Format a date string if it is defined, otherwise return an empty string. diff --git a/docs/components/ALToolbox/save_input_data.md b/docs/components/ALToolbox/save_input_data.md index 14affdefc..44ab2f5b9 100644 --- a/docs/components/ALToolbox/save_input_data.md +++ b/docs/components/ALToolbox/save_input_data.md @@ -1,9 +1,22 @@ +# Table of Contents + +* [ALToolbox.save\_input\_data](#ALToolbox.save_input_data) + * [save\_input\_data](#ALToolbox.save_input_data.save_input_data) + --- sidebar_label: save_input_data title: ALToolbox.save_input_data --- -#### save\_input\_data + + +#### save\_input\_data(title: str = "", input\_dict: Optional[Dict[str, Any]] = None, tags: Optional[List[str]] = None) + +```python +def save_input_data(title: str = "", + input_dict: Optional[Dict[str, Any]] = None, + tags: Optional[List[str]] = None) -> None +``` This function is used by survey type interviews to save input data for data reporting purposes. diff --git a/docs/components/AssemblyLine/al_courts.md b/docs/components/AssemblyLine/al_courts.md index 5a32190b5..eeb5201b5 100644 --- a/docs/components/AssemblyLine/al_courts.md +++ b/docs/components/AssemblyLine/al_courts.md @@ -1,3 +1,25 @@ +# Table of Contents + +* [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) + * [short\_label\_and\_address](#AssemblyLine.al_courts.ALCourt.short_label_and_address) + * [short\_description](#AssemblyLine.al_courts.ALCourt.short_description) + * [from\_row](#AssemblyLine.al_courts.ALCourt.from_row) + * [geolocate](#AssemblyLine.al_courts.ALCourt.geolocate) + * [geocode](#AssemblyLine.al_courts.ALCourt.geocode) + * [ALCourtLoader](#AssemblyLine.al_courts.ALCourtLoader) + * [init](#AssemblyLine.al_courts.ALCourtLoader.init) + * [all\_courts](#AssemblyLine.al_courts.ALCourtLoader.all_courts) + * [unique\_column\_values](#AssemblyLine.al_courts.ALCourtLoader.unique_column_values) + * [county\_list](#AssemblyLine.al_courts.ALCourtLoader.county_list) + * [county\_has\_one\_court](#AssemblyLine.al_courts.ALCourtLoader.county_has_one_court) + * [county\_court](#AssemblyLine.al_courts.ALCourtLoader.county_court) + * [matching\_courts\_in\_county](#AssemblyLine.al_courts.ALCourtLoader.matching_courts_in_county) + * [filter\_courts](#AssemblyLine.al_courts.ALCourtLoader.filter_courts) + * [as\_court](#AssemblyLine.al_courts.ALCourtLoader.as_court) + --- sidebar_label: al_courts title: AssemblyLine.al_courts @@ -5,6 +27,8 @@ title: AssemblyLine.al_courts Package for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now + + ## ALCourt Objects ```python @@ -18,7 +42,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Create a new court object. @@ -27,7 +57,13 @@ Create a new court object. - `*pargs` - Standard DAObject positional arguments - `**kwargs` - Standard DAObject keyword arguments -#### short\_label + + +#### short\_label() + +```python +def short_label() -> str +``` Returns a string that represents a nice, disambiguated label for the court. This may not match the court's name. If the name omits city, we @@ -38,7 +74,13 @@ list. - `str` - string representing the court's name, with city if needed to disambiguate -#### short\_label\_and\_address + + +#### short\_label\_and\_address() + +```python +def short_label_and_address() -> str +``` Returns a markdown formatted string with the name and address of the court. More concise version without description; suitable for a responsive case. @@ -47,7 +89,13 @@ More concise version without description; suitable for a responsive case. - `str` - string representing the court's name and address -#### short\_description + + +#### short\_description() + +```python +def short_description() -> str +``` Returns a Markdown formatted string that includes the disambiguated name and the description of the court, for inclusion in the results page with radio @@ -57,7 +105,14 @@ buttons. - `str` - string representing the court's name and description -#### from\_row + + +#### from\_row(df\_row: Union[pd.Series, pd.DataFrame], ensure\_lat\_long: bool = True) + +```python +def from_row(df_row: Union[pd.Series, pd.DataFrame], + ensure_lat_long: bool = True) -> None +``` Loads data from a single Pandas Dataframe into the current court object. Note: It will try to convert column names that don't make valid @@ -69,16 +124,30 @@ 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() + +```python +def geolocate() -> None +``` Use Google Maps to geocode the court's address and store the result in the location attribute. Deprecated: use geocode() instead. -#### geocode + + +#### geocode() + +```python +def geocode() -> None +``` Use Google Maps to geocode the court's address and store the result in the location attribute. + + ## ALCourtLoader Objects ```python @@ -94,7 +163,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Create a new courtloader object. @@ -103,7 +178,13 @@ Create a new courtloader object. - `*pargs` - Standard DAObject positional arguments - `**kwargs` - Standard DAObject keyword arguments -#### all\_courts + + +#### all\_courts() + +```python +def all_courts() -> List[Dict[int, str]] +``` Return a list of all courts in the spreadsheet. @@ -111,7 +192,13 @@ Return a list of all courts in the spreadsheet. List[Dict[int, str]]: List of all ALCourt instances without filtering. -#### unique\_column\_values + + +#### unique\_column\_values(column\_name: str) + +```python +def unique_column_values(column_name: str) -> Set[str] +``` Retrieve a set of unique values present in a specified dataframe column. @@ -126,7 +213,13 @@ 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 + + +#### county\_list(column\_name: str = "address\_county") + +```python +def county_list(column_name: str = "address_county") -> Set[str] +``` Get a set of all unique names for the specified column in the given spreadsheet. Typically used to get a list of all possible counties that have a court. @@ -140,7 +233,14 @@ 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\_has\_one\_court(county\_name: str, county\_column: str = "address\_county") + +```python +def county_has_one_court(county_name: str, + county_column: str = "address_county") -> bool +``` Returns True if there is only one court associated with the specified county in the spreadsheet. Returns False otherwise. @@ -156,7 +256,15 @@ in the spreadsheet. Returns False otherwise. - `bool` - True if there is only one court associated with the specified county in the spreadsheet. -#### county\_court + + +#### county\_court(intrinsicName: str, county\_name: str, county\_column: str = "address\_county") + +```python +def county_court(intrinsicName: str, + county_name: str, + county_column: str = "address_county") -> ALCourt +``` Return the first court matching the county name. Should only be used when you know there is exactly one match @@ -173,7 +281,19 @@ when you know there is exactly one match - `ALCourt` - The first court matching the county name. -#### matching\_courts\_in\_county + + +#### 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) + +```python +def 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 +) -> List[Dict[int, str]] +``` Retrieve a list of all courts in the specified county. @@ -195,7 +315,19 @@ useful for retrieving the court's full details later using the as_court() m List[Dict[int, str]]: List of dictionaries representing matching courts. -#### filter\_courts + + +#### 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) + +```python +def 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 +) -> List[Dict[int, str]] +``` Return a filtered subset of courts represented as a list of dictionaries. @@ -217,7 +349,15 @@ is determined by the `display_column`. List[Dict[int, str]]: List of dictionaries representing filtered courts. -#### as\_court + + +#### as\_court(intrinsicName: str, index: Union[int, str], ensure\_lat\_long: bool = True) + +```python +def as_court(intrinsicName: str, + index: Union[int, str], + ensure_lat_long: bool = True) -> ALCourt +``` Retrieve the court at the specified index as an ALCourt object. diff --git a/docs/components/AssemblyLine/al_document.md b/docs/components/AssemblyLine/al_document.md index 3719edc70..e2b7bc032 100644 --- a/docs/components/AssemblyLine/al_document.md +++ b/docs/components/AssemblyLine/al_document.md @@ -1,9 +1,134 @@ +# Table of Contents + +* [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) + * [key](#AssemblyLine.al_document.key) + * [safeattr](#AssemblyLine.al_document.safeattr) + * [html\_safe\_str](#AssemblyLine.al_document.html_safe_str) + * [table\_row](#AssemblyLine.al_document.table_row) + * [pdf\_page\_parity](#AssemblyLine.al_document.pdf_page_parity) + * [add\_blank\_page](#AssemblyLine.al_document.add_blank_page) + * [ALAddendumField](#AssemblyLine.al_document.ALAddendumField) + * [init](#AssemblyLine.al_document.ALAddendumField.init) + * [overflow\_value](#AssemblyLine.al_document.ALAddendumField.overflow_value) + * [max\_lines](#AssemblyLine.al_document.ALAddendumField.max_lines) + * [value](#AssemblyLine.al_document.ALAddendumField.value) + * [has\_overflow](#AssemblyLine.al_document.ALAddendumField.has_overflow) + * [original\_or\_overflow\_message](#AssemblyLine.al_document.ALAddendumField.original_or_overflow_message) + * [safe\_value](#AssemblyLine.al_document.ALAddendumField.safe_value) + * [value\_if\_defined](#AssemblyLine.al_document.ALAddendumField.value_if_defined) + * [\_\_str\_\_](#AssemblyLine.al_document.ALAddendumField.__str__) + * [columns](#AssemblyLine.al_document.ALAddendumField.columns) + * [type](#AssemblyLine.al_document.ALAddendumField.type) + * [is\_list](#AssemblyLine.al_document.ALAddendumField.is_list) + * [is\_object\_list](#AssemblyLine.al_document.ALAddendumField.is_object_list) + * [overflow\_markdown](#AssemblyLine.al_document.ALAddendumField.overflow_markdown) + * [overflow\_docx](#AssemblyLine.al_document.ALAddendumField.overflow_docx) + * [ALAddendumFieldDict](#AssemblyLine.al_document.ALAddendumFieldDict) + * [init](#AssemblyLine.al_document.ALAddendumFieldDict.init) + * [initializeObject](#AssemblyLine.al_document.ALAddendumFieldDict.initializeObject) + * [from\_list](#AssemblyLine.al_document.ALAddendumFieldDict.from_list) + * [defined\_fields](#AssemblyLine.al_document.ALAddendumFieldDict.defined_fields) + * [overflow](#AssemblyLine.al_document.ALAddendumFieldDict.overflow) + * [has\_overflow](#AssemblyLine.al_document.ALAddendumFieldDict.has_overflow) + * [DALazyAttribute](#AssemblyLine.al_document.DALazyAttribute) + * [\_\_getstate\_\_](#AssemblyLine.al_document.DALazyAttribute.__getstate__) + * [ALDocument](#AssemblyLine.al_document.ALDocument) + * [init](#AssemblyLine.al_document.ALDocument.init) + * [as\_pdf](#AssemblyLine.al_document.ALDocument.as_pdf) + * [as\_docx](#AssemblyLine.al_document.ALDocument.as_docx) + * [as\_list](#AssemblyLine.al_document.ALDocument.as_list) + * [need\_addendum](#AssemblyLine.al_document.ALDocument.need_addendum) + * [has\_overflow](#AssemblyLine.al_document.ALDocument.has_overflow) + * [overflow](#AssemblyLine.al_document.ALDocument.overflow) + * [original\_or\_overflow\_message](#AssemblyLine.al_document.ALDocument.original_or_overflow_message) + * [safe\_value](#AssemblyLine.al_document.ALDocument.safe_value) + * [overflow\_value](#AssemblyLine.al_document.ALDocument.overflow_value) + * [is\_enabled](#AssemblyLine.al_document.ALDocument.is_enabled) + * [ALStaticDocument](#AssemblyLine.al_document.ALStaticDocument) + * [init](#AssemblyLine.al_document.ALStaticDocument.init) + * [\_\_getitem\_\_](#AssemblyLine.al_document.ALStaticDocument.__getitem__) + * [as\_list](#AssemblyLine.al_document.ALStaticDocument.as_list) + * [as\_pdf](#AssemblyLine.al_document.ALStaticDocument.as_pdf) + * [as\_docx](#AssemblyLine.al_document.ALStaticDocument.as_docx) + * [show](#AssemblyLine.al_document.ALStaticDocument.show) + * [is\_enabled](#AssemblyLine.al_document.ALStaticDocument.is_enabled) + * [ALDocumentBundle](#AssemblyLine.al_document.ALDocumentBundle) + * [init](#AssemblyLine.al_document.ALDocumentBundle.init) + * [as\_pdf](#AssemblyLine.al_document.ALDocumentBundle.as_pdf) + * [\_\_str\_\_](#AssemblyLine.al_document.ALDocumentBundle.__str__) + * [as\_zip](#AssemblyLine.al_document.ALDocumentBundle.as_zip) + * [preview](#AssemblyLine.al_document.ALDocumentBundle.preview) + * [has\_enabled\_documents](#AssemblyLine.al_document.ALDocumentBundle.has_enabled_documents) + * [enabled\_documents](#AssemblyLine.al_document.ALDocumentBundle.enabled_documents) + * [as\_flat\_list](#AssemblyLine.al_document.ALDocumentBundle.as_flat_list) + * [get\_titles](#AssemblyLine.al_document.ALDocumentBundle.get_titles) + * [as\_pdf\_list](#AssemblyLine.al_document.ALDocumentBundle.as_pdf_list) + * [as\_docx\_list](#AssemblyLine.al_document.ALDocumentBundle.as_docx_list) + * [as\_editable\_list](#AssemblyLine.al_document.ALDocumentBundle.as_editable_list) + * [get\_cacheable\_documents](#AssemblyLine.al_document.ALDocumentBundle.get_cacheable_documents) + * [download\_list\_html](#AssemblyLine.al_document.ALDocumentBundle.download_list_html) + * [download\_html](#AssemblyLine.al_document.ALDocumentBundle.download_html) + * [send\_email\_table\_row](#AssemblyLine.al_document.ALDocumentBundle.send_email_table_row) + * [send\_button\_to\_html](#AssemblyLine.al_document.ALDocumentBundle.send_button_to_html) + * [send\_button\_html](#AssemblyLine.al_document.ALDocumentBundle.send_button_html) + * [send\_email](#AssemblyLine.al_document.ALDocumentBundle.send_email) + * [is\_enabled](#AssemblyLine.al_document.ALDocumentBundle.is_enabled) + * [as\_docx](#AssemblyLine.al_document.ALDocumentBundle.as_docx) + * [as\_list](#AssemblyLine.al_document.ALDocumentBundle.as_list) + * [ALExhibit](#AssemblyLine.al_document.ALExhibit) + * [init](#AssemblyLine.al_document.ALExhibit.init) + * [ocr\_ready](#AssemblyLine.al_document.ALExhibit.ocr_ready) + * [ocr\_pages](#AssemblyLine.al_document.ALExhibit.ocr_pages) + * [as\_pdf](#AssemblyLine.al_document.ALExhibit.as_pdf) + * [num\_pages](#AssemblyLine.al_document.ALExhibit.num_pages) + * [complete](#AssemblyLine.al_document.ALExhibit.complete) + * [\_\_str\_\_](#AssemblyLine.al_document.ALExhibit.__str__) + * [ocrmypdf\_task](#AssemblyLine.al_document.ocrmypdf_task) + * [ALExhibitList](#AssemblyLine.al_document.ALExhibitList) + * [init](#AssemblyLine.al_document.ALExhibitList.init) + * [as\_pdf](#AssemblyLine.al_document.ALExhibitList.as_pdf) + * [size\_in\_bytes](#AssemblyLine.al_document.ALExhibitList.size_in_bytes) + * [ocr\_ready](#AssemblyLine.al_document.ALExhibitList.ocr_ready) + * [hook\_after\_gather](#AssemblyLine.al_document.ALExhibitList.hook_after_gather) + * [ALExhibitDocument](#AssemblyLine.al_document.ALExhibitDocument) + * [init](#AssemblyLine.al_document.ALExhibitDocument.init) + * [has\_overflow](#AssemblyLine.al_document.ALExhibitDocument.has_overflow) + * [ocr\_ready](#AssemblyLine.al_document.ALExhibitDocument.ocr_ready) + * [\_\_getitem\_\_](#AssemblyLine.al_document.ALExhibitDocument.__getitem__) + * [as\_list](#AssemblyLine.al_document.ALExhibitDocument.as_list) + * [as\_pdf](#AssemblyLine.al_document.ALExhibitDocument.as_pdf) + * [as\_docx](#AssemblyLine.al_document.ALExhibitDocument.as_docx) + * [ALTableDocument](#AssemblyLine.al_document.ALTableDocument) + * [init](#AssemblyLine.al_document.ALTableDocument.init) + * [has\_overflow](#AssemblyLine.al_document.ALTableDocument.has_overflow) + * [\_\_getitem\_\_](#AssemblyLine.al_document.ALTableDocument.__getitem__) + * [as\_list](#AssemblyLine.al_document.ALTableDocument.as_list) + * [as\_pdf](#AssemblyLine.al_document.ALTableDocument.as_pdf) + * [as\_docx](#AssemblyLine.al_document.ALTableDocument.as_docx) + * [ALUntransformedDocument](#AssemblyLine.al_document.ALUntransformedDocument) + * [init](#AssemblyLine.al_document.ALUntransformedDocument.init) + * [has\_overflow](#AssemblyLine.al_document.ALUntransformedDocument.has_overflow) + * [as\_list](#AssemblyLine.al_document.ALUntransformedDocument.as_list) + * [as\_pdf](#AssemblyLine.al_document.ALUntransformedDocument.as_pdf) + * [as\_docx](#AssemblyLine.al_document.ALUntransformedDocument.as_docx) + * [ALDocumentUpload](#AssemblyLine.al_document.ALDocumentUpload) + * [unpack\_dafilelist](#AssemblyLine.al_document.unpack_dafilelist) + --- sidebar_label: al_document title: AssemblyLine.al_document --- -#### random\_suffix + + +#### random\_suffix(length: int = 8) + +```python +def random_suffix(length: int = 8) -> str +``` Return a random string for use in unique IDs. @@ -19,7 +144,13 @@ a true GUID. - `str` - A random string of lowercase letters and digits. -#### base\_name + + +#### base\_name(filename: str) + +```python +def base_name(filename: str) -> str +``` Extracts the base name of a file without its extension. @@ -32,7 +163,13 @@ Extracts the base name of a file without its extension. - `str` - The base name of the file without its extension. -#### label + + +#### label(dictionary: dict) + +```python +def label(dictionary: dict) -> str +``` Return the value of the first dictionary item. @@ -48,7 +185,13 @@ 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 + + +#### key(dictionary: dict) + +```python +def key(dictionary: dict) -> str +``` Return the key of the first dictionary item. @@ -64,7 +207,13 @@ 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 + + +#### safeattr(object: Any, key: str) + +```python +def safeattr(object: Any, key: str) -> str +``` Safely retrieve an attribute or key value from an object. @@ -83,7 +232,13 @@ 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 + + +#### html\_safe\_str(the\_string: str) + +```python +def html_safe_str(the_string: str) -> str +``` Convert a string into a format that's safe for use as an HTML class or ID. @@ -96,7 +251,13 @@ 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 + + +#### table\_row(title: str, button\_htmls: List[str] = []) + +```python +def table_row(title: str, button_htmls: List[str] = []) -> str +``` Generate an HTML row string for an AL document-styled table. @@ -110,7 +271,13 @@ 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\_page\_parity(pdf\_path: str) + +```python +def pdf_page_parity(pdf_path: str) -> Literal["even", "odd"] +``` Count the number of pages in the PDF and return "even" if it is divisible by 2 and "odd" @@ -125,7 +292,13 @@ if it is not divisible by 2. Literal["even", "odd"]: The parity of the number of pages in the PDF -#### add\_blank\_page + + +#### add\_blank\_page(pdf\_path: str) + +```python +def add_blank_page(pdf_path: str) -> None +``` Add a blank page to the end of a PDF. @@ -133,6 +306,8 @@ Add a blank page to the end of a PDF. - `pdf_path` _str_ - Path to the PDF in the filesystem + + ## ALAddendumField Objects ```python @@ -161,7 +336,13 @@ is not currently supported. The attributes `headers` and `field_style` are planned for future releases and are not currently implemented. -#### init + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -170,7 +351,16 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### overflow\_value + + +#### overflow\_value(preserve\_newlines: bool = False, input\_width: int = 80, overflow\_message: str = "", preserve\_words: bool = True) + +```python +def overflow_value(preserve_newlines: bool = False, + input_width: int = 80, + overflow_message: str = "", + preserve_words: bool = True) -> Any +``` Retrieve the overflow portion of a variable that exceeds the content of `safe_value()`. @@ -198,7 +388,13 @@ 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 + + +#### max\_lines(input\_width: int = 80) + +```python +def max_lines(input_width: int = 80) -> int +``` Compute the maximum number of lines that can fit in the input given the specified input width. @@ -211,7 +407,13 @@ 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() + +```python +def value() -> Any +``` Retrieve the complete value without considering overflow constraints. @@ -222,7 +424,17 @@ without the necessity of toggling between various sections or pages. - `Any` - The whole value of the field, irrespective of overflow. -#### has\_overflow + + +#### has\_overflow(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) + +```python +def has_overflow(overflow_message: str = "", + input_width: int = 80, + preserve_newlines: bool = False, + _original_value: Optional[str] = None, + preserve_words: bool = True) -> bool +``` Return True only if the value's length exceeds the overflow trigger. @@ -245,7 +457,18 @@ 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 + + +#### original\_or\_overflow\_message(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) + +```python +def original_or_overflow_message( + overflow_message: str = "", + input_width: int = 80, + preserve_newlines: bool = False, + _original_value: Optional[str] = None, + preserve_words: bool = True) -> Union[str, List[Any]] +``` Return the original value if it is less than the overflow trigger (once processed), otherwise return the overflow message. @@ -270,7 +493,17 @@ 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 + + +#### safe\_value(overflow\_message: str = "", input\_width: int = 80, preserve\_newlines: bool = False, \_original\_value: Optional[str] = None, preserve\_words: bool = True) + +```python +def safe_value(overflow_message: str = "", + input_width: int = 80, + preserve_newlines: bool = False, + _original_value: Optional[str] = None, + preserve_words: bool = True) -> Union[str, List[Any]] +``` Return just the portion of the variable that heuristics suggest will fit in the specified overflow_trigger limit. If the value is not defined, return an empty string. @@ -303,7 +536,13 @@ 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() + +```python +def value_if_defined() -> Any +``` Fetch the value of the designated field if it exists; otherwise, return an empty string. @@ -313,7 +552,13 @@ 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\_\_() + +```python +def __str__() +``` Represent the ALAddendumField instance as a string. @@ -321,7 +566,14 @@ Represent the ALAddendumField instance as a string. - `str` - The string representation of the value contained within the field. -#### columns + + +#### columns(skip\_empty\_attributes: bool = True, skip\_attributes: Optional[set] = None) + +```python +def columns(skip_empty_attributes: bool = True, + skip_attributes: Optional[set] = None) -> Optional[list] +``` Return a list of the attributes present within the object that would make sense to go in the table of an addendum. @@ -345,7 +597,13 @@ 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() + +```python +def type() -> str +``` Determine the data type of the contained value. @@ -358,7 +616,13 @@ Categories: - `str` - The type category of the value. -#### is\_list + + +#### is\_list() + +```python +def is_list() -> bool +``` Check if the field contains a list value, whether it consists of objects, dictionaries, or standard values. @@ -366,7 +630,13 @@ 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() + +```python +def is_object_list() -> bool +``` Determine if the field contains a list of dictionaries or objects. @@ -374,7 +644,13 @@ 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() + +```python +def overflow_markdown() -> str +``` Generate a markdown representation of the overflow values. @@ -386,7 +662,15 @@ to manually control the output's format. - `str` - A markdown representation of the overflow values. -#### overflow\_docx + + +#### overflow\_docx(path: str = "docassemble.ALDocumentDict:data/templates/addendum\_table.docx") + +```python +def overflow_docx( + path: str = "docassemble.ALDocumentDict:data/templates/addendum_table.docx" +) -> Any +``` Insert a formatted table into a docx file, representing the overflow values. @@ -404,6 +688,8 @@ fetching the overflow values using the `overflow_value()` method. A docx template with the inserted table. + + ## ALAddendumFieldDict Objects ```python @@ -424,7 +710,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -433,7 +725,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### initializeObject + + +#### initializeObject(\*pargs, \*\*kwargs) + +```python +def initializeObject(*pargs, **kwargs) -> Any +``` Initializes a new dictionary entry and sets its `field_name` attribute. @@ -451,7 +749,13 @@ its own field name by setting the `field_name` attribute. The new dictionary entry created -#### from\_list + + +#### from\_list(data: List[Dict]) + +```python +def from_list(data: List[Dict]) -> None +``` Populate the dictionary using a list of field data. @@ -460,7 +764,13 @@ 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 + + +#### defined\_fields(style: str = "overflow\_only") + +```python +def defined_fields(style: str = "overflow_only") -> list +``` Fetch a list of fields that are defined. @@ -474,7 +784,13 @@ Fetch a list of fields that are defined. - `list` - List of defined fields based on the specified style. -#### overflow + + +#### overflow() + +```python +def overflow() -> list +``` Retrieve fields that have overflowed their character limits. @@ -482,7 +798,13 @@ Retrieve fields that have overflowed their character limits. - `list` - A list of fields with overflow values. -#### has\_overflow + + +#### has\_overflow() + +```python +def has_overflow() -> bool +``` Determine if any field within the dictionary exceeds its overflow limit. @@ -490,6 +812,8 @@ Determine if any field within the dictionary exceeds its overflow limit. - `bool` - True if at least one field overflows, False otherwise. + + ## DALazyAttribute Objects ```python @@ -506,7 +830,13 @@ The implementation leverages Docassemble's object pickling process by custo - `instanceName` _str_ - A unique identifier for the object instance, if available. -#### \_\_getstate\_\_ + + +#### \_\_getstate\_\_() + +```python +def __getstate__() -> dict +``` Overrides the default method used by Pickle for object serialization. @@ -518,6 +848,8 @@ persisted across page loads. - `dict` - A dictionary containing only the `instanceName` if it exists, or empty otherwise. + + ## ALDocument Objects ```python @@ -651,7 +983,13 @@ on the final download screen. my_doc.overflow_fields.gathered = True ``` -#### init + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -660,7 +998,16 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### as\_pdf + + +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True) + +```python +def as_pdf(key: str = "final", + refresh: bool = True, + pdfa: bool = False, + append_matching_suffix: bool = True) -> DAFile +``` Generates a PDF version of the assembled document. @@ -676,7 +1023,15 @@ Generates a PDF version of the assembled document. - `DAFile` - Assembled document in PDF format, possibly combined with addendum. -#### as\_docx + + +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) + +```python +def as_docx(key: str = "final", + refresh: bool = True, + append_matching_suffix: bool = True) -> DAFile +``` Generates a DOCX version of the assembled document, if possible. Falls back to PDF if not. @@ -691,7 +1046,13 @@ Generates a DOCX version of the assembled document, if possible. Falls back to P - `DAFile` - Assembled document in DOCX or PDF format. -#### as\_list + + +#### as\_list(key: str = "final", refresh: bool = True) + +```python +def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] +``` Generates a list containing the main document and its addendum, if applicable. @@ -705,7 +1066,13 @@ 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() + +```python +def need_addendum() -> bool +``` Determines if there's a need for an addendum in the document. First checks if the addendum is enabled, and then checks if there's overflow. @@ -714,7 +1081,13 @@ 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() + +```python +def has_overflow() -> bool +``` Checks if the document has fields that exceed their character limits. @@ -722,7 +1095,13 @@ Checks if the document has fields that exceed their character limits. - `bool` - True if there are overflow fields, False otherwise. -#### overflow + + +#### overflow() + +```python +def overflow() -> list +``` Retrieves a list of fields that have overflowed their character limits. @@ -730,7 +1109,19 @@ Retrieves a list of fields that have overflowed their character limits. - `list` - List of overflow fields. -#### original\_or\_overflow\_message + + +#### 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) + +```python +def 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) -> Union[str, List[Any]] +``` Helper syntax to access a member field. @@ -758,7 +1149,17 @@ 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 + + +#### safe\_value(field\_name: str, overflow\_message: Optional[str] = None, preserve\_newlines: bool = False, input\_width: int = 80, preserve\_words: bool = True) + +```python +def safe_value(field_name: str, + overflow_message: Optional[str] = None, + preserve_newlines: bool = False, + input_width: int = 80, + preserve_words: bool = True) -> str +``` Retrieve the "safe" value of a specified field, which is shorter than the overflow trigger. @@ -775,7 +1176,17 @@ Retrieve the "safe" value of a specified field, which is shorter than - `str` - The "safe" value of the specified field. -#### overflow\_value + + +#### overflow\_value(field\_name: str, overflow\_message: Optional[str] = None, preserve\_newlines: bool = False, input\_width: int = 80, preserve\_words: bool = True) + +```python +def overflow_value(field_name: str, + overflow_message: Optional[str] = None, + preserve_newlines: bool = False, + input_width: int = 80, + preserve_words: bool = True) -> str +``` Retrieve the "overflow" value of a specified field, which is the amount exceeding the overflow trigger. @@ -792,7 +1203,13 @@ Retrieve the "overflow" value of a specified field, which is the amoun - `str` - The "overflow" value of the specified field. -#### is\_enabled + + +#### is\_enabled(refresh: bool = True) + +```python +def is_enabled(refresh: bool = True) -> bool +``` Determine if a document is considered "enabled" based on various conditions. @@ -810,6 +1227,8 @@ A document is "enabled" if: - `bool` - True if the document is enabled, otherwise False. + + ## ALStaticDocument Objects ```python @@ -846,7 +1265,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -855,7 +1280,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### \_\_getitem\_\_ + + +#### \_\_getitem\_\_(key) + +```python +def __getitem__(key) +``` Override to ensure 'final' and 'private' keys always exist and reference the same file. @@ -863,7 +1294,13 @@ Override to ensure 'final' and 'private' keys always exist a - `ALStaticDocument` - Returns self. -#### as\_list + + +#### as\_list(key: str = "final", refresh: bool = True) + +```python +def as_list(key: str = "final", refresh: bool = True) -> List[DAStaticFile] +``` Get the document as a list. @@ -877,7 +1314,17 @@ Get the document as a list. - `List[DAStaticFile]` - A list containing this document. -#### as\_pdf + + +#### as\_pdf(key: str = "final", pdfa: bool = False, filename: str = "", append\_matching\_suffix: bool = True, refresh: bool = False) + +```python +def as_pdf(key: str = "final", + pdfa: bool = False, + filename: str = "", + append_matching_suffix: bool = True, + refresh: bool = False) -> Union[DAStaticFile, DAFile] +``` Convert the document into PDF format. @@ -894,7 +1341,16 @@ Convert the document into PDF format. Union[DAStaticFile, DAFile]: The document in PDF format. -#### as\_docx + + +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = False) + +```python +def as_docx( + key: str = "final", + refresh: bool = True, + append_matching_suffix: bool = False) -> Union[DAStaticFile, DAFile] +``` Convert the document into DOCX format, if possible. If not, return as PDF. @@ -909,7 +1365,13 @@ Convert the document into DOCX format, if possible. If not, return as PDF. Union[DAStaticFile, DAFile]: The document in DOCX or PDF format. -#### show + + +#### show(\*\*kwargs) + +```python +def show(**kwargs) -> DAFile +``` Display the document. @@ -924,7 +1386,13 @@ This method provides a workaround for problems generating thumbnails. - `DAFile` - Displayable version of the document. -#### is\_enabled + + +#### is\_enabled(\*\*kwargs) + +```python +def is_enabled(**kwargs) -> bool +``` Check if the document is enabled. @@ -937,6 +1405,8 @@ Check if the document is enabled. - `bool` - True if the document is enabled, otherwise False. + + ## ALDocumentBundle Objects ```python @@ -982,7 +1452,13 @@ bundles, each can be rendered as a merged PDF or a list of documents. zipped_files = bundle.as_zip() ``` -#### init + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -991,7 +1467,19 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### as\_pdf + + +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, ensure\_parity: Optional[Literal["even", "odd"]] = None) + +```python +def as_pdf( + key: str = "final", + refresh: bool = True, + pdfa: bool = False, + append_matching_suffix: bool = True, + ensure_parity: Optional[Literal["even", + "odd"]] = None) -> Optional[DAFile] +``` Returns a consolidated PDF of all enabled documents in the bundle. @@ -1010,7 +1498,13 @@ 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\_\_() + +```python +def __str__() -> str +``` Produces a string representation of the PDF in a compatible method with the DAFile class. In an interview, this will show a thumbnail of @@ -1020,7 +1514,18 @@ the PDF by default. - `str` - String representation of the PDF. -#### as\_zip + + +#### as\_zip(key: str = "final", refresh: bool = True, pdfa: bool = False, title: str = "", format: Optional[str] = "pdf", include\_pdf: Optional[bool] = True) + +```python +def as_zip(key: str = "final", + refresh: bool = True, + pdfa: bool = False, + title: str = "", + format: Optional[str] = "pdf", + include_pdf: Optional[bool] = True) -> DAFile +``` Returns a zip file containing all enabled documents in the bundle in the specified format. @@ -1038,7 +1543,13 @@ Returns a zip file containing all enabled documents in the bundle in the specifi - `DAFile` - A zip file containing the enabled documents. -#### preview + + +#### preview(refresh: bool = True) + +```python +def preview(refresh: bool = True) -> Optional[DAFile] +``` Returns a preview version of the bundle as a PDF. @@ -1051,7 +1562,13 @@ 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 + + +#### has\_enabled\_documents(refresh=False) + +```python +def has_enabled_documents(refresh=False) -> bool +``` Checks if there is at least one enabled document in the bundle. @@ -1064,7 +1581,13 @@ 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 + + +#### enabled\_documents(refresh: bool = True) + +```python +def enabled_documents(refresh: bool = True) -> List[Any] +``` Retrieves all enabled documents within the bundle. @@ -1077,7 +1600,13 @@ Retrieves all enabled documents within the bundle. - `List[Any]` - List of enabled documents. -#### as\_flat\_list + + +#### as\_flat\_list(key: str = "final", refresh: bool = True) + +```python +def as_flat_list(key: str = "final", refresh: bool = True) -> List[DAFile] +``` Flattens and returns all enabled documents in the bundle, even from nested bundles. @@ -1091,7 +1620,13 @@ Flattens and returns all enabled documents in the bundle, even from nested bundl - `List[DAFile]` - Flattened list of enabled documents. -#### get\_titles + + +#### get\_titles(key: str = "final", refresh: bool = True) + +```python +def get_titles(key: str = "final", refresh: bool = True) -> List[str] +``` Retrieves the titles of all enabled documents in the bundle. @@ -1105,7 +1640,15 @@ Retrieves the titles of all enabled documents in the bundle. - `List[str]` - Titles of the enabled documents. -#### as\_pdf\_list + + +#### as\_pdf\_list(key: str = "final", refresh: bool = True, pdfa: bool = False) + +```python +def as_pdf_list(key: str = "final", + refresh: bool = True, + pdfa: bool = False) -> List[DAFile] +``` Returns all enabled documents in the bundle as individual PDFs, even from nested bundles. @@ -1120,7 +1663,13 @@ 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 + + +#### as\_docx\_list(key: str = "final", refresh: bool = True) + +```python +def as_docx_list(key: str = "final", refresh: bool = True) -> List[DAFile] +``` Generates a list of enabled documents from the bundle represented as DOCX files. @@ -1136,7 +1685,13 @@ 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 + + +#### as\_editable\_list(key: str = "final", refresh: bool = True) + +```python +def as_editable_list(key: str = "final", refresh: bool = True) -> List[DAFile] +``` Generates a list of editable (DOCX or RTF) versions of the documents in the bundle. @@ -1152,7 +1707,25 @@ 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 + + +#### 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) + +```python +def 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 +) -> Tuple[List[Dict[str, DAFile]], Optional[DAFile], Optional[DAFile]] +``` Generates a cache of all enabled documents in the bundle, and returns it in a structure that can be cached and returned for use in a background process. @@ -1184,7 +1757,34 @@ 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 + + +#### 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) + +```python +def 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) -> str +``` Constructs an HTML table displaying a list of documents with 'view' and 'download' buttons. @@ -1219,7 +1819,21 @@ 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 + + +#### 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") + +```python +def 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") -> str +``` Returns an HTML string of a table to display all the docs combined into one pdf with 'view' and 'download' buttons. @@ -1243,7 +1857,15 @@ Deprecated; use download_list_html instead - `str` - HTML representation of a table with documents and their associated actions. -#### send\_email\_table\_row + + +#### send\_email\_table\_row(key: str = "final", send\_label: str = "Send", send\_icon: str = "envelope") + +```python +def send_email_table_row(key: str = "final", + send_label: str = "Send", + send_icon: str = "envelope") -> str +``` Generate HTML doc table row for an input box and button that allows someone to send the bundle to the specified email address. @@ -1259,7 +1881,21 @@ someone to send the bundle to the specified email address. - `str` - The generated HTML string for the table row. -#### send\_button\_to\_html + + +#### 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) + +```python +def 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) -> str +``` Generate HTML for a button that allows someone to send the bundle to a specific email address. The email address is not editable by the end user @@ -1281,7 +1917,19 @@ in contrast to send_button_html. - `str` - The generated HTML string for the button. -#### send\_button\_html + + +#### 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) + +```python +def 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) -> str +``` Generate HTML for an input box and button that allows someone to send the bundle to the specified email address. @@ -1307,7 +1955,18 @@ 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 + + +#### 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) + +```python +def 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) -> bool +``` Send an email with the current bundle as a series of flat pdfs (one per bundle entry) or as editable documents. This function is similar to @@ -1327,7 +1986,13 @@ https://docassemble.org/docs/functions.html#send_email with additional parameter - `bool` - Indicates if the email was sent successfully. -#### is\_enabled + + +#### is\_enabled(refresh=True) + +```python +def is_enabled(refresh=True) -> bool +``` Check if the bundle itself is enabled, and if it has at least one enabled child document. @@ -1340,7 +2005,15 @@ 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 + + +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) + +```python +def as_docx(key: str = "final", + refresh: bool = True, + append_matching_suffix: bool = True) -> DAFile +``` Convert the enabled documents to a single DOCX file or PDF file if conversion fails. @@ -1355,7 +2028,13 @@ 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 + + +#### as\_list(key: str = "final", refresh: bool = True) + +```python +def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] +``` Return a list of enabled documents. @@ -1369,6 +2048,8 @@ Return a list of enabled documents. - `List[DAFile]` - A list of enabled DAFile objects. + + ## ALExhibit Objects ```python @@ -1385,7 +2066,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -1394,7 +2081,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### ocr\_ready + + +#### ocr\_ready() + +```python +def ocr_ready() -> bool +``` Returns True if the OCR process is complete. OCR is non-blocking, and assembly will work even if OCR is not complete. Check this status if you want to wait to deliver a document until @@ -1407,7 +2100,13 @@ 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() + +```python +def ocr_pages() -> List[DAFile] +``` Retrieve the OCR-processed version of pages if available, else return the original pages. @@ -1415,7 +2114,20 @@ 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 + + +#### 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) + +```python +def 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) -> DAFile +``` Generates a PDF version of the exhibit, with optional features like Bates numbering or a cover page. @@ -1436,7 +2148,13 @@ Note that these are keyword only parameters, not positional. - `DAFile` - PDF representation of the exhibit. -#### num\_pages + + +#### num\_pages() + +```python +def num_pages() -> int +``` Calculate the total number of pages in the exhibit. @@ -1444,7 +2162,14 @@ Calculate the total number of pages in the exhibit. - `int` - Total page count. -#### complete + + +#### complete() + +```python +@property +def complete() -> bool +``` For purposes of list gathering, trigger the attributes in the order necessary to gather a complete exhibit object. @@ -1453,7 +2178,13 @@ Indicates if the exhibit is complete. NOTE: This property always returns True after triggering the required attributes. -#### \_\_str\_\_ + + +#### \_\_str\_\_() + +```python +def __str__() -> str +``` Return the title of the exhibit. @@ -1461,7 +2192,14 @@ Return the title of the exhibit. - `str` - Title of the exhibit. -#### ocrmypdf\_task + + +#### ocrmypdf\_task(from\_file: Union[DAFile, DAFileList], to\_pdf: DAFile) + +```python +def ocrmypdf_task(from_file: Union[DAFile, DAFileList], + to_pdf: DAFile) -> Optional[str] +``` Processes the provided files using the 'ocrmypdf' utility to apply Optical Character Recognition (OCR). @@ -1485,6 +2223,8 @@ 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 ```python @@ -1502,7 +2242,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -1511,7 +2257,17 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### as\_pdf + + +#### as\_pdf(filename="file.pdf", pdfa: bool = False, add\_page\_numbers: bool = False, toc\_pages: int = 0, append\_matching\_suffix: bool = True) + +```python +def as_pdf(filename="file.pdf", + pdfa: bool = False, + add_page_numbers: bool = False, + toc_pages: int = 0, + append_matching_suffix: bool = True) -> DAFile +``` Compiles all exhibits in the list into a single PDF. @@ -1528,7 +2284,13 @@ Compiles all exhibits in the list into a single PDF. - `DAFile` - A single PDF containing all exhibits. -#### size\_in\_bytes + + +#### size\_in\_bytes() + +```python +def size_in_bytes() -> int +``` Calculates the total size in bytes of all exhibits in the list. @@ -1536,7 +2298,13 @@ Calculates the total size in bytes of all exhibits in the list. - `int` - Total size of all exhibits in bytes. -#### ocr\_ready + + +#### ocr\_ready() + +```python +def ocr_ready() -> bool +``` Checks if all exhibits in the list have completed the OCR process. @@ -1544,11 +2312,19 @@ 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() + +```python +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 ```python @@ -1600,7 +2376,13 @@ objects: - exhibit_attachment: ALExhibitDocument.using(title="Exhibits", filename="exhibits" , auto_labeler=item_label) ``` -#### init + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -1609,7 +2391,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### has\_overflow + + +#### has\_overflow() + +```python +def has_overflow() -> bool +``` Check if there is any overflow in the document. @@ -1619,7 +2407,13 @@ This is for compatibility with ALDocument; Exhibits inherently don't have o - `bool` - Always False for this implementation. -#### ocr\_ready + + +#### ocr\_ready() + +```python +def ocr_ready() -> bool +``` Determine if all exhibits within the document have undergone OCR processing. @@ -1627,7 +2421,13 @@ 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\_\_ + + +#### \_\_getitem\_\_(key) + +```python +def __getitem__(key) +``` Overridden method to ensure 'final' and 'private' keys always reference the same file. @@ -1640,7 +2440,13 @@ Overridden method to ensure 'final' and 'private' keys alway - `ALExhibitDocument` - Returns the current instance of the class. -#### as\_list + + +#### as\_list(key: str = "final", refresh: bool = True) + +```python +def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] +``` Retrieve the document as a list. @@ -1654,7 +2460,16 @@ Retrieve the document as a list. - `List[DAFile]` - A list containing the document. -#### as\_pdf + + +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True) + +```python +def as_pdf(key: str = "final", + refresh: bool = True, + pdfa: bool = False, + append_matching_suffix: bool = True) -> DAFile +``` Render the document as a PDF. @@ -1672,7 +2487,15 @@ Render the document as a PDF. - `DAFile` - The document rendered as a PDF. -#### as\_docx + + +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) + +```python +def as_docx(key: str = "final", + refresh: bool = True, + append_matching_suffix: bool = True) -> DAFile +``` Despite the name, renders the document as a PDF. Provided for signature compatibility. @@ -1687,6 +2510,8 @@ Despite the name, renders the document as a PDF. Provided for signature compatib - `DAFile` - The document rendered as a PDF. + + ## ALTableDocument Objects ```python @@ -1703,7 +2528,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -1712,7 +2543,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### has\_overflow + + +#### has\_overflow() + +```python +def has_overflow() -> bool +``` Check for overflow in the document. @@ -1722,7 +2559,13 @@ For compatibility with ALDocument; Tables inherently don't have overflow. - `bool` - Always False for this implementation. -#### \_\_getitem\_\_ + + +#### \_\_getitem\_\_(key) + +```python +def __getitem__(key) +``` Allows for index-based retrieval of a document. @@ -1737,7 +2580,15 @@ Overridden to ensure 'final' and 'private' keys always retur - `DAFile` - The document in its PDF format. -#### as\_list + + +#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) + +```python +def as_list(key: str = "final", + refresh: bool = True, + **kwargs) -> List[DAFile] +``` Retrieve the document as a list. @@ -1751,7 +2602,17 @@ Retrieve the document as a list. - `List[DAFile]` - A list containing the document. -#### as\_pdf + + +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, \*\*kwargs) + +```python +def as_pdf(key: str = "final", + refresh: bool = True, + pdfa: bool = False, + append_matching_suffix: bool = True, + **kwargs) -> DAFile +``` Despite the name, returns the document as an Excel Spreadsheet (XLSX file). Name retained for signature compatibility. @@ -1768,7 +2629,15 @@ Name retained for signature compatibility. - `DAFile` - The table rendered as an XLSX spreadsheet -#### as\_docx + + +#### as\_docx(key: str = "bool", refresh: bool = True, append\_matching\_suffix: bool = True) + +```python +def as_docx(key: str = "bool", + refresh: bool = True, + append_matching_suffix: bool = True) -> DAFile +``` Despite the name, returns the document as an Excel Spreadsheet (XLSX file). Name retained for signature compatibility. @@ -1785,6 +2654,8 @@ Name retained for signature compatibility. - `DAFile` - The table rendered as an XLSX spreadsheet + + ## ALUntransformedDocument Objects ```python @@ -1800,7 +2671,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -1809,7 +2686,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### has\_overflow + + +#### has\_overflow() + +```python +def has_overflow() -> bool +``` Check for overflow in the document. @@ -1819,7 +2702,15 @@ For compatibility with ALDocument. Untransformed documents inherently don't - `bool` - Always False for this implementation. -#### as\_list + + +#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) + +```python +def as_list(key: str = "final", + refresh: bool = True, + **kwargs) -> List[DAFile] +``` Retrieve the document as a list. @@ -1833,7 +2724,17 @@ Retrieve the document as a list. - `List[DAFile]` - A list containing the document. -#### as\_pdf + + +#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True, \*\*kwargs) + +```python +def as_pdf(key: str = "final", + refresh: bool = True, + pdfa: bool = False, + append_matching_suffix: bool = True, + **kwargs) -> DAFile +``` Fetch the document in its original form, without any transformations. @@ -1851,7 +2752,15 @@ This method is primarily for duck-typing compatibility with ALDocument. - `DAFile` - The original, untransformed document. -#### as\_docx + + +#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) + +```python +def as_docx(key: str = "final", + refresh: bool = True, + append_matching_suffix: bool = True) -> DAFile +``` Fetch the document in its original form, without any transformations. @@ -1868,6 +2777,8 @@ This method is primarily for duck-typing compatibility with ALDocument. - `DAFile` - The original, untransformed document. + + ## ALDocumentUpload Objects ```python @@ -1877,7 +2788,13 @@ class ALDocumentUpload(ALUntransformedDocument) Simplified class to handle uploaded documents, without any of the complexity of the ALExhibitDocument class. -#### unpack\_dafilelist + + +#### unpack\_dafilelist(the\_file: DAFileList) + +```python +def unpack_dafilelist(the_file: DAFileList) -> DAFile +``` Creates a plain DAFile out of the first item in a DAFileList diff --git a/docs/components/AssemblyLine/al_general.md b/docs/components/AssemblyLine/al_general.md index 89d5f09c0..1fe4cab75 100644 --- a/docs/components/AssemblyLine/al_general.md +++ b/docs/components/AssemblyLine/al_general.md @@ -1,9 +1,91 @@ +# Table of Contents + +* [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) + * [formatted\_unit](#AssemblyLine.al_general.ALAddress.formatted_unit) + * [block](#AssemblyLine.al_general.ALAddress.block) + * [line\_one](#AssemblyLine.al_general.ALAddress.line_one) + * [line\_two](#AssemblyLine.al_general.ALAddress.line_two) + * [on\_one\_line](#AssemblyLine.al_general.ALAddress.on_one_line) + * [normalized\_address](#AssemblyLine.al_general.ALAddress.normalized_address) + * [state\_name](#AssemblyLine.al_general.ALAddress.state_name) + * [ALAddressList](#AssemblyLine.al_general.ALAddressList) + * [init](#AssemblyLine.al_general.ALAddressList.init) + * [\_\_str\_\_](#AssemblyLine.al_general.ALAddressList.__str__) + * [ALNameList](#AssemblyLine.al_general.ALNameList) + * [init](#AssemblyLine.al_general.ALNameList.init) + * [\_\_str\_\_](#AssemblyLine.al_general.ALNameList.__str__) + * [ALPeopleList](#AssemblyLine.al_general.ALPeopleList) + * [init](#AssemblyLine.al_general.ALPeopleList.init) + * [names\_and\_addresses\_on\_one\_line](#AssemblyLine.al_general.ALPeopleList.names_and_addresses_on_one_line) + * [familiar](#AssemblyLine.al_general.ALPeopleList.familiar) + * [familiar\_or](#AssemblyLine.al_general.ALPeopleList.familiar_or) + * [short\_list](#AssemblyLine.al_general.ALPeopleList.short_list) + * [full\_names](#AssemblyLine.al_general.ALPeopleList.full_names) + * [pronoun\_reflexive](#AssemblyLine.al_general.ALPeopleList.pronoun_reflexive) + * [ALIndividual](#AssemblyLine.al_general.ALIndividual) + * [init](#AssemblyLine.al_general.ALIndividual.init) + * [signature\_if\_final](#AssemblyLine.al_general.ALIndividual.signature_if_final) + * [phone\_numbers](#AssemblyLine.al_general.ALIndividual.phone_numbers) + * [contact\_methods](#AssemblyLine.al_general.ALIndividual.contact_methods) + * [merge\_letters](#AssemblyLine.al_general.ALIndividual.merge_letters) + * [formatted\_age](#AssemblyLine.al_general.ALIndividual.formatted_age) + * [normalized\_address](#AssemblyLine.al_general.ALIndividual.normalized_address) + * [name\_fields](#AssemblyLine.al_general.ALIndividual.name_fields) + * [address\_fields](#AssemblyLine.al_general.ALIndividual.address_fields) + * [gender\_fields](#AssemblyLine.al_general.ALIndividual.gender_fields) + * [pronoun\_fields](#AssemblyLine.al_general.ALIndividual.pronoun_fields) + * [get\_pronouns](#AssemblyLine.al_general.ALIndividual.get_pronouns) + * [list\_pronouns](#AssemblyLine.al_general.ALIndividual.list_pronouns) + * [language\_fields](#AssemblyLine.al_general.ALIndividual.language_fields) + * [language\_name](#AssemblyLine.al_general.ALIndividual.language_name) + * [gender\_male](#AssemblyLine.al_general.ALIndividual.gender_male) + * [gender\_female](#AssemblyLine.al_general.ALIndividual.gender_female) + * [gender\_other](#AssemblyLine.al_general.ALIndividual.gender_other) + * [gender\_nonbinary](#AssemblyLine.al_general.ALIndividual.gender_nonbinary) + * [gender\_unknown](#AssemblyLine.al_general.ALIndividual.gender_unknown) + * [gender\_undisclosed](#AssemblyLine.al_general.ALIndividual.gender_undisclosed) + * [gender\_self\_described](#AssemblyLine.al_general.ALIndividual.gender_self_described) + * [contact\_fields](#AssemblyLine.al_general.ALIndividual.contact_fields) + * [initials](#AssemblyLine.al_general.ALIndividual.initials) + * [address\_block](#AssemblyLine.al_general.ALIndividual.address_block) + * [pronoun](#AssemblyLine.al_general.ALIndividual.pronoun) + * [pronoun\_objective](#AssemblyLine.al_general.ALIndividual.pronoun_objective) + * [pronoun\_possessive](#AssemblyLine.al_general.ALIndividual.pronoun_possessive) + * [pronoun\_subjective](#AssemblyLine.al_general.ALIndividual.pronoun_subjective) + * [pronoun\_reflexive](#AssemblyLine.al_general.ALIndividual.pronoun_reflexive) + * [name\_full](#AssemblyLine.al_general.ALIndividual.name_full) + * [name\_initials](#AssemblyLine.al_general.ALIndividual.name_initials) + * [name\_short](#AssemblyLine.al_general.ALIndividual.name_short) + * [familiar](#AssemblyLine.al_general.ALIndividual.familiar) + * [\_\_str\_\_](#AssemblyLine.al_general.ALIndividual.__str__) + * [section\_links](#AssemblyLine.al_general.section_links) + * [will\_send\_to\_real\_court](#AssemblyLine.al_general.will_send_to_real_court) + * [filter\_letters](#AssemblyLine.al_general.filter_letters) + * [fa\_icon](#AssemblyLine.al_general.fa_icon) + * [is\_sms\_enabled](#AssemblyLine.al_general.is_sms_enabled) + * [is\_phone\_or\_email](#AssemblyLine.al_general.is_phone_or_email) + * [github\_modified\_date](#AssemblyLine.al_general.github_modified_date) + * [language\_name](#AssemblyLine.al_general.language_name) + * [safe\_states\_list](#AssemblyLine.al_general.safe_states_list) + * [has\_parsable\_pronouns](#AssemblyLine.al_general.has_parsable_pronouns) + * [parse\_custom\_pronouns](#AssemblyLine.al_general.parse_custom_pronouns) + * [get\_visible\_al\_nav\_items](#AssemblyLine.al_general.get_visible_al_nav_items) + --- sidebar_label: al_general title: AssemblyLine.al_general --- -#### safe\_subdivision\_type + + +#### safe\_subdivision\_type(country\_code: str) + +```python +def safe_subdivision_type(country_code: str) -> Optional[str] +``` Returns the subdivision type for the country with the given country code. If no subdivision type is found, returns None. @@ -17,6 +99,8 @@ If no subdivision type is found, returns None. - `Optional[str]` - The subdivision type for the country with the given country code. + + ## ALAddress Objects ```python @@ -37,7 +121,22 @@ 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 + + +#### 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) + +```python +def 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) -> List[Dict[str, Any]] +``` Return a YAML structure representing the list of fields for the object's address. @@ -77,7 +176,15 @@ 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 + + +#### formatted\_unit(language: Optional[str] = None, require: bool = False, bare: bool = False) + +```python +def formatted_unit(language: Optional[str] = None, + require: bool = False, + bare: bool = False) -> str +``` Returns the unit, formatted appropriately. @@ -98,7 +205,18 @@ 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 + + +#### block(language: Optional[str] = None, international: bool = False, show\_country: Optional[bool] = None, bare: bool = False, long\_state: bool = False, show\_impounded: bool = False) + +```python +def block(language: Optional[str] = None, + international: bool = False, + show_country: Optional[bool] = None, + bare: bool = False, + long_state: bool = False, + show_impounded: bool = False) -> str +``` Returns a one-line formatted address, primarily for geocoding. @@ -117,7 +235,15 @@ Returns a one-line formatted address, primarily for geocoding. - `str` - The one-line formatted address. -#### line\_one + + +#### line\_one(language: Optional[str] = None, bare: bool = False, show\_impounded: bool = False) + +```python +def line_one(language: Optional[str] = None, + bare: bool = False, + show_impounded: bool = False) -> str +``` Returns the first line of the address, including the unit number if it exists. @@ -132,7 +258,15 @@ Returns the first line of the address, including the unit number if it exists. - `str` - The first line of the address. -#### line\_two + + +#### line\_two(language: Optional[str] = None, long\_state: bool = False, show\_impounded: bool = False) + +```python +def line_two(language: Optional[str] = None, + long_state: bool = False, + show_impounded: bool = False) -> str +``` Returns the second line of the address, including city, state, and postal code. @@ -147,7 +281,19 @@ Returns the second line of the address, including city, state, and postal code. - `str` - The second line of the address. -#### on\_one\_line + + +#### 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) + +```python +def 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) -> str +``` Returns a one-line formatted address. @@ -167,7 +313,13 @@ Returns a one-line formatted address. - `str` - The one-line formatted address. -#### normalized\_address + + +#### normalized\_address() + +```python +def normalized_address() -> Union[Address, "ALAddress"] +``` Try geocoding the address, returning the normalized version if successful. @@ -185,7 +337,13 @@ 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 + + +#### state\_name(country\_code: Optional[str] = None) + +```python +def state_name(country_code: Optional[str] = None) -> str +``` Returns the full state name based on the state abbreviation. @@ -207,6 +365,8 @@ 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 ```python @@ -219,7 +379,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -228,7 +394,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### \_\_str\_\_ + + +#### \_\_str\_\_() + +```python +def __str__() -> str +``` Provide a string representation of the ALAddressList. @@ -239,6 +411,8 @@ comma-separated manner using the on_one_line method of ALAddress. - `str` - Formatted string of all addresses in the list. + + ## ALNameList Objects ```python @@ -249,7 +423,13 @@ A class to store a list of IndividualName objects. Extends the DAList class and is tailored for IndividualName objects. -#### init + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -258,7 +438,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### \_\_str\_\_ + + +#### \_\_str\_\_() + +```python +def __str__() -> str +``` Provide a string representation of the ALNameList. @@ -266,6 +452,8 @@ Provide a string representation of the ALNameList. - `str` - Formatted string of all names in the list. + + ## ALPeopleList Objects ```python @@ -276,7 +464,13 @@ Class to store a list of ALIndividual objects, representing people. For example, defendants, plaintiffs, or children. -#### init + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -285,7 +479,14 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### names\_and\_addresses\_on\_one\_line + + +#### names\_and\_addresses\_on\_one\_line(comma\_string: str = "; ", bare=False) + +```python +def names_and_addresses_on_one_line(comma_string: str = "; ", + bare=False) -> str +``` Provide names and addresses of individuals on one line. @@ -299,7 +500,13 @@ Provide names and addresses of individuals on one line. - `str` - Formatted string of names followed by addresses. -#### familiar + + +#### familiar(\*\*kwargs) + +```python +def familiar(**kwargs) -> str +``` Provide a list of familiar forms of names of individuals. @@ -311,7 +518,13 @@ Provide a list of familiar forms of names of individuals. - `str` - Formatted string of familiar names. -#### familiar\_or + + +#### familiar\_or(\*\*kwargs) + +```python +def familiar_or(**kwargs) -> str +``` Provide a list of familiar forms of names of individuals separated by 'or'. @@ -324,7 +537,13 @@ Provide a list of familiar forms of names of individuals separated by 'or&# - `str` - Formatted string of familiar names separated by 'or'. -#### short\_list + + +#### short\_list(limit: int, truncate\_string: str = ", et. al.") + +```python +def short_list(limit: int, truncate_string: str = ", et. al.") -> str +``` Return a subset of the list, truncated with 'et. al.' if it exceeds a given limit. @@ -338,7 +557,13 @@ Return a subset of the list, truncated with 'et. al.' if it exceeds a - `str` - Formatted string of names, truncated if needed. -#### full\_names + + +#### full\_names(comma\_string=", ", and\_string=word("and")) + +```python +def full_names(comma_string=", ", and_string=word("and")) -> str +``` Return a formatted list of full names of individuals. @@ -352,7 +577,13 @@ Return a formatted list of full names of individuals. - `str` - Formatted string of full names. -#### pronoun\_reflexive + + +#### pronoun\_reflexive(\*\*kwargs) + +```python +def pronoun_reflexive(**kwargs) -> str +``` Returns the appropriate reflexive pronoun for the list of people, depending on the `person` keyword argument and the number of items in the list. @@ -371,6 +602,8 @@ If it is plural, return the appropriate plural reflexive pronoun (e.g., "th - `str` - The reflexive pronoun for the list. + + ## ALIndividual Objects ```python @@ -399,7 +632,13 @@ 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 + + +#### init(\*pargs, \*\*kwargs) + +```python +def init(*pargs, **kwargs) -> None +``` Standard DAObject init method. @@ -408,7 +647,13 @@ Standard DAObject init method. - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### signature\_if\_final + + +#### signature\_if\_final(i: str) + +```python +def signature_if_final(i: str) -> Union[DAFile, str] +``` Returns the individual's signature if `i` is "final", which usually means we are assembling the final version of the document (as opposed to a preview). @@ -421,7 +666,14 @@ 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 + + +#### phone\_numbers(country: Optional[str] = None, show\_impounded: bool = False) + +```python +def phone_numbers(country: Optional[str] = None, + show_impounded: bool = False) -> str +``` Fetches and formats the phone numbers of the individual. @@ -443,7 +695,13 @@ Supports the following attributes: - `str` - Formatted string of phone numbers. -#### contact\_methods + + +#### contact\_methods() + +```python +def contact_methods() -> str +``` Generates a formatted string of all provided contact methods. @@ -451,7 +709,13 @@ Generates a formatted string of all provided contact methods. - `str` - A formatted string indicating the available methods to contact the individual. -#### merge\_letters + + +#### merge\_letters(new\_letters: str) + +```python +def merge_letters(new_letters: str) -> None +``` If the Individual has a child_letters attribute, add the new letters to the existing list @@ -461,7 +725,13 @@ Avoid using. Only used in 209A. - `new_letters` _str_ - The new letters to add to the existing list of letters -#### formatted\_age + + +#### formatted\_age() + +```python +def formatted_age() -> str +``` Calculates and formats the age of the individual based on their birthdate. @@ -469,7 +739,13 @@ 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() + +```python +def normalized_address() -> Union[Address, ALAddress] +``` Fetches the normalized version of the address. @@ -477,7 +753,22 @@ Fetches the normalized version of the address. Union[Address, ALAddress]: The normalized address object. -#### name\_fields + + +#### 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) + +```python +def 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 +) -> List[Dict[str, str]] +``` Generates suitable field prompts for a name based on the type of entity (person or business) and other provided parameters. @@ -509,7 +800,22 @@ 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 + + +#### 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) + +```python +def 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) -> List[Dict[str, str]] +``` Generate field prompts for capturing an address. @@ -530,7 +836,18 @@ Generate field prompts for capturing an address. List[Dict[str, str]]: A list of dictionaries with field prompts for addresses. -#### gender\_fields + + +#### 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) + +```python +def 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 +) -> List[Dict[str, str]] +``` Generate fields for capturing gender information, including a self-described option. @@ -552,7 +869,21 @@ self-described option. self-described will provide an input that overrides the value of `gender` and is not persisted. -#### pronoun\_fields + + +#### 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) + +```python +def 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) -> List[Dict[str, str]] +``` Generate fields for capturing pronoun information. @@ -571,7 +902,13 @@ Generate fields for capturing pronoun information. List[Dict[str, str]]: A list of dictionaries with field prompts for pronouns. -#### get\_pronouns + + +#### get\_pronouns() + +```python +def get_pronouns() -> set +``` Retrieve a set of the individual's pronouns. @@ -583,7 +920,13 @@ Can be formatted however the author likes. - `set` - A set of strings representing the individual's pronouns. -#### list\_pronouns + + +#### list\_pronouns() + +```python +def list_pronouns() -> str +``` Retrieve a formatted string of the individual's pronouns, arranged with the comma_list() function. @@ -592,7 +935,17 @@ the comma_list() function. - `str` - A formatted string of the individual's pronouns. -#### language\_fields + + +#### 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) + +```python +def 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) -> List[Dict[str, str]] +``` Generate fields for capturing language preferences. @@ -608,7 +961,13 @@ Generate fields for capturing language preferences. List[Dict[str, str]]: A list of dictionaries with field prompts for language preferences. -#### language\_name + + +#### language\_name() + +```python +def language_name() -> str +``` Get the human-readable version of the individual's selected language. @@ -618,66 +977,138 @@ 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() + +```python +@property +def gender_male() -> bool +``` 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() + +```python +@property +def gender_female() -> bool +``` 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() + +```python +@property +def gender_other() -> bool +``` 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() + +```python +@property +def gender_nonbinary() -> bool +``` 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() + +```python +@property +def gender_unknown() -> bool +``` 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() + +```python +@property +def gender_undisclosed() -> bool +``` 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() + +```python +@property +def gender_self_described() -> bool +``` 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() + +```python +def contact_fields() -> None +``` Return field prompts for other contact info -#### initials + + +#### initials() + +```python +@property +def initials() -> str +``` Returns the initials of the individual as a string. For example, "Quinten K Steenhuis" would return "QKS". -#### address\_block + + +#### address\_block(language=None, international=False, show\_country=False, bare=False, show\_impounded=False) + +```python +def address_block(language=None, + international=False, + show_country=False, + bare=False, + show_impounded=False) -> str +``` Generate a formatted address block for mailings. @@ -694,7 +1125,13 @@ Generate a formatted address block for mailings. - `str` - The formatted address block. -#### pronoun + + +#### pronoun(\*\*kwargs) + +```python +def pronoun(**kwargs) -> str +``` Returns an objective pronoun as appropriate, based on the user's `pronouns` attribute or `gender` attribute. @@ -714,7 +1151,13 @@ with `pronouns` taking precedence. As a default, it will either use the value of - `str` - The appropriate pronoun. -#### pronoun\_objective + + +#### pronoun\_objective(\*\*kwargs) + +```python +def pronoun_objective(**kwargs) -> str +``` Returns the same pronoun as the `pronoun()` method. @@ -727,7 +1170,13 @@ Returns the same pronoun as the `pronoun()` method. - `str` - The appropriate objective pronoun. -#### pronoun\_possessive + + +#### pronoun\_possessive(target, \*\*kwargs) + +```python +def pronoun_possessive(target, **kwargs) -> str +``` Returns a possessive pronoun and a target word, based on attributes. @@ -750,7 +1199,13 @@ and whether the individual is the current user. - `str` - The appropriate possessive phrase, e.g., "her book", "their document". -#### pronoun\_subjective + + +#### pronoun\_subjective(\*\*kwargs) + +```python +def pronoun_subjective(**kwargs) -> str +``` Returns a subjective pronoun, based on attributes. @@ -768,7 +1223,13 @@ is the current user. - `str` - The appropriate subjective pronoun. -#### pronoun\_reflexive + + +#### pronoun\_reflexive(\*\*kwargs) + +```python +def pronoun_reflexive(**kwargs) -> str +``` Returns the appropriate reflexive pronoun ("herself", "themself", "myself"), based on the user's pronouns or gender and whether we are asked to return a 1st, 2nd, or 3rd person pronoun. @@ -788,7 +1249,13 @@ See: https://www.merriam-webster.com/wordplay/themself - `str` - The appropriate reflexive pronoun. -#### name\_full + + +#### name\_full() + +```python +def name_full() -> str +``` Returns the individual's full name. @@ -800,7 +1267,13 @@ the first name, even if middle, last, or suffix are defined. - `str` - The individual or business's full name. -#### name\_initials + + +#### name\_initials() + +```python +def name_initials() -> str +``` Returns the individual's name with the middle name as an initial. Equivalent to `name.full(middle="initial")`, which is also the default. @@ -814,7 +1287,13 @@ 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() + +```python +def name_short() -> str +``` Returns the individual's name without any middle name. @@ -828,7 +1307,14 @@ the first name, even if middle, last, or suffix are defined. - `str` - The individual' -#### familiar + + +#### familiar(unique\_names: Optional[List[Any]] = None, default: Optional[str] = None) + +```python +def familiar(unique_names: Optional[List[Any]] = None, + default: Optional[str] = None) -> str +``` Returns the individual's name in the most familiar form possible. @@ -868,7 +1354,13 @@ 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\_\_() + +```python +def __str__() -> str +``` Returns a string representation of the individual, which is their full name with the middle name shortened to one letter. @@ -881,7 +1373,13 @@ the first name, even if middle, last, or suffix are defined. - `str` - The individual's name. -#### section\_links + + +#### section\_links(nav) + +```python +def section_links(nav) -> List[str] +``` Returns a list of clickable navigation links without animation. @@ -894,7 +1392,13 @@ 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() + +```python +def will_send_to_real_court() -> bool +``` For legacy email to court forms, this checks to see if the form is being run on the dev, test, or production server. @@ -905,7 +1409,13 @@ 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 + + +#### filter\_letters(letter\_strings: Union[List[str], str]) + +```python +def filter_letters(letter_strings: Union[List[str], str]) -> str +``` Used to take a list of letters like ["A","ABC","AB"] and filter out any duplicate letters. @@ -920,7 +1430,16 @@ Avoid using, this is created for 209A. - `str` - A string of unique letters. -#### fa\_icon + + +#### fa\_icon(icon: str, color: str = "primary", color\_css: Optional[str] = None, size: str = "sm") + +```python +def fa_icon(icon: str, + color: str = "primary", + color_css: Optional[str] = None, + size: str = "sm") -> str +``` Return HTML for a font-awesome icon of the specified size and color. You can reference a CSS variable (such as Bootstrap theme color) or a true CSS color reference, such as 'blue' or @@ -938,7 +1457,13 @@ 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() + +```python +def is_sms_enabled() -> bool +``` Checks if SMS (Twilio) is enabled on the server. Does not verify that it works. @@ -948,7 +1473,13 @@ 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 + + +#### is\_phone\_or\_email(text: str) + +```python +def is_phone_or_email(text: str) -> bool +``` Returns True if the string is either a valid phone number or a valid email address. If SMS is not enabled on the server (through the Twilio config), only accepts emails. @@ -969,7 +1500,15 @@ strings. DAValidationError if the string is neither a valid phone number nor a valid email address. -#### github\_modified\_date + + +#### github\_modified\_date(github\_user: str, github\_repo\_name: str, auth=None) + +```python +def github_modified_date(github_user: str, + github_repo_name: str, + auth=None) -> Union[DADateTime, None] +``` Returns the date that the given GitHub repository was modified or None if API call fails. @@ -1001,7 +1540,13 @@ 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\_name(language\_code: str) + +```python +def language_name(language_code: str) -> str +``` Given a 2 digit language code abbreviation, returns the full name of the language. The language name will be passed through the `word()` @@ -1016,7 +1561,13 @@ function. - `str` - The full name of the language. -#### safe\_states\_list + + +#### safe\_states\_list(country\_code: str) + +```python +def safe_states_list(country_code: str) -> List[Dict[str, str]] +``` Wrapper around states_list that doesn't error if passed an invalid country_code (e.g., a country name spelled out) @@ -1030,7 +1581,13 @@ 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 + + +#### has\_parsable\_pronouns(pronouns: str) + +```python +def has_parsable_pronouns(pronouns: str) -> bool +``` Returns True if the pronouns string can be parsed into a dictionary of pronouns. @@ -1043,7 +1600,13 @@ 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 + + +#### parse\_custom\_pronouns(pronouns: str) + +```python +def parse_custom_pronouns(pronouns: str) -> Dict[str, str] +``` Parses a custom pronoun string into a dictionary of pronouns. @@ -1056,7 +1619,14 @@ 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 + + +#### get\_visible\_al\_nav\_items(nav\_items: List[Union[str, dict]]) + +```python +def get_visible_al_nav_items( + nav_items: List[Union[str, dict]]) -> List[Union[str, dict]] +``` Processes a list of nav items and returns only the ones that are not hidden. Can be used to control the visible nav items in a more declarative way while keeping diff --git a/docs/components/AssemblyLine/custom_jinja_filters.md b/docs/components/AssemblyLine/custom_jinja_filters.md index e8a5d0874..0eebcaca3 100644 --- a/docs/components/AssemblyLine/custom_jinja_filters.md +++ b/docs/components/AssemblyLine/custom_jinja_filters.md @@ -1,9 +1,26 @@ +# Table of Contents + +* [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) + * [catchall\_question](#AssemblyLine.custom_jinja_filters.catchall_question) + * [catchall\_subquestion](#AssemblyLine.custom_jinja_filters.catchall_subquestion) + * [if\_final](#AssemblyLine.custom_jinja_filters.if_final) + * [catchall\_fields\_code](#AssemblyLine.custom_jinja_filters.catchall_fields_code) + --- sidebar_label: custom_jinja_filters title: AssemblyLine.custom_jinja_filters --- -#### catchall\_options + + +#### catchall\_options(value: Any, \*raw\_items: Any) + +```python +def catchall_options(value: Any, *raw_items: Any) -> DACatchAll +``` Jinja2 filter to support defining options for DACatchAll fields inside a DOCX template. @@ -52,7 +69,13 @@ fields: - `DACatchAll` - The modified DACatchAll object with the assigned options. -#### catchall\_label + + +#### catchall\_label(value: Any, label: str) + +```python +def catchall_label(value: Any, label: str) -> DACatchAll +``` Jinja2 filter to allow you to define a label for a DACatchAll field inside a DOCX template. @@ -84,7 +107,13 @@ fields: - `DACatchAll` - The modified DACatchAll object with the assigned label. -#### catchall\_datatype + + +#### catchall\_datatype(value: Any, datatype: str) + +```python +def catchall_datatype(value: Any, datatype: str) -> DACatchAll +``` Jinja2 filter to allow you to define a datatype for a DACatchAll field inside a DOCX template. @@ -108,7 +137,13 @@ Example usage in a DOCX template: - `DACatchAll` - The modified DACatchAll object with the assigned datatype. -#### catchall\_question + + +#### catchall\_question(value: Any, question: str) + +```python +def catchall_question(value: Any, question: str) -> DACatchAll +``` Jinja2 filter to allow you to define a question for a DACatchAll field inside a DOCX template. @@ -132,7 +167,13 @@ Example usage in a DOCX template: - `DACatchAll` - The modified DACatchAll object with the assigned question. -#### catchall\_subquestion + + +#### catchall\_subquestion(value: Any, subquestion: str) + +```python +def catchall_subquestion(value: Any, subquestion: str) -> DACatchAll +``` Jinja2 filter to allow you to define a subquestion for a DACatchAll field inside a DOCX template. @@ -156,7 +197,18 @@ Example usage in a DOCX template: - `DACatchAll` - The modified DACatchAll object with the assigned subquestion. -#### if\_final + + +#### if\_final(context: Jinja2Context, value: Any, i: Optional[str] = None, expected\_i: Union[str, List[str]] = "final", placeholder: Optional[str] = None) + +```python +@pass_context +def if_final(context: Jinja2Context, + value: Any, + i: Optional[str] = None, + expected_i: Union[str, List[str]] = "final", + placeholder: Optional[str] = None) -> Any +``` Jinja2 filter to only seek the definition of a variable if the current value of `i` is equal to the expected value (normally "final"); otherwise, @@ -231,7 +283,13 @@ as in an ALDocument's "preview" or "final" values. - `Any` - The original `value` if `i` matches `expected_i`, otherwise the `placeholder`. -#### catchall\_fields\_code + + +#### catchall\_fields\_code(value: Any) + +```python +def catchall_fields_code(value: Any) -> List[Dict[str, Any]] +``` Create Docassemble code for a catchall field with the appropriate datatypes. diff --git a/docs/components/AssemblyLine/language.md b/docs/components/AssemblyLine/language.md index bf19f6e3a..e08beac65 100644 --- a/docs/components/AssemblyLine/language.md +++ b/docs/components/AssemblyLine/language.md @@ -1,9 +1,25 @@ +# Table of Contents + +* [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) + * [get\_language\_list\_dropdown\_item](#AssemblyLine.language.get_language_list_dropdown_item) + * [get\_language\_list](#AssemblyLine.language.get_language_list) + * [get\_language\_list\_item](#AssemblyLine.language.get_language_list_item) + --- sidebar_label: language title: AssemblyLine.language --- -#### get\_local\_languages\_yaml + + +#### get\_local\_languages\_yaml() + +```python +def get_local_languages_yaml() -> str +``` Get the path to the local languages.yml file. If it does not exist, it will return the path to the languages.yml @@ -11,7 +27,14 @@ 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 + + +#### get\_tuples(lang\_codes: List[str], languages\_path: Optional[str] = None) + +```python +def get_tuples(lang_codes: List[str], + languages_path: Optional[str] = None) -> List[Tuple[str, str]] +``` Returns a list of tuples representing the language name, followed by language ISO 639-1 code. @@ -28,7 +51,18 @@ 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 + + +#### 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") + +```python +def 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") -> str +``` Get a Bootstrap 5 dropdown menu for language selection that can be added to navigation bar. @@ -45,7 +79,15 @@ 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 + + +#### get\_language\_list\_dropdown\_item(language: Tuple[str, str], link: bool = True, event\_name="al\_change\_language") + +```python +def get_language_list_dropdown_item(language: Tuple[str, str], + link: bool = True, + event_name="al_change_language") -> str +``` Given an ordered tuple, returns a link to the current interview with lang=language code and the link title given in the first part of the tuple. @@ -61,7 +103,17 @@ 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 + + +#### 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\_change\_language") + +```python +def 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_change_language") -> str +``` Given a list of language codes, returns a Bootstrap-formatted unordered inline list. The current language will not be a link. @@ -82,7 +134,15 @@ 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 + + +#### get\_language\_list\_item(language, link=True, event\_name="al\_change\_language") + +```python +def get_language_list_item(language, + link=True, + event_name="al_change_language") -> str +``` Given an ordered tuple, returns a link to the current interview with lang=language code and the link title given in the first part of the tuple. diff --git a/docs/components/AssemblyLine/sessions.md b/docs/components/AssemblyLine/sessions.md index 1051cb677..f48a7d18e 100644 --- a/docs/components/AssemblyLine/sessions.md +++ b/docs/components/AssemblyLine/sessions.md @@ -1,9 +1,47 @@ +# Table of Contents + +* [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) + * [get\_saved\_interview\_list](#AssemblyLine.sessions.get_saved_interview_list) + * [find\_matching\_sessions](#AssemblyLine.sessions.find_matching_sessions) + * [delete\_interview\_sessions](#AssemblyLine.sessions.delete_interview_sessions) + * [interview\_list\_html](#AssemblyLine.sessions.interview_list_html) + * [nice\_interview\_title](#AssemblyLine.sessions.nice_interview_title) + * [pascal\_to\_zwspace](#AssemblyLine.sessions.pascal_to_zwspace) + * [nice\_interview\_subtitle](#AssemblyLine.sessions.nice_interview_subtitle) + * [radial\_progress](#AssemblyLine.sessions.radial_progress) + * [local\_date](#AssemblyLine.sessions.local_date) + * [session\_list\_html](#AssemblyLine.sessions.session_list_html) + * [rename\_interview\_answers](#AssemblyLine.sessions.rename_interview_answers) + * [set\_current\_session\_metadata](#AssemblyLine.sessions.set_current_session_metadata) + * [rename\_current\_session](#AssemblyLine.sessions.rename_current_session) + * [save\_interview\_answers](#AssemblyLine.sessions.save_interview_answers) + * [get\_filtered\_session\_variables](#AssemblyLine.sessions.get_filtered_session_variables) + * [get\_filtered\_session\_variables\_string](#AssemblyLine.sessions.get_filtered_session_variables_string) + * [load\_interview\_answers](#AssemblyLine.sessions.load_interview_answers) + * [load\_interview\_json](#AssemblyLine.sessions.load_interview_json) + * [export\_interview\_variables](#AssemblyLine.sessions.export_interview_variables) + * [is\_valid\_json](#AssemblyLine.sessions.is_valid_json) + * [config\_with\_language\_fallback](#AssemblyLine.sessions.config_with_language_fallback) + * [get\_filenames\_having\_sessions](#AssemblyLine.sessions.get_filenames_having_sessions) + * [get\_combined\_filename\_list](#AssemblyLine.sessions.get_combined_filename_list) + * [update\_session\_metadata](#AssemblyLine.sessions.update_session_metadata) + * [update\_current\_session\_metadata](#AssemblyLine.sessions.update_current_session_metadata) + --- sidebar_label: sessions title: AssemblyLine.sessions --- -#### is\_file\_like + + +#### is\_file\_like(obj: Any) + +```python +def is_file_like(obj: Any) -> bool +``` Return True if the object is a file-like object. @@ -16,7 +54,16 @@ Return True if the object is a file-like object. - `bool` - True if the object is a file-like object. -#### set\_interview\_metadata + + +#### set\_interview\_metadata(filename: str, session\_id: str, data: Dict, metadata\_key\_name="metadata") + +```python +def set_interview_metadata(filename: str, + session_id: str, + data: Dict, + metadata_key_name="metadata") -> None +``` Add searchable interview metadata for the specified filename and session ID. Intended to be used to add an interview title, etc. @@ -33,7 +80,16 @@ 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 + + +#### get\_interview\_metadata(filename: str, session\_id: str, metadata\_key\_name: str = "metadata") + +```python +def get_interview_metadata( + filename: str, + session_id: str, + metadata_key_name: str = "metadata") -> Dict[str, Any] +``` Retrieve the unencrypted metadata associated with an interview. We implement this with the docassemble jsonstorage table and a dedicated `tag` which defaults to `metadata`. @@ -49,7 +105,22 @@ 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 + + +#### 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) + +```python +def 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) -> List[Dict[str, Any]] +``` Get a list of saved sessions for the specified filename. If the save_interview_answers function was used to add metadata, the result list will include columns containing the metadata. @@ -79,7 +150,28 @@ an existing interview to the answer set. List[Dict[str, Any]]: A list of saved sessions for the specified filename. -#### find\_matching\_sessions + + +#### 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) + +```python +def 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 +) -> List[Dict[str, Any]] +``` Get a list of sessions where the metadata for the session matches the provided keyword search terms and metadata filters. This function is designed to be used in a search interface where the user can search for sessions by keyword and specific metadata values. @@ -129,7 +221,16 @@ 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 + + +#### delete\_interview\_sessions(user\_id: Optional[int] = None, filename\_to\_exclude: str = al\_session\_store\_default\_filename, exclude\_current\_filename: bool = True) + +```python +def delete_interview_sessions( + user_id: Optional[int] = None, + filename_to_exclude: str = al_session_store_default_filename, + exclude_current_filename: bool = True) -> None +``` Delete all sessions for the specified user, excluding the current filename and by default, the intentionally saved "answer sets". Created because @@ -141,7 +242,29 @@ 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 + + +#### 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) + +```python +def 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) -> str +``` Return a string containing an HTML-formatted table with the list of saved answers associated with the specified filename. @@ -179,7 +302,13 @@ itself in a way that adds additional steps) - `str` - HTML-formatted table containing the list of saved answers. -#### nice\_interview\_title + + +#### nice\_interview\_title(answer: Dict[str, str]) + +```python +def nice_interview_title(answer: Dict[str, str]) -> str +``` Return a human readable version of the interview name. Will try several strategies in descending priority order. @@ -196,7 +325,13 @@ in descending priority order. - `str` - The human readable interview title -#### pascal\_to\_zwspace + + +#### pascal\_to\_zwspace(text: str) + +```python +def pascal_to_zwspace(text: str) -> str +``` Insert a zero-width space into words that are PascalCased to help with word breaks on small viewports. @@ -210,7 +345,14 @@ with word breaks on small viewports. - `str` - The text with zero-width spaces inserted -#### nice\_interview\_subtitle + + +#### nice\_interview\_subtitle(answer: Dict[str, str], exclude\_identical=True) + +```python +def nice_interview_subtitle(answer: Dict[str, str], + exclude_identical=True) -> str +``` Return first defined of the "title" metadata, the "auto_title" metadata, or empty string. @@ -226,7 +368,13 @@ If exclude_identical, return empty string when title is the same as the subtitle - `str` - The human readable interview subtitle -#### radial\_progress + + +#### radial\_progress(answer: Dict[str, Union[str, int]]) + +```python +def radial_progress(answer: Dict[str, Union[str, int]]) -> str +``` Return HTML for a radial progress bar, or the number of steps if progress isn't available in the metadata. @@ -239,7 +387,13 @@ Return HTML for a radial progress bar, or the number of steps if progress isn&#x - `str` - the HTML as a string -#### local\_date + + +#### local\_date(utcstring: Optional[str]) + +```python +def local_date(utcstring: Optional[str]) -> DADateTime +``` Return a localized date from a UTC string. @@ -252,7 +406,35 @@ Return a localized date from a UTC string. - `DADateTime` - The localized date -#### session\_list\_html + + +#### 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) + +```python +def 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) -> str +``` Return a string containing an HTML-formatted table with the list of user sessions. While interview_list_html() is for answer sets, this feature is for standard @@ -289,7 +471,16 @@ user sessions. The results exclude the answer set filename by default. - `str` - HTML-formatted table containing the list of user sessions. -#### rename\_interview\_answers + + +#### rename\_interview\_answers(filename: str, session\_id: str, new\_name: str, metadata\_key\_name: str = "metadata") + +```python +def rename_interview_answers(filename: str, + session_id: str, + new_name: str, + metadata_key_name: str = "metadata") -> None +``` Update the 'title' metadata of an interview, as stored in the dedicated `metadata` column, without touching other metadata that may be present. @@ -303,7 +494,14 @@ 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 + + +#### set\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") + +```python +def set_current_session_metadata(data: Dict[str, Any], + metadata_key_name: str = "metadata") -> None +``` Set metadata for the current session, such as the title, in an unencrypted database entry. @@ -312,7 +510,14 @@ 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 + + +#### rename\_current\_session(new\_name: str, metadata\_key\_name: str = "metadata") + +```python +def rename_current_session(new_name: str, + metadata_key_name: str = "metadata") -> None +``` Update the "title" metadata entry for the current session without changing any other metadata that might be present. @@ -322,7 +527,21 @@ 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 + + +#### 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) + +```python +def 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) -> str +``` Copies the answers from a given session into a new session with a specified interview filename. @@ -342,7 +561,18 @@ 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 + + +#### 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) + +```python +def 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 +) -> Dict[str, Any] +``` Retrieves a filtered subset of variables from a specified interview and session. If no filename and session ID are given, it will return a filtered list of variables @@ -360,7 +590,19 @@ from the current interview. Dict[str, Any]: A dictionary of filtered session variables. -#### get\_filtered\_session\_variables\_string + + +#### 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) + +```python +def 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) -> str +``` Returns a JSON string that represents the filtered contents of a specified filename and session ID. If no filename and session ID are provided, the current session's variables will be used. @@ -378,7 +620,20 @@ 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 + + +#### 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) + +```python +def 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 +) -> Optional[Union[int, bool]] +``` Loads answers from a specified session. If the parameter `new_session` is set to True, it will create a new session with the provided or current interview filename. Otherwise, it will load the answers into @@ -398,7 +653,17 @@ 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 + + +#### load\_interview\_json(json\_string: str, new\_session: bool = False, new\_interview\_filename: Optional[str] = None, variables\_to\_filter: Optional[List[str]] = None) + +```python +def load_interview_json( + json_string: str, + new_session: bool = False, + new_interview_filename: Optional[str] = None, + variables_to_filter: Optional[List[str]] = None) -> Optional[int] +``` Given a JSON string, this function loads the specified variables into a Docassemble session. JSON strings containing annotated class names will be transformed into Docassemble objects. @@ -416,7 +681,19 @@ 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 + + +#### 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) + +```python +def 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) -> DAFile +``` Generates a DAFile containing a JSON representation of a specified session's interview answers. The resultant output is compatible with `set_session_variables(process_objects=True)` and @@ -435,7 +712,13 @@ The resultant output is compatible with `set_session_variables(process_objects=T - `DAFile` - DAFile with a JSON representation of the answers -#### is\_valid\_json + + +#### is\_valid\_json(json\_string: str) + +```python +def is_valid_json(json_string: str) -> bool +``` Checks if the provided string is a valid JSON-formatted string. @@ -448,7 +731,15 @@ 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\_with\_language\_fallback(config\_key: str, top\_level\_config\_key: Optional[str] = None) + +```python +def config_with_language_fallback( + config_key: str, + top_level_config_key: Optional[str] = None) -> Optional[str] +``` Returns the value of a config key under `assembly line` `interview list` with options to fallback to an alternative key at the top level of the global configuration. @@ -475,7 +766,16 @@ short title: My forms - `str` - The value of the config key, or the alternative key, or None. -#### get\_filenames\_having\_sessions + + +#### get\_filenames\_having\_sessions(user\_id: Optional[Union[int, str]] = None, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None) + +```python +def get_filenames_having_sessions( + user_id: Optional[Union[int, str]] = None, + global_search_allowed_roles: Optional[Union[Set[str], List[str]]] = None +) -> List[str] +``` Get a list of all filenames that have sessions saved for a given user, in order to help show the user a good list of interviews to filter search results. @@ -490,7 +790,16 @@ 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 + + +#### get\_combined\_filename\_list(user\_id: Optional[Union[int, str]] = None, global\_search\_allowed\_roles: Optional[Union[Set[str], List[str]]] = None) + +```python +def get_combined_filename_list( + user_id: Optional[Union[int, str]] = None, + global_search_allowed_roles: Optional[Union[Set[str], List[str]]] = None +) -> List[Dict[str, str]] +``` Get a list of all filenames that have sessions saved for a given user. If it is possible to show a descriptive name for the filename (from the main dispatch area of the configuration), @@ -509,7 +818,16 @@ radio button and dropdown list expect. List[Dict[str, str]]: List of filenames that have sessions saved for the user. -#### update\_session\_metadata + + +#### update\_session\_metadata(filename: str, session\_id: str, data: Dict[str, Any], metadata\_key\_name: str = "metadata") + +```python +def update_session_metadata(filename: str, + session_id: str, + data: Dict[str, Any], + metadata_key_name: str = "metadata") -> None +``` Upsert session metadata into jsonstorage using a PostgreSQL advisory lock (two-int form) to serialize concurrent upserts on the same (session_id,filename,tags) key. @@ -521,7 +839,15 @@ 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 + + +#### update\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") + +```python +def update_current_session_metadata(data: Dict[str, Any], + metadata_key_name: str = "metadata" + ) -> None +``` Updates metadata for the current session without retrieving the data first. diff --git a/docs/components/AssemblyLine/sign.md b/docs/components/AssemblyLine/sign.md index b2f606285..1d2e98e14 100644 --- a/docs/components/AssemblyLine/sign.md +++ b/docs/components/AssemblyLine/sign.md @@ -1,9 +1,23 @@ +# Table of Contents + +* [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) + --- sidebar_label: sign title: AssemblyLine.sign --- -#### find\_font\_file\_by\_name + + +#### find\_font\_file\_by\_name(font\_name: str, search\_dirs: List[str]) + +```python +def find_font_file_by_name(font_name: str, + search_dirs: List[str]) -> Optional[str] +``` Recursively search for a font file by name in the specified directories. @@ -21,7 +35,16 @@ matches the font name (case-insensitive). - `Optional[str]` - The full path to the font file if found; otherwise, None. -#### get\_font + + +#### get\_font(font\_name: Optional[str] = None, font\_size: int = 48) + +```python +def get_font( + font_name: Optional[str] = None, + font_size: int = 48 +) -> Union[ImageFont.ImageFont, ImageFont.FreeTypeFont] +``` Loads a font by name from candidate directories and returns an ImageFont instance. @@ -40,7 +63,17 @@ if necessary. If no font is found, the function falls back to the default Pillow - `ImageFont.ImageFont` - The loaded font instance. -#### create\_signature + + +#### create\_signature(name: str, output\_file: str, signature\_prefix: str = "/s/", font\_name: Optional[str] = None, font\_size: int = 48) + +```python +def create_signature(name: str, + output_file: str, + signature_prefix: str = "/s/", + font_name: Optional[str] = None, + font_size: int = 48) -> None +``` Creates an image file that simulates a signature. diff --git a/docs/components/EFSPIntegration/conversions.md b/docs/components/EFSPIntegration/conversions.md index f5fe66102..a722257ed 100644 --- a/docs/components/EFSPIntegration/conversions.md +++ b/docs/components/EFSPIntegration/conversions.md @@ -1,3 +1,23 @@ +# Table of Contents + +* [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) + * [choices\_and\_map](#EFSPIntegration.conversions.choices_and_map) + * [pretty\_display](#EFSPIntegration.conversions.pretty_display) + * [debug\_display](#EFSPIntegration.conversions.debug_display) + * [tyler\_daterep\_to\_datetime](#EFSPIntegration.conversions.tyler_daterep_to_datetime) + * [tyler\_timestamp\_to\_datetime](#EFSPIntegration.conversions.tyler_timestamp_to_datetime) + * [validate\_tyler\_regex](#EFSPIntegration.conversions.validate_tyler_regex) + * [parse\_service\_contacts](#EFSPIntegration.conversions.parse_service_contacts) + * [parse\_case\_info](#EFSPIntegration.conversions.parse_case_info) + * [fetch\_case\_info](#EFSPIntegration.conversions.fetch_case_info) + * [filter\_payment\_accounts](#EFSPIntegration.conversions.filter_payment_accounts) + * [payment\_account\_labels](#EFSPIntegration.conversions.payment_account_labels) + * [filing\_id\_and\_label](#EFSPIntegration.conversions.filing_id_and_label) + * [get\_tyler\_roles](#EFSPIntegration.conversions.get_tyler_roles) + --- sidebar_label: conversions title: EFSPIntegration.conversions @@ -5,7 +25,13 @@ title: EFSPIntegration.conversions Functions that help convert the JSON-ized XML from the proxy server into usable information. -#### error\_notification + + +#### error\_notification(err, message=None, trace=None, referer=None) + +```python +def error_notification(err, message=None, trace=None, referer=None) +``` Copied from docassemble.webapp.server.error_notification, since: 1) things from webapp.* are unstable @@ -13,12 +39,24 @@ Copied from docassemble.webapp.server.error_notification, since: Some slight modifications to work without server backends -#### log\_error\_and\_notify + + +#### log\_error\_and\_notify(context: str, resp: Optional[ApiResponse] = None) + +```python +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 + + +#### convert\_court\_to\_id(trial\_court) + +```python +def convert_court_to_id(trial_court) -> str +``` Converts a court type to the specific id string expected by Tyler. @@ -36,7 +74,15 @@ 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 + + +#### choices\_and\_map(codes\_list: List[Dict[str, Any]], display: str = None, backing: str = None) + +```python +def choices_and_map(codes_list: List[Dict[str, Any]], + display: str = None, + backing: str = None) -> Tuple[List[Any], Dict] +``` Takes the responses from the 'codes' service and make a DA ready list of choices and a map back to the full code object @@ -55,7 +101,13 @@ 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 + + +#### pretty\_display(data, tab\_depth=0, skip\_xml=True, item\_name=None) + +```python +def pretty_display(data, tab_depth=0, skip_xml=True, item_name=None) -> str +``` Given an arbitrarily nested JSON structure, print it nicely as markdown. Recursive, for subsequent calls `tab_depth` increases. @@ -73,32 +125,74 @@ Recursive, for subsequent calls `tab_depth` increases. The string of markdown text that displays info about the given JSON structure -#### debug\_display + + +#### debug\_display(resp: ApiResponse) + +```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) -#### tyler\_daterep\_to\_datetime + + +#### tyler\_daterep\_to\_datetime(tyler\_daterep: Mapping) + +```python +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 + + +#### tyler\_timestamp\_to\_datetime(timestamp\_ms: int) + +```python +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 + + +#### validate\_tyler\_regex(data\_field: Mapping) + +```python +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 + + +#### parse\_service\_contacts(service\_list) + +```python +def parse_service_contacts(service_list) +``` 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 + + +#### parse\_case\_info(proxy\_conn: ProxyConnection, new\_case: DAObject, entry: dict, court\_id: str, \*, fetch: bool = True, roles: dict = None) + +```python +def parse_case_info(proxy_conn: ProxyConnection, + new_case: DAObject, + entry: dict, + court_id: str, + *, + fetch: bool = True, + roles: dict = None) +``` Given sparse information about a case, gets the full details about it @@ -113,7 +207,15 @@ 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 + + +#### fetch\_case\_info(proxy\_conn: ProxyConnection, new\_case: DAObject, roles: Optional[dict] = None) + +```python +def fetch_case_info(proxy_conn: ProxyConnection, + new_case: DAObject, + roles: Optional[dict] = None) -> None +``` Fills in these attributes with the full case details: * attorneys @@ -125,7 +227,13 @@ Fills in these attributes with the full case details: * date * participants -#### filter\_payment\_accounts + + +#### filter\_payment\_accounts(account\_list, allowable\_card\_types: List) + +```python +def filter_payment_accounts(account_list, allowable_card_types: List) -> List +``` Gets a list of all payment accounts and filters them by if the card is accepted at a particular court. @@ -142,17 +250,39 @@ accepted at a particular court. the list of payment account choices that are valid for a particular court -#### payment\_account\_labels + + +#### payment\_account\_labels(resp: ApiResponse) + +```python +def payment_account_labels(resp: ApiResponse) -> Optional[List[Dict]] +``` Returns all payment accounts as choices, without filters. -#### filing\_id\_and\_label + + +#### filing\_id\_and\_label(case: Mapping, style: str = "FILING\_ID") + +```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) 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 + + +#### get\_tyler\_roles(proxy\_conn: ProxyConnection, login\_data: Optional[Mapping], user\_details: Optional[ApiResponse] = None) + +```python +def get_tyler_roles( + proxy_conn: ProxyConnection, + login_data: Optional[Mapping], + user_details: Optional[ApiResponse] = None) -> Tuple[bool, bool] +``` Gets whether or not the user of this interview is a Tyler Admin, and a 'global' admin. The global admin means that they are allowed to change specific Global payment methods, diff --git a/docs/components/EFSPIntegration/efm_client.md b/docs/components/EFSPIntegration/efm_client.md index b2dfa02d8..86387fa37 100644 --- a/docs/components/EFSPIntegration/efm_client.md +++ b/docs/components/EFSPIntegration/efm_client.md @@ -1,19 +1,41 @@ +# Table of Contents + +* [EFSPIntegration.efm\_client](#EFSPIntegration.efm_client) + * [DALogger](#EFSPIntegration.efm_client.DALogger) + * [log](#EFSPIntegration.efm_client.DALogger.log) + * [ProxyConnection](#EFSPIntegration.efm_client.ProxyConnection) + * [\_\_init\_\_](#EFSPIntegration.efm_client.ProxyConnection.__init__) + * [authenticate\_user](#EFSPIntegration.efm_client.ProxyConnection.authenticate_user) + * [register\_user](#EFSPIntegration.efm_client.ProxyConnection.register_user) + * [get\_service\_types](#EFSPIntegration.efm_client.ProxyConnection.get_service_types) + * [serialize\_person](#EFSPIntegration.efm_client.serialize_person) + --- sidebar_label: efm_client title: EFSPIntegration.efm_client --- + + ## DALogger Objects ```python class DALogger(LoggerAdapter) ``` -#### log + + +#### log(level, msg, \*args, \*\*kwargs) + +```python +def log(level, msg, *args, **kwargs) +``` Delegate a log call to Docassemble's `log` function, after adding contextual information from this adapter instance. + + ## ProxyConnection Objects ```python @@ -25,29 +47,73 @@ The main class you use to communicate with the E-file proxy server from docassem Many methods are unchanged from the parent class, [EfspConnection](py_efsp_client#EfspConnection), and are documented there. -#### \_\_init\_\_ + + +#### \_\_init\_\_(\*, url: str = None, api\_key: str = None, credentials\_code\_block: str = "tyler\_login", default\_jurisdiction: str = None) + +```python +def __init__(*, + url: str = None, + api_key: str = None, + credentials_code_block: str = "tyler_login", + default_jurisdiction: str = None) +``` Creates the connection. Tries to get params from docassemble's config, but can be overriden with parameters to __init__. -#### authenticate\_user + + +#### authenticate\_user(tyler\_email: str = None, tyler\_password: str = None, jeffnet\_key: str = None, \*, jurisdiction: str = None) + +```python +def authenticate_user(tyler_email: str = None, + tyler_password: str = None, + jeffnet_key: str = None, + *, + jurisdiction: str = None) -> ApiResponse +``` Params: tyler_email (str) tyler_password (str) jeffnet_key (str) -#### register\_user + + +#### register\_user(person: Union[Individual, dict], registration\_type: str, \*, password: str = None, firm\_name\_or\_id: str = None) + +```python +def register_user(person: Union[Individual, dict], + registration_type: str, + *, + password: str = None, + firm_name_or_id: str = None) -> ApiResponse +``` registration_type needs to be INDIVIDUAL, FIRM_ADMINISTRATOR, or FIRM_ADMIN_NEW_MEMBER. 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 + + +#### get\_service\_types(court\_id: str, court\_bundle: Union[ALDocumentBundle, dict] = None) + +```python +def get_service_types( + court_id: str, + court_bundle: Union[ALDocumentBundle, 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 -#### serialize\_person + + +#### serialize\_person(person: Union[Person, Individual]) + +```python +def serialize_person(person: Union[Person, Individual]) -> Dict +``` Converts a Docassemble Person or Individual into a dictionary suitable for json.dumps and in format expected by Tyler-specific endpoints on the EFSPProxy diff --git a/docs/components/EFSPIntegration/interview_logic.md b/docs/components/EFSPIntegration/interview_logic.md index d462d0b8f..4c76b1e76 100644 --- a/docs/components/EFSPIntegration/interview_logic.md +++ b/docs/components/EFSPIntegration/interview_logic.md @@ -1,3 +1,18 @@ +# Table of Contents + +* [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) + * [num\_case\_choices](#EFSPIntegration.interview_logic.num_case_choices) + * [search\_case\_by\_name](#EFSPIntegration.interview_logic.search_case_by_name) + * [shift\_case\_select\_window](#EFSPIntegration.interview_logic.shift_case_select_window) + * [get\_full\_court\_info](#EFSPIntegration.interview_logic.get_full_court_info) + * [get\_max\_allowed\_sizes](#EFSPIntegration.interview_logic.get_max_allowed_sizes) + * [make\_filter](#EFSPIntegration.interview_logic.make_filter) + * [filter\_codes](#EFSPIntegration.interview_logic.filter_codes) + * [get\_available\_efile\_courts](#EFSPIntegration.interview_logic.get_available_efile_courts) + --- sidebar_label: interview_logic title: EFSPIntegration.interview_logic @@ -6,6 +21,8 @@ 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 ```python @@ -14,11 +31,24 @@ 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() + +```python +def search_went_wrong() -> bool +``` Returns true if something errored during the case search process -#### get\_lookup\_choices + + +#### get\_lookup\_choices(can\_file\_non\_indexed\_case: bool) + +```python +def get_lookup_choices( + can_file_non_indexed_case: bool) -> List[Dict[str, str]] +``` Returns the DA choice list of what ways you are allowed to search for a case; By default, this is "party_search", and "docket_lookup", and depending on the @@ -28,30 +58,81 @@ 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() + +```python +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 + + +#### search\_case\_by\_name(\*, proxy\_conn, var\_name: str = None, court\_id: str, somebody, filter\_fn: Callable[[Any], bool], roles=None) + +```python +def search_case_by_name(*, + proxy_conn, + var_name: str = None, + court_id: str, + somebody, + filter_fn: Callable[[Any], bool], + roles=None) -> Tuple[bool, DAList] +``` 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 + + +#### shift\_case\_select\_window(proxy\_conn, found\_cases: DAList, \*, direction: str, start\_idx: int, end\_idx: int, roles: dict = None) + +```python +def shift_case_select_window(proxy_conn, + found_cases: DAList, + *, + direction: str, + start_idx: int, + end_idx: int, + roles: dict = None) -> Tuple[int, int] +``` 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 + + +#### get\_full\_court\_info(proxy\_conn, court\_id: str) + +```python +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 + + +#### get\_max\_allowed\_sizes(proxy\_conn, court\_id: str) + +```python +def get_max_allowed_sizes(proxy_conn, + court_id: str) -> Optional[Tuple[int, int]] +``` Returns attachment max size, then message max size -#### make\_filter + + +#### make\_filter(search: Union[Callable[..., bool], SearchType, None]) + +```python +def make_filter( + search: Union[Callable[..., bool], SearchType, + None]) -> Callable[..., bool] +``` Makes a 'filter' function from some simple type. @@ -59,12 +140,29 @@ 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 + + +#### filter\_codes(options: Iterable, filters: Iterable[Union[Callable[..., bool], SearchType]], default: str, exclude: Union[Callable[..., bool], SearchType, None] = None) + +```python +def filter_codes( + options: Iterable, + filters: Iterable[Union[Callable[..., bool], SearchType]], + default: str, + exclude: Union[Callable[..., bool], SearchType, None] = None +) -> Tuple[List[Any], Optional[str]] +``` 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 + + +#### get\_available\_efile\_courts(proxy\_conn) + +```python +def get_available_efile_courts(proxy_conn) -> list +``` Gets the list of efilable courts, if it can diff --git a/docs/components/EFSPIntegration/py_efsp_client.md b/docs/components/EFSPIntegration/py_efsp_client.md index 3dcf79519..805abcbf7 100644 --- a/docs/components/EFSPIntegration/py_efsp_client.md +++ b/docs/components/EFSPIntegration/py_efsp_client.md @@ -1,3 +1,23 @@ +# Table of Contents + +* [EFSPIntegration.py\_efsp\_client](#EFSPIntegration.py_efsp_client) + * [CORR\_ID\_HEADER](#EFSPIntegration.py_efsp_client.CORR_ID_HEADER) + * [LoggerWithContext](#EFSPIntegration.py_efsp_client.LoggerWithContext) + * [EfspConnection](#EFSPIntegration.py_efsp_client.EfspConnection) + * [\_\_init\_\_](#EFSPIntegration.py_efsp_client.EfspConnection.__init__) + * [authenticate\_user](#EFSPIntegration.py_efsp_client.EfspConnection.authenticate_user) + * [register\_user](#EFSPIntegration.py_efsp_client.EfspConnection.register_user) + * [get\_password\_rules](#EFSPIntegration.py_efsp_client.EfspConnection.get_password_rules) + * [get\_notification\_options](#EFSPIntegration.py_efsp_client.EfspConnection.get_notification_options) + * [get\_firm](#EFSPIntegration.py_efsp_client.EfspConnection.get_firm) + * [update\_firm](#EFSPIntegration.py_efsp_client.EfspConnection.update_firm) + * [get\_courts](#EFSPIntegration.py_efsp_client.EfspConnection.get_courts) + * [get\_court](#EFSPIntegration.py_efsp_client.EfspConnection.get_court) + * [get\_court\_list](#EFSPIntegration.py_efsp_client.EfspConnection.get_court_list) + * [get\_filing\_list](#EFSPIntegration.py_efsp_client.EfspConnection.get_filing_list) + * [get\_service\_types](#EFSPIntegration.py_efsp_client.EfspConnection.get_service_types) + * [get\_cases\_raw](#EFSPIntegration.py_efsp_client.EfspConnection.get_cases_raw) + --- sidebar_label: py_efsp_client title: EFSPIntegration.py_efsp_client @@ -7,10 +27,14 @@ 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. + + #### CORR\_ID\_HEADER TODO(brycew): Figure out how to add + + ## LoggerWithContext Objects ```python @@ -21,6 +45,8 @@ Acts like the `merge_extra` feature from LoggerAdapter (python 3.13) is always o See https://github.com/python/cpython/pull/107292/files. + + ## EfspConnection Objects ```python @@ -29,7 +55,17 @@ class EfspConnection() A python client that communicates with the E-file proxy server. -#### \_\_init\_\_ + + +#### \_\_init\_\_(\*, url: str, api\_key: str, default\_jurisdiction: str = None, logger=None) + +```python +def __init__(*, + url: str, + api_key: str, + default_jurisdiction: str = None, + logger=None) +``` **Arguments**: @@ -37,32 +73,76 @@ A python client that communicates with the E-file proxy server. api_key (str) default_jurisdiction (str) -#### authenticate\_user + + +#### authenticate\_user(\*, tyler\_email: Optional[str] = None, tyler\_password: Optional[str] = None, jeffnet\_key: Optional[str] = None, jurisdiction: str = None) + +```python +def authenticate_user(*, + tyler_email: Optional[str] = None, + tyler_password: Optional[str] = None, + jeffnet_key: Optional[str] = None, + jurisdiction: str = None) -> ApiResponse +``` Authenticates the user with the EFM server (not the E-file proxy). -#### register\_user + + +#### register\_user(person: dict, registration\_type: str, \*, password: str = None, firm\_name\_or\_id: str = None) + +```python +def register_user(person: dict, + registration_type: str, + *, + password: str = None, + firm_name_or_id: str = None) -> ApiResponse +``` registration_type needs to be INDIVIDUAL, FIRM_ADMINISTRATOR, or FIRM_ADMIN_NEW_MEMBER. 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() + +```python +def get_password_rules() -> ApiResponse +``` 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() + +```python +def get_notification_options() -> ApiResponse +``` AKA NotificationPreferencesList -#### get\_firm + + +#### get\_firm() + +```python +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 + + +#### update\_firm(firm: dict) + +```python +def update_firm(firm: dict) -> ApiResponse +``` firm should have the below keys: * firstName, middleName, lastName if it's a person @@ -71,28 +151,72 @@ firm should have the below keys: * phoneNumber * email -#### get\_courts + + +#### get\_courts(fileable\_only: bool = False, with\_names: bool = False) + +```python +def get_courts(fileable_only: bool = False, + with_names: bool = False) -> ApiResponse +``` Gets the list of courts. -#### get\_court + + +#### get\_court(court\_id: str) + +```python +def get_court(court_id: str) -> ApiResponse +``` Gets codes for a specific court -#### get\_court\_list + + +#### 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\_filing\_list + + +#### get\_filing\_list(court\_id: str, user\_id: str = None, start\_date: datetime = None, before\_date: datetime = None) + +```python +def get_filing_list(court_id: str, + user_id: str = None, + start_date: datetime = None, + before_date: datetime = None) -> ApiResponse +``` Returns a list of filings that a particular user has made with a court. -#### get\_service\_types + + +#### get\_service\_types(court\_id: str, all\_vars: dict = None) + +```python +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 + + +#### get\_cases\_raw(court\_id: str, \*, person\_name: dict = None, business\_name: str = None, docket\_number: str = None) + +```python +def get_cases_raw(court_id: str, + *, + person_name: dict = None, + business_name: str = None, + docket_number: str = None) -> ApiResponse +``` Finds existing cases at a particular court. Only one of person_name, business_name, or docket_number should be provided at a time. diff --git a/docs/components/EFSPIntegration/test/test_proxy_conn.md b/docs/components/EFSPIntegration/test/test_proxy_conn.md index e68283cfc..09cfcc66d 100644 --- a/docs/components/EFSPIntegration/test/test_proxy_conn.md +++ b/docs/components/EFSPIntegration/test/test_proxy_conn.md @@ -1,3 +1,8 @@ +# Table of Contents + +* [EFSPIntegration.test.test\_proxy\_conn](#EFSPIntegration.test.test_proxy_conn) + * [jurisdiction](#EFSPIntegration.test.test_proxy_conn.jurisdiction) + --- sidebar_label: test_proxy_conn title: EFSPIntegration.test.test_proxy_conn @@ -10,6 +15,8 @@ Env vars needed to run: * TYLER_USER_EMAIL: the email of a user account in the specific jurisdiction of Tyler's EFM (should be a firm account) * TYLER_USER_PASSWORD: the password for that user account + + #### jurisdiction 'massachusetts' diff --git a/docs/components/formfyxer/docx_wrangling.md b/docs/components/formfyxer/docx_wrangling.md new file mode 100644 index 000000000..a444a2602 --- /dev/null +++ b/docs/components/formfyxer/docx_wrangling.md @@ -0,0 +1,185 @@ +# Table of Contents + +* [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) + * [get\_modified\_docx\_runs](#formfyxer.docx_wrangling.get_modified_docx_runs) + * [make\_docx\_plain\_language](#formfyxer.docx_wrangling.make_docx_plain_language) + * [modify\_docx\_with\_openai\_guesses](#formfyxer.docx_wrangling.modify_docx_with_openai_guesses) + +--- +sidebar_label: docx_wrangling +title: formfyxer.docx_wrangling +--- + + + +#### update\_docx(document: Union[docx.document.Document, str], modified\_runs: List[Tuple[int, int, str, int]]) + +```python +def update_docx( + document: Union[docx.document.Document, str], + modified_runs: List[Tuple[int, int, str, + int]]) -> docx.document.Document +``` + +Update the document with the modified runs. + +Note: OpenAI is probabilistic, so the modified run indices may not be correct. +When the index of a run or paragraph is out of range, a new paragraph +will be inserted at the end of the document or a new run at the end of the +paragraph's runs. + +Take a careful look at the output document to make sure it is still correct. + +**Arguments**: + +- `document` - the docx.Document object, or the path to the DOCX file +- `modified_runs` - a tuple of paragraph number, run number, the modified text, a question (not used), and whether a new paragraph should be inserted (for conditional text) + + +**Returns**: + + The modified document. + + + +#### get\_docx\_repr(docx\_path: str, paragraph\_start: int = 0, paragraph\_end: Optional[int] = None) + +```python +def get_docx_repr(docx_path: str, + paragraph_start: int = 0, + paragraph_end: Optional[int] = None) +``` + +Return a JSON representation of the paragraphs and runs in the DOCX file. + +**Arguments**: + +- `docx_path` - path to the DOCX file + + +**Returns**: + + 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) + +```python +def 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) -> List[Tuple[int, int, str, int]] +``` + +Scan the DOCX and return a list of modified text with Jinja2 variable names inserted. + +**Arguments**: + +- `docx_path` - path to the DOCX file +- `docx_repr` - a string representation of the paragraphs and runs in the DOCX file, if docx_path is not provided. This might be useful if you want +- `custom_people_names` - a tuple of custom names and descriptions to use in addition to the default ones. Like: ("clients", "the person benefiting from the form") + + +**Returns**: + + 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) + +```python +def 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) -> List[Tuple[int, int, str, int]] +``` + +Use GPT to rewrite the contents of a DOCX file paragraph by paragraph. Does not handle tables, footers, or +other structures yet. + +This is a light wrapper that provides the structure of DOCX paragraphs and runs to your prompt +to OpenAI to facilitate the rewriting of the document without disrupting formatting. + +For example, this could be used to: +* Remove any passive voice +* Replace placeholder text with variable names +* Rewrite to a 6th grade reading level +* Do an advanced search and replace, without requiring you to use a regex + +By default, the example prompt includes a sample like this: + +[ +[0, 0, "Dear "], +[0, 1, "John Smith:"], +[1, 0, "I hope this letter finds you well."], +] + +Your custom instructions should include an example of how the sample will be modified, like the one below: + +Example reply, indicating paragraph, run, the new text, and a number indicating if this changes the +current paragraph, adds one before, or adds one after (-1, 0, 1): + +\{"results": +[ +[0, 1, "Dear \{\{ other_parties[0] \}\}:", 0], +[2, 0, "\{%p if is_tenant %\}", -1], +[3, 0, "\{%p endif %\}", 1], +] +\} + +You may also want to customize the input example to better match your use case. + +**Arguments**: + +- `docx_path` _str_ - path to the DOCX file +- `docx_repr` _str_ - a string representation of the paragraphs and runs in the DOCX file, if docx_path is not provided. +- `custom_example` _Optional[str]_ - a string containing the purpose and overview of the task + instructions (str) a string containing specific instructions for the task +- `openai_client` _Optional[OpenAI]_ - an OpenAI client object. If not provided a new one will be created. +- `api_key` _Optional[str]_ - an OpenAI API key. If not provided, it will be obtained from the environment +- `temperature` _float_ - the temperature to use when generating text. Lower temperatures are more conservative. + + +**Returns**: + + 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) + +```python +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) + +```python +def modify_docx_with_openai_guesses(docx_path: str) -> docx.document.Document +``` + +Uses OpenAI to guess the variable names for a document and then modifies the document with the guesses. + +**Arguments**: + +- `docx_path` _str_ - Path to the DOCX file to modify. + + +**Returns**: + +- `docx.Document` - The modified document, ready to be saved to the same or a new path + diff --git a/docs/components/formfyxer/lit_explorer.md b/docs/components/formfyxer/lit_explorer.md new file mode 100644 index 000000000..bd2548754 --- /dev/null +++ b/docs/components/formfyxer/lit_explorer.md @@ -0,0 +1,528 @@ +# Table of Contents + +* [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) + * [regex\_norm\_field](#formfyxer.lit_explorer.regex_norm_field) + * [reformat\_field](#formfyxer.lit_explorer.reformat_field) + * [norm](#formfyxer.lit_explorer.norm) + * [vectorize](#formfyxer.lit_explorer.vectorize) + * [normalize\_name](#formfyxer.lit_explorer.normalize_name) + * [cluster\_screens](#formfyxer.lit_explorer.cluster_screens) + * [InputType](#formfyxer.lit_explorer.InputType) + * [field\_types\_and\_sizes](#formfyxer.lit_explorer.field_types_and_sizes) + * [AnswerType](#formfyxer.lit_explorer.AnswerType) + * [classify\_field](#formfyxer.lit_explorer.classify_field) + * [get\_adjusted\_character\_count](#formfyxer.lit_explorer.get_adjusted_character_count) + * [time\_to\_answer\_field](#formfyxer.lit_explorer.time_to_answer_field) + * [time\_to\_answer\_form](#formfyxer.lit_explorer.time_to_answer_form) + * [cleanup\_text](#formfyxer.lit_explorer.cleanup_text) + * [text\_complete](#formfyxer.lit_explorer.text_complete) + * [complete\_with\_command](#formfyxer.lit_explorer.complete_with_command) + * [needs\_calculations](#formfyxer.lit_explorer.needs_calculations) + * [tools\_passive](#formfyxer.lit_explorer.tools_passive) + * [get\_passive\_sentences](#formfyxer.lit_explorer.get_passive_sentences) + * [get\_citations](#formfyxer.lit_explorer.get_citations) + * [get\_sensitive\_data\_types](#formfyxer.lit_explorer.get_sensitive_data_types) + * [substitute\_phrases](#formfyxer.lit_explorer.substitute_phrases) + * [substitute\_neutral\_gender](#formfyxer.lit_explorer.substitute_neutral_gender) + * [substitute\_plain\_language](#formfyxer.lit_explorer.substitute_plain_language) + * [transformed\_sentences](#formfyxer.lit_explorer.transformed_sentences) + * [parse\_form](#formfyxer.lit_explorer.parse_form) + * [form\_complexity](#formfyxer.lit_explorer.form_complexity) + +--- +sidebar_label: lit_explorer +title: formfyxer.lit_explorer +--- + + + +#### recursive\_get\_id(values\_to\_unpack: Union[dict, list], tmpl: Optional[set] = None) + +```python +def recursive_get_id(values_to_unpack: Union[dict, list], + tmpl: Optional[set] = None) +``` + +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 = "") + +```python +def spot(text: str, + lower: float = 0.25, + pred: float = 0.5, + upper: float = 0.6, + verbose: float = 0, + token: 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) + +```python +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) + +```python +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://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/document_variables + + + +#### reformat\_field(text: str, max\_length: int = 30, tools\_token: Optional[str] = None) + +```python +def reformat_field(text: str, + max_length: int = 30, + tools_token: Optional[str] = None) +``` + +Transforms a string of text into a snake_case variable close in length to `max_length` name by +summarizing the string and stitching the summary together in snake_case. +h/t https://towardsdatascience.com/nlp-building-a-summariser-68e0c19e3a93 + + + +#### norm(row) + +```python +def norm(row) +``` + +Normalize a word vector. + + + +#### vectorize(text: Union[List[str], str], tools\_token: Optional[str] = None) + +```python +def vectorize(text: Union[List[str], str], tools_token: Optional[str] = None) +``` + +Vectorize a string of text. + +**Arguments**: + +- `text` - a string of multiple words to vectorize +- `tools_token` - the token to tools.suffolklitlab.org, used for micro-service + to reduce the amount of memory you need on your machine. If + not passed, you need to have `en_core_web_lg` installed. NOTE: this + 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) + +```python +def normalize_name(jur: str, + group: str, + n: int, + per, + last_field: str, + this_field: str, + tools_token: Optional[str] = None) -> Tuple[str, float] +``` + +Normalize a field name, if possible to the Assembly Line conventions, and if +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) + +```python +def cluster_screens(fields: List[str] = [], + damping: float = 0.7, + tools_token: Optional[str] = None) -> Dict[str, List[str]] +``` + +Groups the given fields into screens based on how much they are related. + +**Arguments**: + +- `fields` - a list of field names +- `damping` - a value >= 0.5 and < 1. Tunes how related screens should be +- `tools_token` - the token to tools.suffolklitlab.org, needed of doing + micro-service vectorization + +- `Returns` - a suggested screen grouping, each screen name mapped to the list of fields on it + + + +## InputType Objects + +```python +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]]) + +```python +def field_types_and_sizes( + fields: Optional[Iterable[FormField]]) -> List[FieldInfo] +``` + +Transform the fields provided by get_existing_pdf_fields into a summary format. +Result will look like: +[ +\{ +"var_name": var_name, +"type": "text | checkbox | signature", +"max_length": n +\} +] + + + +## AnswerType Objects + +```python +class AnswerType(Enum) +``` + +Answer type describes the effort the user answering the form will require. +"Slot-in" answers are a matter of almost instantaneous recall, e.g., name, address, etc. +"Gathered" answers require looking around one's desk, for e.g., a health insurance number. +"Third party" answers require picking up the phone to call someone else who is the keeper +of the information. +"Created" answers don't exist before the user is presented with the question. They may include +a choice, creating a narrative, or even applying legal reasoning. "Affidavits" are a special +form of created answers. +See Jarret and Gaffney, Forms That Work (2008) + + + +#### classify\_field(field: FieldInfo, new\_name: str) + +```python +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) + +```python +def get_adjusted_character_count(field: FieldInfo) -> float +``` + +Determines the bracketed length of an input field based on its max_length attribute, +returning a float representing the approximate length of the field content. + +The function chunks the answers into 5 different lengths (checkboxes, 2 words, short, medium, and long) +instead of directly using the character count, as forms can allocate different spaces +for the same data without considering the space the user actually needs. + +**Arguments**: + +- `field` _FieldInfo_ - An object containing information about the input field, + including the "max_length" attribute. + + +**Returns**: + +- `float` - The approximate length of the field content, categorized into checkboxes, 2 words, short, + medium, or long based on the max_length attribute. + + +**Examples**: + + >>> get_adjusted_character_count(\{"type"\}: InputType.CHECKBOX) + 4.7 + >>> get_adjusted_character_count(\{"max_length": 100\}) + 9.4 + >>> get_adjusted_character_count(\{"max_length": 300\}) + 230 + >>> get_adjusted_character_count(\{"max_length": 600\}) + 115 + >>> 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) + +```python +def time_to_answer_field(field: FieldInfo, + new_name: str, + cpm: int = 40, + cpm_std_dev: int = 17) -> Callable[[int], np.ndarray] +``` + +Apply a heuristic for the time it takes to answer the given field, in minutes. +It is hand-written for now. +It will factor in the input type, the answer type (slot in, gathered, third party or created), and the +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) + +```python +def time_to_answer_form(processed_fields, + normalized_fields) -> Tuple[float, float] +``` + +Provide an estimate of how long it would take an average user to respond to the questions +on the provided form. +We use signals such as the field type, name, and space provided for the response to come up with a +rough estimate, based on whether the field is: +1. fill in the blank +2. gathered - e.g., an id number, case number, etc. +3. third party: need to actually ask someone the information - e.g., income of not the user, anything else? +4. created: +a. short created (3 lines or so?) +b. long created (anything over 3 lines) + + + +#### cleanup\_text(text: str, fields\_to\_sentences: bool = False) + +```python +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) + +```python +def text_complete(prompt: str, + max_tokens: int = 500, + creds: Optional[OpenAiCreds] = None, + temperature: float = 0) -> str +``` + +Run a prompt via openAI's API and return the result. + +**Arguments**: + +- `prompt` _str_ - The prompt to send to the API. +- `max_tokens` _int, optional_ - The number of tokens to generate. Defaults to 500. +- `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) + +```python +def complete_with_command(text, + command, + tokens, + creds: Optional[OpenAiCreds] = None) -> str +``` + +Combines some text with a command to send to open ai. + + + +#### needs\_calculations(text: Union[str]) + +```python +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) + +```python +def tools_passive(input: Union[List[str], str], + tools_token: Optional[str] = None) +``` + +Ping passive voice API for list of sentences using the passive voice + + + +#### get\_passive\_sentences(text: Union[List, str], tools\_token: Optional[str] = None) + +```python +def get_passive_sentences( + text: Union[List, str], + tools_token: Optional[str] = None +) -> List[Tuple[str, List[Tuple[int, int]]]] +``` + +Return a list of tuples, where each tuple represents a +sentence in which passive voice was detected along with a list of the +starting and ending position of each fragment that is phrased in the passive voice. +The combination of the two can be used in the PDFStats frontend to highlight the +passive text in an individual sentence. + +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]) + +```python +def get_citations(text: str, tokenized_sentences: List[str]) -> List[str] +``` + +Get citations and some extra surrounding context (the full sentence), if the citation is +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) + +```python +def get_sensitive_data_types( + fields: List[str], + fields_old: Optional[List[str]] = None) -> Dict[str, List[str]] +``` + +Given a list of fields, identify those related to sensitive information and return a dictionary with the sensitive +fields grouped by type. A list of the old field names can also be provided. These fields should be in the same +order. Passing the old field names allows the sensitive field algorithm to match more accurately. The return value +will not contain the old field name, only the corresponding field name from the first parameter. + +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]) + +```python +def substitute_phrases( + input_string: str, + substitution_phrases: Dict[str, + str]) -> Tuple[str, List[Tuple[int, int]]] +``` + +Substitute phrases in the input string and return the new string and positions of substituted phrases. + +**Arguments**: + +- `input_string` _str_ - The input string containing phrases to be replaced. +- `substitution_phrases` _Dict[str, str]_ - A dictionary mapping original phrases to their replacement phrases. + + +**Returns**: + + Tuple[str, List[Tuple[int, int]]]: A tuple containing the new string with substituted phrases and a list of + tuples, each containing the start and end positions of the substituted + phrases in the new string. + + +**Example**: + + >>> input_string = "The quick brown fox jumped over the lazy dog." + >>> substitution_phrases = \{"quick brown": "swift reddish", "lazy dog": "sleepy canine"\} + >>> new_string, positions = substitute_phrases(input_string, substitution_phrases) + >>> print(new_string) + "The swift reddish fox jumped over the sleepy canine." + >>> print(positions) + [(4, 17), (35, 48)] + + + +#### substitute\_neutral\_gender(input\_string: str) + +```python +def substitute_neutral_gender( + input_string: str) -> Tuple[str, List[Tuple[int, int]]] +``` + +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) + +```python +def substitute_plain_language( + input_string: str) -> Tuple[str, List[Tuple[int, int]]] +``` + +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) + +```python +def transformed_sentences( + sentence_list: List[str], + fun: Callable) -> List[Tuple[str, str, List[Tuple[int, int]]]] +``` + +Apply a function to a list of sentences and return only the sentences with changed terms. +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) + +```python +def 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) +``` + +Read in a pdf, pull out basic stats, attempt to normalize its form fields, and re-write the +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) + +```python +def form_complexity(stats) +``` + +Gets a single number of how hard the form is to complete. Higher is harder. + diff --git a/docs/components/formfyxer/pdf_wrangling.md b/docs/components/formfyxer/pdf_wrangling.md new file mode 100644 index 000000000..7268a80d7 --- /dev/null +++ b/docs/components/formfyxer/pdf_wrangling.md @@ -0,0 +1,529 @@ +# Table of Contents + +* [formfyxer.pdf\_wrangling](#formfyxer.pdf_wrangling) + * [FieldType](#formfyxer.pdf_wrangling.FieldType) + * [TEXT](#formfyxer.pdf_wrangling.FieldType.TEXT) + * [AREA](#formfyxer.pdf_wrangling.FieldType.AREA) + * [LIST\_BOX](#formfyxer.pdf_wrangling.FieldType.LIST_BOX) + * [CHOICE](#formfyxer.pdf_wrangling.FieldType.CHOICE) + * [FormField](#formfyxer.pdf_wrangling.FormField) + * [\_\_init\_\_](#formfyxer.pdf_wrangling.FormField.__init__) + * [set\_fields](#formfyxer.pdf_wrangling.set_fields) + * [rename\_pdf\_fields](#formfyxer.pdf_wrangling.rename_pdf_fields) + * [unlock\_pdf\_in\_place](#formfyxer.pdf_wrangling.unlock_pdf_in_place) + * [has\_fields](#formfyxer.pdf_wrangling.has_fields) + * [get\_existing\_pdf\_fields](#formfyxer.pdf_wrangling.get_existing_pdf_fields) + * [swap\_pdf\_page](#formfyxer.pdf_wrangling.swap_pdf_page) + * [copy\_pdf\_fields](#formfyxer.pdf_wrangling.copy_pdf_fields) + * [get\_textboxes\_in\_pdf](#formfyxer.pdf_wrangling.get_textboxes_in_pdf) + * [get\_bracket\_chars\_in\_pdf](#formfyxer.pdf_wrangling.get_bracket_chars_in_pdf) + * [intersect\_bbox](#formfyxer.pdf_wrangling.intersect_bbox) + * [intersect\_bboxs](#formfyxer.pdf_wrangling.intersect_bboxs) + * [contain\_boxes](#formfyxer.pdf_wrangling.contain_boxes) + * [get\_dist\_sq](#formfyxer.pdf_wrangling.get_dist_sq) + * [get\_dist](#formfyxer.pdf_wrangling.get_dist) + * [get\_connected\_edges](#formfyxer.pdf_wrangling.get_connected_edges) + * [bbox\_distance](#formfyxer.pdf_wrangling.bbox_distance) + * [get\_possible\_fields](#formfyxer.pdf_wrangling.get_possible_fields) + * [get\_possible\_checkboxes](#formfyxer.pdf_wrangling.get_possible_checkboxes) + * [get\_possible\_radios](#formfyxer.pdf_wrangling.get_possible_radios) + * [get\_possible\_text\_fields](#formfyxer.pdf_wrangling.get_possible_text_fields) + * [auto\_add\_fields](#formfyxer.pdf_wrangling.auto_add_fields) + * [is\_tagged](#formfyxer.pdf_wrangling.is_tagged) + +--- +sidebar_label: pdf_wrangling +title: formfyxer.pdf_wrangling +--- + + + +## FieldType Objects + +```python +class FieldType(Enum) +``` + + + +#### TEXT + +Text input Field + + + +#### AREA + +Text input Field, but an area + + + +#### LIST\_BOX + +allows multiple selection + + + +#### CHOICE + +allows only one selection + + + +## FormField Objects + +```python +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) + +```python +def __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) +``` + +Constructor + +**Arguments**: + +- `x` - the x position of the lower left corner of the field. Should be in X,Y coordinates, + where (0, 0) is the lower left of the page, x goes to the right, and units are in + points (1/72th of an inch) +- `y` - the y position of the lower left corner of the field. Should be in X,Y coordinates, + where (0, 0) is the lower left of the page, y goes up, and units are in points + (1/72th of an inch) +- `config` - a dictionary containing any keyword argument to the reportlab field functions, + which will vary depending on what type of field this is. See section 4.7 of the + [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) + +```python +def set_fields(in_file: Union[str, Path, BinaryIO], + out_file: Union[str, Path, BinaryIO], + fields_per_page: Iterable[Iterable[FormField]], + *, + overwrite=False) +``` + +Adds fields per page to the in_file PDF, writing the new PDF to a new file. + +Example usage: + +```python +set_fields('no_fields.pdf', 'four_fields_on_second_page.pdf', + [ + [], # nothing on the first page + [ # Second page + FormField('new_field', 'text', 110, 105, configs=\{'width': 200, 'height': 30\}), + # Choice needs value to be one of the possible options, and options to be a list of strings or tuples + FormField('new_choices', 'choice', 110, 400, configs=\{'value': 'Option 1', 'options': ['Option 1', 'Option 2']\}), + # Radios need to have the same name, with different values + FormField('new_radio1', 'radio', 110, 600, configs=\{'value': 'option a'\}), + FormField('new_radio1', 'radio', 110, 500, configs=\{'value': 'option b'\}) + ] + ] +) +``` + +**Arguments**: + +- `in_file` - the input file name or path of a PDF that we're adding the fields to +- `out_file` - the output file name or path where the new version of in_file will + be written. Doesn't need to exist. +- `fields_per_page` - for each page, a series of fields that should be added to that + page. +- `owerwrite` - if the input file already some fields (AcroForm fields specifically) + and this value is true, it will erase those existing fields and just add + `fields_per_page`. If not true and the input file has fields, this won't generate + a PDF, since there isn't currently a way to merge AcroForm fields from + different PDFs. + + +**Returns**: + + Nothing. + + + +#### rename\_pdf\_fields(in\_file: Union[str, Path, BinaryIO], out\_file: Union[str, Path, BinaryIO], mapping: Mapping[str, str]) + +```python +def rename_pdf_fields(in_file: Union[str, Path, BinaryIO], + out_file: Union[str, Path, BinaryIO], + mapping: Mapping[str, str]) -> None +``` + +Given a dictionary that maps old to new field names, rename the AcroForm +field with a matching key to the specified value. + +**Example**: + +```python +rename_pdf_fields('current.pdf', 'new_field_names.pdf', + \{'abc123': 'user1_name', 'abc124', 'user1_address_city'\}) + +Args: + in_file: the filename of an input file + out_file: the filename of the output file. Doesn't need to exist, + will be overwritten if it does exist. + mapping: the python dict that maps from a current field name to the desired name + +Returns: + Nothing + + + +#### unlock\_pdf\_in\_place(in\_file: Union[str, Path, BinaryIO]) + +```python +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) + +```python +def has_fields(pdf_file: str) -> bool +``` + +Check if a PDF has at least one form field using PikePDF. + +**Arguments**: + +- `pdf_file` _str_ - The path to the PDF file. + + +**Returns**: + +- `bool` - True if the PDF has at least one form field, False otherwise. + + + +#### get\_existing\_pdf\_fields(in\_file: Union[str, Path, BinaryIO, Pdf]) + +```python +def get_existing_pdf_fields( + in_file: Union[str, Path, BinaryIO, Pdf]) -> List[List[FormField]] +``` + +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) + +```python +def 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) -> Pdf +``` + +(DEPRECATED: use copy_pdf_fields) Copies the AcroForm fields from one PDF to another blank PDF form. Optionally, choose a starting page for both +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) + +```python +def 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) -> Pdf +``` + +Copies the AcroForm fields from one PDF to another blank PDF form (without AcroForm fields). +Useful for getting started with an updated PDF form, where the old fields are pretty close to where +they should go on the new document. + +Optionally, you can choose a starting page for both +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` + +**Example**: + +```python +new_pdf_with_fields = copy_pdf_fields( + source_pdf="old_pdf.pdf", + destination_pdf="new_pdf_with_no_fields.pdf") +new_pdf_with_fields.save("new_pdf_with_fields.pdf") +``` + + +**Arguments**: + +- `source_pdf` - a file name or path to a PDF that has AcroForm fields +- `destination_pdf` - a file name or path to a PDF without AcroForm fields. Existing fields will be removed. +- `source_offset` - the starting page that fields will be copied from. Defaults to 0. +- `destination_offset` - the starting page that fields will be copied to. Defaults to 0. +- `append_annotations` - controls whether formfyxer will try to append form fields instead of + overwriting. Defaults to false; when enabled may lead to undefined behavior. + + +**Returns**: + + 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) + +```python +def get_textboxes_in_pdf(in_file: Union[str, Path, BinaryIO], + line_margin=0.02, + char_margin=2.0) -> List[List[Textbox]] +``` + +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) + +```python +def get_bracket_chars_in_pdf(in_file: Union[str, Path, BinaryIO], + line_margin=0.02, + char_margin=0.0) -> List +``` + +Gets all of the bracket characters ('[' and ']') found by pdfminer in a PDF, as well as their bounding boxes +TODO: Will eventually be used to find [ ] as checkboxes, but right now we can't tell the difference between [ ] and [i]. +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) + +```python +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) + +```python +def intersect_bboxs(bbox_a, + bboxes, + vert_dilation=2, + horiz_dilation=2) -> Iterable[bool] +``` + +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) + +```python +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) + +```python +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) + +```python +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) + +```python +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) + +```python +def bbox_distance( + bbox_a: BoundingBoxF, bbox_b: BoundingBoxF +) -> Tuple[float, Tuple[XYPair, XYPair], Tuple[XYPair, XYPair]] +``` + +Gets our specific "distance measure" between two different bounding boxes. +This distance is roughly the sum of the horizontal and vertical difference in alignment of +the closest shared field-bounding box edge. We are trying to find which, given a list of text boxes +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) + +```python +def get_possible_fields( + in_pdf_file: Union[str, Path], + textboxes: Optional[List[List[Textbox]]] = None +) -> List[List[FormField]] +``` + +Given an input PDF, runs a series of heuristics to predict where there +might be places for user enterable information (i.e. PDF fields), and returns +those predictions. + +**Example**: + +```python +fields = get_possible_fields('no_field.pdf') +print(fields[0][0]) +# Type: FieldType.TEXT, Name: name, User name: , X: 67.68, Y: 666.0, Configs: \{'fieldFlags': 'doNotScroll', 'width': 239.4, 'height': 16\} +``` + + +**Arguments**: + +- `in_pdf_file` - the input PDF +- `textboxes` _optional_ - the location of various lines of text in the PDF. + If not given, will be calculated automatically. This allows us to + pass through expensive info to calculate through several functions. + + +**Returns**: + + For each page in the input PDF, a list of predicted form fields + + + +#### get\_possible\_checkboxes(img: Union[str, cv2.Mat], find\_small=False) + +```python +def get_possible_checkboxes(img: Union[str, cv2.Mat], + find_small=False) -> Union[np.ndarray, List] +``` + +Uses boxdetect library to determine if there are checkboxes on an image of a PDF page. +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]) + +```python +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) + +```python +def get_possible_text_fields( + img: Union[str, BinaryIO, cv2.Mat], + text_lines: List[Textbox], + default_line_height: int = 44) -> List[Tuple[BoundingBox, int]] +``` + +Uses openCV to attempt to find places where a PDF could expect an input text field. + +Caveats so far: only considers straight, normal horizonal lines that don't touch any vertical lines as fields +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]) + +```python +def auto_add_fields(in_pdf_file: Union[str, Path], out_pdf_file: Union[str, + Path]) +``` + +Uses [get_possible_fields](#formfyxer.pdf_wrangling.get_possible_fields) and +[set_fields](#formfyxer.pdf_wrangling.set_fields) to automatically add new detected fields +to an input PDF. + +**Example**: + +```python +auto_add_fields('no_fields.pdf', 'newly_added_fields.pdf') +``` + + +**Arguments**: + +- `in_pdf_file` - the input file name or path of the PDF where we'll try to find possible fields +- `out_pdf_file` - the output file name or path of the PDF where a new version of `in_pdf_file` will + be stored, with the new fields. Doesn't need to existing, but if a file does exist at that + filename, it will be overwritten. + + +**Returns**: + + Nothing + + + +#### is\_tagged(in\_pdf\_file: Union[str, Path, pikepdf.Pdf]) + +```python +def is_tagged(in_pdf_file: Union[str, Path, pikepdf.Pdf]) -> bool +``` + +Determines if the input PDF file is tagged for accessibility. + +**Arguments**: + +- `in_pdf_file` _Union[str, Path]_ - The path to the PDF file, as a string or a Path object. + + +**Returns**: + +- `bool` - True if the PDF is tagged, False otherwise. + diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml index 7b60d8ff6..c1b0794a9 100644 --- a/pydoc-markdown.yml +++ b/pydoc-markdown.yml @@ -18,8 +18,29 @@ renderer: relative_sidebar_path: sidebar.json sidebar_top_level_label: null markdown: + # Better escaping and HTML handling escape_html_in_docstring: true escape_curly_braces_in_docstring: true - signature_code_block: false + + # Enhanced code and signature formatting + signature_code_block: true + signature_in_header: true + code_headers: false + html_headers: false + + # Better type hints and data rendering render_typehint_in_data_header: true - toc_maxdepth: 6 + + # Enhanced table of contents with proper depth + render_toc: true + toc_maxdepth: 3 + + # Better titles and descriptions + descriptive_class_title: true + descriptive_module_title: false + + # Fixed header levels for better hierarchy + use_fixed_header_levels: true + + # Better anchor insertion + insert_header_anchors: true diff --git a/src/css/custom.css b/src/css/custom.css index 20df0c9ab..73c958b0e 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -294,4 +294,142 @@ html[data-theme="dark"] { .positive { color: var(--ifm-color-success-dark); +} + +/* API Documentation improvements */ + +/* Apply to all auto-generated API documentation pages */ +html[class*="docs-doc-id-components/"] { + /* Better spacing for method sections */ + h4[id*="init"], + h4[id*="__init__"], + h4[id*="all_"], + h4[id*="short_"], + h4[id*="from_"], + h4[id*="geo"], + h4[id*="county"], + h4[id*="matching"], + h4[id*="filter"], + h4[id*="as_"], + h4[id*="unique"] { + margin-top: 2rem; + padding-top: 1rem; + border-top: 1px solid var(--ifm-table-border-color); + } + + /* Better styling for class headings */ + h2[id*="Objects"] code { + background-color: var(--ifm-color-primary-light); + color: white; + padding: 0.2rem 0.5rem; + border-radius: var(--ifm-code-border-radius); + font-weight: bold; + } + + /* Improve code block appearance in method signatures */ + h4 code { + background-color: var(--ifm-code-background); + border: 1px solid var(--ifm-table-border-color); + padding: 0.3rem 0.6rem; + border-radius: var(--ifm-code-border-radius); + font-family: var(--ifm-font-family-monospace); + font-size: 0.9rem; + } + + /* Better styling for argument and return value sections */ + p strong:first-child { + color: var(--ifm-color-primary); + font-size: 1.1rem; + } + + /* Improve parameter lists */ + ul li code:first-child { + background-color: var(--ifm-color-info-contrast-background); + color: var(--ifm-color-info-dark); + padding: 0.1rem 0.3rem; + border-radius: 3px; + font-weight: 600; + } + + /* Better spacing for method descriptions */ + p + p strong { + margin-top: 1rem; + } + + /* Enhance table of contents in right sidebar */ + .table-of-contents { + h4 code, + a code { + background-color: var(--ifm-code-background); + padding: 0.1rem 0.3rem; + border-radius: 3px; + font-size: 0.85rem; + } + + /* Better nesting for class methods */ + li li a { + padding-left: 1rem; + font-size: 0.9rem; + } + } + + /* Improve the main table of contents */ + h1 + ul { + background-color: var(--ifm-color-secondary-contrast-background); + border: 1px solid var(--ifm-table-border-color); + border-radius: var(--ifm-card-border-radius); + padding: 1.5rem; + margin-bottom: 2rem; + + li { + margin-bottom: 0.5rem; + } + + /* Style class names in TOC */ + > li > a { + font-weight: 600; + color: var(--ifm-color-primary); + } + + /* Style method names in TOC */ + li li a { + color: var(--ifm-color-emphasis-700); + font-family: var(--ifm-font-family-monospace); + font-size: 0.9rem; + } + } + + /* Better code block styling */ + pre code { + border-radius: var(--ifm-code-border-radius); + } + + /* Improve signature code blocks */ + .language-python { + margin: 1rem 0; + + .token.keyword { + color: var(--ifm-color-primary); + } + + .token.function { + color: var(--ifm-color-info-dark); + } + + .token.string { + color: var(--ifm-color-success-dark); + } + } +} + +/* Dark mode adjustments for API docs */ +html[data-theme="dark"][class*="docs-doc-id-components/"] { + h2[id*="Objects"] code { + background-color: var(--ifm-color-primary-dark); + } + + ul li code:first-child { + background-color: var(--ifm-color-info-dark); + color: var(--ifm-color-info-contrast-foreground); + } } \ No newline at end of file From 31817a7f09ba15c2f59ea4a2b533946e5085a576 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Tue, 9 Sep 2025 17:28:08 -0400 Subject: [PATCH 4/7] WIP - fix some style issues from Copilot's PR --- docs/components/ALToolbox/al_income.md | 7 +- docs/components/ALToolbox/business_days.md | 7 +- docs/components/ALToolbox/copy_button.md | 7 +- docs/components/ALToolbox/llms.md | 7 +- docs/components/ALToolbox/misc.md | 7 +- docs/components/ALToolbox/save_input_data.md | 7 +- docs/components/AssemblyLine/al_courts.md | 7 +- docs/components/AssemblyLine/al_document.md | 7 +- docs/components/AssemblyLine/al_general.md | 7 +- .../AssemblyLine/custom_jinja_filters.md | 7 +- docs/components/AssemblyLine/language.md | 7 +- docs/components/AssemblyLine/sessions.md | 7 +- docs/components/AssemblyLine/sign.md | 7 +- .../components/EFSPIntegration/conversions.md | 17 ++- docs/components/EFSPIntegration/efm_client.md | 28 +--- .../EFSPIntegration/interview_logic.md | 7 +- .../EFSPIntegration/py_efsp_client.md | 37 +---- docs/components/formfyxer/docx_wrangling.md | 134 ++---------------- docs/components/formfyxer/lit_explorer.md | 79 ++--------- docs/components/formfyxer/pdf_wrangling.md | 7 +- pydoc-markdown.yml | 1 + pydoc-module-header.hbs | 4 + 22 files changed, 51 insertions(+), 354 deletions(-) create mode 100644 pydoc-module-header.hbs diff --git a/docs/components/ALToolbox/al_income.md b/docs/components/ALToolbox/al_income.md index ee254a586..81c20e0e6 100644 --- a/docs/components/ALToolbox/al_income.md +++ b/docs/components/ALToolbox/al_income.md @@ -63,12 +63,7 @@ * [deduction\_total](#ALToolbox.al_income.ALItemizedJobList.deduction_total) * [net\_total](#ALToolbox.al_income.ALItemizedJobList.net_total) ---- -sidebar_label: al_income -title: ALToolbox.al_income ---- - - +pydoc-module-header.hbs #### times\_per\_year(times\_per\_year\_list: List[Tuple[int, str]], times\_per\_year: float) diff --git a/docs/components/ALToolbox/business_days.md b/docs/components/ALToolbox/business_days.md index 4edf85447..728c05323 100644 --- a/docs/components/ALToolbox/business_days.md +++ b/docs/components/ALToolbox/business_days.md @@ -6,12 +6,7 @@ * [get\_next\_business\_day](#ALToolbox.business_days.get_next_business_day) * [get\_date\_after\_n\_business\_days](#ALToolbox.business_days.get_date_after_n_business_days) ---- -sidebar_label: business_days -title: ALToolbox.business_days ---- - - +pydoc-module-header.hbs #### standard\_holidays(year, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) diff --git a/docs/components/ALToolbox/copy_button.md b/docs/components/ALToolbox/copy_button.md index 6c42cc731..4b921fe57 100644 --- a/docs/components/ALToolbox/copy_button.md +++ b/docs/components/ALToolbox/copy_button.md @@ -3,12 +3,7 @@ * [ALToolbox.copy\_button](#ALToolbox.copy_button) * [copy\_button\_html](#ALToolbox.copy_button.copy_button_html) ---- -sidebar_label: copy_button -title: ALToolbox.copy_button ---- - - +pydoc-module-header.hbs #### 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 = "") diff --git a/docs/components/ALToolbox/llms.md b/docs/components/ALToolbox/llms.md index 5d536e4cb..d62815ea8 100644 --- a/docs/components/ALToolbox/llms.md +++ b/docs/components/ALToolbox/llms.md @@ -25,12 +25,7 @@ * [IntakeQuestionList](#ALToolbox.llms.IntakeQuestionList) * [need\_more\_questions](#ALToolbox.llms.IntakeQuestionList.need_more_questions) ---- -sidebar_label: llms -title: ALToolbox.llms ---- - - +pydoc-module-header.hbs #### 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 = False, openai\_base\_url: Optional[str] = None, max\_output\_tokens: Optional[int] = None, max\_input\_tokens: Optional[int] = None) diff --git a/docs/components/ALToolbox/misc.md b/docs/components/ALToolbox/misc.md index 3411cefcd..d3924a9d7 100644 --- a/docs/components/ALToolbox/misc.md +++ b/docs/components/ALToolbox/misc.md @@ -23,12 +23,7 @@ * [age\_in\_years](#ALToolbox.misc.age_in_years) * [format\_date\_if\_defined](#ALToolbox.misc.format_date_if_defined) ---- -sidebar_label: misc -title: ALToolbox.misc ---- - - +pydoc-module-header.hbs #### thousands(num: Union[float, str, Decimal], show\_decimals=False) diff --git a/docs/components/ALToolbox/save_input_data.md b/docs/components/ALToolbox/save_input_data.md index 44ab2f5b9..a86613d1e 100644 --- a/docs/components/ALToolbox/save_input_data.md +++ b/docs/components/ALToolbox/save_input_data.md @@ -3,12 +3,7 @@ * [ALToolbox.save\_input\_data](#ALToolbox.save_input_data) * [save\_input\_data](#ALToolbox.save_input_data.save_input_data) ---- -sidebar_label: save_input_data -title: ALToolbox.save_input_data ---- - - +pydoc-module-header.hbs #### save\_input\_data(title: str = "", input\_dict: Optional[Dict[str, Any]] = None, tags: Optional[List[str]] = None) diff --git a/docs/components/AssemblyLine/al_courts.md b/docs/components/AssemblyLine/al_courts.md index eeb5201b5..882ceb824 100644 --- a/docs/components/AssemblyLine/al_courts.md +++ b/docs/components/AssemblyLine/al_courts.md @@ -20,12 +20,7 @@ * [filter\_courts](#AssemblyLine.al_courts.ALCourtLoader.filter_courts) * [as\_court](#AssemblyLine.al_courts.ALCourtLoader.as_court) ---- -sidebar_label: al_courts -title: AssemblyLine.al_courts ---- - -Package for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now +pydoc-module-header.hbsPackage for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now diff --git a/docs/components/AssemblyLine/al_document.md b/docs/components/AssemblyLine/al_document.md index e2b7bc032..713487f43 100644 --- a/docs/components/AssemblyLine/al_document.md +++ b/docs/components/AssemblyLine/al_document.md @@ -117,12 +117,7 @@ * [ALDocumentUpload](#AssemblyLine.al_document.ALDocumentUpload) * [unpack\_dafilelist](#AssemblyLine.al_document.unpack_dafilelist) ---- -sidebar_label: al_document -title: AssemblyLine.al_document ---- - - +pydoc-module-header.hbs #### random\_suffix(length: int = 8) diff --git a/docs/components/AssemblyLine/al_general.md b/docs/components/AssemblyLine/al_general.md index 1fe4cab75..006d007dd 100644 --- a/docs/components/AssemblyLine/al_general.md +++ b/docs/components/AssemblyLine/al_general.md @@ -74,12 +74,7 @@ * [parse\_custom\_pronouns](#AssemblyLine.al_general.parse_custom_pronouns) * [get\_visible\_al\_nav\_items](#AssemblyLine.al_general.get_visible_al_nav_items) ---- -sidebar_label: al_general -title: AssemblyLine.al_general ---- - - +pydoc-module-header.hbs #### safe\_subdivision\_type(country\_code: str) diff --git a/docs/components/AssemblyLine/custom_jinja_filters.md b/docs/components/AssemblyLine/custom_jinja_filters.md index 0eebcaca3..ce7f9a074 100644 --- a/docs/components/AssemblyLine/custom_jinja_filters.md +++ b/docs/components/AssemblyLine/custom_jinja_filters.md @@ -9,12 +9,7 @@ * [if\_final](#AssemblyLine.custom_jinja_filters.if_final) * [catchall\_fields\_code](#AssemblyLine.custom_jinja_filters.catchall_fields_code) ---- -sidebar_label: custom_jinja_filters -title: AssemblyLine.custom_jinja_filters ---- - - +pydoc-module-header.hbs #### catchall\_options(value: Any, \*raw\_items: Any) diff --git a/docs/components/AssemblyLine/language.md b/docs/components/AssemblyLine/language.md index e08beac65..05fb20183 100644 --- a/docs/components/AssemblyLine/language.md +++ b/docs/components/AssemblyLine/language.md @@ -8,12 +8,7 @@ * [get\_language\_list](#AssemblyLine.language.get_language_list) * [get\_language\_list\_item](#AssemblyLine.language.get_language_list_item) ---- -sidebar_label: language -title: AssemblyLine.language ---- - - +pydoc-module-header.hbs #### get\_local\_languages\_yaml() diff --git a/docs/components/AssemblyLine/sessions.md b/docs/components/AssemblyLine/sessions.md index f48a7d18e..2b6f6fdbb 100644 --- a/docs/components/AssemblyLine/sessions.md +++ b/docs/components/AssemblyLine/sessions.md @@ -30,12 +30,7 @@ * [update\_session\_metadata](#AssemblyLine.sessions.update_session_metadata) * [update\_current\_session\_metadata](#AssemblyLine.sessions.update_current_session_metadata) ---- -sidebar_label: sessions -title: AssemblyLine.sessions ---- - - +pydoc-module-header.hbs #### is\_file\_like(obj: Any) diff --git a/docs/components/AssemblyLine/sign.md b/docs/components/AssemblyLine/sign.md index 1d2e98e14..8edc2f498 100644 --- a/docs/components/AssemblyLine/sign.md +++ b/docs/components/AssemblyLine/sign.md @@ -5,12 +5,7 @@ * [get\_font](#AssemblyLine.sign.get_font) * [create\_signature](#AssemblyLine.sign.create_signature) ---- -sidebar_label: sign -title: AssemblyLine.sign ---- - - +pydoc-module-header.hbs #### find\_font\_file\_by\_name(font\_name: str, search\_dirs: List[str]) diff --git a/docs/components/EFSPIntegration/conversions.md b/docs/components/EFSPIntegration/conversions.md index a722257ed..6325a1ed9 100644 --- a/docs/components/EFSPIntegration/conversions.md +++ b/docs/components/EFSPIntegration/conversions.md @@ -18,19 +18,18 @@ * [filing\_id\_and\_label](#EFSPIntegration.conversions.filing_id_and_label) * [get\_tyler\_roles](#EFSPIntegration.conversions.get_tyler_roles) ---- -sidebar_label: conversions -title: EFSPIntegration.conversions ---- - -Functions that help convert the JSON-ized XML from the proxy server into usable information. +pydoc-module-header.hbsFunctions that help convert the JSON-ized XML from the proxy server into usable information. -#### error\_notification(err, message=None, trace=None, referer=None) +#### error\_notification(err, message=None, trace=None, referer=None, the\_vars=None) ```python -def error_notification(err, message=None, trace=None, referer=None) +def error_notification(err, + message=None, + trace=None, + referer=None, + the_vars=None) ``` Copied from docassemble.webapp.server.error_notification, since: @@ -145,7 +144,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. +returns the datetime it repsents. diff --git a/docs/components/EFSPIntegration/efm_client.md b/docs/components/EFSPIntegration/efm_client.md index 86387fa37..97adb9160 100644 --- a/docs/components/EFSPIntegration/efm_client.md +++ b/docs/components/EFSPIntegration/efm_client.md @@ -1,8 +1,6 @@ # Table of Contents * [EFSPIntegration.efm\_client](#EFSPIntegration.efm_client) - * [DALogger](#EFSPIntegration.efm_client.DALogger) - * [log](#EFSPIntegration.efm_client.DALogger.log) * [ProxyConnection](#EFSPIntegration.efm_client.ProxyConnection) * [\_\_init\_\_](#EFSPIntegration.efm_client.ProxyConnection.__init__) * [authenticate\_user](#EFSPIntegration.efm_client.ProxyConnection.authenticate_user) @@ -10,31 +8,7 @@ * [get\_service\_types](#EFSPIntegration.efm_client.ProxyConnection.get_service_types) * [serialize\_person](#EFSPIntegration.efm_client.serialize_person) ---- -sidebar_label: efm_client -title: EFSPIntegration.efm_client ---- - - - -## DALogger Objects - -```python -class DALogger(LoggerAdapter) -``` - - - -#### log(level, msg, \*args, \*\*kwargs) - -```python -def log(level, msg, *args, **kwargs) -``` - -Delegate a log call to Docassemble's `log` function, after adding -contextual information from this adapter instance. - - +pydoc-module-header.hbs ## ProxyConnection Objects diff --git a/docs/components/EFSPIntegration/interview_logic.md b/docs/components/EFSPIntegration/interview_logic.md index 4c76b1e76..8c9efd27f 100644 --- a/docs/components/EFSPIntegration/interview_logic.md +++ b/docs/components/EFSPIntegration/interview_logic.md @@ -13,12 +13,7 @@ * [filter\_codes](#EFSPIntegration.interview_logic.filter_codes) * [get\_available\_efile\_courts](#EFSPIntegration.interview_logic.get_available_efile_courts) ---- -sidebar_label: interview_logic -title: EFSPIntegration.interview_logic ---- - -A group of methods that were code blocks in various parts of the EFSP +pydoc-module-header.hbsA group of methods that were code blocks in various parts of the EFSP package, but for better python tooling support, were moved here. diff --git a/docs/components/EFSPIntegration/py_efsp_client.md b/docs/components/EFSPIntegration/py_efsp_client.md index 805abcbf7..5416129f4 100644 --- a/docs/components/EFSPIntegration/py_efsp_client.md +++ b/docs/components/EFSPIntegration/py_efsp_client.md @@ -1,8 +1,6 @@ # Table of Contents * [EFSPIntegration.py\_efsp\_client](#EFSPIntegration.py_efsp_client) - * [CORR\_ID\_HEADER](#EFSPIntegration.py_efsp_client.CORR_ID_HEADER) - * [LoggerWithContext](#EFSPIntegration.py_efsp_client.LoggerWithContext) * [EfspConnection](#EFSPIntegration.py_efsp_client.EfspConnection) * [\_\_init\_\_](#EFSPIntegration.py_efsp_client.EfspConnection.__init__) * [authenticate\_user](#EFSPIntegration.py_efsp_client.EfspConnection.authenticate_user) @@ -18,33 +16,10 @@ * [get\_service\_types](#EFSPIntegration.py_efsp_client.EfspConnection.get_service_types) * [get\_cases\_raw](#EFSPIntegration.py_efsp_client.EfspConnection.get_cases_raw) ---- -sidebar_label: py_efsp_client -title: EFSPIntegration.py_efsp_client ---- - -The base python client used to communicate with the E-file proxy server. +pydoc-module-header.hbsThe 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. - - -#### CORR\_ID\_HEADER - -TODO(brycew): Figure out how to add - - - -## LoggerWithContext Objects - -```python -class LoggerWithContext(LoggerAdapter) -``` - -Acts like the `merge_extra` feature from LoggerAdapter (python 3.13) is always on. - -See https://github.com/python/cpython/pull/107292/files. - ## EfspConnection Objects @@ -57,14 +32,10 @@ A python client that communicates with the E-file proxy server. -#### \_\_init\_\_(\*, url: str, api\_key: str, default\_jurisdiction: str = None, logger=None) +#### \_\_init\_\_(\*, url: str, api\_key: str, default\_jurisdiction: str = None) ```python -def __init__(*, - url: str, - api_key: str, - default_jurisdiction: str = None, - logger=None) +def __init__(*, url: str, api_key: str, default_jurisdiction: str = None) ``` **Arguments**: @@ -223,6 +194,6 @@ provided at a time. Params: court_id (str) person_name (dict) -business_name (str) +buisness_name (str) docket_number (str) diff --git a/docs/components/formfyxer/docx_wrangling.md b/docs/components/formfyxer/docx_wrangling.md index a444a2602..dfc7e2ff5 100644 --- a/docs/components/formfyxer/docx_wrangling.md +++ b/docs/components/formfyxer/docx_wrangling.md @@ -2,40 +2,24 @@ * [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) - * [get\_modified\_docx\_runs](#formfyxer.docx_wrangling.get_modified_docx_runs) - * [make\_docx\_plain\_language](#formfyxer.docx_wrangling.make_docx_plain_language) * [modify\_docx\_with\_openai\_guesses](#formfyxer.docx_wrangling.modify_docx_with_openai_guesses) ---- -sidebar_label: docx_wrangling -title: formfyxer.docx_wrangling ---- +pydoc-module-header.hbs - - -#### update\_docx(document: Union[docx.document.Document, str], modified\_runs: List[Tuple[int, int, str, int]]) +#### update\_docx(document: docx.Document, modified\_runs: Tuple[int,int,str,str,int]) ```python def update_docx( - document: Union[docx.document.Document, str], - modified_runs: List[Tuple[int, int, str, - int]]) -> docx.document.Document + document: docx.Document, modified_runs: Tuple[int, int, str, str, + int]) -> docx.Document ``` Update the document with the modified runs. -Note: OpenAI is probabilistic, so the modified run indices may not be correct. -When the index of a run or paragraph is out of range, a new paragraph -will be inserted at the end of the document or a new run at the end of the -paragraph's runs. - -Take a careful look at the output document to make sure it is still correct. - **Arguments**: -- `document` - the docx.Document object, or the path to the DOCX file +- `document` - the docx.Document object - `modified_runs` - a tuple of paragraph number, run number, the modified text, a question (not used), and whether a new paragraph should be inserted (for conditional text) @@ -43,38 +27,15 @@ 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) - -```python -def get_docx_repr(docx_path: str, - paragraph_start: int = 0, - paragraph_end: Optional[int] = None) -``` - -Return a JSON representation of the paragraphs and runs in the DOCX file. - -**Arguments**: - -- `docx_path` - path to the DOCX file - - -**Returns**: - - 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: str, custom\_people\_names: Optional[Tuple[str, str]] = None) ```python def 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) -> List[Tuple[int, int, str, int]] + docx_path: str, + custom_people_names: Optional[Tuple[str, str]] = None +) -> List[Tuple[int, int, str]] ``` Scan the DOCX and return a list of modified text with Jinja2 variable names inserted. @@ -82,7 +43,6 @@ Scan the DOCX and return a list of modified text with Jinja2 variable names inse **Arguments**: - `docx_path` - path to the DOCX file -- `docx_repr` - a string representation of the paragraphs and runs in the DOCX file, if docx_path is not provided. This might be useful if you want - `custom_people_names` - a tuple of custom names and descriptions to use in addition to the default ones. Like: ("clients", "the person benefiting from the form") @@ -90,86 +50,12 @@ 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) - -```python -def 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) -> List[Tuple[int, int, str, int]] -``` - -Use GPT to rewrite the contents of a DOCX file paragraph by paragraph. Does not handle tables, footers, or -other structures yet. - -This is a light wrapper that provides the structure of DOCX paragraphs and runs to your prompt -to OpenAI to facilitate the rewriting of the document without disrupting formatting. - -For example, this could be used to: -* Remove any passive voice -* Replace placeholder text with variable names -* Rewrite to a 6th grade reading level -* Do an advanced search and replace, without requiring you to use a regex - -By default, the example prompt includes a sample like this: - -[ -[0, 0, "Dear "], -[0, 1, "John Smith:"], -[1, 0, "I hope this letter finds you well."], -] - -Your custom instructions should include an example of how the sample will be modified, like the one below: - -Example reply, indicating paragraph, run, the new text, and a number indicating if this changes the -current paragraph, adds one before, or adds one after (-1, 0, 1): - -\{"results": -[ -[0, 1, "Dear \{\{ other_parties[0] \}\}:", 0], -[2, 0, "\{%p if is_tenant %\}", -1], -[3, 0, "\{%p endif %\}", 1], -] -\} - -You may also want to customize the input example to better match your use case. - -**Arguments**: - -- `docx_path` _str_ - path to the DOCX file -- `docx_repr` _str_ - a string representation of the paragraphs and runs in the DOCX file, if docx_path is not provided. -- `custom_example` _Optional[str]_ - a string containing the purpose and overview of the task - instructions (str) a string containing specific instructions for the task -- `openai_client` _Optional[OpenAI]_ - an OpenAI client object. If not provided a new one will be created. -- `api_key` _Optional[str]_ - an OpenAI API key. If not provided, it will be obtained from the environment -- `temperature` _float_ - the temperature to use when generating text. Lower temperatures are more conservative. - - -**Returns**: - - 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) - -```python -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) ```python -def modify_docx_with_openai_guesses(docx_path: str) -> docx.document.Document +def modify_docx_with_openai_guesses(docx_path: str) -> docx.Document ``` Uses OpenAI to guess the variable names for a document and then modifies the document with the guesses. diff --git a/docs/components/formfyxer/lit_explorer.md b/docs/components/formfyxer/lit_explorer.md index bd2548754..ec13526a9 100644 --- a/docs/components/formfyxer/lit_explorer.md +++ b/docs/components/formfyxer/lit_explorer.md @@ -18,13 +18,10 @@ * [time\_to\_answer\_field](#formfyxer.lit_explorer.time_to_answer_field) * [time\_to\_answer\_form](#formfyxer.lit_explorer.time_to_answer_form) * [cleanup\_text](#formfyxer.lit_explorer.cleanup_text) - * [text\_complete](#formfyxer.lit_explorer.text_complete) * [complete\_with\_command](#formfyxer.lit_explorer.complete_with_command) * [needs\_calculations](#formfyxer.lit_explorer.needs_calculations) - * [tools\_passive](#formfyxer.lit_explorer.tools_passive) * [get\_passive\_sentences](#formfyxer.lit_explorer.get_passive_sentences) * [get\_citations](#formfyxer.lit_explorer.get_citations) - * [get\_sensitive\_data\_types](#formfyxer.lit_explorer.get_sensitive_data_types) * [substitute\_phrases](#formfyxer.lit_explorer.substitute_phrases) * [substitute\_neutral\_gender](#formfyxer.lit_explorer.substitute_neutral_gender) * [substitute\_plain\_language](#formfyxer.lit_explorer.substitute_plain_language) @@ -32,12 +29,7 @@ * [parse\_form](#formfyxer.lit_explorer.parse_form) * [form\_complexity](#formfyxer.lit_explorer.form_complexity) ---- -sidebar_label: lit_explorer -title: formfyxer.lit_explorer ---- - - +pydoc-module-header.hbs #### recursive\_get\_id(values\_to\_unpack: Union[dict, list], tmpl: Optional[set] = None) @@ -87,12 +79,10 @@ See: https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/docum -#### reformat\_field(text: str, max\_length: int = 30, tools\_token: Optional[str] = None) +#### reformat\_field(text: str, max\_length: int = 30, tools\_token=None) ```python -def reformat_field(text: str, - max_length: int = 30, - tools_token: Optional[str] = None) +def reformat_field(text: str, max_length: int = 30, tools_token=None) ``` Transforms a string of text into a snake_case variable close in length to `max_length` name by @@ -124,9 +114,7 @@ Vectorize a string of text. - `text` - a string of multiple words to vectorize - `tools_token` - the token to tools.suffolklitlab.org, used for micro-service to reduce the amount of memory you need on your machine. If - not passed, you need to have `en_core_web_lg` installed. NOTE: this - last bit is nolonger correct, you have to use the micor-service - as we have had to remove SpaCY due to a breaking change + not passed, you need to have `en_core_web_lg` installed @@ -315,26 +303,6 @@ 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) - -```python -def text_complete(prompt: str, - max_tokens: int = 500, - creds: Optional[OpenAiCreds] = None, - temperature: float = 0) -> str -``` - -Run a prompt via openAI's API and return the result. - -**Arguments**: - -- `prompt` _str_ - The prompt to send to the API. -- `max_tokens` _int, optional_ - The number of tokens to generate. Defaults to 500. -- `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) @@ -350,35 +318,22 @@ Combines some text with a command to send to open ai. -#### needs\_calculations(text: Union[str]) +#### needs\_calculations(text: Union[str, Doc]) ```python -def needs_calculations(text: Union[str]) -> bool +def needs_calculations(text: Union[str, Doc]) -> 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) - -```python -def tools_passive(input: Union[List[str], str], - tools_token: Optional[str] = None) -``` - -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]) ```python def get_passive_sentences( - text: Union[List, str], - tools_token: Optional[str] = None -) -> List[Tuple[str, List[Tuple[int, int]]]] + text: Union[List, str]) -> List[Tuple[str, List[Tuple[int, int]]]] ``` Return a list of tuples, where each tuple represents a @@ -403,24 +358,6 @@ 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) - -```python -def get_sensitive_data_types( - fields: List[str], - fields_old: Optional[List[str]] = None) -> Dict[str, List[str]] -``` - -Given a list of fields, identify those related to sensitive information and return a dictionary with the sensitive -fields grouped by type. A list of the old field names can also be provided. These fields should be in the same -order. Passing the old field names allows the sensitive field algorithm to match more accurately. The return value -will not contain the old field name, only the corresponding field name from the first parameter. - -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]) diff --git a/docs/components/formfyxer/pdf_wrangling.md b/docs/components/formfyxer/pdf_wrangling.md index 7268a80d7..6d82c3e49 100644 --- a/docs/components/formfyxer/pdf_wrangling.md +++ b/docs/components/formfyxer/pdf_wrangling.md @@ -31,12 +31,7 @@ * [auto\_add\_fields](#formfyxer.pdf_wrangling.auto_add_fields) * [is\_tagged](#formfyxer.pdf_wrangling.is_tagged) ---- -sidebar_label: pdf_wrangling -title: formfyxer.pdf_wrangling ---- - - +pydoc-module-header.hbs ## FieldType Objects diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml index c1b0794a9..66a41cc1e 100644 --- a/pydoc-markdown.yml +++ b/pydoc-markdown.yml @@ -44,3 +44,4 @@ renderer: # Better anchor insertion insert_header_anchors: true + render_module_header_template: "pydoc-module-header.hbs" diff --git a/pydoc-module-header.hbs b/pydoc-module-header.hbs new file mode 100644 index 000000000..1d343774d --- /dev/null +++ b/pydoc-module-header.hbs @@ -0,0 +1,4 @@ +--- +sidebar_label: "{{ module.name }}" +title: "{{ module.name }}" +--- From 7cf022e820082afb2969abf1a9cf4ef1f0901cb7 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Wed, 10 Sep 2025 10:08:08 -0400 Subject: [PATCH 5/7] Worked through several quirky nuances; now in good shape as an improved auto code layout --- .github/workflows/deploy.yml | 1 + .github/workflows/test-deploy.yml | 1 + docs/components/ALToolbox/al_income.md | 151 ++--- docs/components/ALToolbox/business_days.md | 17 +- docs/components/ALToolbox/copy_button.md | 9 +- docs/components/ALToolbox/llms.md | 79 +-- docs/components/ALToolbox/misc.md | 85 +-- docs/components/ALToolbox/save_input_data.md | 7 +- docs/components/AssemblyLine/al_courts.md | 81 +-- docs/components/AssemblyLine/al_document.md | 587 +++++++++--------- docs/components/AssemblyLine/al_general.md | 345 +++++----- .../AssemblyLine/custom_jinja_filters.md | 88 +-- docs/components/AssemblyLine/language.md | 39 +- docs/components/AssemblyLine/sessions.md | 159 ++--- docs/components/AssemblyLine/sign.md | 21 +- .../components/EFSPIntegration/conversions.md | 57 +- docs/components/EFSPIntegration/efm_client.md | 15 +- .../EFSPIntegration/interview_logic.md | 25 +- .../EFSPIntegration/py_efsp_client.md | 35 +- .../EFSPIntegration/test/test_proxy_conn.md | 2 +- docs/components/formfyxer/docx_wrangling.md | 146 ++++- docs/components/formfyxer/lit_explorer.md | 133 ++-- docs/components/formfyxer/pdf_wrangling.md | 85 +-- pydoc-markdown.yml | 1 - pydoc-module-header.hbs | 11 +- 25 files changed, 1162 insertions(+), 1018 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 94edfbe0d..4b6ab5073 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -42,6 +42,7 @@ jobs: run: | cd docs pydoc-markdown + ./fix-doc-titles.sh - uses: actions/setup-node@v3 with: node-version: 20 diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index bfbe7a881..c6cfbd79b 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -42,6 +42,7 @@ jobs: run: | cd docs pydoc-markdown + ./fix-doc-titles.sh - uses: actions/setup-node@v3 with: node-version: 20 diff --git a/docs/components/ALToolbox/al_income.md b/docs/components/ALToolbox/al_income.md index 81c20e0e6..bddad4afe 100644 --- a/docs/components/ALToolbox/al_income.md +++ b/docs/components/ALToolbox/al_income.md @@ -1,4 +1,4 @@ -# Table of Contents +# ALToolbox.al_income * [ALToolbox.al\_income](#ALToolbox.al_income) * [times\_per\_year](#ALToolbox.al_income.times_per_year) @@ -63,9 +63,10 @@ * [deduction\_total](#ALToolbox.al_income.ALItemizedJobList.deduction_total) * [net\_total](#ALToolbox.al_income.ALItemizedJobList.net_total) -pydoc-module-header.hbs -#### times\_per\_year(times\_per\_year\_list: List[Tuple[int, str]], times\_per\_year: float) + + +### times\_per\_year ```python def times_per_year(times_per_year_list: List[Tuple[int, str]], @@ -96,7 +97,7 @@ the nearest whole integer. -#### recent\_years(past: int = 25, order: str = "descending", future: int = 1) +### recent\_years ```python def recent_years(past: int = 25, @@ -127,7 +128,7 @@ Represents an amount (could be an income or an expense depending on the context) that reoccurs some times per year. E.g, to express a weekly period, use 52. The default is 1 (a year). -**Attributes**: +#### Attributes .value \{str | float | Decimal\} A number representing an amount of money accumulated during the `times_per_year` of this income. @@ -139,7 +140,7 @@ is 1 (a year). -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -149,7 +150,7 @@ Returns the income's `.total()` as string, not its object name. -#### total(times\_per\_year: float = 1) +### total ```python def total(times_per_year: float = 1) -> Decimal @@ -172,7 +173,7 @@ incomes must include hours per period (times per year). Period is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year). -**Attributes**: +#### Attributes .value \{str | float | Decimal\} A number representing an amount of money accumulated during the `times_per_year` of this income. @@ -188,7 +189,7 @@ is 1 (a year). -#### total(times\_per\_year: float = 1) +### total ```python def total(times_per_year: float = 1) -> Decimal @@ -231,7 +232,7 @@ use of these attributes and methods in its items: -#### sources() +### sources ```python def sources() -> Set[str] @@ -241,7 +242,7 @@ Returns a set of the unique sources in the ALIncomeList. -#### matches(source: SourceType, exclude\_source: Optional[SourceType] = None) +### matches ```python def matches(source: SourceType, @@ -254,7 +255,7 @@ may be a list. -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) +### total ```python def total(times_per_year: float = 1, @@ -273,7 +274,7 @@ exclude deductions. -#### move\_checks\_to\_list(selected\_types: Optional[DADict] = None, selected\_terms: Optional[Mapping] = None) +### move\_checks\_to\_list ```python def move_checks_to_list(selected_types: Optional[DADict] = None, @@ -305,7 +306,7 @@ user must enter the total amount for "net" and "gross" incom Can be stored in an ALJobList. -**Attributes**: +#### Attributes .value \{float | Decimal\} A number representing an amount of money accumulated during the `times_per_year` of this income. @@ -324,7 +325,7 @@ Can be stored in an ALJobList. -#### gross\_total(times\_per\_year: float = 1) +### gross\_total ```python def gross_total(times_per_year: float = 1) -> Decimal @@ -338,7 +339,7 @@ period, use 52. The default is 1 (a year). -#### deductions(times\_per\_year: float = 1) +### deductions ```python def deductions(times_per_year: float = 1) -> Decimal @@ -352,7 +353,7 @@ period, use 52. The default is 1 (a year). -#### net\_total(times\_per\_year: float = 1) +### net\_total ```python def net_total(times_per_year: float = 1) -> Decimal @@ -371,7 +372,7 @@ This will force the gathering of the ALJob's `.value` and `.deduction` attr -#### employer\_name\_address\_phone() +### employer\_name\_address\_phone ```python def employer_name_address_phone() -> str @@ -383,7 +384,7 @@ attributes. -#### normalized\_hours(times\_per\_year: float = 1) +### normalized\_hours ```python def normalized_hours(times_per_year: float = 1) -> float @@ -415,7 +416,7 @@ way of reporting income than ALItemizedJobList. -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, owner: Optional[str] = None) +### total ```python def total(times_per_year: float = 1, @@ -433,7 +434,7 @@ 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 ```python def gross_total(times_per_year: float = 1, @@ -450,7 +451,7 @@ period, use 52. The default is 1 (a year). -#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### net\_total ```python def net_total(times_per_year: float = 1, @@ -470,7 +471,7 @@ period, use 52. The default is 1 (a year). -#### deductions(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### deductions ```python def deductions(times_per_year: float = 1, @@ -511,7 +512,7 @@ asset represents a financial account rather than a physical asset. Can be stored in an ALAssetList. -**Attributes**: +#### Attributes .market_value \{float | Decimal\} Market value of the asset. .balance \{float | Decimal \} Current balance of the account, e.g., like @@ -528,7 +529,7 @@ Can be stored in an ALAssetList. -#### total(times\_per\_year: float = 1) +### total ```python def total(times_per_year: float = 1) -> Decimal @@ -538,18 +539,18 @@ Returns the .value attribute divided by the times per year you want to calculate `times_per_year` is some denominator of a year. E.g, to express a weekly period, use 52. The default is 1 (a year). -**Arguments**: +#### Arguments - `times_per_year` _float, optional_ - The number of times per year to calculate. Defaults to 1. -**Returns**: +#### Returns - `Decimal` - The .value attribute divided by the times per year. -#### equity(loan\_attribute="balance") +### equity ```python def equity(loan_attribute="balance") -> Decimal @@ -557,12 +558,12 @@ def equity(loan_attribute="balance") -> Decimal Returns the total equity in the asset (e.g., market value minus balance). -**Arguments**: +#### Arguments - `loan_attribute` _str, optional_ - The attribute of the asset to use as the loan value. Defaults to "balance". -**Returns**: +#### Returns - `Decimal` - The total equity in the asset. @@ -578,7 +579,7 @@ A list of ALAssets. The `total()` of the list will be the total income earned, which may not be what you want for a list of assets. To get the total value of all assets, use the `market_value()` method. -**Attributes**: +#### Attributes - `market_value` _float | Decimal_ - Market value of the asset. - `balance` _float | Decimal_ - Current balance of the account, e.g., like @@ -595,7 +596,7 @@ total value of all assets, use the `market_value()` method. -#### market\_value(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### market\_value ```python def market_value(source: Optional[SourceType] = None, @@ -606,7 +607,7 @@ Returns the total `.market_value` of assets in the list. You can filter the assets by `source`. `source` can be a string or a list. -**Arguments**: +#### Arguments - `source` _Optional[SourceType]_ - The source of the assets to include in the calculation. If None, all sources are included. Can be a string or a list. @@ -614,13 +615,13 @@ You can filter the assets by `source`. `source` can be a string or a list. If None, no sources are excluded. -**Returns**: +#### Returns - `Decimal` - The total market value of the assets. -#### balance(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### balance ```python def balance(source: Optional[SourceType] = None, @@ -631,7 +632,7 @@ Returns the total `.balance` of assets in the list, which typically corresponds You can filter the assets by `source`. `source` can be a string or a list. -**Arguments**: +#### Arguments - `source` _Optional[SourceType]_ - The source of the assets to include in the calculation. If None, all sources are included. Can be a string or a list. @@ -639,13 +640,13 @@ You can filter the assets by `source`. `source` can be a string or a list. If None, no sources are excluded. -**Returns**: +#### Returns - `Decimal` - The total balance of the assets. -#### equity(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None, loan\_attribute: str = "balance") +### equity ```python def equity(source: Optional[SourceType] = None, @@ -658,20 +659,20 @@ Calculates and returns the total equity in the assets. This method triggers the gathering of assets, then iterates over each asset. If a source or exclude_source is not specified, or if the asset's source satisfies the source criteria, the equity of the asset is added to the total. -**Arguments**: +#### Arguments - `source` _Optional[SourceType]_ - The source of the assets to include in the calculation. If None, all sources are included. - `exclude_source` _Optional[SourceType]_ - The source of the assets to exclude from the calculation. If None, no sources are excluded. - `loan_attribute` _str, optional_ - The attribute of the asset to use as the loan value. Defaults to "balance". -**Returns**: +#### Returns - `Decimal` - The total equity in the assets. -#### owners(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### owners ```python def owners(source: Optional[SourceType] = None, @@ -682,7 +683,7 @@ Returns a set of the unique owners of the assets. You can filter the assets by `source`. `source` can be a string or a list. -**Arguments**: +#### Arguments - `source` _Optional[SourceType]_ - The source of the assets to include in the calculation. If None, all sources are included. Can be a string or a list. @@ -690,7 +691,7 @@ You can filter the assets by `source`. `source` can be a string or a list. If None, no sources are excluded. -**Returns**: +#### Returns - `Set[str]` - A set of the unique owners of the assets. @@ -709,7 +710,7 @@ such as year, make, and model, and includes methods for representing these attributes in a standardized format, as often required on financial statement forms. -**Attributes**: +#### Attributes - `year` _str_ - The model year of the vehicle, e.g., '2022'. - `make` _str_ - The make of the vehicle, e.g., 'Honda'. @@ -723,7 +724,7 @@ statement forms. -#### year\_make\_model(separator: str = " / ") +### year\_make\_model ```python def year_make_model(separator: str = " / ") -> str @@ -732,12 +733,12 @@ def year_make_model(separator: str = " / ") -> str Returns a string of the format year/make/model of the vehicle. Triggers gathering those attributes. -**Arguments**: +#### Arguments separator \{str\} (Optional) The separator between the year, make and model. -**Returns**: +#### Returns A string of the format year/make/model of the vehicle. @@ -762,7 +763,7 @@ class ALSimpleValue(DAObject) Represents a currency value. It's meant to be stored in a list. Can be an item in an ALSimpleValueList. -**Attributes**: +#### Attributes .value \{str | float \} The monetary value of the item. .transaction_type \{str\} (Optional) Can be "expense", which will give a @@ -771,7 +772,7 @@ item in an ALSimpleValueList. -#### total() +### total ```python def total() -> Decimal @@ -786,7 +787,7 @@ object. The `total()` method may return unexpected results in that case. -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -806,7 +807,7 @@ Represents a filterable DAList of ALSimpleValues. -#### sources() +### sources ```python def sources() -> Set @@ -816,7 +817,7 @@ Returns a set of the unique sources of values stored in the list. -#### total(source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### total ```python def total(source: Optional[SourceType] = None, @@ -843,7 +844,7 @@ WARNING: This item's period-based value can't be calculated correctly outside of an ALItemizedJob. Its value should only be accessed through the filtering methods of the ALItemizedJob that contains it. -**Attributes**: +#### Attributes .value \{float | Decimal\} A number representing an amount of money accumulated during the `times_per_year` of this item or this item's job. @@ -859,7 +860,7 @@ filtering methods of the ALItemizedJob that contains it. -#### income\_fields(use\_exists=True) +### income\_fields ```python def income_fields(use_exists=True) -> List[Dict[str, Any]] @@ -870,7 +871,7 @@ to be passed to a `code` attribute of a question's fields -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -897,7 +898,7 @@ you may get unexpected results. -#### hook\_after\_gather() +### hook\_after\_gather ```python def hook_after_gather() -> None @@ -913,7 +914,7 @@ they can use similar code in their question's `validation code:` -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -949,7 +950,7 @@ If the financial statement only requires "gross" and "net" i ALJobList has a simpler API and may be the preferred way to represent the income in code. -**Attributes**: +#### Attributes .to_add \{ALItemizedValueDict\} Dict of ALItemizedValues that would be added to a job's net total, like wages and tips. @@ -985,7 +986,7 @@ income in code. -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### total ```python def total(times_per_year: float = 1, @@ -997,7 +998,7 @@ Alias for ALItemizedJob.gross_total to integrate with ALIncomeList math. -#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### gross\_total ```python def gross_total(times_per_year: float = 1, @@ -1009,7 +1010,7 @@ Returns the sum of positive values (payments) for a given times_per_year. You can filter the items by `source`. `source` can be a string or a list. If you use sources from deductions, they will be ignored. -**Arguments**: +#### Arguments - `kwarg` - times_per_year \{float\} (Optional) Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Default is 1. @@ -1018,7 +1019,7 @@ If you use sources from deductions, they will be ignored. -#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### deduction\_total ```python def deduction_total(times_per_year: float = 1, @@ -1030,7 +1031,7 @@ Returns the sum of money going out (normally, deductions like union dues) divided by a pay times_per_year as a positive value. You can filter the items by `source`. `source` can be a string or a list. -**Arguments**: +#### Arguments - `kwarg` - times_per_year \{float\} (Optional) Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Default is 1. @@ -1039,7 +1040,7 @@ filter the items by `source`. `source` can be a string or a list. -#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### net\_total ```python def net_total(times_per_year: float = 1, @@ -1051,7 +1052,7 @@ Returns the net (gross minus deductions) value of the job divided by `times_per_year`. You can filter the items by `source`. `source` can be a string or a list. E.g. "full time" or ["full time", "union dues"] -**Arguments**: +#### Arguments - `kwarg` - times_per_year \{float\} (Optional) Number of times per year you want to calculate. E.g, to express a weekly period, use 52. Default is 1. @@ -1060,7 +1061,7 @@ string or a list. E.g. "full time" or ["full time", "un -#### employer\_name\_address\_phone() +### employer\_name\_address\_phone ```python def employer_name_address_phone() -> str @@ -1071,7 +1072,7 @@ address and phone number. -#### normalized\_hours(times\_per\_year: float = 1) +### normalized\_hours ```python def normalized_hours(times_per_year: float = 1) -> float @@ -1096,7 +1097,7 @@ out. This is a less common way of reporting income. -#### sources(which\_side: Optional[str] = None) +### sources ```python def sources(which_side: Optional[str] = None) -> Set[str] @@ -1107,7 +1108,7 @@ By default gets from both sides, if which_side is "deductions", only g -#### total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### total ```python def total(times_per_year: float = 1, @@ -1120,7 +1121,7 @@ ALIncomeList math. -#### gross\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### gross\_total ```python def gross_total(times_per_year: float = 1, @@ -1132,7 +1133,7 @@ Returns the sum of the gross incomes of the list's jobs divided by the times_per_year. You can filter the items by `source`. `source` can be a string or a list. -**Arguments**: +#### Arguments - `kwarg` - source \{str | [str]\} - (Optional) Source or list of sources of desired job items to sum from every itemized job. @@ -1142,7 +1143,7 @@ string or a list. -#### deduction\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### deduction\_total ```python def deduction_total(times_per_year: float = 1, @@ -1154,7 +1155,7 @@ Returns the sum of the deductions of the list's jobs divided by the times_per_year. You can filter the items by `source`. `source` can be a string or a list. -**Arguments**: +#### Arguments - `kwarg` - source \{str | [str]\} - (Optional) Source or list of sources of desired job items to sum from every itemized job. @@ -1164,7 +1165,7 @@ string or a list. -#### net\_total(times\_per\_year: float = 1, source: Optional[SourceType] = None, exclude\_source: Optional[SourceType] = None) +### net\_total ```python def net_total(times_per_year: float = 1, @@ -1176,7 +1177,7 @@ Returns the net of the list's jobs (money in minus money out) divided by the times_per_year. You can filter the items by `source`. `source` can be a string or a list. -**Arguments**: +#### Arguments - `kwarg` - source \{str | List[str]\} - (Optional) Source or list of sources of desired job items to sum from every itemized job. diff --git a/docs/components/ALToolbox/business_days.md b/docs/components/ALToolbox/business_days.md index 728c05323..0ee57f76c 100644 --- a/docs/components/ALToolbox/business_days.md +++ b/docs/components/ALToolbox/business_days.md @@ -1,4 +1,4 @@ -# Table of Contents +# ALToolbox.business_days * [ALToolbox.business\_days](#ALToolbox.business_days) * [standard\_holidays](#ALToolbox.business_days.standard_holidays) @@ -6,9 +6,10 @@ * [get\_next\_business\_day](#ALToolbox.business_days.get_next_business_day) * [get\_date\_after\_n\_business\_days](#ALToolbox.business_days.get_date_after_n_business_days) -pydoc-module-header.hbs -#### standard\_holidays(year, country="US", subdiv="MA", add\_holidays: Optional[Mapping] = None, remove\_holidays: Optional[Iterable[str]] = None) + + +### standard\_holidays ```python def standard_holidays( @@ -41,7 +42,7 @@ the keys are datetime.date objects. -#### 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 ```python def is_business_day(date: Union[str, DADateTime], @@ -64,7 +65,7 @@ assert(is_business_day("2023-03-26") == False) -#### 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 ```python def get_next_business_day( @@ -86,7 +87,7 @@ holidays around the world and in various states and provinces, but local court rules may differ. You can see what holidays are used at https://github.com/dr-prodigy/python-holidays/tree/master/holidays/countries -**Arguments**: +#### Arguments - `start_date` - the date to start with. Can be a date-formatted string (i.e. "2023-03-37", or "3-27-2023") or a DADateTime object @@ -100,7 +101,7 @@ https://github.com/dr-prodigy/python-holidays/tree/master/holidays/countries -#### 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 ```python def get_date_after_n_business_days( @@ -114,7 +115,7 @@ def get_date_after_n_business_days( Returns a time period which contains a minimum of `n` business days. -**Arguments**: +#### Arguments - `start_date` - the date to start with. Can be a date-formatted string (i.e. "2023-03-37", or "3-27-2023") or a DADateTime object diff --git a/docs/components/ALToolbox/copy_button.md b/docs/components/ALToolbox/copy_button.md index 4b921fe57..c37110d7f 100644 --- a/docs/components/ALToolbox/copy_button.md +++ b/docs/components/ALToolbox/copy_button.md @@ -1,11 +1,12 @@ -# Table of Contents +# ALToolbox.copy_button * [ALToolbox.copy\_button](#ALToolbox.copy_button) * [copy\_button\_html](#ALToolbox.copy_button.copy_button_html) -pydoc-module-header.hbs -#### 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 ```python def copy_button_html(text_to_copy: str, @@ -23,7 +24,7 @@ Return the html for a button that will let a user copy the given text To use, include `docassemble.ALToolbox:copy_button.yml` in your DA interview. -**Arguments**: +#### Arguments - `text_to_copy` - text you want the user to be able to copy. - `text_before` - the prompt that will appear to the left of the HTML input diff --git a/docs/components/ALToolbox/llms.md b/docs/components/ALToolbox/llms.md index d62815ea8..66e481fdb 100644 --- a/docs/components/ALToolbox/llms.md +++ b/docs/components/ALToolbox/llms.md @@ -1,4 +1,4 @@ -# Table of Contents +# ALToolbox.llms * [ALToolbox.llms](#ALToolbox.llms) * [chat\_completion](#ALToolbox.llms.chat_completion) @@ -25,9 +25,10 @@ * [IntakeQuestionList](#ALToolbox.llms.IntakeQuestionList) * [need\_more\_questions](#ALToolbox.llms.IntakeQuestionList.need_more_questions) -pydoc-module-header.hbs -#### 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 = False, openai\_base\_url: Optional[str] = None, max\_output\_tokens: Optional[int] = None, max\_input\_tokens: Optional[int] = None) + + +### chat\_completion ```python def chat_completion( @@ -39,7 +40,7 @@ def chat_completion( json_mode=False, model: str = "gpt-4o", messages: Optional[List[Dict[str, str]]] = None, - skip_moderation: bool = False, + skip_moderation: bool = True, openai_base_url: Optional[str] = None, max_output_tokens: Optional[int] = None, max_input_tokens: Optional[int] = None @@ -50,7 +51,7 @@ A light wrapper on the OpenAI chat endpoint. Includes support for token limits, minimal error handling, and moderation. -**Arguments**: +#### Arguments - `system_message` _str_ - The role the chat engine should play - `user_message` _str_ - The message (data) from the user @@ -66,13 +67,13 @@ Includes support for token limits, minimal error handling, and moderation. - `max_input_tokens` _Optional[int]_ - The maximum number of tokens to send to the API. Defaults to 128000. -**Returns**: +#### Returns 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 ```python def extract_fields_from_text(text: str, @@ -85,19 +86,19 @@ def extract_fields_from_text(text: str, Extracts fields from text. -**Arguments**: +#### Arguments - `text` _str_ - The text to extract fields from - `field_list` _Dict[str,str]_ - A list of fields to extract, with the key being the field name and the value being a description of the field -**Returns**: +#### Returns 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 ```python def match_goals_from_text(question: str, @@ -111,19 +112,19 @@ def match_goals_from_text(question: str, Reads a user's message and determines whether it meets a set of goals, with the help of an LLM. -**Arguments**: +#### Arguments - `text` _str_ - The text to extract goals from - `field_list` _Dict[str,str]_ - A list of goals to extract, with the key being the goal name and the value being a description of the goal -**Returns**: +#### Returns 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 ```python def classify_text(text: str, @@ -137,7 +138,7 @@ def classify_text(text: str, Given a text, classify it into one of the provided choices with the assistance of a large language model. -**Arguments**: +#### Arguments - `text` _str_ - The text to classify - `choices` _Dict[str,str]_ - A list of choices to classify the text into, with the key being the choice name and the value being a description of the choice @@ -148,7 +149,7 @@ Given a text, classify it into one of the provided choices with the assistance o -#### 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 ```python def synthesize_user_responses(messages: List[Dict[str, str]], @@ -162,7 +163,7 @@ def synthesize_user_responses(messages: List[Dict[str, str]], Given a first draft and a series of follow-up questions and answers, use an LLM to synthesize the user's responses into a single, coherent reply. -**Arguments**: +#### Arguments - `custom_instructions` _str_ - Custom instructions for the LLM to follow in constructing the synthesized response - `initial_draft` _str_ - The initial draft of the response from the user @@ -174,7 +175,7 @@ into a single, coherent reply. -#### define\_fields\_from\_dict(field\_dict: Dict[str, Any], fields\_to\_ignore: Optional[List] = None) +### define\_fields\_from\_dict ```python def define_fields_from_dict(field_dict: Dict[str, Any], @@ -185,7 +186,7 @@ Assigns the values in a dictionary of fields to the corresponding fields in a Do Docassemble and built-in keywords are never defined by this function. If fields_to_ignore is provided, those fields will also be ignored. -**Arguments**: +#### Arguments - `field_dict` _Dict[str, Any]_ - A dictionary of fields to define, with the key being the field name and the value presumably taken from the output of extract_fields_from_text. @@ -193,7 +194,7 @@ Docassemble and built-in keywords are never defined by this function. If fields_ safety when defining fields from untrusted sources. E.g., ["user_is_logged_in"] -**Returns**: +#### Returns None @@ -207,7 +208,7 @@ class Goal(DAObject) A class to represent a goal. -**Attributes**: +#### Attributes - `name` _str_ - The name of the goal - `description` _str_ - A description of the goal @@ -215,7 +216,7 @@ A class to represent a goal. -#### 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 ```python def response_satisfies_me_or_follow_up( @@ -230,18 +231,18 @@ def response_satisfies_me_or_follow_up( Returns the text of the next question to ask the user or the string "satisfied" if the user's response satisfies the goal. -**Arguments**: +#### Arguments - `response` _str_ - The response to check -**Returns**: +#### Returns True if the response satisfies the goal, False otherwise -#### get\_next\_question(thread\_so\_far: List[Dict[str, str]], openai\_client: Optional[OpenAI] = None, model="gpt-4o-mini") +### get\_next\_question ```python def get_next_question(thread_so_far: List[Dict[str, str]], @@ -263,7 +264,7 @@ A class to represent a DADict of Goals. -#### satisfied() +### satisfied ```python def satisfied() @@ -281,7 +282,7 @@ class GoalQuestion(DAObject) A class to represent a question about a goal. -**Attributes**: +#### Attributes - `goal` _Goal_ - The goal the question is about - `question` _str_ - The question to ask the user @@ -315,7 +316,7 @@ open ai: key: sk-... ``` -**Attributes**: +#### Attributes - `goals` _List[Goal]_ - The goals in the list, provided as a dictionary - `goal_list` _GoalList_ - The list of Goals @@ -326,7 +327,7 @@ open ai: -#### mark\_satisfied\_goals() +### mark\_satisfied\_goals ```python def mark_satisfied_goals() -> None @@ -335,13 +336,13 @@ 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. -**Returns**: +#### Returns None -#### keep\_going() +### keep\_going ```python def keep_going() @@ -351,7 +352,7 @@ Returns True if there is at least one unsatisfied goal and if the number of foll -#### need\_more\_questions() +### need\_more\_questions ```python def need_more_questions() @@ -364,7 +365,7 @@ and updating the next question to be asked. -#### satisfied() +### satisfied ```python def satisfied() @@ -374,7 +375,7 @@ Returns True if all goals are satisfied, False otherwise. -#### get\_next\_goal\_and\_question() +### get\_next\_goal\_and\_question ```python def get_next_goal_and_question() @@ -382,14 +383,14 @@ def get_next_goal_and_question() Returns the next unsatisfied goal, along with a follow-up question to ask the user, if relevant. -**Returns**: +#### Returns 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 ```python def synthesize_draft_response() @@ -399,7 +400,7 @@ Returns a draft response that synthesizes the user's responses to the quest -#### provide\_feedback(feedback\_prompt: str = "") +### provide\_feedback ```python def provide_feedback(feedback_prompt: str = "") @@ -417,7 +418,7 @@ class IntakeQuestion(DAObject) A class to represent a question in an LLM-assisted intake questionnaire. -**Attributes**: +#### Attributes - `question` _str_ - The question to ask the user - `response` _str_ - The user's response to the question @@ -440,7 +441,7 @@ enough information to determine if the user meets the criteria. In/out criteria are often pretty short, so we do not make or support embeddings at the moment. -**Attributes**: +#### Attributes - `criteria` _Dict[str, str]_ - A dictionary of criteria to match, indexed by problem type - `problem_type_descriptions` _Dict[str, str]_ - A dictionary of descriptions of the problem types @@ -458,7 +459,7 @@ embeddings at the moment. -#### need\_more\_questions() +### need\_more\_questions ```python def need_more_questions() diff --git a/docs/components/ALToolbox/misc.md b/docs/components/ALToolbox/misc.md index d3924a9d7..6e270b74f 100644 --- a/docs/components/ALToolbox/misc.md +++ b/docs/components/ALToolbox/misc.md @@ -1,4 +1,4 @@ -# Table of Contents +# ALToolbox.misc * [ALToolbox.misc](#ALToolbox.misc) * [thousands](#ALToolbox.misc.thousands) @@ -23,9 +23,10 @@ * [age\_in\_years](#ALToolbox.misc.age_in_years) * [format\_date\_if\_defined](#ALToolbox.misc.format_date_if_defined) -pydoc-module-header.hbs -#### thousands(num: Union[float, str, Decimal], show\_decimals=False) + + +### thousands ```python def thousands(num: Union[float, str, Decimal], show_decimals=False) -> str @@ -40,7 +41,7 @@ rounding to the closest int. -#### tel(phone\_number) +### tel ```python def tel(phone_number) -> str @@ -50,7 +51,7 @@ Format a phone number so you can click on it to open in your phone dialer -#### 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 ```python def fa_icon(icon: str, @@ -67,7 +68,7 @@ Docassemble allows you to display an icon from [fontawesome](https://fontawesome but it does not provide control over the size or color of the icon. This function gives you more control over the icon that is inserted. -**Arguments**: +#### Arguments - `icon` - a string representing a fontawesome icon. The icon needs to be in the [free library](https://fontawesome.com/search?o=r&m=free). @@ -82,13 +83,13 @@ you more control over the icon that is inserted. - `aria_hidden` - if True, adds `aria-hidden="true"` to the icon, which is the default -**Returns**: +#### Returns HTML for a font-awesome icon of the specified size and color. -#### space(var\_name: str, prefix=" ", suffix="") +### space ```python def space(var_name: str, prefix=" ", suffix="") -> str @@ -100,7 +101,7 @@ HotDocs. -#### yes\_no\_unknown(var\_name: str, condition: Optional[bool], unknown="Unknown", placeholder=0) +### yes\_no\_unknown ```python def yes_no_unknown(var_name: str, @@ -114,7 +115,7 @@ yesnomaybe fields -#### number\_to\_letter(n: Optional[int]) +### number\_to\_letter ```python def number_to_letter(n: Optional[int]) -> str @@ -125,7 +126,7 @@ once you reach 26 in a way compatible with Excel/Google Sheets column naming con -#### collapse\_template(template: DALazyTemplate, classname: str | None = None, closed\_icon: str = "caret-right", open\_icon: str = "caret-down", collapsed: bool = True) +### collapse\_template ```python def collapse_template(template: DALazyTemplate, @@ -144,7 +145,7 @@ The default icons are "right caret" which displays when the text is co -#### tabbed\_templates\_html(tab\_group\_name: str, \*pargs) +### tabbed\_templates\_html ```python def tabbed_templates_html(tab_group_name: str, *pargs) -> str @@ -154,7 +155,7 @@ Provided a list of templates, create Bootstrap v 4.5 tabs with the `subject` as -#### 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 ```python def review_widget( @@ -176,7 +177,7 @@ If `review_action` is provided, once you press either of the thumbs, a text inpu a submit button appears, and once the text review is submitted (or after the thumbs, if no `review_action` was provided), a final "thank you" message is displayed. -**Arguments**: +#### Arguments - `up_action` - the variable name of an event to be executed on the server if the thumbs up is pressed @@ -189,13 +190,13 @@ a submit button appears, and once the text review is submitted (or after the thu - `submit_review_button` - text on the button to submit their text review - `post_review_display` - text displayed to user after review is submitted -**Returns**: +#### Returns the HTML string of the widget -#### sum\_if\_defined(\*pargs) +### sum\_if\_defined ```python def sum_if_defined(*pargs) @@ -205,7 +206,7 @@ Lets you add up the value of variables that are not in a list -#### add\_records(obj, labels) +### add\_records ```python def add_records(obj, labels) @@ -215,7 +216,7 @@ List demo interviews in the current package to be run from the landing page -#### output\_checkbox(value\_to\_check: bool, checked\_value: str = "[X]", unchecked\_value: str = "[ ]") +### output\_checkbox ```python def output_checkbox(value_to_check: bool, @@ -225,7 +226,7 @@ def output_checkbox(value_to_check: bool, Generate a conditional checkbox for docx templates -**Arguments**: +#### Arguments - `checked_value` - defaults to `[X]` but can be set to any string or even a `DAFile` or `DAStaticFile` with the image of a checkbox @@ -233,7 +234,7 @@ Generate a conditional checkbox for docx templates -#### nice\_county\_name(address: Address) +### nice\_county\_name ```python def nice_county_name(address: Address) -> str @@ -244,7 +245,7 @@ Autocomplete does by default, remove it. -#### button\_array(buttons: List[ButtonDict], custom\_container\_class="", custom\_link\_class="") +### button\_array ```python def button_array(buttons: List[ButtonDict], @@ -261,7 +262,7 @@ on any page of an interview in the `subquestion` area. Optionally, you can limit access to paricular buttons by specifying a privilege or a list of privileges. -**Arguments**: +#### Arguments - `button_list` - a dictionary of ButtonDicts (or plain dictionaries) with the following keys: - `name`: the text to display on the button @@ -273,13 +274,13 @@ of privileges. - `custom_link_class` - optional, a string of additional CSS classes to add to each link -**Returns**: +#### Returns HTML for a grid of buttons -#### none\_to\_empty(val: Any) +### none\_to\_empty ```python def none_to_empty(val: Any) @@ -293,17 +294,17 @@ when handling a radio button that is not required and left unanswered. A DAEmpty value appears as an empty string in the output. You can also safely transform it or use any method on it without raising an error. -**Arguments**: +#### Arguments - `val` - the value to check -**Returns**: +#### Returns 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 ```python def option_or_other(variable_name: str, @@ -314,18 +315,18 @@ If the variable is set to 'Other', return the value of the 'other This is useful for filling in a template and to prevent the word 'Other' from appearing in the output. -**Arguments**: +#### Arguments - `variable_name` - the name of the variable to check - `other_variable_name` - the name of the variable to return if the value of the first variable is 'Other' -**Returns**: +#### Returns 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 ```python def true_values_with_other( @@ -337,18 +338,18 @@ Return a list of values that are True, with the value of the 'other' v This is useful for filling in a template and to prevent the word 'Other' from appearing in the output. -**Arguments**: +#### Arguments - `variable` - the dictionary of variables to check - `other_variable_name` - the name of the variable (as a string) to return if the value of the first variable is 'Other' -**Returns**: +#### Returns a list of values that are True, with the value of the 'other' variable appended to the end of the list. -#### include\_a\_year(text: str, field: Optional[str] = None) +### include\_a\_year ```python def include_a_year(text: str, field: Optional[str] = None) -> bool @@ -363,7 +364,7 @@ Returns True if found, otherwise raises a DAValidationError. -#### is\_leap\_year(year: int) +### is\_leap\_year ```python def is_leap_year(year: int) -> bool @@ -371,17 +372,17 @@ def is_leap_year(year: int) -> bool Helper function for `age_in_years` to determine if a year is a leap year. -**Arguments**: +#### Arguments - `year` - The year to check. -**Returns**: +#### Returns True if the year is a leap year, False otherwise. -#### age\_in\_years(the\_date: Union[str, DADateTime]) +### age\_in\_years ```python def age_in_years(the_date: Union[str, DADateTime]) -> int @@ -389,17 +390,17 @@ def age_in_years(the_date: Union[str, DADateTime]) -> int Calculate the age in years from a date (treated like a date of birth). -**Arguments**: +#### Arguments - `the_date` - A string or DADateTime object representing the date of birth. -**Returns**: +#### Returns The age in years as an integer. -#### format\_date\_if\_defined(date\_object\_name: str, \*pargs, default: str = "", \*\*kwargs) +### format\_date\_if\_defined ```python def format_date_if_defined(date_object_name: str, @@ -412,7 +413,7 @@ Format a date string if it is defined, otherwise return an empty string. Passes all additional arguments to the `format_date` function. -**Arguments**: +#### Arguments - `date_object_name` - The date string to format. - `*pargs` - Additional positional arguments to pass to `format_date`. @@ -420,7 +421,7 @@ Passes all additional arguments to the `format_date` function. - `**kwargs` - Additional keyword arguments to pass to `format_date`. E.g., format="yyyy-MM-dd" -**Returns**: +#### Returns A formatted date string if `date_object_name` is defined, otherwise an empty string. diff --git a/docs/components/ALToolbox/save_input_data.md b/docs/components/ALToolbox/save_input_data.md index a86613d1e..9d3e5bca0 100644 --- a/docs/components/ALToolbox/save_input_data.md +++ b/docs/components/ALToolbox/save_input_data.md @@ -1,11 +1,12 @@ -# 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) -pydoc-module-header.hbs -#### save\_input\_data(title: str = "", input\_dict: Optional[Dict[str, Any]] = None, tags: Optional[List[str]] = None) + + +### 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 882ceb824..d5a5b098e 100644 --- a/docs/components/AssemblyLine/al_courts.md +++ b/docs/components/AssemblyLine/al_courts.md @@ -1,4 +1,4 @@ -# Table of Contents +# AssemblyLine.al_courts * [AssemblyLine.al\_courts](#AssemblyLine.al_courts) * [ALCourt](#AssemblyLine.al_courts.ALCourt) @@ -20,7 +20,8 @@ * [filter\_courts](#AssemblyLine.al_courts.ALCourtLoader.filter_courts) * [as\_court](#AssemblyLine.al_courts.ALCourtLoader.as_court) -pydoc-module-header.hbsPackage for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now + +Package for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now @@ -39,7 +40,7 @@ address and can use any of those three features of the court to do the filtering -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -47,14 +48,14 @@ def init(*pargs, **kwargs) -> None Create a new court object. -**Arguments**: +#### Arguments - `*pargs` - Standard DAObject positional arguments - `**kwargs` - Standard DAObject keyword arguments -#### short\_label() +### short\_label ```python def short_label() -> str @@ -65,13 +66,13 @@ This may not match the court's name. If the name omits city, we append city name to the court name. This is good for a drop-down selection list. -**Returns**: +#### Returns - `str` - string representing the court's name, with city if needed to disambiguate -#### short\_label\_and\_address() +### short\_label\_and\_address ```python def short_label_and_address() -> str @@ -80,13 +81,13 @@ def short_label_and_address() -> str Returns a markdown formatted string with the name and address of the court. More concise version without description; suitable for a responsive case. -**Returns**: +#### Returns - `str` - string representing the court's name and address -#### short\_description() +### short\_description ```python def short_description() -> str @@ -96,13 +97,13 @@ Returns a Markdown formatted string that includes the disambiguated name and the description of the court, for inclusion in the results page with radio buttons. -**Returns**: +#### Returns - `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 ```python def from_row(df_row: Union[pd.Series, pd.DataFrame], @@ -114,14 +115,14 @@ Note: It will try to convert column names that don't make valid attributes. Best practice is to use good attribute names (no spaces) that don't interfere with existing attributes or methods of DAObject -**Arguments**: +#### Arguments - `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 ```python def geolocate() -> None @@ -133,7 +134,7 @@ Deprecated: use geocode() instead. -#### geocode() +### geocode ```python def geocode() -> None @@ -153,14 +154,14 @@ Object to hold some methods surrounding loading/filtering courts. Built around Pandas dataframe. -**Attributes**: +#### Attributes - `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 ```python def init(*pargs, **kwargs) -> None @@ -168,14 +169,14 @@ def init(*pargs, **kwargs) -> None Create a new courtloader object. -**Arguments**: +#### Arguments - `*pargs` - Standard DAObject positional arguments - `**kwargs` - Standard DAObject keyword arguments -#### all\_courts() +### all\_courts ```python def all_courts() -> List[Dict[int, str]] @@ -183,13 +184,13 @@ def all_courts() -> List[Dict[int, str]] Return a list of all courts in the spreadsheet. -**Returns**: +#### Returns List[Dict[int, str]]: List of all ALCourt instances without filtering. -#### unique\_column\_values(column\_name: str) +### unique\_column\_values ```python def unique_column_values(column_name: str) -> Set[str] @@ -197,12 +198,12 @@ def unique_column_values(column_name: str) -> Set[str] Retrieve a set of unique values present in a specified dataframe column. -**Arguments**: +#### Arguments - `column_name` _str_ - The name of the column in the dataframe. -**Returns**: +#### Returns Set[str]: - A set containing unique values from the specified column. @@ -210,7 +211,7 @@ Retrieve a set of unique values present in a specified dataframe column. -#### county\_list(column\_name: str = "address\_county") +### county\_list ```python def county_list(column_name: str = "address_county") -> Set[str] @@ -219,18 +220,18 @@ def county_list(column_name: str = "address_county") -> Set[str] Get a set of all unique names for the specified column in the given spreadsheet. Typically used to get a list of all possible counties that have a court. -**Arguments**: +#### Arguments - `column_name` _str_ - The name of the column in the dataframe. -**Returns**: +#### Returns - `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 ```python def county_has_one_court(county_name: str, @@ -240,20 +241,20 @@ def county_has_one_court(county_name: str, Returns True if there is only one court associated with the specified county in the spreadsheet. Returns False otherwise. -**Arguments**: +#### Arguments - `county_name` _str_ - The name of the county to check. - `county_column` _str_ - The name of the column in the dataframe that contains the county names. Defaults to "address_county". -**Returns**: +#### Returns - `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 ```python def county_court(intrinsicName: str, @@ -264,7 +265,7 @@ def county_court(intrinsicName: str, Return the first court matching the county name. Should only be used when you know there is exactly one match -**Arguments**: +#### Arguments - `intrinsicName` _str_ - The intrinsic name you want the newly returned object to have (used for DA namespace searching). - `county_name` _str_ - The name of the county to check. @@ -272,13 +273,13 @@ when you know there is exactly one match Defaults to "address_county". -**Returns**: +#### Returns - `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 ```python def matching_courts_in_county( @@ -296,7 +297,7 @@ This function fetches courts suitable for displaying as a drop-down or radio but in Docassemble. The results are dictionaries where the key is the index in the dataframe, useful for retrieving the court's full details later using the as_court() method. -**Arguments**: +#### Arguments - `county_name` _str_ - Name of the county. - `county_column` _str, optional_ - Column heading which contains county name. Defaults to "address_county". @@ -306,13 +307,13 @@ useful for retrieving the court's full details later using the as_court() m the search_string in a case-insensitive manner. Defaults to None. -**Returns**: +#### Returns List[Dict[int, str]]: List of dictionaries representing matching courts. -#### 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 ```python def filter_courts( @@ -329,7 +330,7 @@ Return a filtered subset of courts represented as a list of dictionaries. Each dictionary has the format \{index: name\}, where "index" refers to the dataframe index and "name" is determined by the `display_column`. -**Arguments**: +#### Arguments - `court_types` _Optional[Union[List[str], str]]_ - Exact string match or matches used to filter results (inclusive). Examples include "District" or ["Municipal","Superior"]. @@ -340,13 +341,13 @@ is determined by the `display_column`. the search_string in a case-insensitive manner. Defaults to None. -**Returns**: +#### Returns List[Dict[int, str]]: List of dictionaries representing filtered courts. -#### as\_court(intrinsicName: str, index: Union[int, str], ensure\_lat\_long: bool = True) +### as\_court ```python def as_court(intrinsicName: str, @@ -356,14 +357,14 @@ def as_court(intrinsicName: str, Retrieve the court at the specified index as an ALCourt object. -**Arguments**: +#### Arguments - `intrinsicName` _str_ - The intrinsic name you want to assign to the returned object (used for DA namespace searching). - `index` _Union[int, str]_ - The index position of the court in the dataframe. - `ensure_lat_long` _bool, optional_ - Whether to ensure the presence of latitude and longitude data. Defaults to True. -**Returns**: +#### Returns - `ALCourt` - An ALCourt object initialized with data from the specified index. diff --git a/docs/components/AssemblyLine/al_document.md b/docs/components/AssemblyLine/al_document.md index 713487f43..ac6b4e3af 100644 --- a/docs/components/AssemblyLine/al_document.md +++ b/docs/components/AssemblyLine/al_document.md @@ -1,4 +1,4 @@ -# Table of Contents +# AssemblyLine.al_document * [AssemblyLine.al\_document](#AssemblyLine.al_document) * [random\_suffix](#AssemblyLine.al_document.random_suffix) @@ -117,9 +117,10 @@ * [ALDocumentUpload](#AssemblyLine.al_document.ALDocumentUpload) * [unpack\_dafilelist](#AssemblyLine.al_document.unpack_dafilelist) -pydoc-module-header.hbs -#### random\_suffix(length: int = 8) + + +### random\_suffix ```python def random_suffix(length: int = 8) -> str @@ -131,17 +132,17 @@ Note: this is powerful enough for the expected usecase of distinguishing a few HTML elements from each other, but not cryptographically secure or as strong as a true GUID. -**Arguments**: +#### Arguments - `length` _int_ - The length of the random string to generate. Defaults to 8. -**Returns**: +#### Returns - `str` - A random string of lowercase letters and digits. -#### base\_name(filename: str) +### base\_name ```python def base_name(filename: str) -> str @@ -149,18 +150,18 @@ def base_name(filename: str) -> str Extracts the base name of a file without its extension. -**Arguments**: +#### Arguments - `filename` _str_ - The full name of the file. -**Returns**: +#### Returns - `str` - The base name of the file without its extension. -#### label(dictionary: dict) +### label ```python def label(dictionary: dict) -> str @@ -171,18 +172,18 @@ Return the value of the first dictionary item. Given a dictionary like: \{"some_attribute":"Some label"\}, this function returns the value of the first dictionary item. Useful for working with the `columns` method of an ALAddendumField. -**Arguments**: +#### Arguments - `dictionary` _dict_ - The dictionary to extract the value from. -**Returns**: +#### Returns - `str` - The value of the first dictionary item or an empty string if not found. -#### key(dictionary: dict) +### key ```python def key(dictionary: dict) -> str @@ -193,18 +194,18 @@ Return the key of the first dictionary item. Given a dictionary like: \{"some_attribute":"Some label"\}, this function returns the key of the first dictionary item. Useful for working with the `columns` method of an ALAddendumField. -**Arguments**: +#### Arguments - `dictionary` _dict_ - The dictionary to extract the key from. -**Returns**: +#### Returns - `str` - The key of the first dictionary item or an empty string if not found. -#### safeattr(object: Any, key: str) +### safeattr ```python def safeattr(object: Any, key: str) -> str @@ -212,24 +213,24 @@ def safeattr(object: Any, key: str) -> str Safely retrieve an attribute or key value from an object. -**Arguments**: +#### Arguments - `object` _Any_ - The object (which could be a dict, DADict, or DAObject) from which to retrieve the value. - `key` _str_ - The key or attribute name. -**Returns**: +#### Returns - `str` - The retrieved value or an empty string if not found or if an error occurred. -**Notes**: +#### Notes 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 ```python def html_safe_str(the_string: str) -> str @@ -237,18 +238,18 @@ def html_safe_str(the_string: str) -> str Convert a string into a format that's safe for use as an HTML class or ID. -**Arguments**: +#### Arguments - `the_string` _str_ - The string to be converted. -**Returns**: +#### Returns - `str` - A string that's safe for use as an HTML class or ID. -#### table\_row(title: str, button\_htmls: List[str] = []) +### table\_row ```python def table_row(title: str, button_htmls: List[str] = []) -> str @@ -256,19 +257,19 @@ def table_row(title: str, button_htmls: List[str] = []) -> str Generate an HTML row string for an AL document-styled table. -**Arguments**: +#### Arguments - `title` _str_ - The title to display in the row. - `button_htmls` _List[str], optional_ - A list of HTML strings representing buttons. Defaults to an empty list. -**Returns**: +#### Returns - `str` - An HTML string representing a row in an AL document-styled table. -#### pdf\_page\_parity(pdf\_path: str) +### pdf\_page\_parity ```python def pdf_page_parity(pdf_path: str) -> Literal["even", "odd"] @@ -278,18 +279,18 @@ Count the number of pages in the PDF and return "even" if it is divisible by 2 and "odd" if it is not divisible by 2. -**Arguments**: +#### Arguments - `pdf_path` _str_ - Path to the PDF in the filesystem -**Returns**: +#### Returns Literal["even", "odd"]: The parity of the number of pages in the PDF -#### add\_blank\_page(pdf\_path: str) +### add\_blank\_page ```python def add_blank_page(pdf_path: str) -> None @@ -297,7 +298,7 @@ def add_blank_page(pdf_path: str) -> None Add a blank page to the end of a PDF. -**Arguments**: +#### Arguments - `pdf_path` _str_ - Path to the PDF in the filesystem @@ -314,7 +315,7 @@ Represents a field with attributes determining its display in an addendum, typic The field can manage items that are either strings or list-like structures. Handling of dictionary overflow is not currently supported. -**Attributes**: +#### Attributes - `field_name` _str_ - The name of a docassemble variable that this object represents. - `overflow_trigger` _Union[int, bool]_ - Specifies the limit after which the text is truncated and moved @@ -327,13 +328,13 @@ is not currently supported. Defaults to "string". Planned for future implementation. -**Notes**: +#### Notes The attributes `headers` and `field_style` are planned for future releases and are not currently implemented. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -341,14 +342,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*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 ```python def overflow_value(preserve_newlines: bool = False, @@ -362,7 +363,7 @@ Retrieve the overflow portion of a variable that exceeds the content of `safe_va This function addresses both list-like objects and strings, ensuring that the returned overflow content adheres to whitespace preferences specified by the parameters. -**Arguments**: +#### Arguments - `preserve_newlines` _bool, optional_ - Determines the treatment of newline characters. If True, the returned string can contain single newline characters. Sequences of newline @@ -379,13 +380,13 @@ content adheres to whitespace preferences specified by the parameters. and the overflow. Defaults to True. -**Returns**: +#### Returns - `Any` - The portion of the variable exceeding the content safe for display, considered as overflow. -#### max\_lines(input\_width: int = 80) +### max\_lines ```python def max_lines(input_width: int = 80) -> int @@ -393,18 +394,18 @@ def max_lines(input_width: int = 80) -> int Compute the maximum number of lines that can fit in the input given the specified input width. -**Arguments**: +#### Arguments - `input_width` _int, optional_ - The width of the input or display area. Defaults to 80. -**Returns**: +#### Returns - `int` - The maximum number of lines accommodated by the input width. -#### value() +### value ```python def value() -> Any @@ -415,13 +416,13 @@ Retrieve the complete value without considering overflow constraints. This can be especially helpful in appendices where there's a desire to showcase the entire value without the necessity of toggling between various sections or pages. -**Returns**: +#### Returns - `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 ```python def has_overflow(overflow_message: str = "", @@ -433,7 +434,7 @@ def has_overflow(overflow_message: str = "", Return True only if the value's length exceeds the overflow trigger. -**Arguments**: +#### Arguments - `overflow_message` _str_ - A short message to go on the page where text is cutoff. - `input_width` _int_ - The width, in characters, of the input box. Defaults to 80. @@ -448,13 +449,13 @@ Return True only if the value's length exceeds the overflow trigger. trigger, regardless of whether it is in the middle of a word. -**Returns**: +#### Returns - `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 ```python def original_or_overflow_message( @@ -469,7 +470,7 @@ Return the original value if it is less than the overflow trigger (once processe Unlike safe_value(), this will never output a partial value. -**Arguments**: +#### Arguments - `overflow_message` _str_ - A short message to go on the page where text is cutoff. - `input_width` _int_ - The width, in characters, of the input box. Defaults to 80. @@ -484,13 +485,13 @@ Unlike safe_value(), this will never output a partial value. trigger, regardless of whether it is in the middle of a word. -**Returns**: +#### Returns 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 ```python def safe_value(overflow_message: str = "", @@ -514,7 +515,7 @@ with a single space. If `preserve_newlines` is false, all whitespace, including newlines and tabs, will be replaced with a single space. -**Arguments**: +#### Arguments - `overflow_message` _str_ - A short message to go on the page where text is cutoff. - `input_width` _int_ - The width, in characters, of the input box. Defaults to 80. @@ -527,13 +528,13 @@ with a single space. - `preserve_words` _bool_ - Indicates whether words should be preserved in their entirety without being split. -**Returns**: +#### Returns Union[str, List[Any]]: The portion of the variable that fits within the overflow trigger. -#### value\_if\_defined() +### value\_if\_defined ```python def value_if_defined() -> Any @@ -543,13 +544,13 @@ Fetch the value of the designated field if it exists; otherwise, return an empty This method ensures that the addendum does not inadvertently trigger docassemble's variable gathering. -**Returns**: +#### Returns - `Any` - The value of the field if it exists, otherwise an empty string. -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() @@ -557,13 +558,13 @@ def __str__() Represent the ALAddendumField instance as a string. -**Returns**: +#### Returns - `str` - The string representation of the value contained within the field. -#### columns(skip\_empty\_attributes: bool = True, skip\_attributes: Optional[set] = None) +### columns ```python def columns(skip_empty_attributes: bool = True, @@ -576,25 +577,25 @@ in the table of an addendum. If the `headers` attribute exists, this will be prioritized. Otherwise, the method will infer columns from the first value in the list. Empty attributes and the `complete` attribute are typically ignored. -**Arguments**: +#### Arguments - `skip_empty_attributes` _bool, optional_ - Determines whether empty attributes are included in the list. Defaults to True. - `skip_attributes` _Optional[set], optional_ - A set of attributes to ignore. Defaults to \{"complete"\}. -**Returns**: +#### Returns - `Optional[list]` - A list of columns or None if no meaningful columns can be determined. -**Notes**: +#### Notes The "location" attribute of an Address object is always skipped in the column list. -#### type() +### type ```python def type() -> str @@ -607,13 +608,13 @@ Categories: - 'object_list': A list containing dictionaries or objects. - 'other': Any other type. -**Returns**: +#### Returns - `str` - The type category of the value. -#### is\_list() +### is\_list ```python def is_list() -> bool @@ -621,13 +622,13 @@ def is_list() -> bool Check if the field contains a list value, whether it consists of objects, dictionaries, or standard values. -**Returns**: +#### Returns - `bool` - True if the field contains a list, otherwise False. -#### is\_object\_list() +### is\_object\_list ```python def is_object_list() -> bool @@ -635,13 +636,13 @@ def is_object_list() -> bool Determine if the field contains a list of dictionaries or objects. -**Returns**: +#### Returns - `bool` - True if the field contains a list of dictionaries or objects, otherwise False. -#### overflow\_markdown() +### overflow\_markdown ```python def overflow_markdown() -> str @@ -653,13 +654,13 @@ The method returns either a markdown table or a bulleted list based on the struc This utility offers a standardized way to represent overflow content, though users might prefer to manually control the output's format. -**Returns**: +#### Returns - `str` - A markdown representation of the overflow values. -#### overflow\_docx(path: str = "docassemble.ALDocumentDict:data/templates/addendum\_table.docx") +### overflow\_docx ```python def overflow_docx( @@ -673,13 +674,13 @@ This method provides a convenient way to add overflow content into a docx file, doesn't offer formatting control. If more formatting flexibility is required, consider directly fetching the overflow values using the `overflow_value()` method. -**Arguments**: +#### Arguments - `path` _str, optional_ - Path to the template docx file to be used. Defaults to a predetermined path. -**Returns**: +#### Returns A docx template with the inserted table. @@ -700,14 +701,14 @@ contexts, ensuring only the necessary text is shown. Adding a new entry will implicitly set the `field_name` attribute of the field -**Attributes**: +#### Attributes - `style` _str_ - Determines the display behavior. If set to "overflow_only", only the overflow text will be displayed. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -715,14 +716,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### initializeObject(\*pargs, \*\*kwargs) +### initializeObject ```python def initializeObject(*pargs, **kwargs) -> Any @@ -733,20 +734,20 @@ Initializes a new dictionary entry and sets its `field_name` attribute. When an entry is implicitly created, this method ensures the item knows its own field name by setting the `field_name` attribute. -**Arguments**: +#### Arguments - `*pargs` - List of arguments to use to create the dict entry. The 0th arg is also used to set the `field_name` attribute. - `**kwargs` - List of keyword arguments used to create the dict entry -**Returns**: +#### Returns The new dictionary entry created -#### from\_list(data: List[Dict]) +### from\_list ```python def from_list(data: List[Dict]) -> None @@ -754,14 +755,14 @@ def from_list(data: List[Dict]) -> None Populate the dictionary using a list of field data. -**Arguments**: +#### Arguments - `data` _list_ - List of dictionaries containing ield data with keys "field_name" and "overflow_trigger". -#### defined\_fields(style: str = "overflow\_only") +### defined\_fields ```python def defined_fields(style: str = "overflow_only") -> list @@ -769,19 +770,19 @@ def defined_fields(style: str = "overflow_only") -> list Fetch a list of fields that are defined. -**Arguments**: +#### Arguments - `style` _str, optional_ - If set to "overflow_only", only the fields with overflow values will be returned. Defaults to "overflow_only". -**Returns**: +#### Returns - `list` - List of defined fields based on the specified style. -#### overflow() +### overflow ```python def overflow() -> list @@ -789,13 +790,13 @@ def overflow() -> list Retrieve fields that have overflowed their character limits. -**Returns**: +#### Returns - `list` - A list of fields with overflow values. -#### has\_overflow() +### has\_overflow ```python def has_overflow() -> bool @@ -803,7 +804,7 @@ def has_overflow() -> bool Determine if any field within the dictionary exceeds its overflow limit. -**Returns**: +#### Returns - `bool` - True if at least one field overflows, False otherwise. @@ -821,13 +822,13 @@ This is particularly helpful when there's a need to cache information on a The implementation leverages Docassemble's object pickling process by customizing the `__getstate__` method that Pickle uses for serialization. -**Attributes**: +#### Attributes - `instanceName` _str_ - A unique identifier for the object instance, if available. -#### \_\_getstate\_\_() +### \_\_getstate\_\_ ```python def __getstate__() -> dict @@ -839,7 +840,7 @@ If the object has an `instanceName` attribute, it is retained during serializati Otherwise, an empty dictionary is returned, ensuring that other attributes are not persisted across page loads. -**Returns**: +#### Returns - `dict` - A dictionary containing only the `instanceName` if it exists, or empty otherwise. @@ -880,7 +881,7 @@ single object representing all of the possible documents an interview can generate, and use encapsulated logic to trigger individual documents inclusion on the final download screen. -**Attributes**: +#### Attributes - `filename` _str_ - name used for output PDF - `title` _str_ - display name for the output PDF @@ -892,7 +893,7 @@ on the final download screen. document could have overflow, like for a PDF template. -**Notes**: +#### Notes The `enabled` attribute should always be defined by a code block or the objects block, because by default it is considered fresh on each page @@ -980,7 +981,7 @@ on the final download screen. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -988,14 +989,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### as\_pdf(key: str = "final", refresh: bool = True, pdfa: bool = False, append\_matching\_suffix: bool = True) +### as\_pdf ```python def as_pdf(key: str = "final", @@ -1006,7 +1007,7 @@ def as_pdf(key: str = "final", Generates a PDF version of the assembled document. -**Arguments**: +#### Arguments - `key` _str_ - Document version key. Defaults to "final". - `refresh` _bool_ - If True, generates the attachment anew each time. Defaults to True. @@ -1014,13 +1015,13 @@ Generates a PDF version of the assembled document. - `append_matching_suffix` _bool_ - If True, appends the key as a suffix to the filename when it matches the suffix to append. Defaults to True. -**Returns**: +#### Returns - `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 ```python def as_docx(key: str = "final", @@ -1030,20 +1031,20 @@ def as_docx(key: str = "final", Generates a DOCX version of the assembled document, if possible. Falls back to PDF if not. -**Arguments**: +#### Arguments - `key` _str_ - Document version key. Defaults to "final". - `refresh` _bool_ - If True, generates the attachment anew each time. Defaults to True. - `append_matching_suffix` _bool_ - If True, appends the key as a suffix to the filename when it matches the suffix to append. Defaults to True. -**Returns**: +#### Returns - `DAFile` - Assembled document in DOCX or PDF format. -#### as\_list(key: str = "final", refresh: bool = True) +### as\_list ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1051,19 +1052,19 @@ def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] Generates a list containing the main document and its addendum, if applicable. -**Arguments**: +#### Arguments - `key` _str_ - Document version key. Defaults to "final". - `refresh` _bool_ - If True, generates the attachments anew each time. Defaults to True. -**Returns**: +#### Returns - `List[DAFile]` - List containing the main document and possibly its addendum. -#### need\_addendum() +### need\_addendum ```python def need_addendum() -> bool @@ -1072,13 +1073,13 @@ def need_addendum() -> bool Determines if there's a need for an addendum in the document. First checks if the addendum is enabled, and then checks if there's overflow. -**Returns**: +#### Returns - `bool` - True if an addendum is needed, False otherwise. -#### has\_overflow() +### has\_overflow ```python def has_overflow() -> bool @@ -1086,13 +1087,13 @@ def has_overflow() -> bool Checks if the document has fields that exceed their character limits. -**Returns**: +#### Returns - `bool` - True if there are overflow fields, False otherwise. -#### overflow() +### overflow ```python def overflow() -> list @@ -1100,13 +1101,13 @@ def overflow() -> list Retrieves a list of fields that have overflowed their character limits. -**Returns**: +#### Returns - `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 ```python def original_or_overflow_message( @@ -1124,7 +1125,7 @@ Return the original value if it is less than the overflow trigger (once processe Unlike safe_value(), this will never output a partial value. -**Arguments**: +#### Arguments - `field_name` _str_ - The name of the field to check. - `overflow_message` _str_ - A short message to go on the page where text is cutoff. @@ -1140,13 +1141,13 @@ Unlike safe_value(), this will never output a partial value. trigger, regardless of whether it is in the middle of a word. -**Returns**: +#### Returns 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 ```python def safe_value(field_name: str, @@ -1158,7 +1159,7 @@ def safe_value(field_name: str, Retrieve the "safe" value of a specified field, which is shorter than the overflow trigger. -**Arguments**: +#### Arguments - `field_name` _str_ - The name of the field to retrieve the safe value from. - `overflow_message` _Optional[str]_ - Message to display when the field value overflows. Defaults to the class's default overflow message. @@ -1167,13 +1168,13 @@ Retrieve the "safe" value of a specified field, which is shorter than - `preserve_words` _bool_ - Whether to avoid splitting words during formatting. Defaults to True. -**Returns**: +#### Returns - `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 ```python def overflow_value(field_name: str, @@ -1185,7 +1186,7 @@ def overflow_value(field_name: str, Retrieve the "overflow" value of a specified field, which is the amount exceeding the overflow trigger. -**Arguments**: +#### Arguments - `field_name` _str_ - The name of the field to retrieve the overflow value from. - `overflow_message` _Optional[str]_ - Message to display when the field value overflows. Defaults to the object's default overflow message. @@ -1194,13 +1195,13 @@ Retrieve the "overflow" value of a specified field, which is the amoun - `preserve_words` _bool_ - Whether to avoid splitting words during formatting. Defaults to True. -**Returns**: +#### Returns - `str` - The "overflow" value of the specified field. -#### is\_enabled(refresh: bool = True) +### is\_enabled ```python def is_enabled(refresh: bool = True) -> bool @@ -1213,12 +1214,12 @@ A document is "enabled" if: 2. The .enabled attribute is set to true (calculated fresh once per page load). 3. The cache.enabled attribute is set to true. -**Arguments**: +#### Arguments - `refresh` _bool_ - If True, refreshes the enabled status of the document. Defaults to True. -**Returns**: +#### Returns - `bool` - True if the document is enabled, otherwise False. @@ -1232,13 +1233,13 @@ class ALStaticDocument(DAStaticFile) A class for initializing static documents for inclusion in an ALDocumentBundle with a one-liner. -**Notes**: +#### Notes Static files should always be placed in the `/data/static` folder of a package. The `/data/templates` folder is private and the ALDocumentBundle requires publicly accessible files. -**Attributes**: +#### Attributes - `filename` _str_ - Path to the file within `/data/static/`. - `title` _str_ - Title displayed as a row when invoking `download_list_html()` method from ALDocumentBundle. @@ -1262,7 +1263,7 @@ A class for initializing static documents for inclusion in an ALDocumentBundle w -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -1270,14 +1271,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### \_\_getitem\_\_(key) +### \_\_getitem\_\_ ```python def __getitem__(key) @@ -1285,13 +1286,13 @@ def __getitem__(key) Override to ensure 'final' and 'private' keys always exist and reference the same file. -**Returns**: +#### Returns - `ALStaticDocument` - Returns self. -#### as\_list(key: str = "final", refresh: bool = True) +### as\_list ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAStaticFile] @@ -1299,19 +1300,19 @@ def as_list(key: str = "final", refresh: bool = True) -> List[DAStaticFile] Get the document as a list. -**Arguments**: +#### Arguments - `key` _str_ - Key to access the document. Defaults to "final". - `refresh` _bool_ - Whether to refresh the document. Defaults to True. -**Returns**: +#### Returns - `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 ```python def as_pdf(key: str = "final", @@ -1323,7 +1324,7 @@ def as_pdf(key: str = "final", Convert the document into PDF format. -**Arguments**: +#### Arguments - `key` _str_ - Key to access the document. Defaults to "final". - `pdfa` _bool_ - Whether to return the document in PDF/A format. Defaults to False. @@ -1332,13 +1333,13 @@ Convert the document into PDF format. - `refresh` _bool_ - Whether to refresh the document. Defaults to False. -**Returns**: +#### Returns Union[DAStaticFile, DAFile]: The document in PDF format. -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = False) +### as\_docx ```python def as_docx( @@ -1349,20 +1350,20 @@ def as_docx( Convert the document into DOCX format, if possible. If not, return as PDF. -**Arguments**: +#### Arguments - `key` _str_ - Key to access the document. Defaults to "final". - `refresh` _bool_ - Whether to refresh the document. Defaults to True. - `append_matching_suffix` _bool_ - Not used for static documents. They remain unchanged. -**Returns**: +#### Returns Union[DAStaticFile, DAFile]: The document in DOCX or PDF format. -#### show(\*\*kwargs) +### show ```python def show(**kwargs) -> DAFile @@ -1372,18 +1373,18 @@ Display the document. This method provides a workaround for problems generating thumbnails. -**Arguments**: +#### Arguments - `**kwargs` - Args to pass to DAFile's show function -**Returns**: +#### Returns - `DAFile` - Displayable version of the document. -#### is\_enabled(\*\*kwargs) +### is\_enabled ```python def is_enabled(**kwargs) -> bool @@ -1391,12 +1392,12 @@ def is_enabled(**kwargs) -> bool Check if the document is enabled. -**Arguments**: +#### Arguments - `**kwargs` - Unused (for signature compatibility only) -**Returns**: +#### Returns - `bool` - True if the document is enabled, otherwise False. @@ -1418,7 +1419,7 @@ or "disabled", which will determine its inclusion in the generated bun A bundle can be output as a single merged PDF or as a list of individual documents. For nested bundles, each can be rendered as a merged PDF or a list of documents. -**Attributes**: +#### Attributes - `filename` _str_ - The name of the output file (without extension). - `title` _str_ - The title of the bundle. @@ -1449,7 +1450,7 @@ bundles, each can be rendered as a merged PDF or a list of documents. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -1457,14 +1458,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*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 ```python def as_pdf( @@ -1478,7 +1479,7 @@ def as_pdf( Returns a consolidated PDF of all enabled documents in the bundle. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `refresh` _bool_ - Flag to return a newly assembled version, default is True. @@ -1489,13 +1490,13 @@ Returns a consolidated PDF of all enabled documents in the bundle. no parity is enforced. Defaults to None. -**Returns**: +#### Returns - `Optional[DAFile]` - Combined PDF file or None if no documents are enabled. -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -1505,13 +1506,13 @@ Produces a string representation of the PDF in a compatible method with the DAFile class. In an interview, this will show a thumbnail of the PDF by default. -**Returns**: +#### Returns - `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 ```python def as_zip(key: str = "final", @@ -1524,7 +1525,7 @@ def as_zip(key: str = "final", Returns a zip file containing all enabled documents in the bundle in the specified format. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is True. @@ -1534,13 +1535,13 @@ Returns a zip file containing all enabled documents in the bundle in the specifi - `include_pdf` _bool_ - Flag to include a PDF version of the document if it's originally in docx format, default is True. -**Returns**: +#### Returns - `DAFile` - A zip file containing the enabled documents. -#### preview(refresh: bool = True) +### preview ```python def preview(refresh: bool = True) -> Optional[DAFile] @@ -1548,18 +1549,18 @@ def preview(refresh: bool = True) -> Optional[DAFile] Returns a preview version of the bundle as a PDF. -**Arguments**: +#### Arguments - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is True. -**Returns**: +#### Returns - `Optional[DAFile]` - Preview PDF file or None if no documents are enabled. -#### has\_enabled\_documents(refresh=False) +### has\_enabled\_documents ```python def has_enabled_documents(refresh=False) -> bool @@ -1567,18 +1568,18 @@ def has_enabled_documents(refresh=False) -> bool Checks if there is at least one enabled document in the bundle. -**Arguments**: +#### Arguments - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is False. -**Returns**: +#### Returns - `bool` - True if there's at least one enabled document, otherwise False. -#### enabled\_documents(refresh: bool = True) +### enabled\_documents ```python def enabled_documents(refresh: bool = True) -> List[Any] @@ -1586,18 +1587,18 @@ def enabled_documents(refresh: bool = True) -> List[Any] Retrieves all enabled documents within the bundle. -**Arguments**: +#### Arguments - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is True. -**Returns**: +#### Returns - `List[Any]` - List of enabled documents. -#### as\_flat\_list(key: str = "final", refresh: bool = True) +### as\_flat\_list ```python def as_flat_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1605,19 +1606,19 @@ def as_flat_list(key: str = "final", refresh: bool = True) -> List[DAFile] Flattens and returns all enabled documents in the bundle, even from nested bundles. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is True. -**Returns**: +#### Returns - `List[DAFile]` - Flattened list of enabled documents. -#### get\_titles(key: str = "final", refresh: bool = True) +### get\_titles ```python def get_titles(key: str = "final", refresh: bool = True) -> List[str] @@ -1625,19 +1626,19 @@ def get_titles(key: str = "final", refresh: bool = True) -> List[str] Retrieves the titles of all enabled documents in the bundle. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is True. -**Returns**: +#### Returns - `List[str]` - Titles of the enabled documents. -#### as\_pdf\_list(key: str = "final", refresh: bool = True, pdfa: bool = False) +### as\_pdf\_list ```python def as_pdf_list(key: str = "final", @@ -1647,20 +1648,20 @@ def as_pdf_list(key: str = "final", Returns all enabled documents in the bundle as individual PDFs, even from nested bundles. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute and regenerate the enabled documents, default is True. - `pdfa` _bool_ - Flag to return the documents in PDF/A format, default is False. -**Returns**: +#### Returns - `List[DAFile]` - List of enabled documents as individual PDFs. -#### as\_docx\_list(key: str = "final", refresh: bool = True) +### as\_docx\_list ```python def as_docx_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1670,19 +1671,19 @@ Generates a list of enabled documents from the bundle represented as DOCX files. If a particular document can't be represented as a DOCX, its original format or a PDF is returned. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is True. -**Returns**: +#### Returns - `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 ```python def as_editable_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -1692,19 +1693,19 @@ Generates a list of editable (DOCX or RTF) versions of the documents in the bund For documents that are not in DOCX or RTF formats, the original file format is returned. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `refresh` _bool_ - Flag to reconsider the 'enabled' attribute, default is True. -**Returns**: +#### Returns - `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 ```python def get_cacheable_documents( @@ -1733,7 +1734,7 @@ The result looks like this: DAFile, # Zip of whole bundle DAFile # PDF of whole bundle -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `pdf` _bool_ - Flag to include a PDF version of each file, default is True. @@ -1748,13 +1749,13 @@ DAFile # PDF of whole bundle - `zip_format` _Optional[str]_ - Format of the primary version of each document. -**Returns**: +#### Returns 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 ```python def download_list_html(key: str = "final", @@ -1783,7 +1784,7 @@ def download_list_html(key: str = "final", Constructs an HTML table displaying a list of documents with 'view' and 'download' buttons. -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `format` _str_ - Specifies the format of the files in the list. Can be "pdf", "docx", or "original". Default is "pdf". @@ -1810,13 +1811,13 @@ Constructs an HTML table displaying a list of documents with 'view' an - `zip_format` _Optional[str]_ - Format of the files in the zip archive. If None, defaults to value of "format" parameter. -**Returns**: +#### Returns - `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 ```python def download_html(key: str = "final", @@ -1835,7 +1836,7 @@ combined into one pdf with 'view' and 'download' buttons. Deprecated; use download_list_html instead -**Arguments**: +#### Arguments - `key` _str_ - Identifier for the document version, default is "final". - `format` _str_ - Specifies the format of the files in the list. Can be "pdf", "docx", or "original". Default is "pdf". @@ -1848,13 +1849,13 @@ Deprecated; use download_list_html instead - `download_icon` _str_ - Icon for the 'download' button, default is "download". -**Returns**: +#### Returns - `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 ```python def send_email_table_row(key: str = "final", @@ -1865,20 +1866,20 @@ def send_email_table_row(key: str = "final", Generate HTML doc table row for an input box and button that allows someone to send the bundle to the specified email address. -**Arguments**: +#### Arguments - `key` _str_ - A key used to identify which version of the ALDocument to send. Defaults to "final". - `send_label` _str_ - Label for the 'send' button. Default is "Send". - `send_icon` _str_ - Icon for the 'send' button. Default is "envelope". -**Returns**: +#### Returns - `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 ```python def send_button_to_html( @@ -1896,7 +1897,7 @@ Generate HTML for a button that allows someone to send the bundle to a specific email address. The email address is not editable by the end user in contrast to send_button_html. -**Arguments**: +#### Arguments - `email` _str_ - The recipient's email address. - `editable` _bool, optional_ - Flag indicating if the bundle is editable. Defaults to False. (deprecated; use preferred_formats instead) @@ -1908,13 +1909,13 @@ in contrast to send_button_html. - `preferred_formats` _Optional[Union[str,List[str]]], optional_ - A list of allowed formats for the document. Defaults to "pdf" if not specified. -**Returns**: +#### Returns - `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 ```python def send_button_html( @@ -1932,7 +1933,7 @@ to the specified email address. Optionally, display a checkbox that allows someone to decide whether or not to include an editable (Word) copy of the file, if and only if it is available. -**Arguments**: +#### Arguments - `key` _str, optional_ - A key used to identify which version of the ALDocument to send. Defaults to "final". - `show_editable_checkbox` _bool, optional_ - Flag indicating if the checkbox @@ -1946,13 +1947,13 @@ include an editable (Word) copy of the file, if and only if it is available. - `preferred_formats` _Optional[Union[str,List[str]]], optional_ - A list of allowed formats for the document. Defaults to "pdf" if not specified. -**Returns**: +#### Returns - `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 ```python def send_email(to: Any = None, @@ -1967,7 +1968,7 @@ Send an email with the current bundle as a series of flat pdfs (one per bundle e or as editable documents. This function is similar to https://docassemble.org/docs/functions.html#send_email with additional parameters. -**Arguments**: +#### Arguments - `to` _Any_ - The email address, list of email addresses, or list of Individuals with a .email attribute to send to. - `key` _str, optional_ - Specifies which version of the document to send. Defaults to "final". @@ -1977,13 +1978,13 @@ https://docassemble.org/docs/functions.html#send_email with additional parameter - `**kwargs` - Additional parameters to pass to the da `send_email` function. -**Returns**: +#### Returns - `bool` - Indicates if the email was sent successfully. -#### is\_enabled(refresh=True) +### is\_enabled ```python def is_enabled(refresh=True) -> bool @@ -1991,18 +1992,18 @@ def is_enabled(refresh=True) -> bool Check if the bundle itself is enabled, and if it has at least one enabled child document. -**Arguments**: +#### Arguments - `refresh` _bool_ - Whether to refresh the enabled status. Defaults to True. -**Returns**: +#### Returns - `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 ```python def as_docx(key: str = "final", @@ -2012,20 +2013,20 @@ def as_docx(key: str = "final", Convert the enabled documents to a single DOCX file or PDF file if conversion fails. -**Arguments**: +#### Arguments - `key` _str, optional_ - The key to identify enabled documents. Defaults to "final". - `refresh` _bool, optional_ - Refresh the enabled documents before conversion. Defaults to True. - `append_matching_suffix` _bool, optional_ - Append a matching suffix to the output filename. Defaults to True. -**Returns**: +#### Returns - `DAFile` - A DAFile object containing the concatenated DOCX or PDF file. -#### as\_list(key: str = "final", refresh: bool = True) +### as\_list ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -2033,13 +2034,13 @@ def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] Return a list of enabled documents. -**Arguments**: +#### Arguments - `key` _str, optional_ - The key to identify enabled documents. Defaults to "final". - `refresh` _bool, optional_ - Refresh the enabled documents before returning the list. Defaults to True. -**Returns**: +#### Returns - `List[DAFile]` - A list of enabled DAFile objects. @@ -2053,7 +2054,7 @@ class ALExhibit(DAObject) Class to represent a single exhibit, with cover page, which may contain multiple documents representing pages. -**Attributes**: +#### Attributes - `pages` _list_ - List of individual DAFiles representing uploaded images or documents. - `cover_page` _DAFile | DAFileCollection_ - (optional) A DAFile or DAFileCollection object created by an `attachment:` block @@ -2063,7 +2064,7 @@ Class to represent a single exhibit, with cover page, which may contain multiple -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -2071,14 +2072,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### ocr\_ready() +### ocr\_ready ```python def ocr_ready() -> bool @@ -2091,13 +2092,13 @@ OCR is complete. Will return true (but log a warning) if OCR was never started on the documents. That situation is likely a developer error, as you shouldn't wait for OCR if it never started -**Returns**: +#### Returns - `bool` - True iff OCR process has finished on all pages. -#### ocr\_pages() +### ocr\_pages ```python def ocr_pages() -> List[DAFile] @@ -2105,13 +2106,13 @@ def ocr_pages() -> List[DAFile] Retrieve the OCR-processed version of pages if available, else return the original pages. -**Returns**: +#### Returns - `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 ```python def as_pdf(*, @@ -2128,7 +2129,7 @@ Generates a PDF version of the exhibit, with optional features like Bates number Note that these are keyword only parameters, not positional. -**Arguments**: +#### Arguments - `refresh` _bool_ - If True, forces the exhibit to refresh before generating the PDF. (unused, provided for signature compatibility) - `prefix` _str_ - Prefix for Bates numbering if 'add_page_numbers' is True. @@ -2139,13 +2140,13 @@ Note that these are keyword only parameters, not positional. - `append_matching_suffix` _bool_ - If True, appends a suffix to the filename based on certain matching criteria. -**Returns**: +#### Returns - `DAFile` - PDF representation of the exhibit. -#### num\_pages() +### num\_pages ```python def num_pages() -> int @@ -2153,13 +2154,13 @@ def num_pages() -> int Calculate the total number of pages in the exhibit. -**Returns**: +#### Returns - `int` - Total page count. -#### complete() +### complete ```python @property @@ -2175,7 +2176,7 @@ NOTE: This property always returns True after triggering the required attributes -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -2183,13 +2184,13 @@ def __str__() -> str Return the title of the exhibit. -**Returns**: +#### Returns - `str` - Title of the exhibit. -#### ocrmypdf\_task(from\_file: Union[DAFile, DAFileList], to\_pdf: DAFile) +### ocrmypdf\_task ```python def ocrmypdf_task(from_file: Union[DAFile, DAFileList], @@ -2203,18 +2204,18 @@ For non-image files, the text in the file is skipped during OCR. This function is designed to be executed as a background task (id: al_exhibit_ocr_pages_bg). -**Arguments**: +#### Arguments - `from_file` _Union[DAFile, DAFileList]_ - The source file or list of files to be OCR-processed. - `to_pdf` _DAFile_ - The destination file where the OCR-processed output will be saved. -**Returns**: +#### Returns - `Optional[str]` - The path of the OCR-processed file if successful; None otherwise. -**Raises**: +#### Raises - `subprocess.TimeoutExpired` - If the ocrmypdf process takes longer than an hour. @@ -2229,7 +2230,7 @@ class ALExhibitList(DAList) A list representation of ALExhibit objects. Provides utility functions for managing exhibits and rendering them into a single PDF file. -**Attributes**: +#### Attributes - `maximum_size` _int_ - The maximum allowed size in bytes of the entire document. - `auto_label` _bool_ - If True, automatically numbers exhibits for cover page and table of contents. Defaults to True. @@ -2239,7 +2240,7 @@ and rendering them into a single PDF file. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -2247,14 +2248,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*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 ```python def as_pdf(filename="file.pdf", @@ -2266,7 +2267,7 @@ def as_pdf(filename="file.pdf", Compiles all exhibits in the list into a single PDF. -**Arguments**: +#### Arguments - `filename` _str_ - Desired filename for the generated PDF. - `pdfa` _bool_ - If True, generates the PDF in PDF/A format. @@ -2275,13 +2276,13 @@ Compiles all exhibits in the list into a single PDF. - `append_matching_suffix` _bool_ - If True, appends matching suffix to the filename. -**Returns**: +#### Returns - `DAFile` - A single PDF containing all exhibits. -#### size\_in\_bytes() +### size\_in\_bytes ```python def size_in_bytes() -> int @@ -2289,13 +2290,13 @@ def size_in_bytes() -> int Calculates the total size in bytes of all exhibits in the list. -**Returns**: +#### Returns - `int` - Total size of all exhibits in bytes. -#### ocr\_ready() +### ocr\_ready ```python def ocr_ready() -> bool @@ -2303,13 +2304,13 @@ def ocr_ready() -> bool Checks if all exhibits in the list have completed the OCR process. -**Returns**: +#### Returns - `bool` - True if all exhibits are OCRed or if OCR hasn't started. False otherwise. -#### hook\_after\_gather() +### hook\_after\_gather ```python def hook_after_gather() -> None @@ -2329,7 +2330,7 @@ class ALExhibitDocument(ALDocument) Represents a collection of uploaded documents, formatted like a record appendix or an exhibit list, complete with an optional table of contents and page numbering. -**Attributes**: +#### Attributes - `exhibits` _ALExhibitList_ - A list of ALExhibit documents. Each item represents a distinct exhibit, which can span multiple pages. @@ -2351,29 +2352,17 @@ or an exhibit list, complete with an optional table of contents and page numberi **Examples**: ``` ---- -objects: - - exhibit_attachment: ALExhibitDocument.using(title="Exhibits", filename="exhibits" ) ---- code: | # This block is not needed, but you can provide and customize for your needs. # This mirrors the fallback block in ql_baseline.yml exhibit_attachment.enabled = exhibit_attachment.exhibits.has_exhibits ---- -objects: - - al_user_bundle: ALDocumentBundle.using(elements=[my_instructions, my_main_attachment, exhibit_attachment], filename="user_bundle.pdf", title="All forms to download for your records") -``` - - Example of using a custom label function, https://docassemble.org/docs/functions.html#item_label: -``` ---- objects: - exhibit_attachment: ALExhibitDocument.using(title="Exhibits", filename="exhibits" , auto_labeler=item_label) ``` -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -2381,14 +2370,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### has\_overflow() +### has\_overflow ```python def has_overflow() -> bool @@ -2398,13 +2387,13 @@ Check if there is any overflow in the document. This is for compatibility with ALDocument; Exhibits inherently don't have overflow. -**Returns**: +#### Returns - `bool` - Always False for this implementation. -#### ocr\_ready() +### ocr\_ready ```python def ocr_ready() -> bool @@ -2412,13 +2401,13 @@ def ocr_ready() -> bool Determine if all exhibits within the document have undergone OCR processing. -**Returns**: +#### Returns - `bool` - True if all exhibits have been OCRed or if the OCR process hasn't been initiated. -#### \_\_getitem\_\_(key) +### \_\_getitem\_\_ ```python def __getitem__(key) @@ -2426,18 +2415,18 @@ def __getitem__(key) Overridden method to ensure 'final' and 'private' keys always reference the same file. -**Arguments**: +#### Arguments - `key` - The key to fetch the item. -**Returns**: +#### Returns - `ALExhibitDocument` - Returns the current instance of the class. -#### as\_list(key: str = "final", refresh: bool = True) +### as\_list ```python def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] @@ -2445,19 +2434,19 @@ def as_list(key: str = "final", refresh: bool = True) -> List[DAFile] Retrieve the document as a list. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document. Default is "final". - `refresh` _bool_ - If True, the document list will be refreshed. Default is True. -**Returns**: +#### Returns - `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 ```python def as_pdf(key: str = "final", @@ -2468,7 +2457,7 @@ def as_pdf(key: str = "final", Render the document as a PDF. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document. Default is "final". For compatibility with ALDocument. @@ -2478,13 +2467,13 @@ Render the document as a PDF. - `append_matching_suffix` _bool_ - If True, appends a matching suffix to the filename. -**Returns**: +#### Returns - `DAFile` - The document rendered as a PDF. -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) +### as\_docx ```python def as_docx(key: str = "final", @@ -2494,14 +2483,14 @@ def as_docx(key: str = "final", Despite the name, renders the document as a PDF. Provided for signature compatibility. -**Arguments**: +#### Arguments - `key` _str, optional_ - Identifier key for the document. Default is "final". - `refresh` _bool, optional_ - If True, refreshes the DOCX document. Default is True. - `append_matching_suffix` _bool, optional_ - If True, appends a matching suffix to the filename (for automated tests). -**Returns**: +#### Returns - `DAFile` - The document rendered as a PDF. @@ -2516,7 +2505,7 @@ class ALTableDocument(ALDocument) Represents a document tailored for table-like data presentation. This class provides functionality to export data as a table in various formats such as PDF and DOCX. -**Attributes**: +#### Attributes - `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". @@ -2525,7 +2514,7 @@ This class provides functionality to export data as a table in various formats s -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -2533,14 +2522,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### has\_overflow() +### has\_overflow ```python def has_overflow() -> bool @@ -2550,13 +2539,13 @@ Check for overflow in the document. For compatibility with ALDocument; Tables inherently don't have overflow. -**Returns**: +#### Returns - `bool` - Always False for this implementation. -#### \_\_getitem\_\_(key) +### \_\_getitem\_\_ ```python def __getitem__(key) @@ -2566,18 +2555,18 @@ Allows for index-based retrieval of a document. Overridden to ensure 'final' and 'private' keys always return the same document. -**Arguments**: +#### Arguments - `key` - The key to fetch the item. -**Returns**: +#### Returns - `DAFile` - The document in its PDF format. -#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) +### as\_list ```python def as_list(key: str = "final", @@ -2587,19 +2576,19 @@ def as_list(key: str = "final", Retrieve the document as a list. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document. Default is "final". - `refresh` _bool_ - If True, the document list will be refreshed. Default is True. -**Returns**: +#### Returns - `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 ```python def as_pdf(key: str = "final", @@ -2612,7 +2601,7 @@ def as_pdf(key: str = "final", Despite the name, returns the document as an Excel Spreadsheet (XLSX file). Name retained for signature compatibility. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document, mainly for compatibility with ALDocument. - `refresh` _bool_ - For signature compatibility @@ -2620,13 +2609,13 @@ Name retained for signature compatibility. - `append_matching_suffix` _bool_ - For signature compatibility -**Returns**: +#### Returns - `DAFile` - The table rendered as an XLSX spreadsheet -#### as\_docx(key: str = "bool", refresh: bool = True, append\_matching\_suffix: bool = True) +### as\_docx ```python def as_docx(key: str = "bool", @@ -2637,7 +2626,7 @@ def as_docx(key: str = "bool", Despite the name, returns the document as an Excel Spreadsheet (XLSX file). Name retained for signature compatibility. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document, mainly for compatibility with ALDocument. - `refresh` _bool_ - For signature compatibility @@ -2645,7 +2634,7 @@ Name retained for signature compatibility. - `append_matching_suffix` _bool_ - For signature compatibility -**Returns**: +#### Returns - `DAFile` - The table rendered as an XLSX spreadsheet @@ -2661,14 +2650,14 @@ Represents an untransformed document. The class provides methods to access the d without making any modifications to it. The provided methods are mainly for duck-typing compatibility with ALDocument. -**Attributes**: +#### Attributes - `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 ```python def init(*pargs, **kwargs) -> None @@ -2676,14 +2665,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### has\_overflow() +### has\_overflow ```python def has_overflow() -> bool @@ -2693,13 +2682,13 @@ Check for overflow in the document. For compatibility with ALDocument. Untransformed documents inherently don't have overflow. -**Returns**: +#### Returns - `bool` - Always False for this implementation. -#### as\_list(key: str = "final", refresh: bool = True, \*\*kwargs) +### as\_list ```python def as_list(key: str = "final", @@ -2709,19 +2698,19 @@ def as_list(key: str = "final", Retrieve the document as a list. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document. Default is "final". - `refresh` _bool_ - If True, the document list will be refreshed. Default is True. -**Returns**: +#### Returns - `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 ```python def as_pdf(key: str = "final", @@ -2735,7 +2724,7 @@ Fetch the document in its original form, without any transformations. This method is primarily for duck-typing compatibility with ALDocument. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document. Unused, but included for compatibility. - `refresh` _bool_ - If True, fetches the latest version of the document. Default is True. @@ -2743,13 +2732,13 @@ This method is primarily for duck-typing compatibility with ALDocument. - `append_matching_suffix` _bool_ - Unused argument for compatibility. -**Returns**: +#### Returns - `DAFile` - The original, untransformed document. -#### as\_docx(key: str = "final", refresh: bool = True, append\_matching\_suffix: bool = True) +### as\_docx ```python def as_docx(key: str = "final", @@ -2761,14 +2750,14 @@ Fetch the document in its original form, without any transformations. This method is primarily for duck-typing compatibility with ALDocument. -**Arguments**: +#### Arguments - `key` _str_ - Identifier key for the document. Default is "final". - `refresh` _bool_ - If True, fetches the latest version of the document. Default is True. - `append_matching_suffix` _bool_ - Unused argument for compatibility. -**Returns**: +#### Returns - `DAFile` - The original, untransformed document. @@ -2785,7 +2774,7 @@ ALExhibitDocument class. -#### unpack\_dafilelist(the\_file: DAFileList) +### unpack\_dafilelist ```python def unpack_dafilelist(the_file: DAFileList) -> DAFile @@ -2793,12 +2782,12 @@ def unpack_dafilelist(the_file: DAFileList) -> DAFile Creates a plain DAFile out of the first item in a DAFileList -**Arguments**: +#### Arguments - `the_file` _DAFileList_ - an item representing an uploaded document in a Docassemble interview -**Returns**: +#### Returns A DAFile representing the first item in the DAFileList, with a fixed instanceName attribute. diff --git a/docs/components/AssemblyLine/al_general.md b/docs/components/AssemblyLine/al_general.md index 006d007dd..8156cf637 100644 --- a/docs/components/AssemblyLine/al_general.md +++ b/docs/components/AssemblyLine/al_general.md @@ -1,4 +1,4 @@ -# Table of Contents +# AssemblyLine.al_general * [AssemblyLine.al\_general](#AssemblyLine.al_general) * [safe\_subdivision\_type](#AssemblyLine.al_general.safe_subdivision_type) @@ -74,9 +74,10 @@ * [parse\_custom\_pronouns](#AssemblyLine.al_general.parse_custom_pronouns) * [get\_visible\_al\_nav\_items](#AssemblyLine.al_general.get_visible_al_nav_items) -pydoc-module-header.hbs -#### safe\_subdivision\_type(country\_code: str) + + +### safe\_subdivision\_type ```python def safe_subdivision_type(country_code: str) -> Optional[str] @@ -85,12 +86,12 @@ def safe_subdivision_type(country_code: str) -> Optional[str] Returns the subdivision type for the country with the given country code. If no subdivision type is found, returns None. -**Arguments**: +#### Arguments - `country_code` _str_ - The ISO-3166-1 alpha-2 code for the country. -**Returns**: +#### Returns - `Optional[str]` - The subdivision type for the country with the given country code. @@ -106,7 +107,7 @@ This class is used to store addresses. The ALAddress class extends the Address class with the `address_fields()` method and "smarter" handling of the unit attribute when printing a formatted address. -**Attributes**: +#### Attributes - `address` _str_ - The street where the person lives. - `unit` _str_ - The unit number where the person lives. @@ -118,7 +119,7 @@ handling of the unit attribute when printing a formatted address. -#### 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 ```python def address_fields( @@ -142,7 +143,7 @@ rather than `users[0].address.address`. If `show_if` is used, it will not be app NOTE: This function is stateful under specific conditions. Refer to the conditions mentioned below. -**Arguments**: +#### Arguments - `country_code` _Optional[str]_ - ISO-3166-1 alpha-2 code of the country. Defaults to None. - `default_state` _Optional[str]_ - Default state to set. Defaults to None. @@ -155,12 +156,12 @@ NOTE: This function is stateful under specific conditions. Refer to the conditio - `required` _Dict[str, bool], optional_ - A dictionary of field names and if they should be required. Default is None (everything but unit and zip is required) -**Returns**: +#### Returns List[Dict[str, Any]]: A list of dictionaries representing address fields. -**Notes**: +#### Notes - The function will set the `country` attribute of the Address to `country_code` under these circumstances: @@ -173,7 +174,7 @@ NOTE: This function is stateful under specific conditions. Refer to the conditio -#### formatted\_unit(language: Optional[str] = None, require: bool = False, bare: bool = False) +### formatted\_unit ```python def formatted_unit(language: Optional[str] = None, @@ -183,7 +184,7 @@ def formatted_unit(language: Optional[str] = None, Returns the unit, formatted appropriately. -**Arguments**: +#### Arguments - `language` _str, optional_ - The language in which to format the unit. Defaults to None (which uses system language). - `require` _bool, optional_ - A flag indicating whether the unit is required. If set to True, the function will @@ -192,7 +193,7 @@ Returns the unit, formatted appropriately. True, the function will not add 'Unit' regardless of other conditions. Defaults to False. -**Returns**: +#### Returns str: The formatted unit. If the unit attribute does not exist and require is set to False, this will be an @@ -202,7 +203,7 @@ Returns the unit, formatted appropriately. -#### 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 ```python def block(language: Optional[str] = None, @@ -215,7 +216,7 @@ def block(language: Optional[str] = None, Returns a one-line formatted address, primarily for geocoding. -**Arguments**: +#### Arguments - `language` _str, optional_ - Language for the address format. - `international` _bool_ - If True, formats the address as an international address. Defaults to False. @@ -226,13 +227,13 @@ Returns a one-line formatted address, primarily for geocoding. - `show_impounded` _bool_ - If True, shows the address even if impounded. Defaults to False. -**Returns**: +#### Returns - `str` - The one-line formatted address. -#### line\_one(language: Optional[str] = None, bare: bool = False, show\_impounded: bool = False) +### line\_one ```python def line_one(language: Optional[str] = None, @@ -242,20 +243,20 @@ def line_one(language: Optional[str] = None, Returns the first line of the address, including the unit number if it exists. -**Arguments**: +#### Arguments - `language` _str, optional_ - Language for the address format. - `bare` _bool_ - If True, excludes certain formatting elements. Defaults to False. - `show_impounded` _bool_ - If True, shows the address even if impounded. Defaults to False. -**Returns**: +#### Returns - `str` - The first line of the address. -#### line\_two(language: Optional[str] = None, long\_state: bool = False, show\_impounded: bool = False) +### line\_two ```python def line_two(language: Optional[str] = None, @@ -265,20 +266,20 @@ def line_two(language: Optional[str] = None, Returns the second line of the address, including city, state, and postal code. -**Arguments**: +#### Arguments - `language` _str, optional_ - Language for the address format. - `long_state` _bool_ - If True, uses the full state name. Defaults to False. - `show_impounded` _bool_ - If True, shows the address even if impounded. Defaults to False. -**Returns**: +#### Returns - `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 ```python def on_one_line(include_unit: bool = True, @@ -292,7 +293,7 @@ def on_one_line(include_unit: bool = True, Returns a one-line formatted address. -**Arguments**: +#### Arguments - `include_unit` _bool_ - If True, includes the unit in the formatted address. Defaults to True. - `omit_default_country` _bool_ - If True, doesn't show the Docassemble default country in the formatted address. Defaults to True. @@ -304,13 +305,13 @@ Returns a one-line formatted address. - `show_impounded` _bool_ - If True, shows the address even if impounded. Defaults to False. -**Returns**: +#### Returns - `str` - The one-line formatted address. -#### normalized\_address() +### normalized\_address ```python def normalized_address() -> Union[Address, "ALAddress"] @@ -326,7 +327,7 @@ the version of the address as entered by the user. Warning: currently the normalized address will not be redacted if the address is impounded. -**Returns**: +#### Returns Union[Address, "ALAddress"]: Normalized address if geocoding is successful, otherwise @@ -334,7 +335,7 @@ Warning: currently the normalized address will not be redacted if the address is -#### state\_name(country\_code: Optional[str] = None) +### state\_name ```python def state_name(country_code: Optional[str] = None) -> str @@ -348,14 +349,14 @@ object. Otherwise, the method uses, in order: 1. The country code associated with the Address object, and then 2. The country set in the global config for the server. -**Arguments**: +#### Arguments - `country_code` _str, optional_ - ISO-3166-1 alpha-2 code to override the country attribute of the Address object. For valid codes, refer to: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements -**Returns**: +#### Returns - `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. @@ -376,7 +377,7 @@ of the list in a formatted manner. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -384,14 +385,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -402,7 +403,7 @@ Provide a string representation of the ALAddressList. This method returns the addresses in the list formatted in a comma-separated manner using the on_one_line method of ALAddress. -**Returns**: +#### Returns - `str` - Formatted string of all addresses in the list. @@ -420,7 +421,7 @@ Extends the DAList class and is tailored for IndividualName objects. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -428,14 +429,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -443,7 +444,7 @@ def __str__() -> str Provide a string representation of the ALNameList. -**Returns**: +#### Returns - `str` - Formatted string of all names in the list. @@ -461,7 +462,7 @@ For example, defendants, plaintiffs, or children. -#### init(\*pargs, \*\*kwargs) +### init ```python def init(*pargs, **kwargs) -> None @@ -469,14 +470,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### names\_and\_addresses\_on\_one\_line(comma\_string: str = "; ", bare=False) +### names\_and\_addresses\_on\_one\_line ```python def names_and_addresses_on_one_line(comma_string: str = "; ", @@ -485,19 +486,19 @@ def names_and_addresses_on_one_line(comma_string: str = "; ", Provide names and addresses of individuals on one line. -**Arguments**: +#### Arguments - `comma_string` _str, optional_ - The string to use between name-address pairs. Defaults to '; '. - `bare` _bool, optional_ - If True, prevents appending the word "Unit" to the unit attribute. Defaults to False. -**Returns**: +#### Returns - `str` - Formatted string of names followed by addresses. -#### familiar(\*\*kwargs) +### familiar ```python def familiar(**kwargs) -> str @@ -505,17 +506,17 @@ def familiar(**kwargs) -> str Provide a list of familiar forms of names of individuals. -**Arguments**: +#### Arguments - `**kwargs` - Keyword arguments to pass to the familiar method. -**Returns**: +#### Returns - `str` - Formatted string of familiar names. -#### familiar\_or(\*\*kwargs) +### familiar\_or ```python def familiar_or(**kwargs) -> str @@ -523,18 +524,18 @@ def familiar_or(**kwargs) -> str Provide a list of familiar forms of names of individuals separated by 'or'. -**Arguments**: +#### Arguments - `**kwargs` - Keyword arguments to pass to the familiar method. -**Returns**: +#### Returns - `str` - Formatted string of familiar names separated by 'or'. -#### short\_list(limit: int, truncate\_string: str = ", et. al.") +### short\_list ```python def short_list(limit: int, truncate_string: str = ", et. al.") -> str @@ -542,19 +543,19 @@ def short_list(limit: int, truncate_string: str = ", et. al.") -> str Return a subset of the list, truncated with 'et. al.' if it exceeds a given limit. -**Arguments**: +#### Arguments - `limit` _int_ - The maximum number of items to display before truncating. - `truncate_string` _str, optional_ - The string to append when truncating. Defaults to ', et. al.'. -**Returns**: +#### Returns - `str` - Formatted string of names, truncated if needed. -#### full\_names(comma\_string=", ", and\_string=word("and")) +### full\_names ```python def full_names(comma_string=", ", and_string=word("and")) -> str @@ -562,19 +563,19 @@ def full_names(comma_string=", ", and_string=word("and")) -> str Return a formatted list of full names of individuals. -**Arguments**: +#### Arguments - `comma_string` _str, optional_ - The string to use between names. Defaults to ','. - `and_string` _str, optional_ - The string to use before the last name in the list. Defaults to 'and'. -**Returns**: +#### Returns - `str` - Formatted string of full names. -#### pronoun\_reflexive(\*\*kwargs) +### pronoun\_reflexive ```python def pronoun_reflexive(**kwargs) -> str @@ -586,14 +587,14 @@ on the `person` keyword argument and the number of items in the list. If the list is singular, return the reflexive pronoun for the first item in the list. If it is plural, return the appropriate plural reflexive pronoun (e.g., "themselves") -**Arguments**: +#### Arguments - `**kwargs` - Additional keyword arguments that are defined [upstream](https://docassemble.org/docs/objects.html#language%20methods). - person (Optional[[Union[str,int]]): Whether to use a first, second, or third person pronoun. Can be one of 1/"1p", 2/"2p", or 3/"3p" (default is 3). See [upstream](https://docassemble.org/docs/objects.html#language%20methods) documentation for more information. - default (Optional[str]): The default word to use if the pronoun is not defined, e.g. "the agent". If not defined, the default term is the user's name. -**Returns**: +#### Returns - `str` - The reflexive pronoun for the list. @@ -611,7 +612,7 @@ This class extends the Individual class and adds more tailored attributes and me relevant for the assembly line project. Specifically, it has attributes for previous addresses, other addresses, mailing addresses, previous names, aliases, and a preferred name. -**Attributes**: +#### Attributes - `previous_addresses` _ALAddressList_ - List of previous addresses. - `other_addresses` _ALAddressList_ - List of other addresses. @@ -622,14 +623,14 @@ other addresses, mailing addresses, previous names, aliases, and a preferred nam - `preferred_name` _IndividualName_ - The preferred name. -**Notes**: +#### Notes 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 ```python def init(*pargs, **kwargs) -> None @@ -637,14 +638,14 @@ def init(*pargs, **kwargs) -> None Standard DAObject init method. -**Arguments**: +#### Arguments - `*pargs` - Positional arguments - `**kwargs` - Keyword arguments -#### signature\_if\_final(i: str) +### signature\_if\_final ```python def signature_if_final(i: str) -> Union[DAFile, str] @@ -652,18 +653,18 @@ def signature_if_final(i: str) -> Union[DAFile, str] Returns the individual's signature if `i` is "final", which usually means we are assembling the final version of the document (as opposed to a preview). -**Arguments**: +#### Arguments - `i` _str_ - The condition which, if set to "final", returns the signature. -**Returns**: +#### Returns 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 ```python def phone_numbers(country: Optional[str] = None, @@ -680,19 +681,19 @@ Supports the following attributes: - `other_number`: Any other phone number - `home_number`: Home phone number (if applicable) -**Arguments**: +#### Arguments - `country` _str, optional_ - The country for phone number formatting. Defaults to the country of the docassemble server. - `show_impounded` _bool_ - If True, shows the phone numbers even if impounded. Defaults to False. -**Returns**: +#### Returns - `str` - Formatted string of phone numbers. -#### contact\_methods() +### contact\_methods ```python def contact_methods() -> str @@ -700,13 +701,13 @@ def contact_methods() -> str Generates a formatted string of all provided contact methods. -**Returns**: +#### Returns - `str` - A formatted string indicating the available methods to contact the individual. -#### merge\_letters(new\_letters: str) +### merge\_letters ```python def merge_letters(new_letters: str) -> None @@ -716,13 +717,13 @@ If the Individual has a child_letters attribute, add the new letters to the exis Avoid using. Only used in 209A. -**Arguments**: +#### Arguments - `new_letters` _str_ - The new letters to add to the existing list of letters -#### formatted\_age() +### formatted\_age ```python def formatted_age() -> str @@ -730,13 +731,13 @@ def formatted_age() -> str Calculates and formats the age of the individual based on their birthdate. -**Returns**: +#### Returns - `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 ```python def normalized_address() -> Union[Address, ALAddress] @@ -744,13 +745,13 @@ def normalized_address() -> Union[Address, ALAddress] Fetches the normalized version of the address. -**Returns**: +#### Returns 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 ```python def name_fields( @@ -768,7 +769,7 @@ def name_fields( Generates suitable field prompts for a name based on the type of entity (person or business) and other provided parameters. -**Arguments**: +#### Arguments - `person_or_business` _str, optional_ - Specifies the entity type. It can either be "person" or "business". Default is "person". @@ -785,19 +786,19 @@ and other provided parameters. - `title_options` - (Union[List[str], Callable], optional): Deprecated parameter, use `title_choices` instead. If provided, it will be used to set the title choices. -**Returns**: +#### Returns List[Dict[str, str]]: A list of dictionaries where each dictionary contains field prompt details. -**Notes**: +#### Notes 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 ```python def address_fields( @@ -814,7 +815,7 @@ def address_fields( Generate field prompts for capturing an address. -**Arguments**: +#### Arguments - `country_code` _str_ - The default country for the address. Defaults to "US". - `default_state` _Optional[str]_ - Default state if applicable. Defaults to None. @@ -827,13 +828,13 @@ Generate field prompts for capturing an address. - `required` _Dict[str, bool], optional_ - A dictionary of field names and if they should be required. Default is None (everything but unit and zip is required) -**Returns**: +#### Returns 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 ```python def gender_fields( @@ -847,7 +848,7 @@ def gender_fields( Generate fields for capturing gender information, including a self-described option. -**Arguments**: +#### Arguments - `show_help` _bool_ - Whether to show additional help text. Defaults to False. - `show_if` _Union[str, Dict[str, str], None]_ - Condition to determine if the field should be shown. Defaults to None. @@ -855,18 +856,18 @@ self-described option. - `choices` _Optional[Union[List[Dict[str, str]], Callable]]_ - A list of choices of genders to use in the prompts, or a callable that returns such a list. Default set of choices includes male, female, nonbinary, prefer-not-to-say, self-described, and unknown. -**Returns**: +#### Returns List[Dict[str, str]]: A list of dictionaries with field prompts for gender. -**Notes**: +#### Notes 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 ```python def pronoun_fields( @@ -882,7 +883,7 @@ def pronoun_fields( Generate fields for capturing pronoun information. -**Arguments**: +#### Arguments - `show_help` _bool_ - Whether to show additional help text. Defaults to False. - `show_if` _Union[str, Dict[str, str], None]_ - Condition to determine if the field should be shown. Defaults to None. @@ -893,13 +894,13 @@ Generate fields for capturing pronoun information. - `choices` _Optional[List[Dict[str, str]]]_ - A list of custom pronoun choices. Defaults to None. If not provided, global magic variable `al_pronoun_choices` will be used. -**Returns**: +#### Returns List[Dict[str, str]]: A list of dictionaries with field prompts for pronouns. -#### get\_pronouns() +### get\_pronouns ```python def get_pronouns() -> set @@ -911,13 +912,13 @@ If the individual has selected the "self-described" option, it will us Can be formatted however the author likes. -**Returns**: +#### Returns - `set` - A set of strings representing the individual's pronouns. -#### list\_pronouns() +### list\_pronouns ```python def list_pronouns() -> str @@ -926,13 +927,13 @@ def list_pronouns() -> str Retrieve a formatted string of the individual's pronouns, arranged with the comma_list() function. -**Returns**: +#### Returns - `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 ```python def language_fields( @@ -944,7 +945,7 @@ def language_fields( Generate fields for capturing language preferences. -**Arguments**: +#### Arguments - `choices` _Optional[Union[List[Dict[str, str]], Callable]]_ - A list or callable of language choices. Defaults to None. - `style` _str_ - The display style of choices. Defaults to "radio". @@ -952,13 +953,13 @@ Generate fields for capturing language preferences. - `maxlengths` _Dict[str, int], optional_ - A dictionary of field names and their maximum lengths. Default is None. -**Returns**: +#### Returns List[Dict[str, str]]: A list of dictionaries with field prompts for language preferences. -#### language\_name() +## language\_name ```python def language_name() -> str @@ -966,7 +967,7 @@ def language_name() -> str Get the human-readable version of the individual's selected language. -**Returns**: +#### Returns - `str` - The human-readable version of the language. If 'other' is selected, it returns the value in `language_other`. Otherwise, it uses the @@ -974,7 +975,7 @@ Get the human-readable version of the individual's selected language. -#### gender\_male() +### gender\_male ```python @property @@ -988,7 +989,7 @@ turned on. -#### gender\_female() +### gender\_female ```python @property @@ -1002,7 +1003,7 @@ turned on. -#### gender\_other() +### gender\_other ```python @property @@ -1016,7 +1017,7 @@ turned on. -#### gender\_nonbinary() +### gender\_nonbinary ```python @property @@ -1030,7 +1031,7 @@ turned on. -#### gender\_unknown() +### gender\_unknown ```python @property @@ -1044,7 +1045,7 @@ turned on. -#### gender\_undisclosed() +### gender\_undisclosed ```python @property @@ -1058,7 +1059,7 @@ turned on. -#### gender\_self\_described() +### gender\_self\_described ```python @property @@ -1072,7 +1073,7 @@ turned on. -#### contact\_fields() +### contact\_fields ```python def contact_fields() -> None @@ -1082,7 +1083,7 @@ Return field prompts for other contact info -#### initials() +### initials ```python @property @@ -1095,7 +1096,7 @@ For example, "Quinten K Steenhuis" would return "QKS". -#### address\_block(language=None, international=False, show\_country=False, bare=False, show\_impounded=False) +### address\_block ```python def address_block(language=None, @@ -1107,7 +1108,7 @@ def address_block(language=None, Generate a formatted address block for mailings. -**Arguments**: +#### Arguments - `language` _Optional_ - The language in which the address is written. - `international` _bool_ - If True, format for international mailing. Defaults to False. @@ -1116,13 +1117,13 @@ Generate a formatted address block for mailings. - `show_impounded` _bool_ - If True, show the address even if it is impounded. Defaults to False. -**Returns**: +#### Returns - `str` - The formatted address block. -#### pronoun(\*\*kwargs) +### pronoun ```python def pronoun(**kwargs) -> str @@ -1136,19 +1137,19 @@ If the user has selected multiple pronouns, each will appear, separated by a &qu This method will not trigger the definition of `gender` or `pronouns`, but it will use them if they are defined, with `pronouns` taking precedence. As a default, it will either use the value of `default` or the individual's full name. -**Arguments**: +#### Arguments - `**kwargs` - Additional keyword arguments that are defined [upstream](https://docassemble.org/docs/objects.html#language%20methods). - person (Optional[[Union[str,int]]): Whether to use a first, second, or third person pronoun. Can be one of 1/"1p", 2/"2p", or 3/"3p" (default is 3). See [upstream](https://docassemble.org/docs/objects.html#language%20methods) documentation for more information. - default (Optional[str]): The default word to use if the pronoun is not defined, e.g. "the agent". If not defined, the default term is the user's name. -**Returns**: +#### Returns - `str` - The appropriate pronoun. -#### pronoun\_objective(\*\*kwargs) +### pronoun\_objective ```python def pronoun_objective(**kwargs) -> str @@ -1156,18 +1157,18 @@ def pronoun_objective(**kwargs) -> str Returns the same pronoun as the `pronoun()` method. -**Arguments**: +#### Arguments - `**kwargs` - Additional keyword arguments. -**Returns**: +#### Returns - `str` - The appropriate objective pronoun. -#### pronoun\_possessive(target, \*\*kwargs) +### pronoun\_possessive ```python def pronoun_possessive(target, **kwargs) -> str @@ -1182,7 +1183,7 @@ Given a target word, the function returns "\{pronoun\} \{target\}". Th "my", "her," "his," "its," or "their". It depends on the `gender` and `person_type` attributes and whether the individual is the current user. -**Arguments**: +#### Arguments - `target` _str_ - The target word to follow the pronoun. - `**kwargs` - Additional keyword arguments that can be passed to modify the behavior. These might include: @@ -1190,13 +1191,13 @@ and whether the individual is the current user. - `person` (Optional[Union[str, int]]): Whether to use a first, second, or third person pronoun. Can be one of 1/"1p", 2/"2p", or 3/"3p" (default is 3). See [upstream documentation](https://docassemble.org/docs/objects.html#language%20methods) for more information. -**Returns**: +#### Returns - `str` - The appropriate possessive phrase, e.g., "her book", "their document". -#### pronoun\_subjective(\*\*kwargs) +### pronoun\_subjective ```python def pronoun_subjective(**kwargs) -> str @@ -1208,19 +1209,19 @@ The pronoun could be "you," "we", "she," "he, on the `gender` and `person_type` attributes and whether the individual is the current user. -**Arguments**: +#### Arguments - `**kwargs` - Additional keyword arguments that are defined [upstream](https://docassemble.org/docs/objects.html#language%20methods). - person (Optional[[Union[str,int]]): Whether to use a first, second, or third person pronoun. Can be one of 1/"1p", 2/"2p", or 3/"3p" (default is 3). See [upstream](https://docassemble.org/docs/objects.html#language%20methods) documentation for more information. - default (Optional[str]): The default word to use if the pronoun is not defined, e.g. "the agent". If not defined, the default term is the user's name. -**Returns**: +#### Returns - `str` - The appropriate subjective pronoun. -#### pronoun\_reflexive(\*\*kwargs) +### pronoun\_reflexive ```python def pronoun_reflexive(**kwargs) -> str @@ -1233,20 +1234,20 @@ Note that if the person has pronouns of they/them/theirs or a nonbinary gender, reflexive pronoun and not "themselves". This has growing acceptance although some consider it nonstandard. See: https://www.merriam-webster.com/wordplay/themself -**Arguments**: +#### Arguments - `**kwargs` - Additional keyword arguments that are defined [upstream](https://docassemble.org/docs/objects.html#language%20methods). - person (Optional[[Union[str,int]]): Whether to use a first, second, or third person pronoun. Can be one of 1/"1p", 2/"2p", or 3/"3p" (default is 3). See [upstream](https://docassemble.org/docs/objects.html#language%20methods) documentation for more information. - default (Optional[str]): The default word to use if the pronoun is not defined, e.g. "the agent". If not defined, the default term is the user's name. -**Returns**: +#### Returns - `str` - The appropriate reflexive pronoun. -#### name\_full() +### name\_full ```python def name_full() -> str @@ -1258,13 +1259,13 @@ If the person has the attribute person_type and it is defined as either `business` or `organization`, it will only return the first name, even if middle, last, or suffix are defined. -**Returns**: +#### Returns - `str` - The individual or business's full name. -#### name\_initials() +### name\_initials ```python def name_initials() -> str @@ -1278,13 +1279,13 @@ If the person has the attribute person_type and it is defined as either `business` or `organization`, it will only return the "initials" of the first name, even if middle, last, or suffix are defined. -**Returns**: +#### Returns - `str` - The individual's name with the middle name as an initial. -#### name\_short() +### name\_short ```python def name_short() -> str @@ -1298,13 +1299,13 @@ If the person has the attribute person_type and it is defined as either `business` or `organization`, it will only return the first name, even if middle, last, or suffix are defined. -**Returns**: +#### Returns - `str` - The individual' -#### familiar(unique\_names: Optional[List[Any]] = None, default: Optional[str] = None) +### familiar ```python def familiar(unique_names: Optional[List[Any]] = None, @@ -1332,13 +1333,13 @@ If the person has the attribute `person_type` and it is defined as either `business` or `organization`, it will only return the first name, even if middle, last, or suffix are defined. -**Arguments**: +#### Arguments - `unique_names` _Optional[List[Any]]_ - A list of unique names to compare against. Defaults to None. - `default` _Optional[str]_ - The default name to return if no unique name is found. Defaults to None. -**Returns**: +#### Returns - `str` - The individual's name in the most familiar form possible. @@ -1351,7 +1352,7 @@ the first name, even if middle, last, or suffix are defined. -#### \_\_str\_\_() +### \_\_str\_\_ ```python def __str__() -> str @@ -1364,13 +1365,13 @@ If the individual has the attribute `person_type` and it is defined as either `business` or `organization`, it will only return the first name, even if middle, last, or suffix are defined. -**Returns**: +#### Returns - `str` - The individual's name. -#### section\_links(nav) +## section\_links ```python def section_links(nav) -> List[str] @@ -1378,18 +1379,18 @@ def section_links(nav) -> List[str] Returns a list of clickable navigation links without animation. -**Arguments**: +#### Arguments - `nav` - The navigation object. -**Returns**: +#### Returns - `List[str]` - A list of clickable navigation links without animation. -#### will\_send\_to\_real\_court() +## will\_send\_to\_real\_court ```python def will_send_to_real_court() -> bool @@ -1400,13 +1401,13 @@ is being run on the dev, test, or production server. The text "dev" or "test" needs to be in the URL root in the DA config: can change in `/config`. -**Returns**: +#### Returns - `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 ```python def filter_letters(letter_strings: Union[List[str], str]) -> str @@ -1416,18 +1417,18 @@ Used to take a list of letters like ["A","ABC","AB" Avoid using, this is created for 209A. -**Arguments**: +#### Arguments - `letter_strings` _Union[List[str], str]_ - A list of letters. -**Returns**: +#### Returns - `str` - A string of unique letters. -#### fa\_icon(icon: str, color: str = "primary", color\_css: Optional[str] = None, size: str = "sm") +## fa\_icon ```python def fa_icon(icon: str, @@ -1440,7 +1441,7 @@ Return HTML for a font-awesome icon of the specified size and color. You can ref a CSS variable (such as Bootstrap theme color) or a true CSS color reference, such as 'blue' or '`DDDDDD`'. Defaults to Bootstrap theme color "primary". -**Arguments**: +#### Arguments - `icon` _str_ - The name of the icon to use. See https://fontawesome.com/icons for a list of icons. - `color` _str_ - The color of the icon. Defaults to "primary". @@ -1448,13 +1449,13 @@ a CSS variable (such as Bootstrap theme color) or a true CSS color reference, su - `size` _str_ - The size of the icon. Defaults to "sm". -**Returns**: +#### Returns - `str` - HTML for the icon. -#### is\_sms\_enabled() +## is\_sms\_enabled ```python def is_sms_enabled() -> bool @@ -1464,13 +1465,13 @@ Checks if SMS (Twilio) is enabled on the server. Does not verify that it works. See https://docassemble.org/docs/config.html#twilio for more info. -**Returns**: +#### Returns - `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 ```python def is_phone_or_email(text: str) -> bool @@ -1481,23 +1482,23 @@ If SMS is not enabled on the server (through the Twilio config), only accepts em Email validation is extremely minimal--just checks for an @ sign between two non-zero length strings. -**Arguments**: +#### Arguments - `text` _str_ - The string to check. -**Returns**: +#### Returns - `bool` - True if the string is either a valid phone number or a valid email address. -**Raises**: +#### Raises 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 ```python def github_modified_date(github_user: str, @@ -1524,20 +1525,20 @@ type: basic If no valid auth information is in the configuration, it will fall back to anonymous authentication. The GitHub API is rate-limited to 60 anonymous API queries/hour. -**Arguments**: +#### Arguments - `github_user` _str_ - The GitHub username of the repository owner. - `github_repo_name` _str_ - The name of the repository. - `auth` _Optional[dict]_ - A dictionary containing authentication information. Defaults to None. -**Returns**: +#### Returns 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 ```python def language_name(language_code: str) -> str @@ -1547,18 +1548,18 @@ Given a 2 digit language code abbreviation, returns the full name of the language. The language name will be passed through the `word()` function. -**Arguments**: +#### Arguments - `language_code` _str_ - A 2 digit language code abbreviation. -**Returns**: +#### Returns - `str` - The full name of the language. -#### safe\_states\_list(country\_code: str) +## safe\_states\_list ```python def safe_states_list(country_code: str) -> List[Dict[str, str]] @@ -1567,18 +1568,18 @@ def safe_states_list(country_code: str) -> List[Dict[str, str]] Wrapper around states_list that doesn't error if passed an invalid country_code (e.g., a country name spelled out) -**Arguments**: +#### Arguments - `country_code` _str_ - A 2 digit country code abbreviation. -**Returns**: +#### Returns List[Dict[str, str]]: A list of dictionaries with field prompts for states. -#### has\_parsable\_pronouns(pronouns: str) +## has\_parsable\_pronouns ```python def has_parsable_pronouns(pronouns: str) -> bool @@ -1586,18 +1587,18 @@ def has_parsable_pronouns(pronouns: str) -> bool Returns True if the pronouns string can be parsed into a dictionary of pronouns. -**Arguments**: +#### Arguments - `pronouns` - a string of pronouns in the format "objective/subjective/possessive" -**Returns**: +#### Returns True if the pronouns string can be parsed into a dictionary of pronouns, False otherwise -#### parse\_custom\_pronouns(pronouns: str) +## parse\_custom\_pronouns ```python def parse_custom_pronouns(pronouns: str) -> Dict[str, str] @@ -1605,18 +1606,18 @@ def parse_custom_pronouns(pronouns: str) -> Dict[str, str] Parses a custom pronoun string into a dictionary of pronouns. -**Arguments**: +#### Arguments - `pronouns` - a string of pronouns in the format "objective/subjective/possessive" -**Returns**: +#### Returns 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 ```python def get_visible_al_nav_items( @@ -1635,12 +1636,12 @@ data = [ \{"key2": [\{"subkey": "subvalue", "hidden": False\}, \{"subkey": "subvalue2", "hidden": True\}]\}, ] -**Arguments**: +#### Arguments - `nav_items` - a list of nav items -**Returns**: +#### Returns a list of nav items with hidden items removed diff --git a/docs/components/AssemblyLine/custom_jinja_filters.md b/docs/components/AssemblyLine/custom_jinja_filters.md index ce7f9a074..6c2aa9ff3 100644 --- a/docs/components/AssemblyLine/custom_jinja_filters.md +++ b/docs/components/AssemblyLine/custom_jinja_filters.md @@ -1,4 +1,4 @@ -# Table of Contents +# AssemblyLine.custom_jinja_filters * [AssemblyLine.custom\_jinja\_filters](#AssemblyLine.custom_jinja_filters) * [catchall\_options](#AssemblyLine.custom_jinja_filters.catchall_options) @@ -9,9 +9,10 @@ * [if\_final](#AssemblyLine.custom_jinja_filters.if_final) * [catchall\_fields\_code](#AssemblyLine.custom_jinja_filters.catchall_fields_code) -pydoc-module-header.hbs -#### catchall\_options(value: Any, \*raw\_items: Any) + + +### catchall\_options ```python def catchall_options(value: Any, *raw_items: Any) -> DACatchAll @@ -44,47 +45,6 @@ Example in an interview with `features: use catchall: True` turned on: \{\{ my_catchall_field_2 | catchall_options(\{"code1": "label1"\}, \{"code2": "label2"\}) \}\} ``` ``` ---- -if: | - hasattr(x, "_catchall_options") -generic object: DACatchAll -question: | - $\{ x.object_name() \}? -fields: - - $\{ x.object_name() \}: x.value - code: x._catchall_options -``` - -**Arguments**: - -- `value` _DACatchAll_ - The DACatchAll object to which the options will be assigned. -- `*raw_items` - A variable number of arguments representing the options to be added. - -**Returns**: - -- `DACatchAll` - The modified DACatchAll object with the assigned options. - - - -#### catchall\_label(value: Any, label: str) - -```python -def catchall_label(value: Any, label: str) -> DACatchAll -``` - -Jinja2 filter to allow you to define a label for a DACatchAll field inside a DOCX template. - -This filter takes a label string and assigns it to the `label` attribute of the -DACatchAll object. This label can be used to provide a more descriptive name for the -catchall field in the user interface. - -Example usage in a DOCX template: -Example in an interview with `features: use catchall: True` turned on: -``` -\{\{ my_catchall_field | catchall_label("My Custom Label") \}\} -``` -``` ---- generic object: DACatchAll question: | $\{ x.label if hasattr(x, "label") else x.object_name() \}? @@ -92,19 +52,19 @@ fields: - $\{ x.label if hasattr(x, "label") else x.object_name() \}: x.value ``` -**Arguments**: +#### Arguments - `value` _DACatchAll_ - The DACatchAll object to which the label will be assigned. - `label` _str_ - The label string to assign to the DACatchAll object. -**Returns**: +#### Returns - `DACatchAll` - The modified DACatchAll object with the assigned label. -#### catchall\_datatype(value: Any, datatype: str) +### catchall\_datatype ```python def catchall_datatype(value: Any, datatype: str) -> DACatchAll @@ -122,19 +82,19 @@ Example usage in a DOCX template: \{\{ my_catchall_field | catchall_datatype("radio") \}\} ``` -**Arguments**: +#### Arguments - `value` _DACatchAll_ - The DACatchAll object to which the datatype will be assigned. - `datatype` _str_ - The datatype string to assign to the DACatchAll object. -**Returns**: +#### Returns - `DACatchAll` - The modified DACatchAll object with the assigned datatype. -#### catchall\_question(value: Any, question: str) +### catchall\_question ```python def catchall_question(value: Any, question: str) -> DACatchAll @@ -152,19 +112,19 @@ Example usage in a DOCX template: \{\{ my_catchall_field | catchall_question("What additional information do you need?") \}\} ``` -**Arguments**: +#### Arguments - `value` _DACatchAll_ - The DACatchAll object to which the question will be assigned. - `question` _str_ - The question string to assign to the DACatchAll object. -**Returns**: +#### Returns - `DACatchAll` - The modified DACatchAll object with the assigned question. -#### catchall\_subquestion(value: Any, subquestion: str) +### catchall\_subquestion ```python def catchall_subquestion(value: Any, subquestion: str) -> DACatchAll @@ -182,26 +142,26 @@ Example usage in a DOCX template: \{\{ my_catchall_field | catchall_subquestion("Please provide additional details.") \}\} ``` -**Arguments**: +#### Arguments - `value` _DACatchAll_ - The DACatchAll object to which the subquestion will be assigned. - `subquestion` _str_ - The subquestion string to assign to the DACatchAll object. -**Returns**: +#### Returns - `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 ```python @pass_context def if_final(context: Jinja2Context, value: Any, i: Optional[str] = None, - expected_i: Union[str, List[str]] = "final", + expected_values: Union[str, List[str]] = "final", placeholder: Optional[str] = None) -> Any ``` @@ -263,24 +223,24 @@ as in an ALDocument's "preview" or "final" values. ``` -**Arguments**: +#### Arguments - `context` _Jinja2Context_ - The Jinja2 context, automatically passed by the `pass_context` decorator. - `value` _Any_ - The original value as passed to the filter. - `i` _str, optional_ - The current value of `i`. If not provided, it will be fetched from the context. -- `expected_i` _Union[str, List[str]], optional_ - The expected value(s) of `i` to trigger passthrough of `value`. +- `expected_values` _Union[str, List[str]], optional_ - The expected value(s) of `i` to trigger returning `value`. Defaults to "final". - `placeholder` _str, optional_ - The placeholder string to return if the condition is not met. If not provided, a default placeholder will be generated based on the variable name. -**Returns**: +#### Returns -- `Any` - The original `value` if `i` matches `expected_i`, otherwise the `placeholder`. +- `Any` - The original `value` if `i` matches `expected_values`, otherwise the `placeholder`. -#### catchall\_fields\_code(value: Any) +### catchall\_fields\_code ```python def catchall_fields_code(value: Any) -> List[Dict[str, Any]] @@ -288,11 +248,11 @@ def catchall_fields_code(value: Any) -> List[Dict[str, Any]] Create Docassemble code for a catchall field with the appropriate datatypes. -**Arguments**: +#### Arguments - `value` _DACatchAll_ - The DACatchAll object containing the question and options. -**Returns**: +#### Returns List[Dict[str, Any]]: A dictionary containing the Docassemble code for the catchall question. diff --git a/docs/components/AssemblyLine/language.md b/docs/components/AssemblyLine/language.md index 05fb20183..a0ade6bbc 100644 --- a/docs/components/AssemblyLine/language.md +++ b/docs/components/AssemblyLine/language.md @@ -1,4 +1,4 @@ -# Table of Contents +# AssemblyLine.language * [AssemblyLine.language](#AssemblyLine.language) * [get\_local\_languages\_yaml](#AssemblyLine.language.get_local_languages_yaml) @@ -8,9 +8,10 @@ * [get\_language\_list](#AssemblyLine.language.get_language_list) * [get\_language\_list\_item](#AssemblyLine.language.get_language_list_item) -pydoc-module-header.hbs -#### get\_local\_languages\_yaml() + + +### get\_local\_languages\_yaml ```python def get_local_languages_yaml() -> str @@ -18,13 +19,13 @@ def get_local_languages_yaml() -> str Get the path to the local languages.yml file. If it does not exist, it will return the path to the languages.yml -**Returns**: +#### Returns - `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 ```python def get_tuples(lang_codes: List[str], @@ -36,19 +37,19 @@ Returns a list of tuples representing the language name, followed by language IS It will use the native_name value from the languages.yml file if available, otherwise it will use the English name from pycountry. If neither is present, it will use the language code itself. -**Arguments**: +#### Arguments - `lang_codes` - a list of ISO 639-1 language codes (e.g. ['en', 'es']) - `languages_path` - the path to the languages.yml file (defaults to data/sources/languages.yml) -**Returns**: +#### Returns 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 ```python def get_language_list_dropdown(lang_codes: List[str], @@ -61,7 +62,7 @@ def get_language_list_dropdown(lang_codes: List[str], Get a Bootstrap 5 dropdown menu for language selection that can be added to navigation bar. -**Arguments**: +#### Arguments - `lang_codes` - a list of ISO 639-1 language codes (e.g. ['en', 'es']) - `current` - the current language code @@ -70,13 +71,13 @@ Get a Bootstrap 5 dropdown menu for language selection that can be added to navi - `icon` - the name of the icon to use for the dropdown menu (defaults to fa-solid fa-language fa-xl) - `extra_class` - additional classes to add to the link -**Returns**: +#### Returns 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 ```python def get_language_list_dropdown_item(language: Tuple[str, str], @@ -87,20 +88,20 @@ def get_language_list_dropdown_item(language: Tuple[str, str], Given an ordered tuple, returns a link to the current interview with lang=language code and the link title given in the first part of the tuple. -**Arguments**: +#### Arguments - `language` - a tuple containing the language name and language code - `link` - whether to return a link or just the text - `event_name` - the name of the event to trigger when the language is changed -**Returns**: +#### Returns - `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\_change\_language") +### get\_language\_list ```python def get_language_list(languages: Optional[List[Tuple[str, str]]] = None, @@ -116,7 +117,7 @@ a Bootstrap-formatted unordered inline list. The current language will not be a Deprecated behavior: instead of a list of language codes, you can provide list of tuples containing the language name and language code. This is deprecated and may be removed in a future version. -**Arguments**: +#### Arguments - `languages` - a list of tuples containing the language name and language code (deprecated) - `current` - the current language code @@ -125,13 +126,13 @@ tuples containing the language name and language code. This is deprecated and ma - `event_name` - the name of the event to trigger when the language is changed -**Returns**: +#### Returns 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 ```python def get_language_list_item(language, @@ -142,14 +143,14 @@ def get_language_list_item(language, Given an ordered tuple, returns a link to the current interview with lang=language code and the link title given in the first part of the tuple. -**Arguments**: +#### Arguments - `language` - a tuple containing the language name and language code - `link` - whether to return a link or just the text - `event_name` - the name of the event to trigger when the language is changed -**Returns**: +#### Returns - `str` - A string containing the HTML for an unordered inline list item for language selection. diff --git a/docs/components/AssemblyLine/sessions.md b/docs/components/AssemblyLine/sessions.md index 2b6f6fdbb..3d19e2f3d 100644 --- a/docs/components/AssemblyLine/sessions.md +++ b/docs/components/AssemblyLine/sessions.md @@ -1,4 +1,4 @@ -# Table of Contents +# AssemblyLine.sessions * [AssemblyLine.sessions](#AssemblyLine.sessions) * [is\_file\_like](#AssemblyLine.sessions.is_file_like) @@ -30,9 +30,10 @@ * [update\_session\_metadata](#AssemblyLine.sessions.update_session_metadata) * [update\_current\_session\_metadata](#AssemblyLine.sessions.update_current_session_metadata) -pydoc-module-header.hbs -#### is\_file\_like(obj: Any) + + +### is\_file\_like ```python def is_file_like(obj: Any) -> bool @@ -40,18 +41,18 @@ def is_file_like(obj: Any) -> bool Return True if the object is a file-like object. -**Arguments**: +#### Arguments - `obj` _Any_ - The object to test -**Returns**: +#### Returns - `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 ```python def set_interview_metadata(filename: str, @@ -68,7 +69,7 @@ Standardized metadata dictionary: - original_interview_filename - variable_count -**Arguments**: +#### Arguments - `filename` _str_ - The filename of the interview to add metadata for - `session_id` _str_ - The session ID of the interview to add metadata for @@ -77,7 +78,7 @@ Standardized metadata dictionary: -#### get\_interview\_metadata(filename: str, session\_id: str, metadata\_key\_name: str = "metadata") +### get\_interview\_metadata ```python def get_interview_metadata( @@ -89,20 +90,20 @@ def get_interview_metadata( Retrieve the unencrypted metadata associated with an interview. We implement this with the docassemble jsonstorage table and a dedicated `tag` which defaults to `metadata`. -**Arguments**: +#### Arguments - `filename` _str_ - The filename of the interview to retrieve metadata for - `session_id` _str_ - The session ID of the interview to retrieve metadata for - `metadata_key_name` _str, optional_ - The name of the metadata key. Defaults to "metadata". -**Returns**: +#### Returns 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 ```python def get_saved_interview_list( @@ -128,7 +129,7 @@ and likely do not need to be resumed, it will also have the side effect of exclu results. Answer sets generally have exactly one "step", which is the step where information was copied from an existing interview to the answer set. -**Arguments**: +#### Arguments - `filename` _str, optional_ - The filename of the interview to retrieve sessions for. Defaults to al_session_store_default_filename. - `user_id` _Union[int, str, None], optional_ - The user ID to retrieve sessions for. Defaults to None. @@ -141,13 +142,13 @@ an existing interview to the answer set. - `exclude_newly_started_sessions` _bool, optional_ - Whether to exclude sessions that are still on "step 1". Defaults to False. -**Returns**: +#### Returns 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 ```python def find_matching_sessions( @@ -172,7 +173,7 @@ Get a list of sessions where the metadata for the session matches the provided k This function is designed to be used in a search interface where the user can search for sessions by keyword and specific metadata values. The keyword search is case-insensitive and will match any part of the metadata column values. -**Arguments**: +#### Arguments - `keyword` _str_ - The keyword to search for in the metadata - `metadata_column_names` _List[str], optional_ - The names of the metadata columns to search. If not provided, defaults to ["title", "auto_title", "description"]. @@ -193,7 +194,7 @@ The keyword search is case-insensitive and will match any part of the metadata c - cast_type: Optional. One of 'int', 'float', or None for string (default) -**Returns**: +#### Returns List[Dict[str, Any]]: A list of saved sessions for the specified filename that match the search keyword and metadata filters @@ -218,7 +219,7 @@ The keyword search is case-insensitive and will match any part of the metadata c -#### 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 ```python def delete_interview_sessions( @@ -231,7 +232,7 @@ Delete all sessions for the specified user, excluding the current filename and by default, the intentionally saved "answer sets". Created because interview_list(action="delete_all") is both quite slow and because it deletes answer sets. -**Arguments**: +#### Arguments - `user_id` _Optional[int], optional_ - The user ID to delete sessions for. Defaults to None. - `filename_to_exclude` _str, optional_ - The filename to exclude from the results. Defaults to al_session_store_default_filename. @@ -239,7 +240,7 @@ interview_list(action="delete_all") is both quite slow and because it -#### 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 ```python def interview_list_html(filename: str = al_session_store_default_filename, @@ -272,7 +273,7 @@ designed when inside an AssemblyLine line interview. are on "page 1" (exactly 1 step was taken to copy the answers and the user isn't able to interact with the answer set itself in a way that adds additional steps) -**Arguments**: +#### Arguments - `filename` _str, optional_ - Name of the file. Defaults to `al_session_store_default_filename`. - `user_id` _Union[int, str, None], optional_ - User's ID. Defaults to None. @@ -293,13 +294,13 @@ itself in a way that adds additional steps) - `answers` _Optional[List[Dict[str, Any]]], optional_ - A list of answers to format and display. Defaults to showing all sessions for the current user. -**Returns**: +#### Returns - `str` - HTML-formatted table containing the list of saved answers. -#### nice\_interview\_title(answer: Dict[str, str]) +### nice\_interview\_title ```python def nice_interview_title(answer: Dict[str, str]) -> str @@ -311,18 +312,18 @@ in descending priority order. 1. Try removing the package and path from the filename and replace _ with spaces. 4. Finally, return "Untitled interview" or translated phrase from system-wide words.yml -**Arguments**: +#### Arguments - `answer` _Dict[str, str]_ - The answer dictionary to get the interview title from -**Returns**: +#### Returns - `str` - The human readable interview title -#### pascal\_to\_zwspace(text: str) +### pascal\_to\_zwspace ```python def pascal_to_zwspace(text: str) -> str @@ -331,18 +332,18 @@ def pascal_to_zwspace(text: str) -> str Insert a zero-width space into words that are PascalCased to help with word breaks on small viewports. -**Arguments**: +#### Arguments - `text` _str_ - The text to insert zero-width spaces into -**Returns**: +#### Returns - `str` - The text with zero-width spaces inserted -#### nice\_interview\_subtitle(answer: Dict[str, str], exclude\_identical=True) +### nice\_interview\_subtitle ```python def nice_interview_subtitle(answer: Dict[str, str], @@ -353,19 +354,19 @@ Return first defined of the "title" metadata, the "auto_title&quo If exclude_identical, return empty string when title is the same as the subtitle. -**Arguments**: +#### Arguments - `answer` _Dict[str, str]_ - The answer dictionary to get the interview subtitle from - `exclude_identical` _bool, optional_ - If True, excludes the subtitle if it is identical to the title. Defaults to True. -**Returns**: +#### Returns - `str` - The human readable interview subtitle -#### radial\_progress(answer: Dict[str, Union[str, int]]) +### radial\_progress ```python def radial_progress(answer: Dict[str, Union[str, int]]) -> str @@ -373,18 +374,18 @@ def radial_progress(answer: Dict[str, Union[str, int]]) -> str Return HTML for a radial progress bar, or the number of steps if progress isn't available in the metadata. -**Arguments**: +#### Arguments - `answer` _Dict[str, Union[str, int]]_ - The answer dictionary to get the interview progress from -**Returns**: +#### Returns - `str` - the HTML as a string -#### local\_date(utcstring: Optional[str]) +### local\_date ```python def local_date(utcstring: Optional[str]) -> DADateTime @@ -392,18 +393,18 @@ def local_date(utcstring: Optional[str]) -> DADateTime Return a localized date from a UTC string. -**Arguments**: +#### Arguments - `utcstring` _Optional[str]_ - The UTC string to convert to a localized date -**Returns**: +#### Returns - `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 ```python def session_list_html( @@ -435,7 +436,7 @@ Return a string containing an HTML-formatted table with the list of user session While interview_list_html() is for answer sets, this feature is for standard user sessions. The results exclude the answer set filename by default. -**Arguments**: +#### Arguments - `filename` _Optional[str], optional_ - Name of the file. Defaults to None. - `user_id` _Union[int, str, None], optional_ - User's ID. Defaults to None. @@ -462,13 +463,13 @@ user sessions. The results exclude the answer set filename by default. -**Returns**: +#### Returns - `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 ```python def rename_interview_answers(filename: str, @@ -480,7 +481,7 @@ def rename_interview_answers(filename: str, Update the 'title' metadata of an interview, as stored in the dedicated `metadata` column, without touching other metadata that may be present. -**Arguments**: +#### Arguments - `filename` _str_ - The filename of the interview to rename - `session_id` _str_ - The session ID of the interview to rename @@ -491,7 +492,7 @@ metadata that may be present. -#### set\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") +### set\_current\_session\_metadata ```python def set_current_session_metadata(data: Dict[str, Any], @@ -500,14 +501,14 @@ def set_current_session_metadata(data: Dict[str, Any], Set metadata for the current session, such as the title, in an unencrypted database entry. -**Arguments**: +#### Arguments - `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 ```python def rename_current_session(new_name: str, @@ -517,14 +518,14 @@ def rename_current_session(new_name: str, Update the "title" metadata entry for the current session without changing any other metadata that might be present. -**Arguments**: +#### Arguments - `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 ```python def save_interview_answers(filename: str = al_session_store_default_filename, @@ -540,7 +541,7 @@ def save_interview_answers(filename: str = al_session_store_default_filename, Copies the answers from a given session into a new session with a specified interview filename. -**Arguments**: +#### Arguments - `filename` _str, optional_ - The desired filename for the new session. Defaults to `al_session_store_default_filename`. - `variables_to_filter` _Union[Set[str], List[str], None], optional_ - The "base" list or set of variables to filter out. Defaults to `al_sessions_variables_to_remove`. There's usually no reason to change this and changing it might break sessions. @@ -552,13 +553,13 @@ Copies the answers from a given session into a new session with a specified inte - `additional_variables_to_filter` _Union[Set[str], List[str], None], optional_ - List or set of variables to filter out. Defaults to None. -**Returns**: +#### Returns - `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 ```python def get_filtered_session_variables( @@ -573,7 +574,7 @@ Retrieves a filtered subset of variables from a specified interview and session. If no filename and session ID are given, it will return a filtered list of variables from the current interview. -**Arguments**: +#### Arguments - `filename` _Optional[str], optional_ - Filename of the session. Defaults to None. - `session_id` _Optional[int], optional_ - Session ID to retrieve variables from. Defaults to None. @@ -581,13 +582,13 @@ from the current interview. - `additional_variables_to_filter` _Union[Set[str], List[str], None], optional_ - List or set of additional variables to exclude. Defaults to None. -**Returns**: +#### Returns 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 ```python def get_filtered_session_variables_string( @@ -602,7 +603,7 @@ def get_filtered_session_variables_string( Returns a JSON string that represents the filtered contents of a specified filename and session ID. If no filename and session ID are provided, the current session's variables will be used. -**Arguments**: +#### Arguments - `filename` _Optional[str], optional_ - Filename of the session. Defaults to None. - `session_id` _Optional[int], optional_ - Session ID to retrieve variables from. Defaults to None. @@ -611,13 +612,13 @@ If no filename and session ID are provided, the current session's variables - `indent` _int, optional_ - Number of spaces to indent the JSON string. Defaults to 4. -**Returns**: +#### Returns - `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 ```python def load_interview_answers( @@ -634,7 +635,7 @@ Loads answers from a specified session. If the parameter `new_session` is set to a new session with the provided or current interview filename. Otherwise, it will load the answers into the active session. This function is primarily used for migrating answers between sessions. -**Arguments**: +#### Arguments - `old_interview_filename` _str_ - Filename of the old interview. - `old_session_id` _str_ - Session ID of the old interview. @@ -644,13 +645,13 @@ the active session. This function is primarily used for migrating answers betwee - `additional_variables_to_filter` _Optional[List[str]], optional_ - List of additional variables to exclude. Defaults to None. -**Returns**: +#### Returns 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 ```python def load_interview_json( @@ -664,7 +665,7 @@ Given a JSON string, this function loads the specified variables into a Docassem JSON strings containing annotated class names will be transformed into Docassemble objects. If the `new_session` argument is not set, the JSON answers will be loaded into the current interview. -**Arguments**: +#### Arguments - `json_string` _str_ - A JSON-formatted string containing session variables. - `new_session` _bool, optional_ - Specifies whether to create a new session or load into the current one. Defaults to False. @@ -672,13 +673,13 @@ If the `new_session` argument is not set, the JSON answers will be loaded into t - `variables_to_filter` _Optional[List[str]], optional_ - List of variables to exclude. Defaults to None. -**Returns**: +#### Returns 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 ```python def export_interview_variables( @@ -694,7 +695,7 @@ Generates a DAFile containing a JSON representation of a specified session' The resultant output is compatible with `set_session_variables(process_objects=True)` and `set_variables(process_objects=True)` methods. -**Arguments**: +#### Arguments - `filename` _Optional[str], optional_ - Filename of the session. Defaults to None. - `session_id` _Optional[int], optional_ - Session ID to retrieve variables from. Defaults to None. @@ -703,13 +704,13 @@ The resultant output is compatible with `set_session_variables(process_objects=T - `additional_variables_to_filter` _Union[Set, List[str], None], optional_ - List or set of additional variables to exclude. Defaults to None. -**Returns**: +#### Returns - `DAFile` - DAFile with a JSON representation of the answers -#### is\_valid\_json(json\_string: str) +### is\_valid\_json ```python def is_valid_json(json_string: str) -> bool @@ -717,18 +718,18 @@ def is_valid_json(json_string: str) -> bool Checks if the provided string is a valid JSON-formatted string. -**Arguments**: +#### Arguments - `json_string` _str_ - The string to be checked for JSON validity. -**Returns**: +#### Returns - `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 ```python def config_with_language_fallback( @@ -751,19 +752,19 @@ en: In progress forms es: Formularios en progreso short title: My forms -**Arguments**: +#### Arguments - `config_key` _str_ - The config key to look up. The config can be a single string or a dictionary with language keys. - `top_level_config_key` _str, optional_ - Optional, alternative top-level config key to look up. Defaults to None. -**Returns**: +#### Returns - `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 ```python def get_filenames_having_sessions( @@ -775,19 +776,19 @@ def get_filenames_having_sessions( Get a list of all filenames that have sessions saved for a given user, in order to help show the user a good list of interviews to filter search results. -**Arguments**: +#### Arguments - `user_id` _Optional[Union[int, str]], optional_ - User ID to get the list of filenames for. Defaults to current logged-in user. Use "all" to get all filenames. - `global_search_allowed_roles` _Optional[Union[Set[str], List[str]]], optional_ - Roles that are allowed to search for all sessions. Defaults to admin, developer, and advocate. -**Returns**: +#### Returns - `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 ```python def get_combined_filename_list( @@ -803,19 +804,19 @@ it will show that instead of the filename. The results will be in the form of [\{filename: Descriptive name\}], which is what the Docassemble radio button and dropdown list expect. -**Arguments**: +#### Arguments - `user_id` _Optional[Union[int, str]], optional_ - User ID to get the list of filenames for. Defaults to current logged in user. Use "all" to get all filenames. - `global_search_allowed_roles` _Optional[Union[Set[str], List[str]]], optional_ - Roles that are allowed to search for all sessions. Defaults to admin, developer, and advocate. -**Returns**: +#### Returns 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 ```python def update_session_metadata(filename: str, @@ -827,7 +828,7 @@ def update_session_metadata(filename: str, Upsert session metadata into jsonstorage using a PostgreSQL advisory lock (two-int form) to serialize concurrent upserts on the same (session_id,filename,tags) key. -**Arguments**: +#### Arguments - `filename` - The filename of the interview session to update. - `session_id` - The ID of the session to update. @@ -836,7 +837,7 @@ Upsert session metadata into jsonstorage using a PostgreSQL advisory lock -#### update\_current\_session\_metadata(data: Dict[str, Any], metadata\_key\_name: str = "metadata") +### update\_current\_session\_metadata ```python def update_current_session_metadata(data: Dict[str, Any], @@ -849,7 +850,7 @@ Updates metadata for the current session without retrieving the data first. This is a wrapper for update_session_metadata() that uses the current interview's filename and session ID from current_context(). -**Arguments**: +#### Arguments - `data` _Dict[str, Any]_ - A dictionary of metadata to add or update. - `metadata_key_name` _str, optional_ - The tag for the metadata in the diff --git a/docs/components/AssemblyLine/sign.md b/docs/components/AssemblyLine/sign.md index 8edc2f498..bb0ba06a1 100644 --- a/docs/components/AssemblyLine/sign.md +++ b/docs/components/AssemblyLine/sign.md @@ -1,13 +1,14 @@ -# 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) -pydoc-module-header.hbs -#### find\_font\_file\_by\_name(font\_name: str, search\_dirs: List[str]) + + +### find\_font\_file\_by\_name ```python def find_font_file_by_name(font_name: str, @@ -20,19 +21,19 @@ This function appends '.ttf' to the font name if it is not already pre searches through each directory in `search_dirs` recursively for a file that matches the font name (case-insensitive). -**Arguments**: +#### Arguments - `font_name` _str_ - The name of the font to search for (without path). - `search_dirs` _List[str]_ - A list of directories to search. -**Returns**: +#### Returns - `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 ```python def get_font( @@ -48,19 +49,19 @@ name (without a path). In the latter case, the function will search for the font `/var/www/.fonts` and `/usr/share/fonts/truetype/`, automatically appending '.ttf' if necessary. If no font is found, the function falls back to the default Pillow font. -**Arguments**: +#### Arguments - `font_name` _Optional[str]_ - The desired font's full path or name. Defaults to None. - `font_size` _int_ - The size of the font to be used. Defaults to 48. -**Returns**: +#### Returns - `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 ```python def create_signature(name: str, @@ -77,7 +78,7 @@ The signature image is generated by combining the provided `signature_prefix` create an image with appropriate dimensions, and then the text is drawn onto a white background. The final image is saved to the specified output file path. -**Arguments**: +#### Arguments - `name` _str_ - The person's name to be signed. - `output_file` _str_ - The full file path where the image will be written. diff --git a/docs/components/EFSPIntegration/conversions.md b/docs/components/EFSPIntegration/conversions.md index 6325a1ed9..928b8462e 100644 --- a/docs/components/EFSPIntegration/conversions.md +++ b/docs/components/EFSPIntegration/conversions.md @@ -1,4 +1,4 @@ -# Table of Contents +# EFSPIntegration.conversions * [EFSPIntegration.conversions](#EFSPIntegration.conversions) * [error\_notification](#EFSPIntegration.conversions.error_notification) @@ -18,11 +18,12 @@ * [filing\_id\_and\_label](#EFSPIntegration.conversions.filing_id_and_label) * [get\_tyler\_roles](#EFSPIntegration.conversions.get_tyler_roles) -pydoc-module-header.hbsFunctions that help convert the JSON-ized XML from the proxy server into usable information. + +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 ```python def error_notification(err, @@ -40,7 +41,7 @@ Some slight modifications to work without server backends -#### log\_error\_and\_notify(context: str, resp: Optional[ApiResponse] = None) +### log\_error\_and\_notify ```python def log_error_and_notify(context: str, resp: Optional[ApiResponse] = None) @@ -51,7 +52,7 @@ the `error_notification_email` in the config. -#### convert\_court\_to\_id(trial\_court) +### convert\_court\_to\_id ```python def convert_court_to_id(trial_court) -> str @@ -64,18 +65,18 @@ A fairly ad-hoc function; it will check if the object has several attributes tries to just make a lower case on the string. We strongly recommend that your court object use the "tyler_court_code" attribute though. -**Arguments**: +#### Arguments - `trial_court` - the court object -**Returns**: +#### Returns 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 ```python def choices_and_map(codes_list: List[Dict[str, Any]], @@ -86,7 +87,7 @@ def choices_and_map(codes_list: List[Dict[str, Any]], Takes the responses from the 'codes' service and make a DA ready list of choices and a map back to the full code object -**Arguments**: +#### Arguments - `codes_list` - should be the direct response from a 'codes' service, i.e. `proxy_conn.get_case_categories(court_id).data` - `display` - a python format string, where the input variables are the keys of the individual code elements. By @@ -94,7 +95,7 @@ to the full code object - `backing` - the key to each dict element in the codes_list that you want to use as the "canonical" representation of the code, i.e. each is unique, and there aren't conflicts -**Returns**: +#### Returns a tuple; first, a list of the codes that can be used at the `choices` in a docassemble field, second, a map of each code, from the backing key to the full code element. Useful for getting @@ -102,7 +103,7 @@ to the full code object -#### pretty\_display(data, tab\_depth=0, skip\_xml=True, item\_name=None) +### pretty\_display ```python def pretty_display(data, tab_depth=0, skip_xml=True, item_name=None) -> str @@ -111,7 +112,7 @@ def pretty_display(data, tab_depth=0, skip_xml=True, item_name=None) -> str Given an arbitrarily nested JSON structure, print it nicely as markdown. Recursive, for subsequent calls `tab_depth` increases. -**Arguments**: +#### Arguments - `data` - the JSON structure (python dicts, lists, strings and ints) to print - `tab_depth` - how many spaces to add before each new line, to make the markdown correct @@ -120,13 +121,13 @@ Recursive, for subsequent calls `tab_depth` increases. - `item_name` - when recursing, will show the parent's name when showing elements in a list -**Returns**: +#### Returns The string of markdown text that displays info about the given JSON structure -#### debug\_display(resp: ApiResponse) +### debug\_display ```python def debug_display(resp: ApiResponse) -> str @@ -137,18 +138,18 @@ or it's data run through [pretty_display](#pretty_display) -#### tyler\_daterep\_to\_datetime(tyler\_daterep: Mapping) +### tyler\_daterep\_to\_datetime ```python 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 repsents. +returns the datetime it represents. -#### tyler\_timestamp\_to\_datetime(timestamp\_ms: int) +### tyler\_timestamp\_to\_datetime ```python def tyler_timestamp_to_datetime(timestamp_ms: int) -> DADateTime @@ -158,7 +159,7 @@ Given a timestamp in milliseconds from epoch (in UTC), make a datetime from it -#### validate\_tyler\_regex(data\_field: Mapping) +### validate\_tyler\_regex ```python def validate_tyler_regex(data_field: Mapping) -> Callable[[str], Any] @@ -169,7 +170,7 @@ suitable for use with Docassemble's `validate:` question modifier -#### parse\_service\_contacts(service\_list) +### parse\_service\_contacts ```python def parse_service_contacts(service_list) @@ -181,7 +182,7 @@ 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 ```python def parse_case_info(proxy_conn: ProxyConnection, @@ -195,7 +196,7 @@ def parse_case_info(proxy_conn: ProxyConnection, Given sparse information about a case, gets the full details about it -**Arguments**: +#### Arguments - `proxy_conn` - the connection to the EFileProxyServer - `new_case` - the object to hold all of the information about the case @@ -208,7 +209,7 @@ Given sparse information about a case, gets the full details about it -#### fetch\_case\_info(proxy\_conn: ProxyConnection, new\_case: DAObject, roles: Optional[dict] = None) +### fetch\_case\_info ```python def fetch_case_info(proxy_conn: ProxyConnection, @@ -228,7 +229,7 @@ Fills in these attributes with the full case details: -#### filter\_payment\_accounts(account\_list, allowable\_card\_types: List) +### filter\_payment\_accounts ```python def filter_payment_accounts(account_list, allowable_card_types: List) -> List @@ -237,7 +238,7 @@ def filter_payment_accounts(account_list, allowable_card_types: List) -> List Gets a list of all payment accounts and filters them by if the card is accepted at a particular court. -**Arguments**: +#### Arguments account_list: - `allowable_card_types` - a list of the accepted card types at a court, usually @@ -245,13 +246,13 @@ accepted at a particular court. [get_full_court_info](interview_logic#get_full_court_info)'s response -**Returns**: +#### Returns the list of payment account choices that are valid for a particular court -#### payment\_account\_labels(resp: ApiResponse) +### payment\_account\_labels ```python def payment_account_labels(resp: ApiResponse) -> Optional[List[Dict]] @@ -261,7 +262,7 @@ Returns all payment accounts as choices, without filters. -#### filing\_id\_and\_label(case: Mapping, style: str = "FILING\_ID") +### filing\_id\_and\_label ```python def filing_id_and_label(case: Mapping, @@ -274,7 +275,7 @@ for that filing. -#### get\_tyler\_roles(proxy\_conn: ProxyConnection, login\_data: Optional[Mapping], user\_details: Optional[ApiResponse] = None) +### 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 97adb9160..badd8537f 100644 --- a/docs/components/EFSPIntegration/efm_client.md +++ b/docs/components/EFSPIntegration/efm_client.md @@ -1,4 +1,4 @@ -# Table of Contents +# EFSPIntegration.efm_client * [EFSPIntegration.efm\_client](#EFSPIntegration.efm_client) * [ProxyConnection](#EFSPIntegration.efm_client.ProxyConnection) @@ -8,7 +8,8 @@ * [get\_service\_types](#EFSPIntegration.efm_client.ProxyConnection.get_service_types) * [serialize\_person](#EFSPIntegration.efm_client.serialize_person) -pydoc-module-header.hbs + + ## ProxyConnection Objects @@ -23,7 +24,7 @@ and are documented there. -#### \_\_init\_\_(\*, url: str = None, api\_key: str = None, credentials\_code\_block: str = "tyler\_login", default\_jurisdiction: str = None) +### \_\_init\_\_ ```python def __init__(*, @@ -38,7 +39,7 @@ 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 ```python def authenticate_user(tyler_email: str = None, @@ -55,7 +56,7 @@ jeffnet_key (str) -#### register\_user(person: Union[Individual, dict], registration\_type: str, \*, password: str = None, firm\_name\_or\_id: str = None) +### register\_user ```python def register_user(person: Union[Individual, dict], @@ -71,7 +72,7 @@ If it's FIRM_ADMINISTRATOR or FIRM_ADMIN_NEW_MEMBER, you need a firm_name_o -#### get\_service\_types(court\_id: str, court\_bundle: Union[ALDocumentBundle, dict] = None) +### get\_service\_types ```python def get_service_types( @@ -83,7 +84,7 @@ Checks the court info: if it has conditional service types, call a special API w -#### serialize\_person(person: Union[Person, Individual]) +### 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 8c9efd27f..4c38a4b1c 100644 --- a/docs/components/EFSPIntegration/interview_logic.md +++ b/docs/components/EFSPIntegration/interview_logic.md @@ -1,4 +1,4 @@ -# Table of Contents +# EFSPIntegration.interview_logic * [EFSPIntegration.interview\_logic](#EFSPIntegration.interview_logic) * [EFCaseSearch](#EFSPIntegration.interview_logic.EFCaseSearch) @@ -13,7 +13,8 @@ * [filter\_codes](#EFSPIntegration.interview_logic.filter_codes) * [get\_available\_efile\_courts](#EFSPIntegration.interview_logic.get_available_efile_courts) -pydoc-module-header.hbsA group of methods that were code blocks in various parts of the EFSP + +A group of methods that were code blocks in various parts of the EFSP package, but for better python tooling support, were moved here. @@ -28,7 +29,7 @@ A data-class that has holds all of the information and state for a single case s -#### search\_went\_wrong() +### search\_went\_wrong ```python def search_went_wrong() -> bool @@ -38,7 +39,7 @@ Returns true if something errored during the case search process -#### get\_lookup\_choices(can\_file\_non\_indexed\_case: bool) +### get\_lookup\_choices ```python def get_lookup_choices( @@ -55,7 +56,7 @@ for each choice. -#### num\_case\_choices() +### num\_case\_choices ```python def num_case_choices() -> int @@ -66,7 +67,7 @@ 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 ```python def search_case_by_name(*, @@ -83,7 +84,7 @@ 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 ```python def shift_case_select_window(proxy_conn, @@ -100,7 +101,7 @@ for a few cases at a time -#### get\_full\_court\_info(proxy\_conn, court\_id: str) +### get\_full\_court\_info ```python def get_full_court_info(proxy_conn, court_id: str) -> Dict @@ -110,7 +111,7 @@ Gets all of the information about the court from the id -#### get\_max\_allowed\_sizes(proxy\_conn, court\_id: str) +### get\_max\_allowed\_sizes ```python def get_max_allowed_sizes(proxy_conn, @@ -121,7 +122,7 @@ Returns attachment max size, then message max size -#### make\_filter(search: Union[Callable[..., bool], SearchType, None]) +### make\_filter ```python def make_filter( @@ -137,7 +138,7 @@ 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 ```python def filter_codes( @@ -153,7 +154,7 @@ Given a list of filter functions from most specific to least specific, -#### get\_available\_efile\_courts(proxy\_conn) +### 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 5416129f4..76069fe09 100644 --- a/docs/components/EFSPIntegration/py_efsp_client.md +++ b/docs/components/EFSPIntegration/py_efsp_client.md @@ -1,4 +1,4 @@ -# Table of Contents +# EFSPIntegration.py_efsp_client * [EFSPIntegration.py\_efsp\_client](#EFSPIntegration.py_efsp_client) * [EfspConnection](#EFSPIntegration.py_efsp_client.EfspConnection) @@ -16,7 +16,8 @@ * [get\_service\_types](#EFSPIntegration.py_efsp_client.EfspConnection.get_service_types) * [get\_cases\_raw](#EFSPIntegration.py_efsp_client.EfspConnection.get_cases_raw) -pydoc-module-header.hbsThe base python client used to communicate with the E-file proxy server. + +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. @@ -32,13 +33,13 @@ A python client that communicates with the E-file proxy server. -#### \_\_init\_\_(\*, url: str, api\_key: str, default\_jurisdiction: str = None) +### \_\_init\_\_ ```python def __init__(*, url: str, api_key: str, default_jurisdiction: str = None) ``` -**Arguments**: +#### Arguments url (str) api_key (str) @@ -46,7 +47,7 @@ def __init__(*, url: str, api_key: str, default_jurisdiction: str = None) -#### authenticate\_user(\*, tyler\_email: Optional[str] = None, tyler\_password: Optional[str] = None, jeffnet\_key: Optional[str] = None, jurisdiction: str = None) +### authenticate\_user ```python def authenticate_user(*, @@ -60,7 +61,7 @@ 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 ```python def register_user(person: dict, @@ -76,7 +77,7 @@ If it's FIRM_ADMINISTRATOR or FIRM_ADMIN_NEW_MEMBER, you need a firm_name_o -#### get\_password\_rules() +### get\_password\_rules ```python def get_password_rules() -> ApiResponse @@ -88,7 +89,7 @@ TODO: They're in other courts too, including 1. Could they ever be differen -#### get\_notification\_options() +### get\_notification\_options ```python def get_notification_options() -> ApiResponse @@ -98,7 +99,7 @@ AKA NotificationPreferencesList -#### get\_firm() +### get\_firm ```python def get_firm() -> ApiResponse @@ -109,7 +110,7 @@ contains their address information. -#### update\_firm(firm: dict) +### update\_firm ```python def update_firm(firm: dict) -> ApiResponse @@ -124,7 +125,7 @@ firm should have the below keys: -#### get\_courts(fileable\_only: bool = False, with\_names: bool = False) +### get\_courts ```python def get_courts(fileable_only: bool = False, @@ -135,7 +136,7 @@ Gets the list of courts. -#### get\_court(court\_id: str) +### get\_court ```python def get_court(court_id: str) -> ApiResponse @@ -145,7 +146,7 @@ Gets codes for a specific court -#### get\_court\_list() +### get\_court\_list ```python def get_court_list() -> ApiResponse @@ -156,7 +157,7 @@ Gets a list of all of the courts that you can file into. Slightly more limited t -#### get\_filing\_list(court\_id: str, user\_id: str = None, start\_date: datetime = None, before\_date: datetime = None) +### get\_filing\_list ```python def get_filing_list(court_id: str, @@ -169,7 +170,7 @@ 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 ```python def get_service_types(court_id: str, all_vars: dict = None) -> ApiResponse @@ -179,7 +180,7 @@ Checks the court info: if it has conditional service types, call a special API w -#### get\_cases\_raw(court\_id: str, \*, person\_name: dict = None, business\_name: str = None, docket\_number: str = None) +### get\_cases\_raw ```python def get_cases_raw(court_id: str, @@ -194,6 +195,6 @@ provided at a time. Params: court_id (str) person_name (dict) -buisness_name (str) +business_name (str) docket_number (str) diff --git a/docs/components/EFSPIntegration/test/test_proxy_conn.md b/docs/components/EFSPIntegration/test/test_proxy_conn.md index 09cfcc66d..b62e1c5a3 100644 --- a/docs/components/EFSPIntegration/test/test_proxy_conn.md +++ b/docs/components/EFSPIntegration/test/test_proxy_conn.md @@ -1,4 +1,4 @@ -# Table of Contents +# EFSPIntegration.test.test_proxy_conn * [EFSPIntegration.test.test\_proxy\_conn](#EFSPIntegration.test.test_proxy_conn) * [jurisdiction](#EFSPIntegration.test.test_proxy_conn.jurisdiction) diff --git a/docs/components/formfyxer/docx_wrangling.md b/docs/components/formfyxer/docx_wrangling.md index dfc7e2ff5..c888ea14f 100644 --- a/docs/components/formfyxer/docx_wrangling.md +++ b/docs/components/formfyxer/docx_wrangling.md @@ -1,71 +1,181 @@ -# 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) + * [get\_modified\_docx\_runs](#formfyxer.docx_wrangling.get_modified_docx_runs) + * [make\_docx\_plain\_language](#formfyxer.docx_wrangling.make_docx_plain_language) * [modify\_docx\_with\_openai\_guesses](#formfyxer.docx_wrangling.modify_docx_with_openai_guesses) -pydoc-module-header.hbs -#### update\_docx(document: docx.Document, modified\_runs: Tuple[int,int,str,str,int]) + + +### update\_docx ```python def update_docx( - document: docx.Document, modified_runs: Tuple[int, int, str, str, - int]) -> docx.Document + document: Union[docx.document.Document, str], + modified_runs: List[Tuple[int, int, str, + int]]) -> docx.document.Document ``` Update the document with the modified runs. -**Arguments**: +Note: OpenAI is probabilistic, so the modified run indices may not be correct. +When the index of a run or paragraph is out of range, a new paragraph +will be inserted at the end of the document or a new run at the end of the +paragraph's runs. + +Take a careful look at the output document to make sure it is still correct. + +#### Arguments -- `document` - the docx.Document object +- `document` - the docx.Document object, or the path to the DOCX file - `modified_runs` - a tuple of paragraph number, run number, the modified text, a question (not used), and whether a new paragraph should be inserted (for conditional text) -**Returns**: +#### Returns The modified document. + + +### get\_docx\_repr + +```python +def get_docx_repr(docx_path: str, + paragraph_start: int = 0, + paragraph_end: Optional[int] = None) +``` + +Return a JSON representation of the paragraphs and runs in the DOCX file. + +#### Arguments + +- `docx_path` - path to the DOCX file + + +#### Returns + + A JSON representation of the paragraphs and runs in the DOCX file. + -#### get\_labeled\_docx\_runs(docx\_path: str, custom\_people\_names: Optional[Tuple[str, str]] = None) +### get\_labeled\_docx\_runs ```python def get_labeled_docx_runs( - docx_path: str, - custom_people_names: Optional[Tuple[str, str]] = None -) -> List[Tuple[int, int, str]] + 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) -> List[Tuple[int, int, str, int]] ``` Scan the DOCX and return a list of modified text with Jinja2 variable names inserted. -**Arguments**: +#### Arguments - `docx_path` - path to the DOCX file +- `docx_repr` - a string representation of the paragraphs and runs in the DOCX file, if docx_path is not provided. This might be useful if you want - `custom_people_names` - a tuple of custom names and descriptions to use in addition to the default ones. Like: ("clients", "the person benefiting from the form") -**Returns**: +#### Returns A list of tuples, each containing a paragraph number, run number, and the modified text of the run. + + +### get\_modified\_docx\_runs + +```python +def 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) -> List[Tuple[int, int, str, int]] +``` + +Use GPT to rewrite the contents of a DOCX file paragraph by paragraph. Does not handle tables, footers, or +other structures yet. + +This is a light wrapper that provides the structure of DOCX paragraphs and runs to your prompt +to OpenAI to facilitate the rewriting of the document without disrupting formatting. + +For example, this could be used to: +* Remove any passive voice +* Replace placeholder text with variable names +* Rewrite to a 6th grade reading level +* Do an advanced search and replace, without requiring you to use a regex + +By default, the example prompt includes a sample like this: + +[ +[0, 0, "Dear "], +[0, 1, "John Smith:"], +[1, 0, "I hope this letter finds you well."], +] + +Your custom instructions should include an example of how the sample will be modified, like the one below: + +Example reply, indicating paragraph, run, the new text, and a number indicating if this changes the +current paragraph, adds one before, or adds one after (-1, 0, 1): + +\{"results": +[ +[0, 1, "Dear \{\{ other_parties[0] \}\}:", 0], +[2, 0, "\{%p if is_tenant %\}", -1], +[3, 0, "\{%p endif %\}", 1], +] +\} + +You may also want to customize the input example to better match your use case. + +#### Arguments + +- `docx_path` _str_ - path to the DOCX file +- `docx_repr` _str_ - a string representation of the paragraphs and runs in the DOCX file, if docx_path is not provided. +- `custom_example` _Optional[str]_ - a string containing the purpose and overview of the task + instructions (str) a string containing specific instructions for the task +- `openai_client` _Optional[OpenAI]_ - an OpenAI client object. If not provided a new one will be created. +- `api_key` _Optional[str]_ - an OpenAI API key. If not provided, it will be obtained from the environment +- `temperature` _float_ - the temperature to use when generating text. Lower temperatures are more conservative. + + +#### Returns + + A list of tuples, each containing a paragraph number, run number, and the modified text of the run. + + + +### make\_docx\_plain\_language + +```python +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 ```python -def modify_docx_with_openai_guesses(docx_path: str) -> docx.Document +def modify_docx_with_openai_guesses(docx_path: str) -> docx.document.Document ``` Uses OpenAI to guess the variable names for a document and then modifies the document with the guesses. -**Arguments**: +#### Arguments - `docx_path` _str_ - Path to the DOCX file to modify. -**Returns**: +#### Returns - `docx.Document` - The modified document, ready to be saved to the same or a new path diff --git a/docs/components/formfyxer/lit_explorer.md b/docs/components/formfyxer/lit_explorer.md index ec13526a9..44995afe3 100644 --- a/docs/components/formfyxer/lit_explorer.md +++ b/docs/components/formfyxer/lit_explorer.md @@ -1,4 +1,4 @@ -# Table of Contents +# formfyxer.lit_explorer * [formfyxer.lit\_explorer](#formfyxer.lit_explorer) * [recursive\_get\_id](#formfyxer.lit_explorer.recursive_get_id) @@ -18,10 +18,13 @@ * [time\_to\_answer\_field](#formfyxer.lit_explorer.time_to_answer_field) * [time\_to\_answer\_form](#formfyxer.lit_explorer.time_to_answer_form) * [cleanup\_text](#formfyxer.lit_explorer.cleanup_text) + * [text\_complete](#formfyxer.lit_explorer.text_complete) * [complete\_with\_command](#formfyxer.lit_explorer.complete_with_command) * [needs\_calculations](#formfyxer.lit_explorer.needs_calculations) + * [tools\_passive](#formfyxer.lit_explorer.tools_passive) * [get\_passive\_sentences](#formfyxer.lit_explorer.get_passive_sentences) * [get\_citations](#formfyxer.lit_explorer.get_citations) + * [get\_sensitive\_data\_types](#formfyxer.lit_explorer.get_sensitive_data_types) * [substitute\_phrases](#formfyxer.lit_explorer.substitute_phrases) * [substitute\_neutral\_gender](#formfyxer.lit_explorer.substitute_neutral_gender) * [substitute\_plain\_language](#formfyxer.lit_explorer.substitute_plain_language) @@ -29,9 +32,10 @@ * [parse\_form](#formfyxer.lit_explorer.parse_form) * [form\_complexity](#formfyxer.lit_explorer.form_complexity) -pydoc-module-header.hbs -#### recursive\_get\_id(values\_to\_unpack: Union[dict, list], tmpl: Optional[set] = None) + + +### recursive\_get\_id ```python def recursive_get_id(values_to_unpack: Union[dict, list], @@ -42,7 +46,7 @@ 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 ```python def spot(text: str, @@ -58,7 +62,7 @@ the NSMIv2/LIST taxonomy (https://taxonomy.legal/), but returns only the IDs of -#### re\_case(text: str) +### re\_case ```python def re_case(text: str) -> str @@ -68,7 +72,7 @@ Capture PascalCase, snake_case and kebab-case terms and add spaces to separate t -#### regex\_norm\_field(text: str) +### regex\_norm\_field ```python def regex_norm_field(text: str) @@ -79,10 +83,12 @@ See: https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/docum -#### reformat\_field(text: str, max\_length: int = 30, tools\_token=None) +### reformat\_field ```python -def reformat_field(text: str, max_length: int = 30, tools_token=None) +def reformat_field(text: str, + max_length: int = 30, + tools_token: Optional[str] = None) ``` Transforms a string of text into a snake_case variable close in length to `max_length` name by @@ -91,7 +97,7 @@ h/t https://towardsdatascience.com/nlp-building-a-summariser-68e0c19e3a93 -#### norm(row) +### norm ```python def norm(row) @@ -101,7 +107,7 @@ Normalize a word vector. -#### vectorize(text: Union[List[str], str], tools\_token: Optional[str] = None) +### vectorize ```python def vectorize(text: Union[List[str], str], tools_token: Optional[str] = None) @@ -109,16 +115,18 @@ def vectorize(text: Union[List[str], str], tools_token: Optional[str] = None) Vectorize a string of text. -**Arguments**: +#### Arguments - `text` - a string of multiple words to vectorize - `tools_token` - the token to tools.suffolklitlab.org, used for micro-service to reduce the amount of memory you need on your machine. If - not passed, you need to have `en_core_web_lg` installed + not passed, you need to have `en_core_web_lg` installed. NOTE: this + 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 ```python def normalize_name(jur: str, @@ -138,7 +146,7 @@ Will be replaced with call to LLM soon. -#### cluster\_screens(fields: List[str] = [], damping: float = 0.7, tools\_token: Optional[str] = None) +### cluster\_screens ```python def cluster_screens(fields: List[str] = [], @@ -148,7 +156,7 @@ def cluster_screens(fields: List[str] = [], Groups the given fields into screens based on how much they are related. -**Arguments**: +#### Arguments - `fields` - a list of field names - `damping` - a value >= 0.5 and < 1. Tunes how related screens should be @@ -170,7 +178,7 @@ handle text, checkbox, and signature fields. -#### field\_types\_and\_sizes(fields: Optional[Iterable[FormField]]) +### field\_types\_and\_sizes ```python def field_types_and_sizes( @@ -207,7 +215,7 @@ See Jarret and Gaffney, Forms That Work (2008) -#### classify\_field(field: FieldInfo, new\_name: str) +### classify\_field ```python def classify_field(field: FieldInfo, new_name: str) -> AnswerType @@ -218,7 +226,7 @@ it as either a "slot-in", "gathered", "third party" -#### get\_adjusted\_character\_count(field: FieldInfo) +### get\_adjusted\_character\_count ```python def get_adjusted_character_count(field: FieldInfo) -> float @@ -231,13 +239,13 @@ The function chunks the answers into 5 different lengths (checkboxes, 2 words, s instead of directly using the character count, as forms can allocate different spaces for the same data without considering the space the user actually needs. -**Arguments**: +#### Arguments - `field` _FieldInfo_ - An object containing information about the input field, including the "max_length" attribute. -**Returns**: +#### Returns - `float` - The approximate length of the field content, categorized into checkboxes, 2 words, short, medium, or long based on the max_length attribute. @@ -258,7 +266,7 @@ for the same data without considering the space the user actually needs. -#### time\_to\_answer\_field(field: FieldInfo, new\_name: str, cpm: int = 40, cpm\_std\_dev: int = 17) +### time\_to\_answer\_field ```python def time_to_answer_field(field: FieldInfo, @@ -275,7 +283,7 @@ The return value is a function that can return N samples of how long it will tak -#### time\_to\_answer\_form(processed\_fields, normalized\_fields) +### time\_to\_answer\_form ```python def time_to_answer_form(processed_fields, @@ -295,7 +303,7 @@ b. long created (anything over 3 lines) -#### cleanup\_text(text: str, fields\_to\_sentences: bool = False) +### cleanup\_text ```python def cleanup_text(text: str, fields_to_sentences: bool = False) -> str @@ -303,9 +311,29 @@ def cleanup_text(text: str, fields_to_sentences: bool = False) -> str Apply cleanup routines to text to provide more accurate readability statistics. + + +### text\_complete + +```python +def text_complete(prompt: str, + max_tokens: int = 500, + creds: Optional[OpenAiCreds] = None, + temperature: float = 0) -> str +``` + +Run a prompt via openAI's API and return the result. + +#### Arguments + +- `prompt` _str_ - The prompt to send to the API. +- `max_tokens` _int, optional_ - The number of tokens to generate. Defaults to 500. +- `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 ```python def complete_with_command(text, @@ -318,22 +346,35 @@ Combines some text with a command to send to open ai. -#### needs\_calculations(text: Union[str, Doc]) +### needs\_calculations ```python -def needs_calculations(text: Union[str, Doc]) -> bool +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 + +```python +def tools_passive(input: Union[List[str], str], + tools_token: Optional[str] = None) +``` + +Ping passive voice API for list of sentences using the passive voice + -#### get\_passive\_sentences(text: Union[List, str]) +### get\_passive\_sentences ```python def get_passive_sentences( - text: Union[List, str]) -> List[Tuple[str, List[Tuple[int, int]]]] + text: Union[List, str], + tools_token: Optional[str] = None +) -> List[Tuple[str, List[Tuple[int, int]]]] ``` Return a list of tuples, where each tuple represents a @@ -348,7 +389,7 @@ sentences containing fewer than 2 words will be ignored. -#### get\_citations(text: str, tokenized\_sentences: List[str]) +### get\_citations ```python def get_citations(text: str, tokenized_sentences: List[str]) -> List[str] @@ -358,9 +399,27 @@ 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 + +```python +def get_sensitive_data_types( + fields: List[str], + fields_old: Optional[List[str]] = None) -> Dict[str, List[str]] +``` + +Given a list of fields, identify those related to sensitive information and return a dictionary with the sensitive +fields grouped by type. A list of the old field names can also be provided. These fields should be in the same +order. Passing the old field names allows the sensitive field algorithm to match more accurately. The return value +will not contain the old field name, only the corresponding field name from the first parameter. + +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 ```python def substitute_phrases( @@ -371,13 +430,13 @@ def substitute_phrases( Substitute phrases in the input string and return the new string and positions of substituted phrases. -**Arguments**: +#### Arguments - `input_string` _str_ - The input string containing phrases to be replaced. - `substitution_phrases` _Dict[str, str]_ - A dictionary mapping original phrases to their replacement phrases. -**Returns**: +#### Returns Tuple[str, List[Tuple[int, int]]]: A tuple containing the new string with substituted phrases and a list of tuples, each containing the start and end positions of the substituted @@ -396,7 +455,7 @@ Substitute phrases in the input string and return the new string and positions o -#### substitute\_neutral\_gender(input\_string: str) +### substitute\_neutral\_gender ```python def substitute_neutral_gender( @@ -408,7 +467,7 @@ Primary source is https://github.com/joelparkerhenderson/inclusive-language -#### substitute\_plain\_language(input\_string: str) +### substitute\_plain\_language ```python def substitute_plain_language( @@ -420,7 +479,7 @@ Source of terms is drawn from https://www.plainlanguage.gov/guidelines/words/ -#### transformed\_sentences(sentence\_list: List[str], fun: Callable) +### transformed\_sentences ```python def transformed_sentences( @@ -434,7 +493,7 @@ 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 ```python def parse_form(in_file: str, @@ -455,7 +514,7 @@ NSMI code. If you pass openai creds, we will give suggestions for the title and -#### form\_complexity(stats) +### form\_complexity ```python def form_complexity(stats) diff --git a/docs/components/formfyxer/pdf_wrangling.md b/docs/components/formfyxer/pdf_wrangling.md index 6d82c3e49..58f4648f2 100644 --- a/docs/components/formfyxer/pdf_wrangling.md +++ b/docs/components/formfyxer/pdf_wrangling.md @@ -1,4 +1,4 @@ -# Table of Contents +# formfyxer.pdf_wrangling * [formfyxer.pdf\_wrangling](#formfyxer.pdf_wrangling) * [FieldType](#formfyxer.pdf_wrangling.FieldType) @@ -31,7 +31,8 @@ * [auto\_add\_fields](#formfyxer.pdf_wrangling.auto_add_fields) * [is\_tagged](#formfyxer.pdf_wrangling.is_tagged) -pydoc-module-header.hbs + + ## FieldType Objects @@ -41,25 +42,25 @@ class FieldType(Enum) -#### TEXT +### TEXT Text input Field -#### AREA +### AREA Text input Field, but an area -#### LIST\_BOX +### LIST\_BOX allows multiple selection -#### CHOICE +### CHOICE allows only one selection @@ -75,7 +76,7 @@ A data holding class, used to easily specify how a PDF form field should be crea -#### \_\_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\_\_ ```python def __init__(field_name: str, @@ -89,7 +90,7 @@ def __init__(field_name: str, Constructor -**Arguments**: +#### Arguments - `x` - the x position of the lower left corner of the field. Should be in X,Y coordinates, where (0, 0) is the lower left of the page, x goes to the right, and units are in @@ -104,7 +105,7 @@ Constructor -#### set\_fields(in\_file: Union[str, Path, BinaryIO], out\_file: Union[str, Path, BinaryIO], fields\_per\_page: Iterable[Iterable[FormField]], \*, overwrite=False) +### set\_fields ```python def set_fields(in_file: Union[str, Path, BinaryIO], @@ -134,7 +135,7 @@ set_fields('no_fields.pdf', 'four_fields_on_second_page.pdf', ) ``` -**Arguments**: +#### Arguments - `in_file` - the input file name or path of a PDF that we're adding the fields to - `out_file` - the output file name or path where the new version of in_file will @@ -148,13 +149,13 @@ set_fields('no_fields.pdf', 'four_fields_on_second_page.pdf', different PDFs. -**Returns**: +#### Returns Nothing. -#### rename\_pdf\_fields(in\_file: Union[str, Path, BinaryIO], out\_file: Union[str, Path, BinaryIO], mapping: Mapping[str, str]) +### rename\_pdf\_fields ```python def rename_pdf_fields(in_file: Union[str, Path, BinaryIO], @@ -182,7 +183,7 @@ Returns: -#### unlock\_pdf\_in\_place(in\_file: Union[str, Path, BinaryIO]) +### unlock\_pdf\_in\_place ```python def unlock_pdf_in_place(in_file: Union[str, Path, BinaryIO]) -> None @@ -192,7 +193,7 @@ Try using pikePDF to unlock the PDF it it is locked. This won't work if it -#### has\_fields(pdf\_file: str) +### has\_fields ```python def has_fields(pdf_file: str) -> bool @@ -200,18 +201,18 @@ def has_fields(pdf_file: str) -> bool Check if a PDF has at least one form field using PikePDF. -**Arguments**: +#### Arguments - `pdf_file` _str_ - The path to the PDF file. -**Returns**: +#### Returns - `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 ```python def get_existing_pdf_fields( @@ -222,7 +223,7 @@ 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 ```python def swap_pdf_page(*, @@ -239,7 +240,7 @@ in the destination PDF. If you wish to append annotations instead, specify `appe -#### 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 ```python def copy_pdf_fields(*, @@ -268,7 +269,7 @@ new_pdf_with_fields.save("new_pdf_with_fields.pdf") ``` -**Arguments**: +#### Arguments - `source_pdf` - a file name or path to a PDF that has AcroForm fields - `destination_pdf` - a file name or path to a PDF without AcroForm fields. Existing fields will be removed. @@ -278,14 +279,14 @@ new_pdf_with_fields.save("new_pdf_with_fields.pdf") overwriting. Defaults to false; when enabled may lead to undefined behavior. -**Returns**: +#### Returns 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 ```python def get_textboxes_in_pdf(in_file: Union[str, Path, BinaryIO], @@ -297,7 +298,7 @@ Gets all of the text boxes found by pdfminer in a PDF, as well as their bounding -#### get\_bracket\_chars\_in\_pdf(in\_file: Union[str, Path, BinaryIO], line\_margin=0.02, char\_margin=0.0) +### get\_bracket\_chars\_in\_pdf ```python def get_bracket_chars_in_pdf(in_file: Union[str, Path, BinaryIO], @@ -312,7 +313,7 @@ Currently going with just "[hi]" doesn't happen, let's hope -#### intersect\_bbox(bbox\_a, bbox\_b, vert\_dilation=2, horiz\_dilation=2) +### intersect\_bbox ```python def intersect_bbox(bbox_a, bbox_b, vert_dilation=2, horiz_dilation=2) -> bool @@ -322,7 +323,7 @@ bboxes are [left edge, bottom edge, horizontal length, vertical length] -#### intersect\_bboxs(bbox\_a, bboxes, vert\_dilation=2, horiz\_dilation=2) +### intersect\_bboxs ```python def intersect_bboxs(bbox_a, @@ -335,7 +336,7 @@ Returns an iterable of booleans, one of each of the input bboxes, true if it col -#### contain\_boxes(bbox\_a: BoundingBoxF, bbox\_b: BoundingBoxF) +### contain\_boxes ```python def contain_boxes(bbox_a: BoundingBoxF, bbox_b: BoundingBoxF) -> BoundingBoxF @@ -345,7 +346,7 @@ Given two bounding boxes, return a single bounding box that contains both of the -#### get\_dist\_sq(point\_a: XYPair, point\_b: XYPair) +### get\_dist\_sq ```python def get_dist_sq(point_a: XYPair, point_b: XYPair) -> float @@ -355,7 +356,7 @@ returns the distance squared between two points. Faster than the true euclidean -#### get\_dist(point\_a: XYPair, point\_b: XYPair) +### get\_dist ```python def get_dist(point_a: XYPair, point_b: XYPair) -> float @@ -365,7 +366,7 @@ euclidean (L^2 norm) distance between two points -#### get\_connected\_edges(point: XYPair, point\_list: Sequence) +### get\_connected\_edges ```python def get_connected_edges(point: XYPair, point_list: Sequence) @@ -376,7 +377,7 @@ i.e. bottom left, top left, top right, bottom right -#### bbox\_distance(bbox\_a: BoundingBoxF, bbox\_b: BoundingBoxF) +### bbox\_distance ```python def bbox_distance( @@ -393,7 +394,7 @@ 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 ```python def get_possible_fields( @@ -415,7 +416,7 @@ print(fields[0][0]) ``` -**Arguments**: +#### Arguments - `in_pdf_file` - the input PDF - `textboxes` _optional_ - the location of various lines of text in the PDF. @@ -423,13 +424,13 @@ print(fields[0][0]) pass through expensive info to calculate through several functions. -**Returns**: +#### Returns 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 ```python def get_possible_checkboxes(img: Union[str, cv2.Mat], @@ -444,7 +445,7 @@ like O and D, if the font is too small -#### get\_possible\_radios(img: Union[str, BinaryIO, cv2.Mat]) +### get\_possible\_radios ```python def get_possible_radios(img: Union[str, BinaryIO, cv2.Mat]) @@ -455,7 +456,7 @@ 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 ```python def get_possible_text_fields( @@ -473,7 +474,7 @@ default_line_height: the default height (16 pt), in pixels (at 200 dpi), which i -#### auto\_add\_fields(in\_pdf\_file: Union[str, Path], out\_pdf\_file: Union[str, Path]) +### auto\_add\_fields ```python def auto_add_fields(in_pdf_file: Union[str, Path], out_pdf_file: Union[str, @@ -491,7 +492,7 @@ auto_add_fields('no_fields.pdf', 'newly_added_fields.pdf') ``` -**Arguments**: +#### Arguments - `in_pdf_file` - the input file name or path of the PDF where we'll try to find possible fields - `out_pdf_file` - the output file name or path of the PDF where a new version of `in_pdf_file` will @@ -499,13 +500,13 @@ auto_add_fields('no_fields.pdf', 'newly_added_fields.pdf') filename, it will be overwritten. -**Returns**: +#### Returns Nothing -#### is\_tagged(in\_pdf\_file: Union[str, Path, pikepdf.Pdf]) +### is\_tagged ```python def is_tagged(in_pdf_file: Union[str, Path, pikepdf.Pdf]) -> bool @@ -513,12 +514,12 @@ def is_tagged(in_pdf_file: Union[str, Path, pikepdf.Pdf]) -> bool Determines if the input PDF file is tagged for accessibility. -**Arguments**: +#### Arguments - `in_pdf_file` _Union[str, Path]_ - The path to the PDF file, as a string or a Path object. -**Returns**: +#### Returns - `bool` - True if the PDF is tagged, False otherwise. diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml index 66a41cc1e..c1b0794a9 100644 --- a/pydoc-markdown.yml +++ b/pydoc-markdown.yml @@ -44,4 +44,3 @@ renderer: # Better anchor insertion insert_header_anchors: true - render_module_header_template: "pydoc-module-header.hbs" diff --git a/pydoc-module-header.hbs b/pydoc-module-header.hbs index 1d343774d..fb547c7ce 100644 --- a/pydoc-module-header.hbs +++ b/pydoc-module-header.hbs @@ -1,4 +1,13 @@ --- sidebar_label: "{{ module.name }}" -title: "{{ module.name }}" +title: "{{#if module.docstring.summary}}{{ module.docstring.summary }}{{else}}{{ module.name }}{{/if}}" --- + +# Table of Contents + +{{#each module.members}} +* [{{ name }}](#{{ name }}) +{{#each members}} + * [{{ name }}](#{{ ../name }}.{{ name }}) +{{/each}} +{{/each}} From df243ac839a25a1e9f0875b40eeca28a9d86da95 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Wed, 10 Sep 2025 10:09:42 -0400 Subject: [PATCH 6/7] Add new file --- fix-doc-titles.sh | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 fix-doc-titles.sh diff --git a/fix-doc-titles.sh b/fix-doc-titles.sh new file mode 100755 index 000000000..8384a69f8 --- /dev/null +++ b/fix-doc-titles.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# Fix auto-generated documentation titles and navigation +# Replace "Table of Contents" with the actual module name +# Improve header hierarchy for better navigation + +echo "Fixing documentation titles and navigation..." + +for file in $(find docs/components -name "*.md" -exec grep -l "# Table of Contents" {} \;); do + # Extract the module name from the first TOC entry + module_name=$(grep -m 1 "^\* \[.*\]" "$file" | sed 's/^\* \[\(.*\)\](#.*)/\1/' | sed 's/\\_/_/g') + if [ ! -z "$module_name" ]; then + echo "Processing $file -> $module_name" + + # Replace "Table of Contents" with module name + sed -i "1s/# Table of Contents/# $module_name/" "$file" + + # Promote method headers from H4 (####) to H3 (###) for better navigation + # This makes methods appear in the right-hand navigation menu + # Handle both regular and escaped method names + sed -i 's/^#### \([a-zA-Z_\\][a-zA-Z0-9_\\]*\)(/### \1(/g' "$file" + + # Also promote method headers that don't have parameters (like properties) + sed -i 's/^#### \([a-zA-Z_\\][a-zA-Z0-9_\\]*\)$/### \1/g' "$file" + + # Clean up method headers to show only method name (without parameters) in navigation + # This keeps the full signature in the content but shows clean names in the TOC + sed -i 's/^### \([a-zA-Z_\\][a-zA-Z0-9_\\]*\)(.*/### \1/g' "$file" + + # Also clean up the table of contents to show clean method names + sed -i 's/\* \[\([a-zA-Z_\\][a-zA-Z0-9_\\]*\)([^)]*)/ * [\1/g' "$file" + + # Promote standalone functions (those at module level, not class methods) to H2 + # Identify standalone functions from TOC: they appear as " * [function_name]" (module level) + # vs class methods which appear as " * [method_name]" (indented further) + # Promote standalone functions (those at module level, not class methods) to H2 + # This creates a clearer navigation hierarchy where standalone functions + # are separate from class methods + + # For al_general.md, promote common standalone functions + if [[ "$file" == *"al_general.md" ]]; then + sed -i 's/^### section\\_links$/## section\\_links/g' "$file" + sed -i 's/^### will\\_send\\_to\\_real\\_court$/## will\\_send\\_to\\_real\\_court/g' "$file" + sed -i 's/^### filter\\_letters$/## filter\\_letters/g' "$file" + sed -i 's/^### fa\\_icon$/## fa\\_icon/g' "$file" + sed -i 's/^### is\\_sms\\_enabled$/## is\\_sms\\_enabled/g' "$file" + sed -i 's/^### is\\_phone\\_or\\_email$/## is\\_phone\\_or\\_email/g' "$file" + sed -i 's/^### github\\_modified\\_date$/## github\\_modified\\_date/g' "$file" + sed -i 's/^### language\\_name$/## language\\_name/g' "$file" + sed -i 's/^### safe\\_states\\_list$/## safe\\_states\\_list/g' "$file" + sed -i 's/^### has\\_parsable\\_pronouns$/## has\\_parsable\\_pronouns/g' "$file" + sed -i 's/^### parse\\_custom\\_pronouns$/## parse\\_custom\\_pronouns/g' "$file" + sed -i 's/^### get\\_visible\\_al\\_nav\\_items$/## get\\_visible\\_al\\_nav\\_items/g' "$file" + fi + + # Convert **Arguments**: and **Returns**: to proper H4 headings for better navigation + sed -i 's/^\*\*Arguments\*\*:/#### Arguments/g' "$file" + sed -i 's/^\*\*Returns\*\*:/#### Returns/g' "$file" + sed -i 's/^\*\*Attributes\*\*:/#### Attributes/g' "$file" + sed -i 's/^\*\*Notes\*\*:/#### Notes/g' "$file" + sed -i 's/^\*\*Raises\*\*:/#### Raises/g' "$file" + + # Remove stray YAML frontmatter blocks that appear in the middle of files + # These are artifacts from the old template processing + sed -i '/^---$/,/^---$/d' "$file" + fi +done + +echo "Done fixing documentation titles and navigation." From 55345dce7b6dcec908175f3bb6f7b9ddd10247d4 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Wed, 10 Sep 2025 10:18:02 -0400 Subject: [PATCH 7/7] Remove test file; add new modules --- sidebars.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index 04c99b26a..ab007f8b5 100644 --- a/sidebars.js +++ b/sidebars.js @@ -130,6 +130,8 @@ module.exports = { "components/AssemblyLine/al_document", "components/AssemblyLine/language", "components/AssemblyLine/sessions", + "components/AssemblyLine/custom_jinja_filters", + "components/AssemblyLine/sign", ] }, 'components/ALRecipes/alrecipes_overview', @@ -183,7 +185,6 @@ module.exports = { 'components/EFSPIntegration/conversions', 'components/EFSPIntegration/interview_logic', 'components/EFSPIntegration/py_efsp_client', - 'components/EFSPIntegration/test/test_conversions', ] }, {